npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

brainmesh

v0.0.1

Published

One encrypted, append-only brain across your devices

Readme

brainmesh

one brain across your devices. append only, end to end encrypted, no required central server.

The target is a laptop, always-on machine, phone and wearable, each holding only what it needs. The CLI and desktop-to-desktop path exist today. Native iOS and Android thin clients exist for grant-scoped search and capture; native phone replicas and watch clients do not. Sync uploads no plaintext. Optional peers or object storage may hold signed ciphertext, while an explicitly authorized hosted model sees only the plaintext slice its grant returns.

Losing one device does not lose history when another enrolled device and a data copy remain. If every device is lost, a separate encrypted recovery kit plus its 24-word paper phrase restores the keys without cloning an old device.

the promise, in plain words

  • it works offline. write on a train, it shows up everywhere later.
  • storage cannot read it. not a bucket, relay, ISP, or sync operator. A hosted model can read only the slice you deliberately return through a grant.
  • nothing is ever silently changed. every entry is signed and chained to the one before it, so a rewrite is detectable, not a matter of trust.
  • you can delete the app and keep the format. ciphertext, signed history and keys are ordinary files with an open spec. Preserve an enrolled key separately from data backups.

documentation

| | | | --- | --- | | docs/PRD.md | what this is, and what it is not | | docs/SPEC.md | the formats, normative, reimplementable from the text | | docs/CONSTRAINTS.md | invariants, threat model, stated limits | | docs/EDGE-CASES.md | 393 cases, each with what it drives | | docs/DECISIONS.md | choices made and rejected, with reasons | | docs/ROADMAP.md | built, next, and known gaps |

the six ideas

  1. a device is a keypair. there is no account and no login.
  2. a record is a signed, sealed fact. immutable.
  3. each device writes only its own durable log, so logs never merge. Two edits to one projected file become an explicit conflict event instead of data loss.
  4. big things are stored by their hash, fetched from whichever device has them.
  5. permission is a signed note saying who may read what, until when.
  6. search and everything you see is a cache. delete it, it rebuilds.

status

early. the core is real and tested, the product around it is not written yet.

| piece | state | |---|---| | record format, signing, sealing | done | | append only log with hash chain | done | | sync between devices | done, offline and resume covered | | chunked blobs, 4gb files, resume, dedup, immutable transfer packs | done | | self-contained offline bundle, signed history plus encrypted file bytes | done | | fork detection, torn tail repair, single writer | done | | enrollment, one command over ssh | done, works between real machines | | cli | done, including path-preserving workspace scan/restore/verify/watch | | transport, stdio over ssh | done | | files, any size, index first then bytes on demand | done, verified between machines | | grants, expiry, attenuation, revocation, read receipts | done | | workspace subtree grants (company/ without personal/) | done | | owner authority separated from shared decryption keys | done for new brains and spaces | | signed company roots, role compartments, keyless limited admins, scoped co-owners, and rotation | done at CLI layer | | remote MCP OAuth, resource binding, refresh rotation, Origin validation | done | | offline 24-word recovery kit for personal, space and organization keys | done; no device identity is cloned | | hosted or company escrow and recovery policy | not built; offline kit is user-held | | personal and shared-space future-access rotation | done; removed devices keep old plaintext but never receive later epoch keys | | the app a non technical person opens | not started |

The test suite is mostly failure cases, not happy paths: writing on both sides of a partition, resuming a transfer that died at chunk three of four, a restored backup forking a log, a power cut mid append, two processes racing one log, a relay holding data it cannot read, a peer claiming a 4gb record, path traversal, a stale workspace scan, mass deletion, and divergent offline edits.

running it for real

The npm preview builds the audited Rust CLI locally. It requires Node 18+, Rust 1.75+, and the same operating-system build dependencies as a Cargo build. The install step compiles only the packaged source; it does not open ~/.brain, create an identity, or start a service.

npm install --global brainmesh
brainmesh --help

Builds use stable Rust. Ubuntu and Debian also need the Secret Service build headers even when a headless node chooses file-backed key storage:

sudo apt-get install build-essential pkg-config libssl-dev libdbus-1-dev
cargo build --release
brainmesh start                      # on the always on machine
brainmesh join mini                  # on every other machine
brainmesh sync                       # no arguments, it remembers peers

join records the peer, so nothing after that needs a hostname. background sync is store-scoped and uses the native user scheduler on macOS, Linux and Windows:

brainmesh service install --interval 300
brainmesh service status

Installation first runs a real sync --require-any. It refuses an empty route list or a setup where no configured peer completes the protocol, rather than installing a timer that moves no data. The generated launch agent, systemd user timer or Windows scheduled task uses the canonical absolute binary and store paths, never a shell. Its private, bounded manifest is inside the store; service-manager files are deterministically derived from that store so a tampered manifest cannot redirect uninstall at another file.

An ordinary interactive sync still tolerates unreachable machines because laptops are closed most of the day. A scheduled sync uses --require-any, so service status reports the last run as unhealthy when every route is down. It also hashes the installed executable and regenerates the expected native scheduler configuration, so replacing the binary or changing the job is shown as unhealthy instead of silently trusting registration alone. An optional independently held rollback witness can be ratcheted only after a successful required sync:

brainmesh service install --interval 300 --witness /Volumes/stick/brain.heads

The witness must already exist and must be outside the store. If it is absent, unwritable, stale relative to the local store, or concurrently changed, that scheduled run exits nonzero and service health exposes the failure. Uninstall never removes the external witness. Windows runs the task only while that user is logged in. A Linux user service requires a working per-user systemd manager; an always-on logged-out server also needs administrator-configured user lingering.

Peer routes are local configuration, not replicated authority. The peers file is bounded, refuses symlinks and control-character injection, and is created or repaired at mode 0600 on Unix because a custom remote command can reveal private topology or arguments.

brainmesh service uninstall removes only that store's scheduler and private manifest. It preserves the brain and macOS sync logs. Removing the data itself is deliberately a separate, manual decision.

using it

brainmesh start                 # first machine
brainmesh join mini             # every other machine, one command
brainmesh write "a thought"
brainmesh sync mini             # pull and push in one round trip
brainmesh read
brainmesh status

three machines need six directions and nobody configures six directions by hand. so a machine announces itself once, into the log, and every other device learns it on the next sync:

brainmesh peer announce [email protected] /Users/louis/.local/bin/brainmesh

announcements are records, so they travel like everything else, sealed like everything else. a device skips its own, and a machine that announces more than one way to reach it becomes one entry with fallbacks, tried in order.

