Secrets

This is the part most dotfile tools get wrong, so it is worth reading properly.

The rule

Secrets never touch git. You declare which values are secret; envkit moves them into the OS keychain on backup and leaves a placeholder in the store. Your shell fetches them at startup from the keychain, so no plaintext lands in your dotfiles or your repository.

The keychain is macOS Keychain on darwin, and pass on Linux.

Declaring one

[[file]]
path    = ".zshrc"
kind    = "shell"
secrets = ["GITHUB_TOKEN"]

On the next backup, envkit lifts the value out of .zshrc, stores it in the keychain, and writes a placeholder into the store copy. Your shell sources a generated ~/.config/envkit/secrets.zsh that calls envkit secret get.

That generated file is never committed.

Managing values directly

envkit secret list                       # names only, never values
envkit secret get  GITHUB_TOKEN
envkit secret set  GITHUB_TOKEN          # prompts, input hidden
envkit secret rm   GITHUB_TOKEN

To store a value non-interactively, pipe it in — this keeps it out of your shell history and out of ps:

printf %s "$VALUE" | envkit secret set GITHUB_TOKEN

Running a command with secrets injected

envkit exec GITHUB_TOKEN -- gh pr list
envkit exec GITHUB_TOKEN:GH_TOKEN -- some-tool     # rename on the way in

Prefer this over export — the value exists only for that process.

secret get is fail-soft, and why that matters

A missing key prints a warning and returns an empty string with exit code 0. That is deliberate: a typo in a key name must not break shell startup and lock you out of your terminal.

The trap: an empty return looks exactly like a working call. If a script silently gets "", check the key exists with envkit secret list before concluding the store is broken.

A genuine keychain error — a locked keychain, a broken pass — exits non-zero, so automation still fails loudly on real faults.

The undeclared-secret scan

On backup, envkit scans tracked files for things that look like secrets you did not declare, and refuses rather than committing one by accident.

envkit backup --allow-unmanaged     # override for this run

Or mark a file noscan = true if it trips the scanner repeatedly for good reason.

Moving secrets between machines

The keychain is per-machine, so load restores your files but not your secrets. Set them on the new machine:

envkit secret set GITHUB_TOKEN

envkit doctor --secrets reads every indexed key and reports the ones with no value, so you can see what still needs setting rather than discovering it when something breaks. Plain doctor deliberately skips this: it costs one keychain read per key and may prompt.