> ## Documentation Index
> Fetch the complete documentation index at: https://capy.sc/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Branch-Aware Secrets: Per-Environment .env Files

> Capy branches give each environment — dev, staging, prod — its own encrypted secret set, pinned to your git branch via keep.lock. Switch with capy checkout.

A Capy **branch** is an independent set of values for the same project. A typical setup has:

* `development` - created automatically on project init. 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 stores its own encrypted `keep.lock` blob, and secrets on one branch are decryptable only by members of that branch.

<Note>
  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.
</Note>

## Git branches vs. Capy branches

You typically have many git branches mapped to a handful of Capy branches. Most feature and bugfix branches share the same `development` secrets; a few branches (e.g., `release-*`) might point at `staging` or `prod`.

<Frame>
  <img src="https://mintcdn.com/capy-c95c79c0/N7qpVCkQCaY3Lo-w/images/diagrams/10-branch-routing.svg?fit=max&auto=format&n=N7qpVCkQCaY3Lo-w&q=85&s=228b24bc3db7292f6edff263b8d089ab" className="block dark:hidden" alt="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." width="616" height="368" data-path="images/diagrams/10-branch-routing.svg" />

  <img src="https://mintcdn.com/capy-c95c79c0/N7qpVCkQCaY3Lo-w/images/diagrams/10-branch-routing-dark.svg?fit=max&auto=format&n=N7qpVCkQCaY3Lo-w&q=85&s=d300e3cbcaf342a4f92b4abbc9f29d35" className="hidden dark:block" alt="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." width="616" height="368" data-path="images/diagrams/10-branch-routing-dark.svg" />
</Frame>

The mapping lives in **`keep.lock`** - a small, committed manifest file at the project root. Every git branch that ships with the same `keep.lock` sees the same Capy secrets. Change the committed `keep.lock` on a specific git branch (for example on `release-v2`) and that branch gets its own Capy-branch pin.

### What `keep.lock` contains

* **Org ID and project ID** - 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 git branch. When a teammate clones your repo and checks out `feature/login`, their `keep.lock` matches yours and `capy` pulls the same Capy branch you're on. No "which environment am I in" question - the git branch answers it.

## Commands

```bash theme={null}
capy branch                    # list branches, optionally switch interactively
capy branch -D <name>          # delete a branch
capy checkout <branch>         # switch to a branch
capy checkout -b <new-name>    # create a branch and switch to it
capy checkout --protected -b <new-name>   # create a protected branch
```

On `checkout`, Capy rewrites `.env` in place with the snippets from the new branch.

## Typical workflow

```bash theme={null}
# Start on dev
capy                                     # first-run creates `development`
# Later, add staging
capy checkout -b staging
# Edit .env, then sync — staging diverges from development
capy
# And production, as an invite-only branch
capy checkout --protected -b production
```

Each branch is a first-class environment. There's no "copy-paste the staging values into production" - each branch has its own encrypted blob and its own access list.

## What's next

<Columns cols={2}>
  <Card title="Protected branches" icon="shield" href="/using/branches/protected" horizontal>
    Invite-only branches for production.
  </Card>

  <Card title="capy branch" icon="terminal" href="/cli/branch" horizontal>
    Full command reference.
  </Card>
</Columns>