some machines cannot use ssh for this. windows openssh does not forward piped stdin, which was measured rather than assumed: five bytes through a file redirect came back answered, the same five through a pipe never arrived. so there is a socket transport too, and both sides prove they hold the brain key before a byte of anything else moves:

brainmesh listen 100.89.216.79:7778        # on the always on machine
brainmesh peer announce tcp://100.89.216.79:7778

nothing new to hand out: the proof is the brain key every member already has, and a stranger is turned away at the greeting.

The direct listener bounds work before that greeting: at most 64 peer sockets are active, at most eight come from one observed source, and one source may start at most 120 admitted sessions per minute. Its source-window table is capped at 4,096 entries, over-limit sockets close without a protocol response, and every admitted stream has 30-second read/write inactivity timeouts. Outbound dialing spends one total 30-second budget across the addresses already returned by the OS resolver. These are process-local resource controls, not a public DDoS service; a proxy collapses its clients into one observed source and must enforce the real-source boundary itself.

When neither device accepts inbound connections, a tiny blind rendezvous can pair their outbound sockets. The public machine runs only the relay command; it does not have a brain directory or any key:

# public machine
brainmesh relay listen 0.0.0.0:7779

# always-on brain node; generate the token once with `brainmesh relay token`
brainmesh relay expose relay://relay.example.com:7779/<64-hex-token>

# another enrolled device, after the exposure is waiting
brainmesh sync relay://relay.example.com:7779/<64-hex-token>

The random token is an unlisted room name, not storage authority. After pairing, the existing mutual brain-key proof runs end to end, before any heads or sealed records move. The relay stores no vault bytes and parses none of the wire stream. It can still observe IP addresses, timing and byte counts, steal a room to cause a failed authentication, drop traffic or go away. Rotate the token to unlink later sessions. This TCP relay gives private desktop peers a route; it does not carry HTTP credentials or plaintext. A separate TLS-passthrough route below makes the grant-scoped endpoint public without changing that boundary.

join is the whole pairing flow. it asks the primary machine over ssh to wrap the brain key and authority public key for this device. The stable authority signing seed is deliberately not cloned to routine devices; otherwise a lost device could authorize its own return after rotation. no key is ever shown to you, typed, or pasted, which is the failure this design exists to avoid.

The device introduction is itself signed: v2 : device signing key : X25519 agreement key : signature. This prevents a relay or clipboard tool from substituting its own encryption key while leaving the visible device id alone. Unsigned legacy introductions are refused; rerun brainmesh id on the joining device.

Personal-device removal is an explicit data-key epoch, not grant theatre:

brainmesh epoch status
brainmesh epoch rotate --keep-self --keep '<signed introduction>'

The root-signed transition pins the exact final head of every omitted device, delivers the next key only to retained devices, and makes all new writes and blobs use that epoch. Sync and bundle import quarantine the complete incoming record transaction, fold every signed transition it carries, and reject a removed author's post-cutoff tail before any author is committed. Old history remains readable to devices that already held it; no cryptography can recall a copy. If an offline node stored a tail before learning the revocation, the signed cutoff later makes that tail logically quarantined: its immutable bytes remain as evidence, but runtime reads, sync advertisements, served pages and authorized bundle exports stop at the cutoff. Create a new recovery kit after every rotation because the old kit is then intentionally stale.

Pre-epoch owner stores migrate once. The authority signs the already-present authors as historical evidence before enforcing membership; a later signed device introduction upgrades that evidence. This preserves existing valid history without silently treating every future unknown author as trusted.

there is no daemon, no port, no certificate and no discovery. sync spawns brainmesh serve on the other machine over ssh and talks to its stdin and stdout, the way git has worked for twenty years. over a tailnet that means it already works everywhere you can already ssh.

where the keys live

in a 0600 file, the same place ssh, gpg and age keep theirs. brainmesh status says so, because a security property you cannot see is one you cannot trust. On Unix, Brainmesh creates the file at mode 0600 before writing any secret byte, opens with no-symlink semantics, checks the effective mode on the opened handle, and refuses an unsafe key before reading it. Creation and replacement first flush a complete private sibling and only then publish it: no-clobber for a new key, atomic replacement for an existing key, plus a parent directory sync on Unix and write-through publication on Windows. A crash can therefore expose the complete old key or the complete new key, never a truncated identity. A filesystem that cannot enforce private modes is an error, not a silently weaker key store. Windows uses the user-profile ACL boundary.

the os keystore is available with BRAINMESH_KEYSTORE=1 and is off by default. that is a reversal, and the reason is worth knowing: a keychain entry is bound to the code signature of the program that wrote it. rebuild the binary and it is a different program, so the read prompts. a prompt is a dialog, a dialog needs a human, and there is no human at a five minute timer. we found this the way you would expect, by replacing the binary and watching every command hang at zero cpu behind an invisible dialog.

a key left in the keystore by an older version is still read, once, and written back out to a file. every keystore call is bounded at five seconds, and one that does not answer raises rather than reporting the key absent, because absent is what makes a device decide it should make a new identity.

the honest limit: neither a file nor a keystore protects against something running as you. only a hardware backed non extractable key does, and both the apple secure enclave and the windows tpm hold p-256 only, never ed25519. that is why every record carries a key type byte: without it, hardware backed identity would be foreclosed forever.

full disk encryption is the control that actually matters here, and it covers swap and backups too, which no keystore does.

owners, members, and why those are different keys

A decryption key answers "may this device open the space?" It must not also answer "may this device give access to somebody else?" New brains and spaces therefore have a random owner authority key that is unrelated to the brain key.

  • the primary/recovery identity holds the authority secret; routine devices receive the data key and authority public key through join
  • space invite gives a member the space key and only the authority public key
  • a member can contribute to that shared space, but cannot issue root grants or invite another member
  • an owner node rejects a grant manufactured from the shared space key, even if its signer has a valid member log

Old stores remain readable in legacy mode. Before using one as a company boundary, make the migration explicit:

brainmesh authority status
brainmesh authority harden
brainmesh space harden team

Hardening deliberately invalidates existing grants. Accepting them afterward would preserve the exact capability being removed. Existing devices must also receive and trust the new authority before they enforce the new boundary; do not interpret one machine's harden output as a fleet-wide migration.

This solves who can grant. It does not make one shared space confidential between its members: anyone holding that space key can read that whole space.

ending shared access without rewriting the past

An owner can move future writes to a fresh key generation and hand that key only to retained devices:

