# USRCP — User Context Protocol [Health: Active]

**Category:** 💻 Developer Tools  
**Repository:** https://github.com/frank-bot07/usrcp  
**GitHub Stars:** 1  
**Views:** 0  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/usrcp-user-context-protocol

## Description
Encrypted local ledger of structured user state, shared across every MCP-aware AI tool.

## Claude Desktop Quick Installation
Install path detected from listing signals. Uses `npx` (confidence: high):

```json
"mcpServers": {
  "usrcp-user-context-protocol": {
    "command": "npx",
    "args": ["-y","usrcp"]
  }
}
```

## Documentation & README

# USRCP — User Context Protocol

**A private context brief for the human behind every AI tool. Continue your work across interfaces without repeating the briefing.**

You told Claude Desktop your stack on Tuesday. On Wednesday, Cursor doesn't know. Thursday, Codex asks again. Every AI tool you use has its own memory, or none.

USRCP is a local, encrypted SQLite ledger that any MCP-aware tool can read and write. One install, one passphrase, and every tool shares the same structured user state — your timezone, your stack, your projects, your preferences.

Registers with **Claude Desktop**, **Cursor**, **Continue**, **Cline**, and terminal agents (**Claude Code**, **Codex CLI**, **Copilot CLI**, **Aider**, **OpenCode**, **Antigravity**). Captures structured activity from **GitHub**, **Linear**, **Obsidian**, **Claude Code sessions**, and **Google Calendar** — plus an [experimental conversation-capture set](#conversation-capture-adapters-experimental).

```bash
brew install frank-bot07/usrcp/usrcp
usrcp init
```

<!-- TODO(chad): swap the demo link below for the 30s screencast once recorded — runbook in tasks/32-demo-script.md -->
→ **See it work:** [the cross-editor demo](https://github.com/frank-bot07/usrcp/blob/HEAD/docs/demos/cross-editor.md), or prove the claim on your own machine in one command — `node scripts/cross-client-proof.mjs` (writes state as one editor, reads it as another, then scans the raw DB to show it's all ciphertext).
→ Apache 2.0 · 600+ tests · threat model in [`docs/SECURITY.md`](https://github.com/frank-bot07/usrcp/blob/HEAD/docs/SECURITY.md)

---

> **Core and optional features:** the structured core uses exact-keyword lookup. Optional `usrcp-stream` adds semantic recall with a different storage/privacy boundary; see the capability matrix below.

## Protocol Stack

```
┌─────────────────────────────────┐
│         Agent Layer             │  ← ACP (Agent-to-Agent)
├─────────────────────────────────┤
│         Model Layer             │  ← MCP (Model Context Protocol)
├─────────────────────────────────┤
│     >>> USRCP <<<               │  ← Structured User State (THIS PROTOCOL)
├─────────────────────────────────┤
│         User / Client           │
└─────────────────────────────────┘
```

## One human, many AI interfaces

USRCP is the human user's context layer. The launch workflow is live retrieval of a compact brief from one shared ledger. Your next assistant should know the relevant ongoing work, decisions, constraints and next steps.

```bash
usrcp handoff --domain=coding --output=HANDOFF.md
```

Connected MCP clients call `usrcp_handoff` to get current context and save meaningful updates immediately. The file command above is an optional manual fallback. The local MCP server provides startup instructions, but clients must honor them; verify actual behavior with the [two-client acceptance test](https://github.com/frank-bot07/usrcp/blob/HEAD/docs/launch/PILOT.md). A shared ledger alone does not prove automatic retrieval.

### Capability and privacy boundaries

| Component | Purpose | Boundary |
| --- | --- | --- |
| Structured core | Identity, preferences, projects, facts and timeline | Content encrypted at rest; authorized agents receive decrypted context |
| Markdown handoff | Condensed next-agent briefing | Explicit plaintext export with restricted file permissions; share only intended context |
| Optional stream | Capture and semantic recall | Local embedding vectors are plaintext on disk; optional external embedding providers receive content after consent |
| Optional device relay | Timeline/stream event sync | Ciphertext content with visible metadata; the local client does not synchronize the entire structured profile |

The initial supported workflow is developers switching Claude Code, Codex and Cursor, with Markdown export available for other interfaces. The broader goal remains continuity for the human user across tools. Read [context ownership](https://github.com/frank-bot07/usrcp/blob/HEAD/docs/launch/CONTEXT.md) for inspection, correction, provenance, expiry and deletion alternatives.

### Alternatives

[OpenMemory](https://mem0.ai/openmemory) also targets cross-tool coding context and automatic capture. [Zep](https://help.getzep.com/graph-overview) provides temporal knowledge graphs. These products overlap with parts of USRCP's workflow. USRCP's proposed advantage is a small, inspectable human-context brief backed by a local encrypted ledger, explicit sharing and no required cloud account for the core workflow. Compare current editions and test against your existing project notes; do not assume other products are merely vector storage or always require a particular provider.

## Quickstart

### Install

**npm (recommended)** — the `usrcp` CLI + encrypted ledger:

```bash
npm install -g usrcp        # the `usrcp` command + local ledger
# …or run without installing:
npx usrcp init
```

No native build, no compiler, no postinstall — usrcp uses Node's built-in SQLite (`node:sqlite`), so `npm install` just works on any npm (including npm 12+, whose `allowScripts` default blocks native build scripts). Requires **Node ≥ 22.13** (Node 24+ recommended).

**Homebrew (macOS / Linux)** — alternative for the core CLI:

```bash
brew install frank-bot07/usrcp/usrcp
```

The CLI ships with the inline adapters (`terminal`, `mcp-agent`, `openclaw`). Capture adapters install as their own packages, then you configure each with the setup wizard:

```bash
# structured-state adapters:
npm install -g usrcp-github   # or usrcp-linear, usrcp-obsidian, usrcp-claude-code, usrcp-google-calendar
usrcp setup --adapter=github

# experimental conversation-capture set:
npm install -g usrcp-slack    # or usrcp-discord, usrcp-telegram, usrcp-imessage, usrcp-gmail
usrcp setup --adapter=slack
```

See the [Adapters](#capture-adapters) table for the full list (the Chrome extension and VS Code viewer ship separately — see their package READMEs).

**From source** — for contributing or running unreleased changes:

```bash
git clone https://github.com/frank-bot07/usrcp.git
# Build the protocol core first — usrcp-local's build compiles it.
cd usrcp/packages/usrcp-core && npm install && npm run build
cd ../usrcp-local && npm install && npm run build && npm link
```

### First run

```bash
# Interactive init — prompts for passphrase by default
usrcp init

# Non-interactive:
usrcp init --passphrase "your secret phrase"       # passphrase mode
usrcp init --dev                                     # dev mode (key on disk)

# Start the server
usrcp serve
```

In passphrase mode, `init` offers to store the passphrase in the **OS keychain** (macOS Keychain / Linux Secret Service); pass `--keychain` / `--no-keychain` to decide non-interactively. With a keychain entry present, MCP clients auto-start the server with no plaintext passphrase in any config file. Manage the entry anytime:

```bash
usrcp keychain store    # add/replace (verifies the passphrase unlocks this ledger first)
usrcp keychain status   # show backend + whether an entry exists
usrcp keychain clear    # remove it

# Prefer no keychain? The env var path still works:
USRCP_PASSPHRASE="your secret phrase" usrcp serve
```

`init` creates `~/.usrcp/users/<slug>/` with an encrypted SQLite ledger and writes the MCP server entry to Claude Desktop's config:

- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Linux: `~/.config/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`

Single-user is the default and what every shared-machine consideration in the rest of this README assumes. If two people use the same OS account (or you run multiple identities side by side), see [Multiple users on one machine](#multiple-users-on-one-machine) below — each user gets an independent ledger and passphrase under a `--user=<name>` slug.

### Adding capture adapters

Adapters watch a source (a GitHub org, an Obsidian vault, a Linear workspace, etc.) and append the activity you authored into the same ledger your local MCP server reads from. Install the adapter's package, then run the setup wizard to configure it:

```bash
npm install -g usrcp-linear          # install the adapter you want
usrcp setup --adapter=linear         # configure it (validates credentials, picks scope)
# or, to browse what's installed:
usrcp setup                          # interactive picker
```

See the [Adapters](#capture-adapters) tables below for the full list.

### Multiple users on one machine

```bash
usrcp init --user=frank
usrcp init --user=jess
usrcp serve --user=frank   # or rely on --user in the registered MCP entry
usrcp users                # list available slugs
```

Each user gets an independent ledger, passphrase, and MCP server entry.

### Passphrase mode and terminal agents

If you initialized USRCP in passphrase mode (`usrcp init` with the default), the MCP server needs the passphrase to decrypt the ledger. The terminal-adapter `register()` writes only `command + args` to each agent's config — it never bakes the passphrase in.

**Recommended: the OS keychain.** One command covers every agent — shell-launched and GUI alike — with nothing in plaintext on disk:

```sh
usrcp keychain store
```

The server checks `USRCP_PASSPHRASE`, then `--passphrase`, then the keychain, so existing setups keep working unchanged. (Windows: keychain support isn't wired up yet — use the env-var paths below.)

**Env-var alternatives**, if you'd rather not use the keychain:

- **Shell-launched agents** (`claude-code`, `codex`, `copilot-cli`, `aider`, `opencode`) — add to `~/.zshrc` / `~/.bashrc` and restart your shell:

  ```sh
  export USRCP_PASSPHRASE="your secret phrase"
  ```

- **GUI/IDE-launched agents** (`cursor`, `cline`, `continue`, `antigravity`) do **not** inherit shell environment. Either add an `env` block under the `usrcp` server entry in the agent's config file (JSON for Cursor/Cline/Continue, TOML for Codex), or set a system-wide GUI env on macOS with `launchctl setenv USRCP_PASSPHRASE "..."` (persists until reboot; use a `~/Library/LaunchAgents/` plist for permanence).

**Treat any config file you bake the passphrase into as a secret** — it sits in plaintext on disk and is the weakest link in an otherwise-encrypted setup. This is exactly what `usrcp keychain store` exists to avoid.

The wizard prints this same guidance after registration, so you can also re-run `usrcp setup` or `usrcp adapter add terminal --targets=<list>` for a reminder.

## Capture Adapters

Adapters are independent processes that read from a source and append events to the local ledger via the same encrypted-at-rest pipeline as the MCP server. Each adapter handles its own auth, idempotency, and cursor persistence.

### Structured-state adapters

These are the headline adapters: they capture genuinely structured dev/work state — issues, PRs, notes, calendar events, coding-session context — the kind of data USRCP's schema and exact-keyword search are built for.

| Adapter | What it captures | Mode | Requirements |
|---------|------------------|------|--------------|
| [`usrcp-github`](https://github.com/frank-bot07/usrcp/blob/HEAD/packages/usrcp-github) | PRs you opened / merged / closed, issues you opened, comments + reviews you authored, in optional org allowlist | Capture-only (v0) | GitHub personal access token (`repo` + `read:user` scopes) |
| [`usrcp-linear`](https://github.com/frank-bot07/usrcp/blob/HEAD/packages/usrcp-linear) | Issues + comments you author in Linear | Capture-only (v0) | Linear personal API key |
| [`usrcp-obsidian`](https://github.com/frank-bot07/usrcp/blob/HEAD/packages/usrcp-obsidian) | Notes you create or edit in an Obsidian vault | Capture-only (v0) | A local vault directory |
| [`usrcp-claude-code`](https://github.com/frank-bot07/usrcp/blob/HEAD/packages/usrcp-claude-code) | User / assistant turns from your Claude Code CLI sessions, tailed from `~/.claude/projects/<cwd>/*.jsonl` | Capture-only (stream) | Claude Code CLI installed; `allowlisted_projects` in `~/.usrcp/claude-code-config.json` |
| [`usrcp-google-calendar`](https://github.com/frank-bot07/usrcp/blob/HEAD/packages/usrcp-google-calendar) | Timed events on your primary calendar that have already ended | Capture-only (v0) | Google Cloud OAuth client + Calendar API enabled |

Alongside these, the inline adapters that ship with the brew CLI (`terminal`, `mcp-agent`, `openclaw`) wire the same structured state into terminal agents and agent harnesses — see [Editor & CLI Integrations](#editor--cli-integrations) and [Agent harness integrations](#agent-harness-integrations). The [VS Code viewer](#ledger-viewers) browses the resulting ledger read-only.

### Conversation capture adapters (experimental)

These adapters capture allowlisted activity into the local ledger. The optional stream layer includes semantic retrieval and has a different storage boundary from the core: consult [security boundaries](https://github.com/frank-bot07/usrcp/blob/HEAD/docs/SECURITY.md) before enabling it. Capture is not proof that another assistant retrieved or correctly understood the context. The initial product test is live cross-interface continuity using concise checkpoints.

| Adapter | What it captures | Mode | Requirements |
|---------|------------------|------|--------------|
| [`usrcp-imessage`](https://github.com/frank-bot07/usrcp/blob/HEAD/packages/usrcp-imessage) | Messages you sent in Apple iMessage | Capture + reader | **macOS only.** Full Disk Access for Messages.app; `brew install steipete/tap/imsg` |
| [`usrcp-slack`](https://github.com/frank-bot07/usrcp/blob/HEAD/packages/usrcp-slack) | Messages you sent in Slack; `@usrcp` queries from chat | Capture + reader + bot | **Paid Slack tier** (Pro/Business+/Enterprise) — bot APIs are restricted on free; Anthropic API key for `@usrcp` replies |
| [`usrcp-discord`](https://github.com/frank-bot07/usrcp/blob/HEAD/packages/usrcp-discord) | Messages you sent in Discord; `@usrcp` queries from chat | Capture + reader + bot | A Discord server you control; Anthropic API key for `@usrcp` replies |
| [`usrcp-telegram`](https://github.com/frank-bot07/usrcp/blob/HEAD/packages/usrcp-telegram) | Messages you sent in Telegram; `@usrcp` queries from chat | Capture + reader + bot | A Telegram bot token (BotFather); Anthropic API key for `@usrcp` replies |
| [`usrcp-gmail`](https://github.com/frank-bot07/usrcp/blob/HEAD/packages/usrcp-gmail) | Messages you sent in Gmail (subject, body, recipients, labels) | Capture-only (v0) | Google Cloud OAuth client + Gmail API enabled |
| [`usrcp-extension`](https://github.com/frank-bot07/usrcp/blob/HEAD/packages/usrcp-extension) | Conversations on claude.ai; `/usrcp` slash-command for ledger lookup | Capture + injector | **Chrome only.** Manual unpacked load (Developer Mode → Load Unpacked) |

Install an adapter's package (`npm install -g usrcp-<value>`), then configure it with `usrcp setup --adapter=<value>` (e.g. `npm i -g usrcp-linear && usrcp setup --adapter=linear`). Run `usrcp setup` alone for an interactive picker over the adapters you've installed.

All adapters write under a configurable `domain` (default matches the source name) and use stable, source-side IDs as idempotency keys, so re-polling or re-watching the same window cannot double-write. Capture-only adapters do not reply; bot adapters reply only to explicit `@usrcp` / `/usrcp` mentions and answer using the same ledger the user sees.

### Agent harness integrations

These adapters expose USRCP's tools to a third-party AI agent harness. They don't capture new events on their own — capture from external surfaces (Discord, Slack, iMessage, etc.) still goes through the dedicated capture adapters above. Install the harness first, then run the USRCP setup route.

| Integration | Purpose | Mode | Requirements |
|-------------|---------|------|--------------|
| [`usrcp-hermes`](https://github.com/frank-bot07/usrcp/blob/HEAD/packages/usrcp-hermes) | Memory-provider plugin for [Hermes Agent](https://github.com/hermesagent/hermes-agent). Adds USRCP as a 9th external memory provider; system-prompt context, prefetch, sync_turn capture. | Bidirectional plugin | Hermes installed; `usrcp` CLI on PATH; `mcp` Python package |
| `openclaw` | Registers `usrcp serve` as an MCP server in your [OpenClaw](https://docs.openclaw.ai) config. OpenClaw agents get all 12 USRCP tools via the same path Claude Code uses. | Read-side (MCP server) | **OpenClaw already installed** — install first at https://docs.openclaw.ai/start/getting-started, then `usrcp setup --adapter=openclaw` |

### Ledger viewers

Read-only clients that browse the encrypted ledger via a local `usrcp serve` subprocess. No network calls; the viewer never sees plaintext outside the host process.

| Viewer | Surface | Mode | Requirements |
|--------|---------|------|--------------|
| [`usrcp-vscode`](https://github.com/frank-bot07/usrcp/blob/HEAD/packages/usrcp-vscode) | VS Code activity-bar **USRCP** view — Facts tree by domain, status indicator, "Open Ledger Directory" command. | Read-only client | VS Code; `usrcp` CLI on PATH (or set `usrcp.binaryPath`) |

### Cross-device sync

[`usrcp-cloud`](https://github.com/frank-bot07/usrcp/blob/HEAD/packages/usrcp-cloud) is an optional experimental ciphertext relay. The local sync client currently transfers timeline events and domain maps only. Full structured-state synchronization is outside the launch workflow; agents on the same machine and profile already share a live ledger; cross-device continuity needs separate validation. Relay metadata remains visible.

## MCP Tools (12)

| Tool | Description |
|------|-------------|
| `usrcp_handoff` | Condensed domain-specific startup brief with reviewed facts and recent work |
| `usrcp_get_state` | Query identity, preferences, projects, timeline |
| `usrcp_append_event` | Record an interaction event |
| `usrcp_update_identity` | Update user roles, expertise, communication style (with optional `expected_version` for read-modify-write) |
| `usrcp_update_preferences` | Update language, timezone, verbosity |
| `usrcp_update_domain_context` | Store domain-scoped key-value context |
| `usrcp_set_fact` | Store a free-form schemaless fact under `(domain, namespace, key)` |
| `usrcp_get_facts` | Read one fact or list all facts in a domain / namespace |
| `usrcp_search_timeline` | Search via blind index tokens (exact keyword, not semantic) |
| `usrcp_manage_project` | Create/update tracked projects |
| `usrcp_audit_log` | View encrypted audit trail |
| `usrcp_rotate_key` | Rotate master encryption key (re-encrypts all data) |
| `usrcp_status` | Ledger stats and health (scope-aware: scoped agents see only their domains) |

## What's Encrypted

**All your content.** Every field that carries what you said, did, or stored is
ciphertext at rest. What stays in the clear is structural metadata — opaque
identifiers and timestamps that reveal *when*, never *what*. An attacker reading
the SQLite file sees:

| Column | What they see |
|--------|--------------|
| `event_id` | Opaque ULID (plaintext — random identifier, no content) |
| `timestamp` | When, not what (plaintext) |
| `domain` | HMAC pseudonym (`d_1ac6397ab4d2`) |
| `summary` | `enc:base64ciphertext...` |
| `intent` | `enc:base64ciphertext...` |
| `outcome` | `enc:base64ciphertext...` |
| `platform` | `enc:base64ciphertext...` |
| `detail` | `enc:base64ciphertext...` |
| `tags` | `enc:base64ciphertext...` |
| `audit_log.*` | `enc:base64ciphertext...` |

The same rule holds in the other tables: in `active_projects`, the content
fields (`name`, `domain`, `status`, `summary`) are `enc:` ciphertext; the
`project_id` you choose is stored as an HMAC (with the original encrypted in
`project_ref_enc`), and only `last_touched` (a timestamp) stays plaintext. No
field that holds user content is ever stored in the clear.

In passphrase mode, no key file exists on disk. The key is derived via scrypt on startup and zeroed on shutdown.

Each adapter's test suite includes a **ciphertext-at-rest** check: it captures real activity, then opens the SQLite file with raw `better-sqlite3` and asserts no plaintext markers (titles, bodies, URLs, IDs) appear in any encrypted column.

## Security Architecture

- **AES-256-GCM** encryption at rest for all content fields
- **Domain-scoped keys** via HKDF-SHA256 — coding key cannot decrypt health data
- **scrypt** passphrase derivation (N=131072, r=8, p=2) — key never on disk
- **HMAC domain pseudonyms** — domain names are opaque identifiers
- **Blind index search** with n-gram tokens and noise injection
- **Encrypted audit log** — access patterns are ciphertext
- **Atomic key rotation** — re-encrypts all data in a single transaction
- **secure_delete pragma** — SQLite zero-fills deleted pages
- **Master key zeroed** on process shutdown
- **Scope enforcement** — agents registered with a `--scope` flag see only the domains they're authorized for; `usrcp_status` and timeline queries filter accordingly

Full model in [docs/SECURITY.md](https://github.com/frank-bot07/usrcp/blob/HEAD/docs/SECURITY.md).

## Editor & CLI Integrations

USRCP works with any MCP-compatible client. The `usrcp init` wizard registers the server entry for editor clients:

| Editor | `--client=` value | Setup doc |
|--------|-------------------|-----------|
| Claude Desktop | `claude` (default) | This README |
| Cursor | `cursor` | [docs/INTEGRATIONS/cursor.md](https://github.com/frank-bot07/usrcp/blob/HEAD/docs/INTEGRATIONS/cursor.md) |
| Continue.dev | `continue` | [docs/INTEGRATIONS/continue.md](https://github.com/frank-bot07/usrcp/blob/HEAD/docs/INTEGRATIONS/continue.md) |
| Cline (VS Code) | `cline` | [docs/INTEGRATIONS/cline.md](https://github.com/frank-bot07/usrcp/blob/HEAD/docs/INTEGRATIONS/cline.md) |

Register with multiple clients at once: `usrcp init --client=claude,cursor` or `--client=all`.

For terminal-based MCP-aware CLI agents (Claude Code, Cursor CLI, Codex, Copilot CLI, Cline, Continue, Aider, Antigravity, OpenCode), a single wizard wires them all up:

```bash
usrcp setup --adapter=terminal
```

No external accounts or bot tokens required — every terminal session in those agents gets cross-platform memory through the same local ledger.

All clients share the same local ledger per user.

## Other Consumers

- [`usrcp-hermes`](https://github.com/frank-bot07/usrcp/blob/HEAD/packages/usrcp-hermes) — Python memory-provider plugin for [Hermes Agent](https://github.com/hermesagent/hermes-agent). Adds USRCP as a memory backend so Hermes runs share state with Claude Code, Cursor, etc. Thin wrapper — ledger logic stays in TypeScript.

## Project Structure

```
usrcp/
├── spec/
│   └── PROTOCOL.md                  # Protocol specification
├── schemas/                          # JSON schemas (get_state, append_event, handshake)
├── docs/
│   ├── SECURITY.md                   # Security & privacy model
│   └── INTEGRATIONS/                 # MCP client integration guides
├── strategy/                         # GTM, pitch, positioning
├── packages/
│   ├── usrcp-core/                   # Framework-agnostic protocol core (ledger, crypto, encryption, pairing, rotation, scope)
│   ├── usrcp-local/                  # Local MCP server + CLI
│   ├── usrcp-cloud/                  # Hosted ledger for ciphertext-only sync
│   ├── usrcp-discord/                # Discord capture+reader adapter
│   ├── usrcp-extension/              # Chrome extension (claude.ai capture)
│   ├── usrcp-hermes/                 # Hermes Agent memory plugin (Python)
│   ├── usrcp-imessage/               # iMessage capture+reader (macOS)
│   ├── usrcp-linear/                 # Linear issues + comments capture
│   ├── usrcp-obsidian/               # Obsidian vault capture
│   ├── usrcp-slack/                  # Slack capture+reader
│   └── usrcp-telegram/               # Telegram capture+reader
└── sdk/                              # Legacy prototype (Jan-Feb 2026); not the reference impl
```

The legacy `sdk/` was a pre-protocol exploration — see [`sdk/README.md`](https://github.com/frank-bot07/usrcp/blob/HEAD/sdk/README.md) for the historical context. New work should target the `usrcp-core` ledger directly.

## Tests

Current snapshot (per-package `npm test`):

| Package | Tests |
|---------|-------|
| `usrcp-local` | 321 |
| `usrcp-core` | 230 |
| `usrcp-stream` | 125 |
| `usrcp-github` | 90 |
| `usrcp-obsidian` | 65 |
| `usrcp-imessage` | 54 |
| `usrcp-telegram` | 53 |
| `usrcp-linear` | 52 |
| `usrcp-slack` | 52 |
| `usrcp-extension` | 46 |
| `usrcp-discord` | 45 |
| `usrcp-gmail` | 41 |
| `usrcp-google-calendar` | 33 |
| `usrcp-adapter-kit` | 32 |
| `usrcp-cloud` | 30 |
| `usrcp-claude-code` | 28 |
| **Total** | **~1297** |

Plus a Python suite in `usrcp-hermes` (`pytest`).

Run a package's suite with `npm test` from inside its directory. Cross-package
`prebuild`/`pretest` hooks build `usrcp-core` (and other siblings) first so types
stay in sync. Coverage spans: ledger CRUD, crypto roundtrips, tamper detection,
domain isolation, audit log, ULID, pruning, multi-user isolation, optimistic
concurrency, schemaless facts, scope enforcement (all in `usrcp-core`); sync
push/pull, Ed25519 signed-request auth (`usrcp-local`/`usrcp-cloud`); and
per-adapter capture/idempotency/ciphertext-at-rest checks.

## Business Model

Open-source protocol (Apache 2.0). The reference implementation is free and local-first. Potential paid offerings will be tested with users; reliable managed handoff/sync and team controls are hypotheses, not shipped commercial or compliance guarantees.

The wedge isn't "every AI-using human." It's **security-conscious developers and regulated enterprises** who can't adopt an AI state store that phones a third party with plaintext. See [strategy/PITCH.md](https://github.com/frank-bot07/usrcp/blob/HEAD/strategy/PITCH.md) and [strategy/GTM.md](https://github.com/frank-bot07/usrcp/blob/HEAD/strategy/GTM.md) for the full positioning.

## License

Apache 2.0

