sealkeep
v0.9.0
Published
Sealkeep by SPALA AI — your AI coding-agent history, sealed, searchable, and shared across your machines.
Maintainers
Readme
⌑ Sealkeep
Keep your agent history, not the disk usage.
Codex and Claude Code write down every session you have. Sealkeep seals them on your machine, verifies a copy landed in your own bucket, and only then lets the local file go.
npm install -g sealkeep
sealkeep autopilotThat is the whole setup. It creates your vault, shows your recovery phrase once, finds the sessions already on this machine, and installs a background service that starts at login.
From then on you do nothing. New sessions are sealed as they finish. Once you point it at a bucket, verified copies go up and old local files move to your trash on their own.
sealkeep autopilot status # is it alive, and what has it done
sealkeep autopilot off # stop it — every archive staysIt tells you it is working rather than leaving you to wonder. The service writes a
heartbeat every cycle, so status, the dashboard, and the local API all answer
"is it running, when did it last check, and what has it sealed" from the same fact.
It also raises a native notification when disk is reclaimed or something needs a
decision — never for routine sealing, which would just train you to ignore it.
Silence it entirely with SEALKEEP_NOTIFICATIONS=off.
Prefer to drive it yourself? sealkeep quickstart does the same setup without installing
a service, and you run sealkeep queue run when you feel like it.
Why
Transcripts are the only record of how a change happened — the dead ends, the constraint you found on the third attempt, the reason that function is strange. They also contain your source, your prompts, and whatever you pasted at 2am.
So the two obvious options are both bad: let them fill the disk, or rm -rf the reasoning
behind six months of work. Sealkeep is the third option.
How it works
The order is the safety property. Nothing is reclaimed before it is verified, and nothing is verified before it is sealed.
1. Catch — your agent's session hook records that a transcript is ready, then exits. It holds no secret, makes no network call, and finishes in milliseconds, so it can never stall your agent.
2. Seal — a worker encrypts the session with a key generated for that archive alone. That key is wrapped once for your recovery phrase and once per device you trust, so revoking a laptop rewraps keys rather than re-encrypting your data.
3. Verify — the sealed archive goes to your bucket, and Sealkeep reads it back. Byte count and checksum must match what was computed locally, or the archive is not marked durable and your local file stays exactly where it is.
4. Reclaim — only a verified, idle, out-of-grace-period session becomes eligible, and then it moves to your trash. There is no code path in Sealkeep that deletes a file.
Autopilot runs all four on a loop. To unlock the vault without a human present, it keeps
your phrase in the OS keystore — macOS Keychain, Freedesktop Secret Service, or Windows
DPAPI. That is a real trade-off, stated plainly: anything running as you can read it once
you are logged in. Opt out with --no-remember and supply
SEALKEEP_RECOVERY_PHRASE to the service yourself. Either way, the phrase you wrote down
stays your disaster-recovery path.
Your recovery phrase is 24 words
Not a base64 string. Words survive bad handwriting, can be read aloud, and carry a checksum — so a misread word is caught and corrected rather than silently locking you out.
acorn oxide lynx atom voyage wool candle umber steel radar east clock
iris brass stork maple ridge ember quilt fable onyx cedar dune cricketsealkeep recovery kit --out ~/sealkeep-kit.txt # printable sheet, blanks for the words
sealkeep recovery verify # type it back to prove your copy worksCase and spacing do not matter when you type it back. A wrong word is named with suggestions: Word 1 "acron" is not in the list. Did you mean acorn, arrow?
Setting up a bucket, without the usual afternoon
The step people give up on is cloud permissions. So Sealkeep writes it out — the console link, the commands with your own bucket and prefix already filled in, and a policy that grants the least it can.
sealkeep storage setup --provider s3 --bucket my-archives --prefix accounts/me
sealkeep storage setup --provider r2 --bucket sessions --prefix me --account-id <id>
sealkeep storage setup --provider gcs --bucket sessions --prefix me --project <project>For S3 that is an IAM policy scoped to bucket/prefix/* with no delete permission and no
wildcard resource. For GCS it is a service account with an IAM condition pinned to your
prefix. Nothing runs automatically — you read each step and paste it yourself, which is the
only honest way to hand someone an IAM policy.
What we can see
The control plane coordinates devices, quotas, and upload permissions.
| It holds | It never receives | | --- | --- | | Account and device identifiers | Transcript content — no endpoint accepts it | | Byte counts and timestamps | Archive keys — generated and wrapped on your machine | | Checksums of sealed archives | Your recovery phrase — shown once, stored nowhere | | Encrypted manifests it cannot read | Device private keys — only public halves are registered |
If you lose your recovery kit and every device you registered, your archives are unreadable. Support cannot get them back. That is not a gap in the product — it is the product.
What your bucket sees
One archive is one folder of fixed-size encrypted chunks plus a small sealed
envelope. By default every path segment — project, date, session — is an HMAC
under a key derived from your phrase, so the bucket's file listing is noise:
no project names, no dates, no session ids. A sealed sidecar in each folder
carries the readable identity, so any machine with the phrase rebuilds the
friendly project/date/session view from the bucket alone. Prefer legible
paths in your own bucket? Set remoteNaming: "readable" and the same layout
is written in plain words.
Search works the same way: the content index is sealed with the archive machinery and synced beside your data, so every machine of the vault searches your whole history — and the provider never sees a token of it.
The layout also answers the worst day: a transcript too large to seal on a nearly-full disk streams straight into its chunk folder — peak local cost is one chunk — instead of waiting for space. Google Drive is the one exception: it stores archives as single objects, and says so.
Commands
| | |
| --- | --- |
| sealkeep autopilot | Set it up once and let it run itself |
| sealkeep autopilot status · off | Check on it, or stop it |
| sealkeep quickstart | Same setup, no background service |
| sealkeep status · doctor | What is archived; whether this machine is healthy |
| sealkeep queue run | Encrypt everything waiting |
| sealkeep daemon | Watch, seal, upload, and reclaim continuously |
| sealkeep search <query> | Metadata search; --content searches inside sessions |
| sealkeep recover <id> <dest> | Restore original bytes; --native puts them back where they came from |
| sealkeep recover <filename> | The file an agent's resume just complained about, back in place |
| sealkeep archive <path> --stream | Seal straight to the bucket as a chunk folder, resumable mid-upload |
| sealkeep share <id> | A sealed bundle under a one-time passcode — the phrase never travels |
| sealkeep mcp install | Register the vault as a tool server with Claude Code and Codex |
| sealkeep retention apply | Dry run; --confirm moves sources to the trash |
| sealkeep desktop · tui | The dashboard, in a browser or the terminal |
| sealkeep audit | Everything Sealkeep has done to your files |
Every command takes --json. Run sealkeep help for the full list.
Your agents know the vault is there
sealkeep mcp install registers a local MCP server with Claude Code and
Codex, so the agent itself can search your sealed history, check vault
status, and restore a session it needs — six tools, all local, nothing new
exposed to the network.
And the failure this whole product could have caused is handled where it
would happen: resuming a session whose transcript was archived and reclaimed.
A SessionStart hook notices the missing file and restores it — exact path,
exact bytes — before the agent reads it, so the resume proceeds as if the
file had never left. If anything is ever missing anyway, sealkeep recover
<filename> with the filename from the agent's error puts it back. Archiving
must never cost you a resume.
Your storage
S3, Cloudflare R2, Google Cloud Storage, Google Drive, or anything S3-compatible like MinIO. Credentials go into your OS keychain — macOS Keychain, Freedesktop Secret Service, or Windows DPAPI — never into a config file in your home directory. On the paid tier, Sealkeep runs the storage instead: quotas and uploads are brokered by the control plane, and your keys and phrase still never leave your machine.
sealkeep storage configure --provider r2 --bucket encrypted-sessions --prefix accounts/me
echo '{"accessKeyId":"…","secretAccessKey":"…"}' | sealkeep storage credentials set
SEALKEEP_ENABLE_SIGNER=1 sealkeep upload --allOr skip storage entirely and keep everything local. Sealkeep still seals every archive; it just has nowhere to copy it.
Encryption
Format v2: a random per-archive key encrypts the session in chunks under ChaCha20-Poly1305 (or AES-256-GCM), and that key is wrapped separately for each recipient. Every chunk is authenticated over its own position, the archive's identity, and the total chunk count — so reordering, truncation, splicing, and suite downgrade are all detectable rather than silent.
The format lives in packages/vaultline-crypto/
with deterministic test vectors and a tamper suite that flips every byte of a stored archive
in turn. Assumptions and limits are in THREAT_MODEL.md.
It has not been independently audited. Until it is, this is authenticated encryption built on published primitives — not an audited end-to-end-encryption product.
Status
| Area | State |
| --- | --- |
| Capture and sealing | Shipping — durable queue, crash-safe, deduplicating, resumable streaming |
| Restore | Shipping — byte-identical, verified twice, never overwrites; rehydrates on agent resume |
| Retention | Shipping — trash-staged, never deletes |
| Search | Shipping — sealed content index, synced across your machines as ciphertext |
| Agent integration | Shipping — MCP server for Claude Code and Codex, session hooks |
| Encryption format | Unaudited — vectors and tamper suite, no third-party audit yet |
| Cloud providers | GCS live in production; S3, R2, and Drive verified against signature vectors and emulators, without a long production soak yet |
| Signed binaries | Not yet — npm provenance and a signed manifest; no OS code-signing certificate |
| Distribution | Published — npm install -g sealkeep |
Self-hosting the control plane
docker build -t vaultline-control-plane .
docker run -p 8787:8787 -v vaultline-data:/data vaultline-control-planeDevices authenticate with Ed25519 request signatures, leases are single-use and expiring,
and revocation blocks new leases without touching archives. See
CONTROL_PLANE.md and docs/RUNBOOK.md.
Development
npm test # the full suite — crypto vectors, a tamper suite, provider emulators, dashboard rendering
npm run buildArchitecture is in ARCHITECTURE.md; designs and operations live in
docs/, including the not-yet-built
sharing and spaces design. The marketing page in
site/ is a single self-contained file.