brainmesh space rotate team \
  --keep '<remaining-device:introduction>' --days 7
# retained device:
brainmesh space join '<signed-rotation-bundle>'

The handoff is signed by the previous space authority, addressed to one device, and carries a conforming-client deadline; copied offline ciphertext is not erased by time. A retained device accepts it only when it already holds the exact previous generation and trusts that authority. An omitted device keeps the old history but cannot decrypt or authenticate future generations. A member with the decryption key but without the owner key cannot rotate. Use --keep-none to make an intentionally empty retained set; an accidentally missing --keep is refused. Bundle delivery and new peer setup are still manual.

companies are key compartments, not folder ACLs

An organization has a durable signing identity, and each role or project is a separately encrypted space with its own key and owner authority. An engineer invited only to engineering never receives the finance key—or even finance role metadata—in the first place. A founder can receive both compartments.

brainmesh org new Acme
brainmesh org role Acme engineering
brainmesh org role Acme finance

brainmesh org invite Acme engineering <employee-introduction> --days 7
# employee:
brainmesh org join <signed-bundle>
# org join prints a device-signed receipt; owner records it:
brainmesh org accept <signed-receipt>
# if the receipt was lost, the employee can prove the installed keys again:
brainmesh org receipt <same-signed-bundle>

brainmesh org roles Acme
brainmesh org members Acme

# root: make another device a full co-owner of engineering@g1
brainmesh org delegate-owner Acme engineering <manager-introduction> --days 2
# manager installs the addressed handoff:
brainmesh org join <role-owner-bundle>
# manager may now issue an employee invitation without the organization root:
brainmesh org invite Acme engineering <employee-introduction> --days 7
# the employee returns both its receipt and the delegated invitation to root:
brainmesh org accept <signed-receipt> <delegated-invitation>
brainmesh org co-owners Acme

# recommended when a manager may nominate people but root must approve first:
brainmesh org delegate-admin Acme engineering <manager-introduction> --days 30
# manager installs the public, keyless certificate:
brainmesh org join <administrator-certificate>
# manager creates a proposal containing no role key:
brainmesh org propose Acme engineering <employee-introduction> --days 2
# employee acknowledges it and seals the keyless request to the company root:
brainmesh org request <access-proposal> \
  --to https://root.example/v1/org/inbox
# a transport delivers the opaque line; root verifies and queues without keys:
brainmesh org receive <access-envelope>
brainmesh org inbox Acme
# root reviews, then releases the first key-bearing bundle by queued request id:
brainmesh org approve <request-id-prefix> --days 7
# or root records a terminal, signed no-key decision:
brainmesh org deny <request-id-prefix>
# employee polls the same trusted inbox; the signed result decrypts locally:
brainmesh org poll <request-id-prefix> https://root.example/v1/org/inbox
# an approval's first line is installed normally, then its receipt is returned:
brainmesh org join <approved-first-line>
brainmesh org accept <signed-receipt>
brainmesh org admins Acme
# root may stop an exact proposal certificate before its deadline:
brainmesh org revoke-admin Acme <manager-device-or-certificate-prefix>

# one-time upgrade for organizations created before role-state certificates:
brainmesh org migrate Acme

# remove future engineering access by omitting that device from --keep:
brainmesh org rotate Acme engineering \
  --keep '<remaining-device:introduction>' --days 7

The bundle is signed by the organization root, addressed to one device, and has a root-confirmation deadline. A conforming joining client refuses it after that deadline. Because the bundle is offline ciphertext already encrypted to that device, the bytes cannot be made undecryptable on a hostile modified client; actual future-key revocation requires rotation. The joining device pins the public organization identity and never receives the root secret. Each encrypted role invitation is checked against the space id before any key is persisted. Changing a role, recipient, deadline, space, or encrypted invitation breaks the organization signature.

New role creation and every rotation also carry a root-signed role-state certificate binding organization, role, generation, new compartment and its predecessor. On a member device, the exact root-signed invitation bundle is the role-state proof. Once either signed form exists for a role, an unsigned JSON summary—even one claiming generation 99—cannot move it forward. Preexisting unsigned roles remain a visible migration boundary until their next signed rotation or an explicit org migrate. Migration keeps the current compartment keys, but root-signs them only after the complete generation-one-to-current lineage has one space per generation, every predecessor matches, and this device proves it owns every current role. All role certificates append as one batch; one missing key or damaged lineage leaves every role untouched. Running the command again is a no-op.

org receipt is a safe, idempotent recovery path while the invitation remains valid: it checks that this is the addressed device and that every installed role key derives the signed space id before producing a fresh acceptance.

First contact still needs a trusted comparison of the organization id, just as SSH needs a host-key check: a valid signature proves continuity with that key, not that a stranger's newly created key really belongs to "Acme".

Agents use the exact same grant path inside a compartment:

brainmesh grant <agent-device> --space 'Acme/engineering@<org-id>' --days 30
brainmesh mcp --as <grant-id> --space 'Acme/engineering@<org-id>'

The authoritative membership chain ends in organization-root confirmation. For a direct invitation, root signs the exact invitation. After installing only those role keys, the employee device signs an acceptance bound to it, and root confirms both before the deadline. org members reconstructs confirmed current membership only from that signed invitation → device receipt → root confirmation chain. Unsigned summary records are explicitly non-authoritative once signed role state exists. The alternate paths below either add a root-authorized co-owner signature or require root approval before the key-bearing invitation exists.

The organization root can also sign a role-owner handoff addressed to one device and exact role generations. This is deliberately called co-ownership, not temporary admin access: the device receives each role's data key and separate owner signing seed, so it can read, grant, and invite within those compartments. It receives neither the organization root nor sibling-role keys. --days is a conforming-client installation window for the encrypted handoff, not cryptographic erasure. A recipient already holding ciphertext addressed to its own device can modify its client and decrypt later. Once the seed is copied, there is no honest wall-clock expiry; rotating the role to a new generation is what ends its authority over future data.

A co-owner's employee invitation is signed by that device and embeds the root-signed role-owner bundle. The employee pins the root, pins each exact role authority, installs ordinary member keys, and signs the normal receipt. The organization root must import that delegated invitation with the receipt and confirm that every role generation is still current. Confirmation is a signed membership and inventory fact, not a key-release gate: the addressed role key was already delivered. An offline co-owner may not yet know a rotation happened and can still disclose the old key—past access cannot be recalled—but root confirmation rejects the superseded membership and the co-owner never receives the new generation.

