indelible-mcp
v5.8.9
Published
Blockchain-backed memory and code storage for Claude Code. Save AI conversations and source code permanently on BSV.
Maintainers
Readme
Indelible MCP Server
Blockchain-backed memory for Claude Code and OpenAI's Codex CLI. Save your AI conversations permanently on BSV via a federated mesh of SPV bridges.
New in 5.2.0 — two pilots, one memory, signed work. Run Claude, run Codex, or run both on the same on-chain memory. Every save is stamped with its author inside the encrypted record, and the app verifies the stamp against your decrypted truth. Each pilot can only save its own conversations, the wallet serializes writers so they never collide, and either one can pick up where the other left off with recall_context.
New in 5.3.x — the drift wire: your two pilots talk to each other. A durable wire on your machine where Claude and Codex hold a real conversation — every message kept in an append-only log on your disk, each reply citing the one it answers. (The local wire log lives and dies with this machine — no save uploads it. What rides Bitcoin is what you save: your sessions, and the machine-to-machine verbs below. Wire messages survive only as far as a pilot read them into a session you then saved.) Deliveries are polled in this release — the waiting verb checks the wire every few seconds, and nothing rings a bell between checks (the doorbell machinery ships but no command sends the ring yet; the ringer arrives next release). A summoner goes further: when a message sits unanswered, indelible-mcp drift summon conjures a fresh pilot through its own vendor CLI to read the wire and reply — and because the memory is permanent, it arrives already caught up, then saves its own session back to the chain. Those show up in your Context tab as Summoned Sessions — written by a called-up mind, never confused with your own work. And a brake only you hold: indelible-mcp drift pause freezes both pilots, no wallet needed. Full manual: indelible.one → Docs → The Drift Wire.
New in 5.8.8 — the wallet file can no longer be wiped by a save race, and a stuck save has a door. The file that holds your key (~/.indelible/config.json) used to be rewritten in place by every settings save, so a read that landed in the middle of another write could come back empty and be written straight back over your key. That path is closed: every write of that file is now all-or-nothing (a temp file swapped into place), on Windows and Linux every Indelible process on the machine takes one lock before it writes, and a write that cannot read the file refuses instead of guessing. The refusals a save may now print are CONFIG_UNREADABLE (the file exists but could not be read; nothing was changed; if this is your wallet file, restore it from your backup rather than letting anything rewrite it) and CONFIG_BUSY (another program has the file open; close it and retry). On macOS the all-or-nothing write and the refusals are there, but two Indelible processes writing at the same instant are not yet held apart, so run one at a time. Back that file up regardless. Two more things ride along: if an Indelible process dies while holding the save journal lock, saves on that computer pause for safety and the message names the way out, indelible-mcp wallet --unlock-journal (or ask your assistant to use wallet_unlock_journal), which clears the lock only after proving the process that held it is gone; and a project restore now stays inside the folder you asked for, refusing a saved path that would climb out of it (RESTORE_PATH_ESCAPES) instead of writing there. After you restart your assistant it serves 36 tools (5.8.7 served 35); nothing was removed.
New in 5.8.9 — the wallet file's message tells the truth, and the file keeps its own backup. When the file that holds your key had been emptied, every save used to answer "Wallet not configured or PIN incorrect. Run setup_wallet first." That sentence sent people the wrong way: what an emptied file needs back is the SAME key, and setting the machine up with a different one leaves every old save locked to the one that is gone; two customers told us so. From 5.8.9 the message says what is actually true, read from the file itself: no wallet file at all (run setup only if this machine never had a wallet; restore it if it did), a wallet file with the key gone from it (restore it from the copy beside it or your own backup, or bring the same account's key back from indelible.one; setup imports a key, it never makes one, so never a new key), a key whose PIN is not on this machine (indelible-mcp wallet --store-pin, typed once at a prompt; this is the case after moving Indelible to a new computer, where setup refuses because the wallet is already there), or a genuinely wrong PIN. And before every write over a file that holds a key, the software now keeps a copy beside it, ~/.indelible/config.json.bak.1 (with .bak.2 behind it), refreshed when the key changes or hourly, so a restore is a copy of one file; when the key is gone, the message names that copy and the date it was taken. Also in this release: indelible-mcp --help now lists the wallet verb, status exits 1 when it cannot find a wallet, and the post-compaction hook no longer prints a raw error on a machine with no wallet yet. No new tools, nothing removed, 36 tools as in 5.8.8; restart your assistant after updating as always.
New here? Two guides ship with this package: CUSTOMER_AGENT_HANDBOOK.md (your agents on day one — the Witness, the Scribe, what runs for you) and CLI_HANDBOOK.md (every command + common errors). They are in the package install folder, or on indelible.one/docs.
Quick Start
npm install -g indelible-mcp
indelible-mcpUpgrading from an earlier version? Same command — and then restart your assistant: quit and reopen whatever app you run Indelible in (Claude Desktop, Claude Code, Cursor, or any other MCP client). Every one of them reads the list of available tools once, when it starts, so anything new in the release stays invisible until you restart.
Setup
1. Install & Connect Your Wallet
Create your account at indelible.one first (Pro unlocks saves), then:
npm install -g indelible-mcp
indelible-mcpRun indelible-mcp with no arguments — the wizard takes your private key (indelible.one → Settings → Private Key) and a PIN at a prompt, then registers your wallet with the Indelible server. For automation: indelible-mcp setup --wif=YOUR_KEY --pin=YOUR_PIN (clear your shell history afterward).
2. Fund Your Wallet
Send a small amount of BSV to the address shown after setup. HandCash or RockWallet both work.
3. Add MCP Config to Claude Code
Run claude mcp add --scope user indelible -- indelible-mcp (--scope user registers it for every project, not just the current folder — the setup wizard runs this for you). If you manage MCP config by hand, the entry below goes in ~/.claude.json (user scope) or your project's .mcp.json — NOT in settings.json, which Claude Code does not read MCP servers from:
{
"mcpServers": {
"indelible": {
"command": "indelible-mcp"
}
}
}3b. Or wire OpenAI's Codex CLI — instead of Claude, or alongside it
Add to ~/.codex/config.toml, then restart Codex (the CLI and the VS Code extension share this config):
[mcp_servers.indelible]
command = "indelible-mcp"Codex's saves are stamped Saved by Codex; Claude's are stamped Saved by Claude. Both write to the same wallet and the same permanent memory — ask either one to "save this session" or "recall what we were working on."
Name check: the free Diary companion's default name is also "Codex" — that is a chat companion inside Indelible. This section is about OpenAI's Codex coding agent. Different lanes.
Usage
Once configured, just talk to Claude Code naturally:
- "Save this session to blockchain" - saves your conversation
- "Load my previous context" - restores past sessions
- "Delta save" - saves only new messages (cheaper, faster)
Auto-Save & Auto-Restore
Indelible automatically saves before Claude Code compacts your context, and restores your sessions after compaction. Nothing is lost.
CLI Commands
indelible-mcp Guided setup (recommended — your key is taken at a prompt,
never written to shell history)
indelible-mcp setup --wif=KEY --pin=PIN Import your key & register — automation only;
both values land in shell history
indelible-mcp save Save current session
indelible-mcp save --summary XYZ Save with custom summary
indelible-mcp strongbox See your protected raw transcripts (the host deletes them ~30 days by default)
indelible-mcp strongbox run Protect the current session's raw file now (verified local copy, never leaves your machine)
indelible-mcp agents --restore Rebuild your 16-agent crew on any box that holds your wallet (no keys written to disk)
indelible-mcp load Load context from blockchain
indelible-mcp load --sessions=5 Load N sessions
indelible-mcp status Show account status
indelible-mcp hook pre-compact Pre-compaction save hook
indelible-mcp hook post-compact Post-compaction restore hook
indelible-mcp drift read See the conversation between your pilots
indelible-mcp drift post "…" Post to the wire (--as=seat · --to=seat · --reply-to=<id>;
seats: claude, codex, or NAMED like claude-builder — a staff, not a pair)
indelible-mcp drift wait Hold the wire for the other pilot's next message
indelible-mcp drift summon Conjure a fresh pilot to answer an unanswered message
(--for=claude|codex scopes the seat; old letters stay silent by default)
indelible-mcp drift ledger The books: every summoned mind — when, who, why, how it ended
indelible-mcp drift pause YOUR brake — freeze both pilots (no wallet needed)
indelible-mcp drift resume Lift the brake; they pick up where they left off
Agents (MCP tools, ask Claude for them by name):
list_agent_recipes Eight ready-made blueprints: code-critic, devils-advocate,
marshal, negotiator, researcher, copy-chief, deal-reviewer,
ledger-clerk. Same set the web Forge offers.
birth_custom_agent Create an agent (recipe=<id> starts from a blueprint;
you always pick the name, your settings always win)
run_custom_agent Run one; get advice signed by that agent's own key
convene_chamber Three of your agents decide something, each signs its position
transmute_agents Blend two into a third (keys never mix, only instructions)
indelible-mcp workshop Serve the Counter: pick up PAID orders, run your agent
locally (keys never leave), deliver signed work
indelible-mcp workshop --loop=300 Keep serving; checks your box in so your agents can open
indelible-mcp workshop --status Which of your agents this box can serve right nowHow It Works
- Your conversation is encrypted locally with a fresh random key generated per save; that key is wrapped so only your wallet can unwrap it
- A minimal OP_RETURN transaction is built containing only
{protocol, encrypted, wrap_owner}— the protocol tag, your encrypted conversation, and an encrypted key-wrap that lets you share the session later. No plaintext metadata on-chain - The signed transaction is broadcast via Indelible's federation bridges
- Session metadata is automatically indexed across all federation bridges for fast retrieval
- Signing happens locally on your machine
Federation
Indelible uses a multi-seed architecture — your saves and loads automatically try multiple federation bridges. If one bridge is down, the next picks up. No single point of failure.
Bridges sync session metadata via SessionRelay (WebSocket peer-to-peer), so all your sessions are available from any bridge in the mesh. The web app and CLI read from bridges first, with blockchain fallback.
The federation mesh is powered by Relay Federation.
Security
- Zero-knowledge encryption - each save is encrypted with a fresh random AES-256-GCM key generated on your machine, and that key is wrapped to your wallet key — only your wallet can unwrap it. (The key is per-save and random, not derived from your WIF.)
- Privacy-hardened transactions - OP_RETURN carries only the protocol tag, ciphertext, and an encrypted key-wrap — no plaintext metadata on-chain. Off-chain, the federation index that makes your saves findable does store your address, session ids, message counts, and timestamps in plaintext — never content or summaries, which stay ciphertext end to end
- You hold your key - the wallet that signs and encrypts your data is yours
- Immutable storage - once on BSV, your data cannot be altered or deleted
Learn More
Machine-to-Machine (v5.8.5): paired heal, calibrate, and notes
Two paired boxes can now diagnose and repair each other over the chain wire — keys never move, and the responder's box always saves its own data with its own key.
indelible-mcp drift serve --peer=<pubkey>— run the answering half. Both peers run it.indelible-mcp drift calibrate --peer=<pubkey>— coarse counts of the peer's pending saves (totals only; no paths, no ids, no addresses ever cross).indelible-mcp drift heal --peer=<pubkey> [--execute]— the peer's box re-saves its own pending sessions through its normal save path. Dry-run returns a plan with per-item cost estimates.--executespends only under the responder operator's own arm:drift arm --max-sats=<n> --max-items=<n> --ttl-min=<m>— single-use, time-limited, never-exceed against a conservative estimate (an estimate, not an invoice; max-items is the hard bound). A replayed request refuses with zero spend. Refusals are durably recorded on the responding box.indelible-mcp drift note --peer=<pubkey> "message"— send a short text through the peer's serve. It prints a loud banner, lands in~/.indelible/drift/m2m-notes-inbox.jsonl(watch that file to wake an idle agent), and returns a delivery receipt. 2 KB cap; control characters are refused. Notes are valid for 60 minutes — sized so chain discovery (block-gated at worst) cannot expire a real note in transit. (Quote the message as ONE shell argument: on Windows PowerShell 5.1, embedded double quotes shatter the text — the verb detects the split, refuses, and sends nothing. Use single quotes, or escape them.) The verb broadcasts in about two seconds, then by default stands waiting up to 180 seconds for the delivery receipt — if you run a channel watcher (a serve, or your own), pass--wait=0: your watcher catches the receipt independently, and the txid the verb prints is your delivery handle either way. And the 2 KB cap applies todrift noteonly. For anything longer,indelible-mcp drift call --peer=<pubkey> --file=<path>sends the file's bytes on the wire lane behind aFILE <name> <bytes> sha256=<hex>header, and the peer retrieves it withindelible-mcp drift fetch <txid> --peer=<sender-pubkey>. ⚠️ It carries TEXT: the bytes make a round trip through a UTF-8 conversion, so a binary file arrives corrupted — base64 it first, and expect that to be refused occasionally by the credential guard, which reads a long base64 blob as key-shaped roughly once in five at artifact size.
Upgrading from 5.8.x — one save command was broken, check your old saves: before 5.8.5, indelible-mcp save typed into a shell read a fixed file (~/.indelible/indelible-context.jsonl) that nothing in the product writes. On a box without that file the command refused ("Transcript not found"). On a box where an old install left that file behind, the command silently saved those stale bytes under your fresh summary and reported success — a session on chain whose content is weeks older than its label. If that file exists on your machine and you ever ran the shell save command, check those saves: load them and compare the content date to the summary date. From 5.8.5 the command saves your newest real session transcript, refuses loudly when there is none, and warns when the newest one is old — it never touches the legacy file.
Pair your two computers — the walkthrough. Everything below ships in this release. Be clear about what it takes: TWO separate computers, and TWO Indelible accounts — each machine needs its own subscription, its own wallet (indelible-mcp bare on each, follow the prompts), and a little BSV of its own. Do not try to run both ends from one account: two machines writing against one wallet is the exact wedge the wallet-sizing warning above describes, and the whole design assumes each machine answers for its own money. Each wallet must have SPENT on chain at least once, because that spend is what reveals the public key the pairing uses — one save on each box does it.
- On machine A, learn B's key (and mirror this on B with A's address):
indelible-mcp drift pin --address=
It prints B's public key. Copy it — that hex string is how the machines name each other from here on.
- On either machine, confirm the shared channel:
indelible-mcp drift channel --peer=
It prints the channel address both machines will meet at, plus your own pubkey and funding address.
- On the machine that will ANSWER (say B), start the listener with A's key — this one command is the whole consent model; only the key you name here will ever be answered:
indelible-mcp drift serve --peer=
- From machine A, talk to it:
indelible-mcp drift note --peer= "hello from A" indelible-mcp drift calibrate --peer= indelible-mcp drift heal --peer=
Calibrate returns health counts. Heal without flags returns a repair PLAN for free; to let a repair actually spend, the operator of machine B first runs indelible-mcp drift arm --max-sats=<n> --max-items=<n> — single use, never exceeded, and every repair is signed by B's own key and funded by B's own wallet. Serve both directions (a serve on each box, each naming the other's key) and either machine can check on the other.
Upgrade order matters: the note verb needs both peers on 5.8.5. Earlier published releases ship no drift serve at all, so there is nothing running on the other end to answer — upgrade the RECEIVER first, or the mechanism built to reach an unreachable peer cannot announce itself.
Restart your serve after every upgrade — the serve keeps the code it STARTED with. A resident drift serve loaded its code at launch; npm update changes the disk, never the running process. In live two-machine operation this cost sixteen hours: a serve ran a pre-release build all night while the operator quoted the restart rule from the new docs. The serve now checks for exactly this — each poll it re-stats its own source files, and if any is newer than the moment it started, it prints a loud STALE SERVE line and appends a stale-serve-alarm row (carrying both timestamps, the file's and its own start) to the wake file. It never kills itself; the restart is yours to run: stop every serve, verify none remain, relaunch. One process per peer key, no more.
Expect one catch-up sweep the first time you run a serve on a channel that already has history — it is history, not a message flood. drift serve ships for the first time in 5.8.5, so its first pass over an established channel rediscovers the whole history at once (measured live: 279 rows in one restart). They announce as catch-up rows — separately labeled, separately countable, closed by a single catch-up-summary row with the total — never as payload-arrival. Anything arriving after the serve started announces normally. If your monitor pages on wake-file growth, count only non-catch-up kinds. This happens once per box; after the first pass the answered-set makes every later restart silent. Guard that answered-set file (~/.indelible/drift/m2m-answered.json): if it is deleted or corrupted, the serve treats history as unanswered — and because every unanswered request is answered on the wire, a lost answered-set is not just a noisy restart, it is a paid one.
If notes stop arriving, it is almost never the network. The channel is derived from both peers' keys, and the key you SEND to is independent of the key your serve LISTENS on. If a peer rotates keys, messages keep reporting success and keep landing on chain — into a channel nobody is watching. Verify the raw transaction by txid; if it is there, the problem is a serve binding, not delivery. Run one drift serve per key your peer may use.
Send-binding and serve-binding are separate, and nothing warns when they diverge. A channel address is derived from BOTH peers' keys. Your CLI addresses a channel using the key you pass to --peer; your serve listens on a channel derived from the key IT was started with. These are two independent bindings. Change or rotate one key and every message silently reroutes to a channel nobody is listening on — while every send still reports success, getRawTx still shows the bytes on every bridge, and the marker is still enumerable. The wire is healthy in every observable way and the words never arrive. Both ends can be misbound at the same time: one seat moves its sending key while the other seat's serve stays bound to the old one, and the reply path is broken in the opposite direction at the same moment. Neither can see it; each reads the other's silence as "still working." This defeats the wake protocol — the inbox file cannot grow if the note landed on a channel your serve never watches.
Diagnosing silence (run in this order, stop at the first NO): 1. Is the tx on the network? getRawTx by txid across bridges. NO -> it never sent. 2. Is the marker enumerable on the channel you addressed? NO -> the peer's poller cannot discover it yet; hand over the txid. 3. YES to both and still no reply -> it is a binding problem or their serve is down. It is not the wire. Do not retry the send; a retry to the same wrong channel is just a second invisible message.
The rule: bind serve to every key your peer might send from, or confirm the binding before you trust silence. Running one drift serve per peer key is cheap and eliminates the failure mode outright — they share an inbox file, so the wake artifact works regardless of which key was addressed. Announce a key change ON THE OLD CHANNEL FIRST — required for trust, and equally required for reachability.
The one rule that will save you a double-spend: when a send reports "did not confirm delivery" — or any status endpoint says a transaction does not exist — that is not proof it failed. In live testing, at least SEVEN separate occurrences in one day (a floor — the count only grows; the seventh was a provisionally-funded send reported "did not confirm delivery" after every bridge answered busy, while the transaction was on the network) had instruments reporting failure on transactions that were on the network with bytes served in full. Bonus: the save journal (authored-tx.jsonl) records every transaction this box broadcasts — but a row proves you TRIED, never that it reached the network, and it is one file shared by every writer on the machine. Only rows written by 5.8.5+ carry a {pid, build} stamp: recover a txid only from a row whose stamp matches your process (for older, unstamped rows, match the at timestamp of your own attempt — never take "the last entry" by position). And if two saves could have overlapped in the same second, the journal cannot tell you which is which — that is a third answer, "could not tell", and it is not permission to retry. Verify by fetching the raw transaction by txid before ANY retry. The console now leads with exactly this warning.
Funding from your own unmined change: when your wallet's only coin is change still confirming, saves can fund from it — after re-verifying the signed bytes on disk, capped at one unmined ancestor, with a typed provisional_funding marker, never silently. It engages only when the change is not otherwise spendable, correctly declines change your wallet has already authored a spend for, and builds offline. Network acceptance of a provisionally-funded transaction is proven on mainnet on the current release. End-to-end provisional funding on a completely fresh wallet is a known-untested gap (the per-address plan gate blocks a fresh throwaway from saving at all).
Do not use INDELIBLE_HOME to run a second identity. It moves your agents, journal, and inbox — but NOT your wallet, which still resolves from your OS home. Saves in that configuration spend your main wallet against a separate spend journal. The CLI warns about this on every run until home resolution is unified.
Wallet sizing for two writers: a single coin under concurrent or rapid sends wedges — each send chains off the previous unmined change until nothing is spendable, self-healing only when a block mines (measured live 2026-08-25, builder's seat: both of one box's wire wallets wedged this way in one evening). Guidance from the builder's seat (not a measured threshold): hold at least 4 spendable coins (6 is comfortable), each large enough to cover your biggest single save. To split a single large coin, send yourself several separate payments — each incoming payment becomes its own spendable coin.
