# ParallelClaw · shared memory + coordination for your AI agents

> **English** · [Русский](README.ru.md)

[![npm](https://img.shields.io/npm/v/parallelclaw.svg)](https://www.npmjs.com/package/parallelclaw)
[![downloads](https://img.shields.io/npm/dw/parallelclaw.svg)](https://www.npmjs.com/package/parallelclaw)
[![license](https://img.shields.io/npm/l/parallelclaw.svg)](LICENSE)

> **One verbatim memory for all your AI agents — and a coordination layer so they can hand tasks to each other.**

ParallelClaw is a local-first **personal AI ops layer**, built in two layers:

1. **Shared memory (the foundation, shipped).** A local-first MCP server indexes **every conversation you have with AI** — Claude Code, Claude Cowork, Cursor, OpenClaw, Hermes, Obsidian notes, and selected Telegram chats — into one searchable SQLite + FTS5 corpus, served to **any MCP-compatible client** through a handful of tools.
2. **Coordination (the direction, rolling out).** On top of that shared memory, any of your agents can **delegate a task to any other** — across tools and across machines. It runs when that agent is available; the result comes back to where you asked. The transport (cross-machine sync + per-row provenance) is live today; the turnkey delegation loop is rolling out.

No cloud. No account. No data leaves your machine.

> **CLI naming:** the binary is `parallelclaw` (short alias `pclaw`). The legacy `memex` / `memex-sync` commands, the `~/.memex` data dir, and the `memex_*` MCP tool names are kept as-is for back-compat — so examples below that say `memex …` still work verbatim.

```
~/.memex/inbox/              ← drop chat exports here (or symlink AI session files)
     ↓ chokidar watcher
parser  (Telegram JSON · Claude Code JSONL · Cursor SQLite · Obsidian md)
     ↓
SQLite + FTS5  (~/.memex/data/memex.db)
     ↓
MCP server  →  Claude Code · Cursor · OpenClaw · …
```

---

## Install in 60 seconds

**One-line install (recommended):**

```sh
curl -fsSL https://memex.parallelclaw.ai/install.sh | bash
```

That single command:
1. Verifies Node ≥ 20.
2. Runs `npm install -g parallelclaw`, auto-fixing `EACCES` by moving npm's prefix to `~/.npm-global` (no `sudo` needed, ever).
3. Installs the auto-capture daemon (`memex-sync install`) **with** the v0.8 Brian Chesky auto-context hook into `~/.claude/settings.json` (preserves existing hooks).
4. Backfills history (`memex-sync scan`) so memex already knows about your past sessions.
5. If `claude` (Claude Code CLI) is on PATH, runs `claude mcp add memex --scope user -- memex` to wire MCP automatically.

Idempotent — safe to re-run. To inspect the script before piping to bash: `curl -fsSL https://memex.parallelclaw.ai/install.sh | less`.

**Prefer manual install?**

```sh
npm install -g parallelclaw
memex-sync install      # macOS LaunchAgent for auto-capture
```

If `npm install -g` hits `EACCES` (system Node on macOS), either fix your prefix once:

```sh
mkdir -p ~/.npm-global
npm config set prefix ~/.npm-global
echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.zshrc
source ~/.zshrc
```

Or use one-shot `sudo npm install -g parallelclaw`.

**Want to try without installing globally?**

```sh
npx -p parallelclaw memex-sync install
```

### Install via AI skill (Claude Code / OpenClaw)

If you'd rather have an AI agent walk you through everything, drop the
[install-memex skill](skills/install-memex/) into `~/.claude/skills/`:

```sh
mkdir -p ~/.claude/skills
curl -fsSL https://raw.githubusercontent.com/parallelclaw/memex-mvp/main/skills/install-memex/SKILL.md \
  -o ~/.claude/skills/install-memex/SKILL.md
```

Then in Claude Code (or any Skills-aware agent) just say:

> install memex

…or `/install-memex`. The agent handles `npm install`, MCP-config wiring,
auto-capture daemon, and verification — ~2 minutes.

---

## Connect to your MCP client

After install, point your client at `memex` (an alias of `server.js` exposed on `PATH`):

### Claude Code

```sh
claude mcp add memex --scope user -- memex
```

### Cursor / OpenClaw

Add to that client's MCP config (e.g. `~/.cursor/mcp.json`):

```json
{
  "mcpServers": {
    "memex": { "command": "memex" }
  }
}
```

Restart the client. Try the prompt:

> *"Use memex_overview to show me what's in my AI memory."*

If you see a snapshot of sources and recent conversations — you're done.

For a fully-automated install across all detected MCP clients, see [the AI-driven install guide](https://memex.parallelclaw.ai) on the landing page (paste the prompt into any MCP-enabled agent, it'll wire everything up itself).

---

## Terminal CLI (v0.7+) — query memex without MCP

The same `memex` binary that runs as an MCP server also has a terminal mode for direct queries. Useful when MCP isn't wired up, when you want to pipe results into shell scripts, or when debugging MCP-config issues:

```sh
memex search "Postgres migration"          # full-text search
memex search "Q2 deck" --chat "Memex Bot"  # scope to one conversation by title
memex search "JWT" --as-of 2026-05-01      # v0.8.1: time-travel — only msgs before date
memex when "Brian Chesky"                   # v0.8.1: "when did we talk about X" — dates + chats
memex recent --limit 5                      # last 5 messages across all sources
memex list --source web                     # all saved URLs
memex get web-1582ab51a7b7                  # full content of one conversation
memex overview                              # snapshot of corpus + v0.8.1: capture streak
memex projects                              # distinct project_paths captured
memex import ~/projects/memex/result.json  # v0.10.12: ingest any file from any path
memex help                                  # full user guide (HELP.md)
memex --help                                # command reference
```

### Ingest from any path (v0.10.12+)

```sh
memex import ~/projects/memex/result.json           # auto-detects Telegram JSON
memex import ~/Downloads/ChatExport_2026-05-18/     # Telegram HTML export directory
memex import ~/path/to/session.jsonl                # Claude Code JSONL
memex import ~/Downloads/result.json --force        # skip Telegram privacy gate
memex import some-file --format claude-jsonl        # explicit format override
```

For Telegram, the privacy gate fires for any chat that isn't on your allow-list — the command exits with a preview (title, message count, date range, senders) so you can review before re-running with `--force`. Same path via MCP: any AI agent can call `memex_import_file({path: "..."})` to ingest one file in one tool call (instead of ~10k tokens of bash `mv`-shuffling).

Every query supports `--json` for machine-readable output: `memex search foo --json | jq '.results[].snippet'`. The DB is opened **read-only** — safe to run while `memex-sync` daemon is writing.

When called **without arguments** (`memex`), the binary still runs as an MCP stdio server (the way Claude Code / Cursor / OpenClaw launch it). CLI mode and MCP mode are the same package — no extra install.

---

## Auto-context (v0.8+) — Claude already knows what you were doing

After `memex-sync install`, you're prompted to enable **auto-context**. When yes, memex adds a SessionStart hook to `~/.claude/settings.json` so that **every time you open Claude Code in a project**, Claude gets injected with ~500-1500 tokens of relevant context — what you did recently in this project, which conversations touched it, which related topics came up. No prompts. No tool calls. Just memory.

```sh
# Adding/removing the hook outside the install flow:
memex hook install        # add SessionStart hook (idempotent)
memex hook uninstall      # remove only the memex entry, preserves other hooks
memex hook status         # show current state

# Inspecting what gets injected:
memex context             # dry-run the hook output for the current dir
memex context --pwd /path # for a different project
memex context --no-source telegram  # exclude a source
```

The hook respects existing hooks (e.g. `gstack`, custom user hooks) — they're preserved untouched.

**Currently only Claude Code has native SessionStart hooks.** For Cursor, an MCP-tool-based fallback is available (v0.9+).

---

## Save URLs into memex (v0.6+)

Once memex is installed, any MCP-aware agent can also save **web pages, AI chat shares, and pasted text** into your memex memory — searchable from any other AI chat later. In Claude Code, Cursor, OpenClaw, …:

```
Save https://www.perplexity.ai/share/<id> to memex
Add this article to my memex: https://example.com/long-post
```

The agent fetches the page via its own WebFetch (auto-falling back to `r.jina.ai` for Cloudflare-protected sites — memex teaches the trick) and calls `memex_store_document`. Memex stores the content verbatim as a `web` source conversation, indistinguishable from AI chats at search time.

Perplexity threads need to be made **Public** in the Share dialog first — memex detects private threads and tells the user how to fix it. Full guide: [HELP.md §8](HELP.md).

**ParallelClaw stays 100% local** — the agent fetches, it only stores. Zero outbound calls from ParallelClaw itself.

---

## Telegram chats (v0.10+) — agent walks you through it

Telegram-export setup used to be 8 steps. v0.10+ collapses it to 2 (you click in Telegram; you pick which chats to keep). The rest is automatic.

**How it works:**
1. The daemon watches `~/Downloads/Telegram Desktop/` in the background. **No setup needed** — already on after install.
2. You export a chat from Telegram Desktop (chat → ⋮ → Export chat history → HTML or JSON).
3. memex detects the export, **moves it to `~/.memex/pending/`** (NOT into your DB yet).
4. Your AI agent (or you in terminal) calls `memex_telegram_pending` — sees a numbered list with chat name, msg count, date range.
5. You pick which to import. Sensitive ones (Bank, Therapist, Tinder) — skip. memex remembers and won't ask again.
6. Future re-exports of allowed chats auto-merge. Skipped ones stay out.

**The agent leads.** Just say *"set up Telegram for memex"* (or **install memex** in a fresh session — the install-memex skill v1.2+ proactively offers it). The agent will:
- Check if Telegram Desktop is installed (give you the right download link if not)
- Check the 24h post-login export-block window (tell you when you can export)
- Show the click-path in Telegram
- Wait for your export, then present the picker

**Three modes:** `pick` (default — review each export), `auto` (allowed chats auto-import; new ones go to pending), `manual` (watcher off — drop files yourself).

Terminal equivalents: `memex telegram check / pending / import 1 3 5 / skip 2 / mode auto`. Full reference: `memex telegram --help`.

**v0.10.1: 4-channel proactive notification.** You'll find out about pending exports from whichever channel reaches you first:

1. **In the AI agent (active session)** — `memex_search` / `memex_recent` / `memex_overview` tool responses include a `telegram_pending` field with chat names. Agent surfaces it as a natural aside.
2. **In the terminal** — any `memex` CLI command appends a 💡 tip line when pending > 0. Throttled to once per 6h.
3. **macOS native notification** (opt-in) — daemon fires a banner when a new export is staged. `memex telegram notifications on` to enable. Default OFF for lock-screen privacy; add `--show-titles` if you want chat names in the banner. **v0.10.4+ clickable:** if `terminal-notifier` is installed (`brew install terminal-notifier`), clicking the banner opens — in priority order — Claude Code CLI in a fresh Terminal (Brian Chesky moment via SessionStart hook), Claude Desktop, or Terminal with `memex telegram pending` queued. Override priority via `memex telegram notifications target <auto|claude-cli|claude-desktop|terminal|none>`.
4. **Brian Chesky hook (next Claude Code session)** — `memex context` injection includes a "🆕 N exports awaiting review" block with chat names. Claude leads with the question before you type anything.

---

## Web dashboard (v0.10.8+) — see your own memory

Opt-in, read-only local UI for browsing the corpus without any AI in the loop. Same SQLite, different surface.

```sh
memex web --open      # localhost:8765, opens in browser
memex web --port 9000 # custom port
memex web --public --token s3cret   # bind on 0.0.0.0 with bearer auth (for remote / tunnel)
memex web --help
```

Five pages:

| Page              | What it shows                                                                            |
|-------------------|------------------------------------------------------------------------------------------|
| `/`               | Stats grid · sources breakdown · pending Telegram callout · recent 10 conversations      |
| `/conversations`  | Live FTS5 search via htmx (200ms debounce) · source-chip filters · hit counts per chat   |
| `/c/:id`          | **Verbatim** transcript in chat-bubbles · in-chat search with `<mark>` highlight · paged |
| `/pending`        | Telegram exports awaiting decision · bulk Import / Skip checkboxes · decision history    |
| `/settings`       | Daemon status · DB path & size · hooks installed · TG decisions counts (read-only)       |

**Design constraints:**
- **Opt-in, not always-on.** `memex web` starts the server; Ctrl+C stops it. No daemon.
- **Read-only by default.** The only writes are TG import / skip on the `/pending` page — same privacy gate as `memex telegram import`.
- **Localhost-only by default.** Binds `127.0.0.1`. Use `--public --token <…>` for remote access (cron-friendly: same endpoint reserved for the future multi-host sync API).
- **No build step.** Node raw `http` + tagged template literals + htmx 14KB CDN. Total client bundle: ~30KB.
- **Brand-aligned.** Same Inter + mint palette as [memex.parallelclaw.ai](https://memex.parallelclaw.ai).

---

## What it captures

| Source                | How it gets in                                                 |
|-----------------------|----------------------------------------------------------------|
| Claude Code sessions  | Auto: `memex-sync` watches `~/.claude/projects/`               |
| Claude Cowork         | Auto: same watcher, including all subagent transcripts         |
| Cursor IDE chats      | Auto: reads Cursor's local SQLite session store                |
| OpenClaw sessions     | Auto: watches `~/.openclaw/agents/main/sessions/`              |
| Obsidian notes        | Auto: per-vault markdown watcher                               |
| Telegram exports      | **v0.10+: auto.** Daemon watches `~/Downloads/Telegram Desktop/`. Each new ChatExport appears in `memex telegram pending` — review chat-by-chat, import the ones you want. Privacy-first: nothing lands in the DB without your `memex telegram import <indices>`. Allow-list remembers your decisions so future re-exports auto-merge. JSON + HTML both supported. (Legacy path still works: drop into `~/.memex/inbox/`.) |
| Telegram (live)       | Run [`memex-bot`](bot/README.md) — captures messages you send/forward to your private bot |
| **Web pages, AI chat shares, pasted text** | From any MCP agent: *"save https://... to memex"*. Agent fetches; memex stores verbatim. Cloudflare-protected pages (Perplexity, npm.com, Twitter, Medium, …) handled via the agent's r.jina.ai fallback. See [HELP.md §8](HELP.md) |

All sources land in the same FTS5 corpus, searchable by one `memex_search` call.

---

## MCP tools

| Tool                          | What it does                                                              |
|-------------------------------|---------------------------------------------------------------------------|
| `memex_overview`              | Corpus snapshot — sources, counts, recent chats, daemon health           |
| `memex_search`                | Full-text search with BM25 × recency boost. Filter by date range (`since_ts`/`until_ts`), one session (`conversation_id`), capture node (`origin`, v0.14), `source`/`project`/`chat` |
| `memex_recent`                | Most recent messages across all sources                                  |
| `memex_get_conversation`      | Transcript by `conversation_id` — page long sessions with `offset`/`order` (`desc` = freshest first); reports `total` |
| `memex_list_conversations`    | Conversations sorted by activity, filterable by source                   |
| `memex_list_projects`         | Distinct project paths captured (for the `project` filter)               |
| `memex_archive_conversation`  | Hide a chat from default listings (data preserved)                       |
| `memex_export_markdown`       | Export one conversation as Markdown (for Obsidian round-trip)            |
| `memex_store_document`        | Save a web page, AI chat share, or pasted text. Agent fetches; memex stores verbatim. Teaches the Jina r.jina.ai trick for Cloudflare-blocked pages |
| `memex_list_sources`          | Per-source enabled/disabled + counts                                     |
| `memex_status`                | Daemon health: PID, last capture, watched files                          |
| `memex_sources_status`        | Which sources are captured + the exact CLI to opt out                    |
| `memex_help`                  | Returns the full user guide with concrete use cases                      |
| `memex_telegram_check`        | v0.10+: Detect Telegram Desktop, login age (24h block), pending count, suggested next step |
| `memex_telegram_pending`      | v0.10+: List exports staged for review with chat name + msg count + dates |
| `memex_telegram_import`       | v0.10+: Import selected exports into memex.db (by index or title) — auto-allowlists |
| `memex_telegram_skip`         | v0.10+: Mark chats as "never index" — applies to future re-exports too  |
| `memex_telegram_mode`         | v0.10+: Get/set capture mode: pick (default) · auto · manual            |

Detailed search parameters (filters, sort, format) live in [HELP.md](HELP.md).

---

## Why ParallelClaw (vs. cloud memory services)

| Concern                       | ParallelClaw                       | Cloud memory (Mem0 / Supermemory / …) |
|-------------------------------|------------------------------------|---------------------------------------|
| Where your data lives         | Your machine, one SQLite file      | Their servers                         |
| Cost per ingested turn        | 0 (no LLM call on write)           | $0.005+/1K tokens                     |
| Cross-AI corpus               | ✅ same DB for all clients         | ⚠️ depends on plugin coverage         |
| Telegram ingestion            | ✅ first-class                     | ❌ not supported                      |
| Verbatim storage              | ✅ raw text preserved              | ❌ usually fact-extracted             |
| Survives if vendor blocks you | ✅ your DB stays on disk           | ❌ data inaccessible                  |
| Offline / air-gapped          | ✅                                 | ❌                                    |
| Trade-off                     | Lexical search (FTS5), not semantic | Semantic + reranker, but cloud-bound  |

---

## Privacy

- **Zero network egress** during normal operation. The MCP server only listens on stdio.
- **No account, no telemetry.** First-time install ping (planned, opt-out) is the only network call ever — and it's anonymous (UUID + version + OS, no content).
- **The DB is one file** at `~/.memex/data/memex.db`. Back it up, encrypt it (FileVault is enough), `rm` it — your call.
- **Source opt-out per category**: `memex-sync sources <name> disable` keeps that source out of the corpus permanently.

See [PRIVACY section in the Russian README](README.ru.md#приватность-и-безопасность--privacy--security) for the full breakdown.

---

## Cross-device

**Built-in real sync (v0.13).** Laptop with Claude/Cursor + a server with an
agent (OpenClaw etc.)? Connect their memory in **two copy-paste steps** — no
public ports, no firewall changes, no manual SSH keys, no hand-written services.

**Step 1 — paste this prompt to the agent on your server:**

```
Set up memex sync as a hub and give me a join token for my laptop:
1. npm install -g parallelclaw@latest   (skip if installed)
2. memex-sync sync-server install --bind 127.0.0.1
3. memex-sync sync-server invite --join
Send me the memex-join:... line.
```

**Step 2 — one command on your laptop:**

```sh
memex-sync sync-join memex-join:eyJ2...
```

What that one command does, in order — and verifies at each step:

```
✓ token valid (openclaw@203.0.113.7, expires in 28m)
✓ SSH access — OK                       (no key? it prints yours + what to do)
✓ self-healing tunnel up                (survives sleep, network changes, reboot)
✓ hub sync-server alive (cert pinned)
✓ first sync: pulled N · pushed M
✓ auto-sync every 15m installed
✓ health watchdog installed             (alerts if sync goes silent > 1h)
✓ end-to-end verified: a test note round-tripped in 3.4s
```

The server binds **loopback only** — nothing is ever exposed to the internet;
all traffic rides inside SSH on port 22 (the one port that's never blocked).
Conflict-free by design: verbatim memory is append-only
(`UNIQUE(source, conversation_id, msg_id)`), so there is nothing to merge.
Interrupted first syncs **resume** from the last good page. Re-joining the same
hub keeps sync cursors — no pointless full re-replication. After a successful
join, no `MEMEX_SYNC_EXPERIMENTAL` env var is needed for any sync command.

**Provenance (v0.14).** Every row is stamped with the node that captured it,
and the stamp travels with sync — so "what did I discuss with the VPS agent
vs. on my laptop?" stays answerable after the corpora merge:
`memex_search(query, origin: "vps1")`. Conversations where two agents
interleave (e.g. two OpenClaw instances bridging one Telegram account) get
per-line `[@node]` tags in `memex_get_conversation`. Name your node by setting
`origin` in `~/.memex/config.json` (defaults to the hostname, persisted) —
best done **before** data accumulates, since old rows keep their stamp.

**Advanced topologies** — multi-node mesh, reverse tunnels (laptop-as-hub),
transit hubs gluing nodes that can't see each other (proven live on a
San-Francisco Mac + Italy VPS + Asia VPS mesh) — are documented with the wire
protocol in **[SYNC.md](SYNC.md)**. Agents can emit pair tokens via the
`memex_sync_invite` MCP tool.

**Simple alternative (no sync engine).** The corpus is one SQLite file plus a small
inbox directory, so a one-time `scp` covers migrations. See
[MULTI_MACHINE.md](MULTI_MACHINE.md) for legacy file-sync recipes.

---

## Limitations (v0.5)

- **FTS5 only** — no semantic search yet. Russian/English cross-lingual queries don't bridge ("git rebase" vs "перебазирование коммитов" return different hits). Vector embeddings are on the roadmap.
- **macOS-first** — daemon installer registers a LaunchAgent. Linux works as a foreground process; Windows untested.
- **Single user** — the Telegram bot serves exactly one Telegram user_id (you).
- **No webhook for the bot** — long-polling only, captures buffer ~24h server-side when laptop is offline.

---

## Resources

- 🏠 Landing: [memex.parallelclaw.ai](https://memex.parallelclaw.ai) — the AI-driven install prompt
- 📖 [HELP.md](HELP.md) — concrete use cases + full tool reference + troubleshooting
- 🤖 [bot/README.md](bot/README.md) — Telegram capture bot setup
- 🇷🇺 [README.ru.md](README.ru.md) — full Russian README with deeper privacy / migration sections
- 🐛 [Issues](https://github.com/parallelclaw/memex-mvp/issues) on GitHub

---

## License

MIT — see [LICENSE](LICENSE).
