Capy has two moving parts: the CLI on your machine, and the service that brokers the co-decrypt handshake. The CLI handles everything local - syncing, encrypting, invites, deploy setup - and spawns your app with decrypted env vars viaDocumentation Index
Fetch the complete documentation index at: https://docs.capy.sc/llms.txt
Use this file to discover all available pages before exploring further.
capy run. The service holds only ciphertext and membership records.
The two components
On-disk state
Inside a Capy-managed project: Gitignored:.env, .env.pre-capy.old, .capy/. Committed: keep.lock.
key.enc is the only long-lived secret on disk, and it lives only on the client. It’s AES-encrypted with an inner key derived from SHA256(userId || ":" || orgId) (never stored anywhere) and then outer-wrapped via the service’s /orgs/{orgId}/wrap endpoint. The service never stores a copy - to use key.enc the CLI presents it for co-decrypt, where the service strips only the outer layer.
keep.lock
keep.lock is a small JSON file that tells Capy which project this directory belongs to and what its current state is. It contains:
- Org ID and project ID - which org and project this directory maps to.
- Schema version - for format evolution.
- Variable manifest - a sorted list of variable names with per-branch resource IDs and value hashes. Hashes, not plaintext, not ciphertext, not keys.
keep.lock is what lets a teammate clone your repo, run capy, and sync the same secrets you’re working with. Active branch is tracked separately in .capy/branch (local state).
.env after Capy
Your.env after capy has run looks like:
capy:… snippet is:
capy:literal prefix{resourceId}- a 5-character hash stable for this{projectKey, varName}pair, used to diff without leaking plaintext{blob}- base64 ofiv || ciphertext || tagfrom AES-256-GCM under the project key
resourceIds are namespaced per project.
Git hooks
On first-run Capy installs two hooks:post-checkout- runscapy statusafter you switch git branches, so you notice drift immediately.post-merge- same, aftergit pull/git merge.
pre-push hook. If an older Capy version installed one, capy cleans it out on the next run.
Sync engine
The sync engine is a three-way merge between:- Local - what’s currently in
.envafter any edits you’ve made. - Pinned - what was in
.envthe last time Capy saw it in sync with the remote. - Remote - what’s currently in the service’s blob for this branch.
The wire
Every CLI request to the service is a plain HTTPS POST with a JSON body and an auth token. The bodies are small and the payloads are already-encrypted blobs - compromising the transport tells an attacker nothing they couldn’t get by compromising the service itself.What’s next
Zero trust
Why two shares, and what each share holds.
Cryptography
Every client-side algorithm, key, and parameter.