Skip to main content
A Capy branch is an independent set of values for the same project. A typical setup has:
  • development - the branch Capy offers by default the first time you run capy in a project. Full read/write for every member.
  • staging - a separate set of values, possibly with different API endpoints.
  • production - protected, invite-only, stricter access.
Branches live inside a single project, so they share the same project key PK - but each branch has its own encrypted blob on the service and its own pins in keep.lock. Access to a protected branch is gated by the service: check out a branch you haven’t been granted and the fetch fails, so Capy tells you the branch is invite-only and to ask a project admin for access instead of handing over the ciphertext.
Capy branches are independent of git branches. They’re tracked separately. That said, when you switch git branches, capy will let you know if your secrets are up to date for the particular version of code you are looking at.

Git branches vs. Capy branches

You typically have many git branches and a handful of Capy branches. Feature and bugfix branches all keep working against whichever Capy branch the directory is on - usually development. When you need staging or production values, you switch explicitly with capy checkout.
Git branches on the left (main, dev, feature/login, feature/signup, feature/billing, bugfix/hotfix, release-v2) route through the committed keep.lock manifest to the Capy development branch on the right, which holds env vars (DATABASE_URL, API_KEY, STRIPE_SECRET, REDIS_URL, etc.). Staging and prod are separate Capy branches shown below development.
Which Capy branch a directory is on is local state, not something git carries. Capy records it in the .env header (# capy:branch=…) and in .capy/branch, and it gitignores both. So switching git branches leaves you on the same Capy branch - only capy checkout, or picking a branch from capy branch, changes it. Every working copy keeps its own record, which means a second clone or a git worktree can sit on a different Capy branch than this one. What git does carry is keep.lock - a small, committed manifest file at the project root. One file holds every branch’s metadata, so whichever git branch you’re on, Capy knows what each Capy branch is supposed to contain.

What keep.lock contains

  • Org ID, project ID, and project name - which Capy project this directory belongs to.
  • Schema version - for format evolution.
  • Variable manifest - every secret name, its resource ID, and a hash per Capy branch. Hashes, not plaintext, not ciphertext, not keys.
No secrets and no keys live in keep.lock. It’s just the list of what exists, enough for Capy to pull the right ciphertext from the service and diff against .env. Safe to commit, because everything sensitive stays on the service side and in your ignored .env.

Why commit it

Because keep.lock is committed, it travels with the repo. A teammate who clones it gets the same project, the same variable list, and the same per-branch hashes, so capy can tell right away whether their .env matches what a branch pins. Capy commits keep.lock for you whenever a sync or a push changes it - set CAPY_NO_AUTOCOMMIT=1 to opt out. A fresh clone has no .env and no .capy/, so no branch is recorded locally yet. On the first capy run there, Capy asks the service for the project’s branches: if there’s only one, it uses it; otherwise it asks which branch you want, never preselecting a protected one.

Commands

On checkout, Capy rewrites .env in place with the snippets from the new branch. It refuses to switch while the branch you’re on has uncommitted changes (.env differs from what keep.lock pins) or unpushed changes (keep.lock differs from your last sync) - run capy or capy push first. Both checks are skipped when you pass -b. Both commands need the Capy service, so both are disabled in local-only mode.

Typical workflow

Each branch is a first-class environment: its own encrypted blob on the service, its own pins in keep.lock, and - for protected branches - its own access list.

What’s next

Protected branches

Invite-only branches for production.

capy branch

Full command reference.
Last modified on August 11, 2026