Encrypted + compressed per-session sync for the pi coding agent. Store your ~/.pi/agent/sessions on any S3-compatible object storage and pull them on another machine.
Each session JSONL is stored as a separate S3 object, wrapped as AES-256-GCM(gzip(plaintext)). There's no single huge snapshot blob and no secret-scanning — everything is encrypted at rest.
pi keeps every session locally under ~/.pi/agent/sessions. If you work across machines (laptop + desktop), those sessions don't follow you. This extension syncs them, encrypted, to object storage you control.
Create a bucket on any S3-compatible storage (IDrive E2, Cloudflare R2, AWS S3, MinIO, …). Grab the endpoint, region, and access keys.
~/.pi/agent/pi-sync.local.json:
{
"endpoint": "https://pi-sessions.s3.eu-central-1.idrivee2.com",
"bucket": "pi-sessions",
"region": "eu-central-1",
"accessKeyId": "...",
"secretAccessKey": "..."
}Or set env vars (PI_SYNC_ENDPOINT, PI_SYNC_BUCKET, PI_SYNC_REGION, PI_SYNC_ACCESS_KEY_ID, PI_SYNC_SECRET_ACCESS_KEY).
Generate once, then use the same key on every machine (keep it out of storage — it never gets synced):
echo "export PI_SYNC_ENCRYPTION_KEY=\"$(openssl rand -base64 32)\"" >> ~/.zshrcpi install npm:@ersintarhan/pi-syncRestart pi, then:
/pisync doctor
— should report config ok, encrypt key ok, bucket reachable.
/pisync status # local vs remote diff (dry run)
/pisync push # upload changed/new local sessions (last-writer-wins)
/pisync pull # download remote-newer sessions, overwrite local
/pisync doctor # config + key + connectivity + lock diagnostic
/pisync unlock --stale # clear a stale lock after a crash
On session shutdown, changed sessions are pushed automatically (best-effort).
The encryption key is shared, the storage is shared, so each machine stays in sync:
- Finish work on machine A — sessions auto-push on exit (or run
/pisync push). - Move to machine B — run
/pisync pulland continue where you left off.
Works across OSes: mac (/Users/you) and linux (/home/you) map to the same session keys — the home prefix is normalized, so your history follows you regardless of platform. Paths outside home (e.g. /tmp, which mac resolves to /private/tmp) can't be reconciled across OSes and stay OS-native.
Conflict resolution is last-writer-wins by file mtime. Don't run two machines on the same session at once.
<bucket>/
├── manifest.json # encrypted index: every synced session + sha256 + mtime
└── sessions/
└── <normalized-cwd>/ # home prefix normalized: ~/Projects/x (mac /Users, linux /home → same key)
└── *.jsonl # each session: AES-256-GCM(gzip(plaintext))
manifest.json drives change detection (sha256) and last-writer-wins (mtime).
- No build step —
piruns the.tsdirectly. - No
npmtoken needed: releases are published via GitHub Actions OIDC trusted publishing (tag-driven:npm version patch && git push --tags). - Upgrading to cross-OS keys (≥0.1.14): the first
/pisync pushafter upgrading re-uploads every session under the normalized key and drops the old OS-specific keys from the manifest (the orphan objects stay in the bucket; delete them manually if you want). No content is lost — local sessions are re-pushed from disk. - Sessions are encrypted at rest, so the bucket can hold API keys that appeared in transcripts. Still — keep your encryption key private and rotate storage keys on suspicion.
MIT.