For strict approval before access, use a limited administrator instead of a co-owner. Its root-signed certificate contains only device identity and exact role-generation references—no data key, owner seed, or organization root. The administrator signs a keyless proposal, the addressed employee signs a keyless request, and root checks administrator expiry plus current role state before creating the first encrypted role invitation. The root-signed approved wrapper binds that request to the key-bearing invitation. A stale proposal after rotation is rejected before the employee receives a key, and repeating approval returns the exact prior bundle. Root may revoke one exact administrator certificate early; approval checks that signed revocation before creating or reprinting a key-bearing bundle.

New administrator certificates also bind a deterministic organization inbox public key. org request seals the complete signed request to that key under a protocol-specific X25519/XChaCha20-Poly1305 domain before printing it. A future mailbox or an existing chat/file transport sees only organization and root pseudonyms, request id, ciphertext size and timing—not the employee, roles, proposal or signatures inside. Any root restored from the same organization authority derives the same inbox secret and can open it. Root still accepts legacy plaintext requests for compatibility; new clients emit envelopes.

org receive is the durable trust boundary for delivery. It opens and verifies the envelope while the request is live, then stores the still-opaque envelope as an encrypted append-only record without approving it. Exact retries are a no-op. org inbox decrypts only on the root and renders request id, employee, administrator, exact role generations, and one of pending, approved, denied, expired, revoked, stale, or conflicting. org approve accepts a unique lowercase request-id prefix, reopens the stored envelope, and repeats every expiry, revocation and current-generation check before key release. org deny signs and durably stores a terminal decision for the exact request without creating any invitation; repeating it returns the same receipt, while a later approval fails. org inspect-denial lets the employee or an auditor verify the root signature and render the request. A scoped listener makes this boundary networkable:

# root node; loopback by default
brainmesh org listen-inbox Acme 127.0.0.1:7781

# employee or native client retries only the opaque envelope
brainmesh org submit - http://127.0.0.1:7781/v1/org/inbox \
  < access-envelope.txt

The listener accepts POST /v1/org/inbox, GET /health, and employee polling at GET /v1/org/decision/<request-id>. It refuses all browser Origin headers, caps bodies at 8 MiB and concurrent connections at 32, verifies the held organization root, and calls the same idempotent durable receive path. It is plain HTTP because public TLS must terminate on the trusted node; expose it through the existing SNI TLS passthrough or another node-local terminator, never by letting a hosted proxy decrypt the connection. Arrival and polling still cannot approve. A one-minute in-process limiter permits 120 submissions and 600 polls per observed source, tracks at most 4,096 source/traffic buckets, returns 429 beyond budget, and exempts health. This contains one-source mistakes and abuse; distributed limits and original-client address recovery still belong at trusted ingress. Notifications remain unbuilt.

org request --to stores and prints the envelope before submitting it, so a network failure never destroys the request. org submit is the explicit retry path, and - reads a bounded envelope from stdin so it need not enter the brainmesh process arguments. Both use curl's HTTPS and system-trust support, stream ciphertext into curl over stdin, require an HTTP(S) URL ending in /v1/org/inbox, and verify that the JSON acknowledgement names the exact request id plus a boolean queue state. A generic 2xx from the wrong service is not delivery proof.

This boundary is cryptographic rather than cooperative: possession of the limited-admin certificate and signing key cannot decrypt a role or manufacture its member invitation. It can only ask root. The direct and co-owner commands remain available for personal teams that prefer offline convenience over mandatory approval.

Rotation creates a new role generation and key, then emits signed invitations only for the explicit --keep devices. Omitted members show as historical and never receive the new key; retained members remain confirmation-pending until their new receipt is root-confirmed. They keep old history. --keep-none is required to rotate everyone out, so an empty retained set is never an accidental command-line omission.

Administrator revocation is authority over future root approvals, not retroactive erasure: it immediately makes the root refuse pending requests from that certificate, but cannot recall a role key released by an earlier approval.

Likewise, approval and denial are first-decision-wins on converged root state. A denial receipt is brainmesh-org-access-denial-v1: and binds the complete employee request, exact request id, organization root and decision time under the root signature. If separately recovered roots decide differently while partitioned, inbox state reports a conflict and refuses further release; it cannot recall a key an isolated root already delivered.

An approval or denial is returned as brainmesh-org-access-decision-envelope-v1:. Root seals the complete signed outcome to the X25519 agreement key in the employee introduction; a distinct KDF domain prevents request, decision, enrollment, epoch and brain-key ciphertexts from being substituted. org poll resolves a locally signed request, fetches only its full 256-bit id, decrypts on the employee device, and stores the verified plaintext outcome inside that employee's encrypted brain. org decision reopens it later without the root being online. An observer sees the stable request pseudonym, pending/ready timing and ciphertext size, but not approval versus denial, roles, employee identity or wrapped role invitations. The service may still delay, drop or falsely remain pending; signatures prevent forged decisions, not denial of service.

Receipt, owner-handoff and rotation delivery are still manual. Role co-owners are full cryptographic owners of selected generations; limited administrators provide approval-gated key release without read access and support root-signed early revocation. Quorums, policy automation and automatic rotation-state delivery are not built. Old plaintext can never be made unread.

versions

nothing is ever overwritten, so every version you have written is already on disk. what was missing was a way to ask for one:

brainmesh add plan.txt          # three times, as it changes
brainmesh files                 # plan.txt   21 bytes  here  3 versions
brainmesh history plan.txt      # each one, dated, latest marked
brainmesh get plan.txt out.txt --version 1

an older version comes back whole, not reconstructed from diffs, because it was never turned into a diff. two machines that add the same name while apart arrive at the same history rather than two unrelated files, since the identity is derived from the name and needs no coordination.

archiving a live screenpipe database without a permanent second local copy

Plaintext SQLite and encrypted ciphertext are different bytes, so a hardlink, reflink or APFS clone cannot safely make them occupy one object. Brainmesh uses a proof-gated cache instead: screenpipe keeps its live database, an archive node keeps the encrypted chunks, and the source keeps only the signed manifest after the archive proves every exact chunk is retained.

# once, on the always-on archive node
brainmesh blobs pin all

# on the machine running screenpipe; metadata is the default
brainmesh blobs pin metadata
brainmesh screenpipe archive mini

# disaster-recovery proof into a separate file, never over the live database
brainmesh get screenpipe.sqlite /tmp/restored-screenpipe.sqlite mini
sqlite3 /tmp/restored-screenpipe.sqlite 'pragma integrity_check;'

