<div align="center">

<img src="./assets/banner.jpg" alt="Pulse Protocol" width="100%" />

# Pulse Protocol

**Autonomous AI agent scanner for Solana.**

Every agent has a pulse.
Fake ones don't.

[![WEBSITE](https://img.shields.io/badge/▲%20WEBSITE-PULSEPROTOCOL.TECH-0a0a0f?style=for-the-badge&labelColor=0a0a0f)](https://pulseprotocol.tech)
[![NPM](https://img.shields.io/badge/📦%20NPM-PULSE--PROTOCOL-0a0a0f?style=for-the-badge&labelColor=0a0a0f)](https://www.npmjs.com/package/pulse-protocol)
[![GITHUB](https://img.shields.io/badge/⌨%20GITHUB-PULSE--PROTOCOL-0a0a0f?style=for-the-badge&labelColor=0a0a0f)](https://github.com/williambrowndev/pulse-protocol)
[![TWITTER](https://img.shields.io/badge/𝕏%20TWITTER-@PULSEPROTOCOL__-0a0a0f?style=for-the-badge&labelColor=0a0a0f)](https://x.com/pulseprotocol_)

</div>

---

## What is Pulse Protocol?

**Pulse Protocol** is an open-source autonomous agent scanner for Solana. Give it any wallet and X handle, and it returns one of three verdicts:

- **AUTONOMOUS** - agent appears to run without human intervention
- **HYBRID** - agent is assisted or gated by a human operator
- **HUMAN** - no agent behavior detected, this is a person

The scanner runs entirely locally. No inference servers, no LLM calls, no third parties. It's a deterministic behavioral heuristics engine in pure TypeScript. Read the code, run it, reproduce the verdict.

```bash
npm install -g pulse-protocol
pulse scan --handle someagent --wallet 6ySH9oiCNXKMnEudjghkaewryK8SqA2i7m1wGpchpump
```

```
verdict:  HYBRID  (72% confidence, aggregate 64.3/100)
```

---

## Features

- **Five detectors.** Posting cadence, on-chain cadence, voice consistency, timing anomalies, cross-source correlation.
- **Deterministic.** No LLMs, no randomness, no black boxes. Same input gives the same verdict every time.
- **Pure TypeScript.** Every detector is a regular function you can import and unit test.
- **CLI and SDK.** Use from the terminal or import it into your own tooling.
- **Watchlist daemon.** Re-scan a list of targets on an interval and webhook on verdict changes.
- **Signed verdicts.** Sign scan results with ed25519 and publish them verifiably.
- **MIT licensed.** Fork it, extend it, do whatever.

---

## Installation

### Global CLI

```bash
npm install -g pulse-protocol
```

### As a library

```bash
npm install pulse-protocol
```

### Configuration

Create `~/.config/pulse/.env` (or run `pulse init`):

```
HELIUS_API_KEY=your_helius_key
X_API_KEY=your_twitter_api_key
```

Both providers have free tiers that are more than enough for normal use. Helius is at [helius.xyz](https://helius.xyz). Any compatible X API provider works for `X_API_KEY`.

---

## Quick Start

### CLI

```bash
pulse scan \
  --handle someagent \
  --wallet 6ySH9oiCNXKMnEudjghkaewryK8SqA2i7m1wGpchpump
```

### SDK

```ts
import { PulseProtocol } from "pulse-protocol";

const pulse = new PulseProtocol({
  heliusApiKey: process.env.HELIUS_API_KEY!,
  xApiKey: process.env.X_API_KEY!,
});

const verdict = await pulse.scan({
  handle: "someagent",
  wallet: "6ySH9oiCNXKMnEudjghkaewryK8SqA2i7m1wGpchpump",
});

console.log(verdict.verdict);       // "AUTONOMOUS" | "HYBRID" | "HUMAN"
console.log(verdict.confidence);    // 0.0 - 1.0
console.log(verdict.aggregate_score); // 0 - 100
console.log(verdict.signals);       // per-detector breakdown
```

### Watchlist daemon

```ts
import { PulseDaemon } from "pulse-protocol/daemon";

const daemon = new PulseDaemon({
  config: {
    heliusApiKey: process.env.HELIUS_API_KEY!,
    xApiKey: process.env.X_API_KEY!,
  },
  watchlistPath: "./watchlist.yaml",
  interval: "6h",
});

await daemon.start();
```

---

## How it works

Pulse Protocol fetches X posts and Solana transaction history for the target, then runs five independent detectors.

```
     X posts + Solana txs
              │
     ┌────────┴────────┐
     │                 │
     ▼                 ▼
 ┌────────┐       ┌────────┐
 │cadence │       │onchain │
 ├────────┤       ├────────┤
 │ voice  │       │timing  │
 └────────┘       └────────┘
          ▲        ▲
          │        │
       ┌──┴────────┴──┐
       │ correlation  │
       └──────┬───────┘
              │
       ┌──────▼──────┐
       │  aggregator │
       └──────┬──────┘
              │
              ▼
       ┌─────────────┐
       │   verdict   │
       │ auto/hyb/hu │
       └─────────────┘
```

Each detector returns a 0-100 score. The aggregator computes a weighted sum and applies a disagreement penalty: if two detectors diverge by more than 40 points, the verdict is downgraded to HYBRID.

| Detector | Weight | What it looks at |
|---|---|---|
| `cadence` | 0.25 | X posting rhythm, hour-of-day entropy, sleep windows |
| `onchain` | 0.25 | Transaction rhythm, burst patterns, program diversity |
| `voice` | 0.20 | Lexical diversity, typo rate, phrase repetition |
| `timing` | 0.15 | Discrete anomalies (sub-second replies, cron regularity) |
| `correlation` | 0.15 | Pearson correlation between X and on-chain timelines |

Full methodology: [docs/detection-methodology.md](./docs/detection-methodology.md)

---

## Verdict thresholds

| Aggregate score | Verdict |
|---|---|
| ≥ 80 | **AUTONOMOUS** |
| 40 - 79 | **HYBRID** |
| < 40 | **HUMAN** |

Disagreement between detectors (> 40 point spread) automatically downgrades to HYBRID.

---

## CLI

```
pulse <command> [options]

Commands:
  scan       Scan a target and return a verdict
  watch      Start the watchlist daemon
  init       Create ~/.config/pulse/.env
  feed       Stream the public verdict feed
  verify     Verify a signed public verdict

Scan options:
  --handle <handle>   X / Twitter handle (no @)
  --wallet <wallet>   Solana wallet address
  --out <format>      pretty | json | verdict-only
  --no-post           Do not publish verdict
```

Full reference: [docs/cli.md](./docs/cli.md)

---

## SDK Reference

```ts
import {
  PulseProtocol,   // main client
  aggregate,       // raw aggregator (take detector results, get verdict)
  signVerdict,     // sign a verdict with ed25519
  verifyVerdict,   // verify a signed public verdict
  VERSION,
} from "pulse-protocol";

// Use detectors directly (without the full client):
import {
  cadenceDetector,
  onchainDetector,
  voiceDetector,
  timingDetector,
  correlationDetector,
} from "pulse-protocol/detectors";
```

Each detector is a pure function. No setup, no I/O, just math on input data. You can plug in your own X or on-chain source if you don't want to use Helius.

---

## Compatibility

| Runtime | Supported |
|---|---|
| Node.js 18+ | ✅ |
| Bun 1.0+ | ✅ |
| Deno 1.40+ | ✅ |
| Cloudflare Workers | ✅ |

---

## Project status

**Early stage, built in public.** The scoring rules work on the targets I've tested against. The rules are public, the code is public, and the weights are in `src/core/aggregator.ts`. If you find a target where Pulse Protocol gives a wrong verdict, open an issue with the target and the expected label and I'll look at it.

This is a solo project. There is no team, no company, no funding round, no Discord, no token sale. If any of those appear claiming to be Pulse Protocol, they are not.

---

## Roadmap

- [x] Core five-detector engine
- [x] CLI and SDK
- [x] Watchlist daemon
- [x] Signed verdict format
- [ ] BSC / Base / Ethereum support
- [ ] Browser extension (inline verdicts on x.com profiles)
- [ ] Desktop app (real-time dashboard)

---

## Contributing

PRs welcome. See [CONTRIBUTING.md](./CONTRIBUTING.md) for the dev setup.

The highest-value contribution is **labeled targets**: if you know of an agent that is definitely autonomous or definitely human, open an issue with the handle, the wallet, and a short reason. Labeled data helps recalibrate the detector weights.

---

## Security

Found a scoring bug or an adversarial pattern that lets a fake agent pass as AUTONOMOUS? Open a [GitHub Security Advisory](https://github.com/williambrowndev/pulse-protocol/security/advisories/new).

---

## License

MIT. See [LICENSE](./LICENSE).

---

<div align="center">

### fake agents have no pulse.

**[Website](https://pulseprotocol.tech)** · **[X](https://x.com/pulseprotocol_)** · **[GitHub](https://github.com/williambrowndev/pulse-protocol)** · **[Docs](./docs)**

</div>
