Skip to content

Credentials & the Keychain

dotty env is a small credential store backed by the macOS Keychain: secrets are Keychain items, never plaintext files on disk, and reach processes as environment variables only when you ask. Keys are grouped into namespaces (--namespace, default default) so one project's secrets don't collide with another's.

Storing

dotty env add GITHUB_TOKEN                 # prompts for the value, hidden
dotty env add --in-file .env               # capture a whole .env file
dotty env --namespace=acme add API_KEY     # namespaced

dotty env add never echoes values and accepts an existing .env file wholesale — a quick way to move a project's secrets off disk (delete the file after).

Reading

dotty env list                             # names only, values stay put
dotty env get GITHUB_TOKEN                 # one value to stdout
dotty env get dotty://acme/API_KEY         # URI form, namespace inline

dotty env get takes either a bare key (with --namespace) or a dotty://<namespace>/<key> URI; --no-newline makes it composable in command substitution.

Injecting into processes

The sanctioned pattern — the secret exists in the child's environment for exactly one command:

dotty env run -- gh api user
dotty env --namespace=acme run -- terraform plan
dotty env run --in-file .env.dotty -- npm test

dotty env run resolves the namespace's keys (or the dotty:// references in a template file) and executes the command with them injected.

Templates and round-tripping

dotty env use renders a template whose values are dotty:// references into a real .env file (--out-file) — for tools that insist on reading one — and --in-file re-captures it. Keep the template (references only, no secrets) in the repo; the global gitignore keeps .env.dotty trackable while ignoring other .env.* files.

Removing

dotty env remove API_KEY
dotty env --namespace=acme remove --all

How this plays with agent hardening

The hardened agent sandboxes deny reads of **/.env* and block the macOS security CLI — a sandboxed agent can neither read secret files nor rummage in the Keychain. dotty env run is the intended escape hatch: you run the command that needs the secret, outside the agent, and the agent never sees the value.