screenpipe archive first requires an authenticated peer whose local policy is all, then pre-syncs existing signed metadata. It obtains the local API token in memory, asks the loopback-only authenticated screenpipe backup endpoint for a transactional VACUUM INTO snapshot, records every run as the next version of screenpipe.sqlite, uploads only missing encrypted chunks, and reproves the complete manifest. Only then does it remove loose source ciphertext and the temporary plaintext snapshot. It never copies db.sqlite plus its live WAL.

Steady state therefore has no second local database-sized copy on the screenpipe machine. Version one still needs temporary free space for one consistent plaintext snapshot plus one encrypted cache while the proof runs; the command checks for the snapshot size plus 512 MiB before encryption. A failure preserves the exact snapshot for inspection or retry and never evicts the encrypted cache before remote proof. Packed chunks already shared with other manifests remain until pack-aware garbage collection exists. Use --port for a non-default local screenpipe port and --staging for a private staging volume.

replacing git for a second brain

The durable log is not a filesystem. A workspace is a safe projection of one: full relative paths point at immutable blob versions, while parent event ids make concurrent offline edits become explicit conflicts instead of last-write wins.

brainmesh start                                      # once, for a new local store
brainmesh workspace status brain ~/Documents/brain   # read-only preview
brainmesh workspace scan brain ~/Documents/brain     # append adds/changes/moves
brainmesh workspace checkpoint brain ~/Documents/brain
                              # timer-safe; defers live files and never deletes
brainmesh workspace verify brain ~/Documents/brain   # hash every current file
brainmesh workspace restore brain /tmp/empty-brain --from mini
                                                        # fetch missing blobs once
brainmesh workspace track brain ~/Documents/brain       # pin one exact local view
brainmesh workspace pull brain ~/Documents/brain --from mini
                                                        # apply remote heads safely
brainmesh workspace watch brain ~/Documents/brain --peer mini
                              # local edits wake it; poll every 5m as a backstop
                              # and run a full byte audit at least daily
brainmesh workspace watch-status brain ~/Documents/brain
brainmesh workspace conflicts brain                  # divergent heads, if any
brainmesh workspace resolve brain <object> <event>    # explicitly choose one

.git and .brainmesh directories and symlinks are skipped. A root .brainmeshignore can list literal files or directories, one per line; it deliberately does not guess at gitignore glob semantics. Obvious credential containers such as .env, .mcp.json, private-key extensions and credential files are blocked and must be inspected; --skip-secret-files explicitly continues without them. Deletions are only proposed until --allow-deletes is present. Removing ten or more files and over ten percent of the workspace additionally requires --allow-mass-delete. An interactive scan is all-or-nothing: a file changed after preview is named and the scan is refused. A checkpoint instead appends every stable file, names files that changed during capture, and retries them on the next run. Tombstones and every prior blob remain in history.

For the personal feedback loop, run checkpoint from a timer. It appends adds, edits and renames, while reporting deletions and leaving their previous state active. Files under active writers are also reported and left for the next checkpoint; one growing log cannot block the rest of a vault. Review deletions with workspace status, then cross the explicit scan --allow-deletes boundary yourself. Automation may preserve knowledge; it does not get permission to erase it.

Bidirectional projection starts only after workspace track proves that the folder exactly matches the stored view. The per-folder cursor is local and crash-safe. Without it, an old local copy and a new remote version are indistinguishable from a deliberate local edit. workspace pull replaces a path only when its current bytes still match that cursor. If both sides edited it, the local file is preserved and the conflict is reported. A remote tombstone also stays pending until the local file is explicitly removed. Installs use same-filesystem .brainmesh/staging; either rename boundary can be replayed safely after a crash.

workspace watch performs sync, safe pull, checkpoint, then a second sync when it appended records. Native filesystem events wake local changes after a bounded debounce. Exact existing-file hints hash only the named paths; a coarse platform event first compares bounded path metadata, and a missing path, possible rename, ignore-rule edit or ambiguous event falls back to the complete planner. The watcher separately observes encrypted store-log changes, so a peer-delivered head can apply only changed projection objects immediately. It never watches its own projection metadata, which would make a self-wake loop. Large projection cursors are buffered while decoding.

--interval remains the remote-sync and lost-event backstop. If the platform watcher cannot start, it falls back to that polling interval. Every event is a hint. Idle backstop polls hash sorted path, size and modification time plus the store's signed log heads, and --full-every 86400 still forces a content-hash audit at least daily, including edits that preserve metadata. Watch health uses two alternating 0600 records and distinguishes the last attempt, last success and last full audit. Pending deletion, a live file deferred during capture, a materialization conflict, or a failed peer leaves the cycle unhealthy and eligible for retry.

This is deliberately the first migration loop, not an automatic cutover: preview, scan, restore into an empty directory, compare, then decide when git stops being the primary copy.

A real local pass on 2026-08-16 exercised 16,244 eligible files and 5.39 GB. Preview took 4.82 seconds. The first checkpoint committed 16,242 stable files in 109.1 seconds and explicitly deferred two files under active writers. Restore took 35.1 seconds; all 16,242 files matched their stored hashes, and an independent checksum pass found byte equality. One add, one update, and one pending deletion over that full vault each took 6.36-6.64 seconds. Two isolated folders then exercised remote add, update, rename, concurrent edit refusal, adoption and a pending tombstone; both ended at 16,242 exact files. An idle watcher full audit took 19.46 seconds and the next metadata-only poll took 3.34 seconds.

On 2026-08-17 the same disposable projection contained the original 16,242 files plus three harmless probes. Before the incremental path, one native edit took about 235 seconds to checkpoint because it hashed every file, then the Mac mini waited for its 300-second backstop; end to end was about 487 seconds. After exact-path checkpointing, encrypted-log wakeups and buffered cursor reads, a new MacBook-to-mini file materialized in about nine seconds by filesystem timestamps and the reverse mini-to-MacBook probe completed in 8.3 seconds from the pre-copy timestamp. Both watcher records said quick, not full, and both folders then verified 16,245 matching files with zero missing, changed, extra or conflicted entries.

The same encrypted store was then restored onto a physical Mac mini through a relayed tailnet path. One resumed command fetched 18,011 chunks needed by 14,405 files and restored all 16,242 represented files in 2,951.64 seconds. Both internal verification and an independent checksum comparison found zero file-content differences. Timestamps differed, and three empty local directories were absent because workspaces currently represent files rather than empty directories. A real add and update crossed the machines; concurrent offline edits surfaced as the same two heads on both, and an explicit merge event selected one without last-writer-wins. A tombstone was refused by the unattended watcher, refused again without --allow-deletes, and remained pending on the laptop until its local copy was moved aside. Both machines finished with 16,242 matching files, zero missing, changed, extra or conflicted files. This is physical cross-device and interruption evidence, not yet a long-run soak or complete disaster-recovery claim.

