Getting started

A first vault in five minutes, then a second device.

Ten minutes: a project in a vault, a second device, a pull request through the local UI. To watch all of it happen first without touching anything of yours, run secretree demo.

1. A vault for a project

In a repository you already have:

$ cd ~/code/app
$ secretree init --vault git@gitlab.com:you/app-vault.git --name alice --kit-out ~/Desktop/app-kit.txt --push
vault:   git@gitlab.com:you/app-vault.git (id 7cac93dda9ebaed9, branch main)
repo:    app (id 02ed7a372737891b)
keys:    macOS Keychain (service secretree)
config:  /Users/you/code/app/.git/secretree/config.json

Recovery kit written to /Users/you/Desktop/app-kit.txt. PRINT IT, then delete the file.
When it is on paper, run: secretree kit --confirm   (status warns until then)
helper:  git-remote-secretree ready
remote:  origin = secretree::git@gitlab.com:you/app-vault.git

pushing every branch and tag through the helper…
 * [new branch]      main -> main

What happened: a fresh age identity and an Ed25519 signing key went into your key store; the empty remote became a vault (a README.md, a signed vault.json listing your public keys and your device's name); origin now points at the vault through the helper; every branch and tag was encrypted into a first generation and pushed. --name is how you appear on reviews and comments (default: the hostname).

The remote must exist and be empty. On GitHub or GitLab, secretree init --vault github:you/app-vault creates it for you as a private repository when the gh (or glab) CLI is installed and logged in.

The recovery kit is the only way back after losing every device. Print it, confirm it, delete the files:

secretree kit --html ~/Desktop/app-kit.html   # printable, with QR codes a phone can scan
secretree kit --print ~/Desktop/app-kit.html
secretree kit --confirm
rm ~/Desktop/app-kit.*

2. Work as usual

$ git checkout -b feature/retry
$ git commit -am "add retry helper"
$ git push origin feature/retry

Each push becomes one generation: an incremental git bundle encrypted to every member, a signed manifest, one commit on the vault. git fetch and git pull replay what you have not seen. The mirror the helper maintains lives in .git/secretree/mirror; you never touch it.

$ secretree status
repository:      /Users/you/code/app (app, id 02ed7a372737891b)
vault:           git@gitlab.com:you/app-vault.git (id 7cac93dda9ebaed9, branch main)
keys:            present in macOS Keychain (service secretree)
generations:     3 (4.1 KiB on the remote)
last backup:     generation 000003, 2026-09-18 10:12 (2m ago)
last proven:     never

"last proven" refers to the full restore proof that secretree backup and secretree verify perform; pushes are verified on every fetch.

3. A second device or a teammate

On the new machine:

$ secretree join --vault git@gitlab.com:you/app-vault.git --name laptop
keys stored in macOS Keychain (service secretree).
join request 9397afa7 pushed to the vault; a member approves it with:
  secretree member approve laptop

The request holds only public keys, encrypted to the current members and pushed into the vault itself; nothing needs to be mailed. A current member sees and approves it:

$ secretree member pending
  laptop           age1n92…  requested 2026-09-19 10:41  (id 9397afa7)
$ secretree member approve laptop
member added: laptop (age1…)
generation 000004 written (full) for the new recipient set

Then, on the new machine:

$ secretree clone git@gitlab.com:you/app-vault.git app
Cloning into 'app'...

The new member can read everything from the full generation written at approval onward; it carries the complete git history. Earlier backup snapshots stay opaque to them.

4. A pull request

$ secretree policy --approvals 1 --checks ci
wrote .secretree/policy.json; commit it on the base branch to enforce it
$ git add .secretree && git commit -m "review policy" && git push origin main

$ secretree pr open --title "Add retry helper" --body "Wraps flaky calls."
pushing feature/retry to origin…
pull request #1 opened: Add retry helper (feature/retry → main, 900c2a69)

A teammate reviews, in the local UI or on the command line:

$ secretree pr comment 1 -m "Should the delay grow between attempts?" --path src/retry.go --line 12
$ secretree pr approve 1 -m "Fine as a first version."

CI runs on a machine that holds a key (any member's machine, or a dedicated box):

$ secretree runner --once
runner: #1 feature/retry @ 900c2a69 → success (./.secretree/ci passed in 4s)

Merge, with the policy enforced from signed inputs:

$ secretree pr merge 1
#1 merged into main as 4ebfacfe

5. Look at it

$ secretree ui --open

opens http://127.0.0.1:7391: code (branches, README, files with highlighting and line anchors, blame, history, search across every branch), pull requests with the diff, inline comments, reviews, checks and the merge button, an activity feed with an unread badge, the disclosure ledger, and the vault as the host sees it. Light and dark follow the system; press / to search. secretree ui --install keeps it running in the background so permalinks always resolve.

What to do next