The full store then passed an identity-loss drill. Its original Mac mini identity was moved completely outside the store, a 216-byte recovery kit and separately held 24-word phrase produced a new device author, and the recovered owner authority exactly matched the original. Without copying or rebuilding the ciphertext, workspace verify again reported all 16,242 files matching. The recovered device signed two new records, pushed them to the laptop, and the laptop decrypted the ordinary note. This proves loss of every local identity file while encrypted data survives.

A separate full ciphertext-loss drill then started with an empty destination, restored the fresh identity from its kit and imported an authorized encrypted bundle. It rebuilt 16,264 signed records and 20,116 encrypted chunks (5,291,099,261 bytes), restored all 16,242 files with zero hash differences, signed and decrypted a new record under the recovered identity, rejected the used kit as stale and verified its successor. Repeating both loss drills over time remains part of the dogfood gate. The built-in non-destructive drill later repeated the complete reconstruction from newly generated artifacts in 32.07 seconds: exact heads for the same 16,264 records, all 20,116 ciphertext chunks, 16,027 historical manifests and 5,290,294,621 authenticated plaintext bytes; the live store and healthy watcher remained unchanged.

agents

an ai client talks to a brain through one grant, and cannot exceed it.

brainmesh ships a reusable operating skill for Claude, Codex, Hermes, Pi and screenpipe under skills/brainmesh. Install it into every agent root on the current device with:

bash skills/brainmesh/scripts/install-agent-skill.sh

On Windows, run powershell -ExecutionPolicy Bypass -File skills/brainmesh/scripts/install-agent-skill.ps1. The skill teaches the agents how to discover stores, verify sync, use narrow grants and avoid destructive recovery mistakes. Installing it grants no data access; each agent still needs an explicit brainmesh grant.

brainmesh grant $(brainmesh id | cut -d: -f2) \
  --kinds note,file --sensitivity personal --days 365 --write
brainmesh grants                        # copy the id
brainmesh mcp --as <grant id>           # json-rpc on stdin and stdout

point claude desktop at it by adding this to ~/Library/Application Support/Claude/claude_desktop_config.json:

{ "mcpServers": { "brainmesh": {
    "command": "/Users/you/.local/bin/brainmesh",
    "args": ["mcp", "--as", "<grant id>"] } } }

eight tools: overview, request_access, access_status, search, recent, record, remember, files. The standing grant remains the ordinary permission model. request_access does not widen it: it queues an owner-visible request for one exact protected search, recent, or files call.

  • reads return only what the scope covers, and tell the model how many records it was not allowed to see, so it does not answer as though it read everything
  • writes are checked against the same scope, so an agent holding a slice for work notes cannot file a medical one
  • every read appends a receipt naming the grant, never the query text; every grant-authorized write records the exact effective grant and its declared grantee alongside the new record
  • a receipt that overlaps a same-device CLI write waits through a bounded writer-lock retry; sustained contention returns an error rather than dropping the receipt or racing the author sequence
  • brainmesh audit lists both grant reads and grant-authorized writes without trusting stored identifiers to be long, printable or well formed
  • brainmesh revoke <id> resolves and revokes the signed grant blob rather than trusting its descriptive JSON id, then cuts it off mid conversation
  • search returns bounded one-line excerpts under a whole-response budget; record reopens one exact result by its source-backed ref and checks the grant and revocation again, so models do not ingest every full note up front
  • when more matches exist, search and recent return a filter-bound next_cursor; pass it back with the same semantic filters to walk older records without repeating the previous page. Relative date windows are frozen at page one, page size may change, and every page rechecks the grant, expiry and revocation because a cursor is never an access capability

one-time access from an AI chat

When a standing grant withholds something needed for the current question, the AI can explain why and call request_access with the target tool and its exact arguments. The request is not authority. It expires after 15 minutes and is stored only in the endpoint's private state. access_status lets the same chat observe pending, approved, denied, consumed, or expired state without learning the owner credential.

The installed PWA has a separate owner approval credential. It renders the AI-provided reason, exact query/date/tag/kind boundary and maximum sensitivity. "Allow one read" makes the trusted node root-sign a read-only grant to the same agent subject for at most two minutes. That grant is bound to the displayed tool arguments and is atomically consumed before the query executes. Changed arguments do not consume it; concurrent or repeated exact calls cannot use it twice. Approval does not authorize record, writes, later searches, another agent, or a wider sensitivity.

Web Push is only the wake-up channel. Its encrypted payload contains an opaque request id, not the reason, query, scope, token, or memory. The phone fetches the request from the trusted node after the owner opens the PWA. Push subscriptions, request events, the VAPID private key and approval.token are bounded private endpoint files and mode 0600 on Unix. The relay transports TLS and push services receive encrypted Web Push bytes; the hosted model still sees plaintext returned by the one approved read.

On iOS/iPadOS, first open /mobile/, use Share → Add to Home Screen, launch the installed app, open Requests, paste the separate owner approval code, and tap Enable permission notifications. Notification permission must be requested from that owner tap. Android and desktop installed browsers use the same flow. A browser stores this owner code in origin-scoped app storage, so this is still a bearer boundary; the native clients should hardware-bind this credential before claiming Keychain/Keystore-grade approval security.

A long-lived MCP/HTTP node keeps a bounded process-local decrypted snapshot so repeated agent searches do not reopen the whole log. It is never written to disk, is capped at 64 MiB/250,000 readable records, zeroizes plaintext on drop, and is reused only while exact verified heads and the complete runtime-key view match. External writes, sync, revocation or key changes invalidate it; exact local receipts and captures advance it, and oversized brains use the ordinary streaming scan. This cache lives on the trusted node, not on the phone.

A hierarchy can be granted without exposing its sibling:

brainmesh grant <agent-device> --workspace brain --paths company --days 30

Workspace records carry ancestor tags, so that grant covers company/ and everything below it but not personal/. The signed permission format remains the same, and the check still happens at the node holding the encryption key.

A phone or hosted model does not decrypt the bucket. It becomes a client of a machine that already holds the key. That trusted node opens records, applies the grant, returns only the permitted plaintext, and appends a read receipt:

encrypted bucket/peers -> your trusted node -> grant filter -> Claude/ChatGPT

That is the mobile architecture today: no brain key or encrypted store is uploaded to an AI vendor. A native phone client can hold only an OAuth token bound to one grant. Claude and ChatGPT are different: their hosted connector holds that grant-bound token and necessarily sees the permitted plaintext your node returns. It still cannot decrypt anything else. Use a narrow, expiring grant and treat the returned slice as disclosed to that model provider.

For a hosted connector, public DNS points at a relay, but the certificate and TLS private key remain on the trusted brain node. Create one no-clobber 0600 route capability, copy it to that node, and allowlist the same file on the relay:

# public relay; brain.example resolves here
brainmesh tunnel route brain.example.route brain.example
brainmesh tunnel listen 0.0.0.0:443 0.0.0.0:7780 \
  --route brain.example.route

# trusted node: a local Caddy/nginx on 127.0.0.1:8443 holds the public
# certificate and proxies decrypted HTTP only to 127.0.0.1:7777
brainmesh serve-http --as <grant-id> --bind 127.0.0.1:7777 \
  --url https://brain.example
brainmesh tunnel expose relay.example:7780 brain.example.route \
  --to 127.0.0.1:8443 --pool 4

Use a local TLS terminator configured with a public certificate for the route; DNS-based certificate issuance works without giving the relay that key. The relay reads the visible ClientHello SNI only, then forwards the original TLS records to one waiting outbound connection. Registration proves the route-file token with a fresh challenge, so the token itself never crosses the control socket. Stealing the route can at most hijack availability: without the TLS private key, a replacement endpoint cannot complete a valid handshake.

The relay still sees the hostname, client and node IPs, timing, connections and byte counts. It can drop traffic, and a route with no waiting pool closes. The current core is deliberately HTTP-version agnostic because it carries TLS bytes. A real TLS 1.3 certificate/hostname check, authenticated MCP search, unauthenticated 401, exact granted result and durable read receipt all passed through the relay. A public domain, public-CA certificate and real Claude/ChatGPT connector pass are still deployment work.

brainmesh serve-http --as <grant id> --url https://your-node.ts.net
tailscale funnel 127.0.0.1:7777      # tls terminates on YOUR machine

Open https://your-node.ts.net/mobile/ for the first usable handset client. It can search, show recent records and an overview, and append a scoped note. Its Requests inbox can also receive privacy-minimized Web Push notifications and approve or deny one exact hosted-agent read. Pairing is OAuth authorization-code flow with S256 PKCE; access tokens last one hour, refresh tokens rotate, and Disconnect durably revokes both tokens. The app shell can remain installed while the node is offline and preserves its revocable credential for retry, but it never caches memory content and cannot pretend an offline query succeeded. This web step stores the refresh token in browser storage and therefore remains an ordinary bearer client. The iOS shell in mobile/ios keeps credentials in device-only Keychain storage, holds a non-exportable Secure Enclave P-256 key, and sender-constrains access and refresh credentials with RFC 9449 DPoP. It adds a text/URL share target and passes its Keychain, DPoP, hostile-callback and pre-network capture-limit tests in the iOS simulator. A native integration test also completes dynamic registration, S256 pairing, scoped search, capture, read-back and durable logout against a live node. Physical-device signing and an on-phone share-sheet/Secure Enclave pass remain. The Android shell in mobile/android uses separate non-exportable Android Keystore AES-GCM and P-256 signing keys: the first protects its no-backup credential envelope and the second sender-constrains every native token and protected request with DPoP. Its build and lint pass; prior API-35 emulator coverage exercised pairing, search, capture, read-back and logout, while the new hardware-key DPoP test still needs an attached emulator or phone. Physical Android hardware remains untested. None of these designs puts a brain data key on the phone.

Mobile privacy also fails closed around OS snapshots and backups. The iOS app replaces its content with an opaque lock shield whenever its scene is inactive or backgrounded; it has no memory database or file cache, and its credential and Secure Enclave representation are non-synchronizing this-device-only Keychain items. Android disables application backup, cloud extraction and device transfer across every data domain, keeps its encrypted envelope in no-backup storage, and marks both main and share windows secure so Android refuses screenshots, screen recording and recent-task thumbnails. These are platform controls, not a claim that a compromised OS cannot observe plaintext.

clients that will not take a header run the oauth flow instead: registration, an approval page, pkce with S256 required rather than optional, single use codes, exact resource binding, one-hour access tokens and rotating refresh tokens. browser Origins are refused unless explicitly allowed with --allow-origins. approving means pasting the pairing token, which is a file only you can read. there is one user here and inventing an account system for them would be inventing something to lose.

Authentication state is namespaced under the signed grant id. The static pairing token remains a raw private 256-bit file because the owner must be able to display and paste it. serve-http displays that value only on an interactive terminal; redirected or background output names the private file without copying the credential into logs. OAuth access and refresh values are different: the node persists only domain-separated BLAKE3 fingerprints, never the raw credentials returned to the client. Existing plaintext logs migrate to the fingerprinted format under one exclusive server lease and are atomically replaced without signing existing clients out. The logs are bounded, durable, symlink-refusing and mode 0600 on Unix; an incomplete final record is removed while complete corruption stops startup. An endpoint restarted under a different grant gets different credentials, so an old phone token can never silently widen with the server configuration. Web and hosted clients remain bearer clients. The first-party iOS and Android clients instead bind the authorization code, rotating refresh credentials, access credentials and every protected request to one non-exportable P-256 key with RFC 9449 DPoP. Copying a native token without that key is insufficient; expiry, durable logout and grant revocation remain the administrative controls.

The trusted-node HTTP listener admits at most 64 active sockets before it creates request threads. Every admitted socket has a 30-second read/write deadline; overflow gets a best-effort 503 and is closed without blocking the accept loop. The separate organization inbox uses 32 slots. These are local resource-exhaustion bounds, not edge DDoS protection; a public deployment still needs connection and request limits at the node-owned TLS terminator.

Before authentication, OAuth mutation work has separate 60-second budgets per observed TCP peer: 60 dynamic registrations, 30 pairing approvals and 120 code or refresh exchanges. The endpoint keeps at most 4,096 source/traffic buckets, returns 429 plus Retry-After before JSON, pairing-state or DPoP work, and does not trust a caller-supplied forwarding header. Health, discovery, the approval page and logout remain available. If a node-owned TLS proxy connects over loopback, every proxied client intentionally shares that loopback budget; the proxy must enforce real-source limits before forwarding. These counters also reset on process restart and are not distributed DDoS protection.

After authentication, protected MCP and capture work is additionally limited to 120 cost units per credential identity and 600 per signed grant in each 60-second window. A DPoP client's identity is its stable public-key thumbprint, so rotating its access token cannot reset the budget; bearer and pairing credentials are represented only by domain-separated fingerprints. Every JSON-RPC batch member costs one unit, and an oversized batch is rejected with 429 plus Retry-After before any member runs. Logout is exempt so a user can always disconnect. The bounded table and counters are process memory and reset on restart, so this is a fair-use and accidental-loop guard, not a substitute for node-owned edge protection against distributed abuse. Give independently budgeted agents separate grants and endpoints.

the phone holds nothing, so losing it is not losing a key. the token names a grant and nothing more, and brainmesh revoke ends it.

over a tailnet you need no certificate at all: wireguard already encrypts and authenticates it, so --bind <tailnet ip> is reachable from your own phone and involves nobody. the caveat is who dials: claude and chatgpt call remote connectors from their servers rather than from the handset, so those two need public reach. anything connecting from the device itself works privately today.

do not put anything in front of this that terminates tls away from your node. the whole claim is that nobody but you can read it. Tailscale can terminate on your own machine; the public brainmesh tunnel passes TLS through to your own local terminator. A provider-managed decrypting proxy withdraws the claim.

capture from a phone needs no app either. one iOS Shortcut in the share sheet, pointed at /capture, files whatever you share:

curl -X POST https://your-node/capture -H "Authorization: Bearer <token>" \
  -d 'a thought worth keeping'

the grant decides, exactly as it does everywhere else: a read only grant is refused rather than quietly obliged.

want to see exactly what an agent sees, before you hand it over:

brainmesh ask <grant id> "pricing"      # the same path, on your terminal
brainmesh audit                         # what a grant has read or written

any cloud, as a peer

a bucket cannot host the live log, because there are no locks and no appends and a log needs both. but it is a near perfect home for what the log produces: segments and blobs are immutable, content addressed ciphertext, which is the one thing object storage is unambiguously good at.

so a bucket is a peer that never talks back. push what it lacks, pull what you lack. two machines that are never awake at the same time converge through it.

brainmesh remote https://<account>.r2.cloudflarestorage.com auto mybucket brain/ <key> <secret>
brainmesh push
brainmesh pull

aws, r2, b2, minio, wasabi, garage: one dialect, any cloud. tls is curl's job, the same bargain already made with ssh.

it holds noise. records are sealed with the brain key and signed, so the provider stores bytes it cannot read and cannot forge. and nothing pulled from a bucket is trusted: segments are decoded and applied through the same path a peer's records take, so a bucket serving something rewritten is refused. a store that trusts its backup is a store with no signatures.

Bucket keys have a closed grammar and are never joined as provider-controlled filesystem paths. Loose chunks must match the ciphertext hash in their key; packs must match their whole-object hash, canonical table and every member hash; and an entire log object must decode and verify before any record is applied. Listing counts, response sizes and each object class are bounded. Local repair markers and forensic packs are never uploaded. On repeated pull, held chunks and exact local packs are skipped before a GET, so a large archive does not repeatedly pay to download immutable bytes it already has. A real local HTTP/curl drill confirms that the second pull performs LIST but no blob GET.

Packs are file-backed end to end. Upload hashes BLAKE3 and SHA-256 in one bounded-buffer pass, then curl --upload-file reads the file directly. A pack download uses one private same-filesystem part and lock per content hash. Curl continues an interrupted prefix with HTTP Range, including on the next pull; an endpoint without Range support safely restarts that object from zero. The completed file is flushed, whole-pack and member hashes are validated from disk, and only then is it renamed live. Oversized or malformed completed parts are deleted; bounded interrupted ciphertext is retained only for resume. A 128 MiB pack is never a 128 MiB Rust allocation.

it does not depend on tailscale

nothing in the crate knows what a network is. sync shells out to ssh, and tailscale only ever enters at name resolution. three ways round it:

several addresses per peer, tried in order. the same machine found over a tailnet from a cafe and over the lan at home, without choosing.

brainmesh peer add "mini.tailnet.ts.net,mini.local,192.168.1.50"

any command that carries stdin and stdout. an address starting with ! is run instead of ssh, so a jump host, kubectl exec, adb shell or a serial link all work unchanged.

brainmesh peer add '!kubectl exec -i pod -- brainmesh serve'

no network at all.

brainmesh bundle /Volumes/stick/brain.bundle
brainmesh import /Volumes/stick/brain.bundle

the bundle is self-contained: it carries signed history and all encrypted file chunks held by this machine. every record still has to verify and fit its author chain, and every chunk must match its ciphertext hash, so a stick someone hands you can add valid history but never rewrite it or smuggle bytes under a false identity. importing twice transfers nothing the second time. version-one record-only bundles remain readable. On an enrolled key-holding device, the entire record section is quarantined and checked against every included root-signed epoch transition before any author log changes.

The bundle alone is data transport, not key recovery. The importing device must already be enrolled, receive an invite wrapped to it, or restore keys from a separate recovery kit and phrase. The bundle never contains a brain key.

recovery without a back door

brainmesh recovery create /Volumes/stick/brain.keys
# write the 24 words it shows once on paper; do not put them beside the kit
brainmesh recovery verify /Volumes/stick/brain.keys
# retype the paper phrase; this decrypts in memory and writes no keys
brainmesh recovery status /Volumes/stick/brain.keys
# fails if a data-key epoch, space, role generation, or organization key changed

# for a headless drill, keep the phrase out of stdout and shell history:
brainmesh recovery create brain.keys --phrase-output /Volumes/other/brain.phrase
brainmesh recovery verify brain.keys --phrase-file /Volumes/other/brain.phrase
brainmesh bundle /Volumes/stick/personal.bundle
brainmesh bundle /Volumes/stick/shared.bundle --space shared
brainmesh recovery drill brain.keys /Volumes/stick/personal.bundle \
  --space-bundle shared /Volumes/stick/shared.bundle \
  --phrase-file /Volumes/other/brain.phrase
# after a forced termination or power loss, or before inspecting leftovers:
brainmesh recovery cleanup

# after losing every device, on a fresh machine:
brainmesh recovery restore /Volumes/stick/brain.keys
brainmesh import /Volumes/stick/brain.bundle
brainmesh witness verify /Volumes/stick/brain.heads

The kit contains every held personal data-key epoch and its signed transition chain, every separately encrypted space held by this device, and organization authority material it holds. It contains no records, blobs, device signing key or device agreement key. Restore therefore creates a fresh device author rather