Secrets
Named bundles of credentials, stored in macOS Keychain, injected into a single child process at run time.
The rule
Use agents secrets exec when you can and the --secrets flag on agents run when you cannot. Do not export credentials into the shell. The shell is shared with every tool you run afterwards.
Bad: export into the shell
export OPENAI_API_KEY=$(agents secrets get openai)
agents run codex "draft the migration"
# OPENAI_API_KEY is now visible to every subsequent process in this shell.Any binary you launch in the same shell — an editor plugin, a build script, a curl one-liner — inherits the key. The key also lands in shell history if the command is edited or recalled with history.
Good: scope to one process
agents secrets exec openai -- agents run codex "draft the migration"The bundle is resolved from Keychain, the env is set on the child process only, and the child exits with the env. Nothing leaks back to the parent shell. The same shape works for any command:
agents secrets exec stripe-prod -- bun run scripts/refund.ts
agents secrets exec hetzner.com -- crabbox run -- bun testCreate a bundle
agents secrets create stripe-prod
agents secrets add stripe-prod STRIPE_API_KEY --type api-key --expires 2027-01-15
agents secrets add stripe-prod STRIPE_WEBHOOK_SECRET --type api-key
agents secrets listadd prompts for the value and writes it to Keychain. Bundle definitions live in Keychain too — nothing about secrets touches disk in plaintext. The EXPIRING column on list flags any secret due in the next 30 days.
Rotate a secret
agents secrets rotate stripe-prod STRIPE_API_KEY --note "rotated after suspected leak"rotate replaces the value and preserves metadata; add refuses to overwrite an existing key.
Touch ID & the prompt policy
On macOS, Keychain access for secret bundles is gated by Touch ID when biometry is available. Every bundle has a prompt policy, shown in the POLICY column of agents secrets list:
- daily (default) — ask once, then the secrets-agent holds the bundle for ~24h, so concurrent commands and teammates read it silently. One Touch ID per day, not per command.
- always — ask on every read; never auto-held. Opt high-value bundles (signing keys, SSH) into this when you want to confirm each read.
Change the default for every bundle in agents.yaml, or override one bundle:
agents secrets policy signing always # this bundle prompts on every read
# ~/.agents/agents.yaml
# secrets:
# policy: daily # default for all bundles (this IS the default)
# agent:
# auto: false # opt out of the 24h hold; prompt every readThe secrets-agent: one prompt, then silence
The hold is delivered by the secrets-agent — a local broker that keeps resolved values in memory behind a user-only socket, modelled on ssh-agent. A daily bundle auto-loads on its first read; you can also unlock explicitly:
agents secrets unlock stripe-prod # one Touch ID; held for 24h
agents teams start checkout # every teammate reads it silently
agents secrets status # what's held, and when it locks
agents secrets lock # wipe it; next read re-promptsThe hold ends on its TTL (default 24h, --ttl 30m to shorten), when you lock, or when the screen locks or the machine sleeps. Nothing is written to disk. The trade-off: while a bundle is unlocked, any process running as you can read it from the socket without a prompt — so mark high-value bundles always and lock when you step away.
Instructing an agent
When you write rules for an agent that will run shell commands on your behalf, make the policy explicit in AGENTS.md:
Run credential-needing commands via 'agents secrets exec <bundle> -- <command>'.
Do not 'export' secrets into the shell. Do not write secrets to .env files.
If a bundle is missing, stop and ask which bundle to use.Across devices
The same rule holds when a bundle has to reach another machine: never copy a plaintext value across. agents secrets push encrypts the bundle before it leaves the device, and agents secrets export --host <name> lands it as a native Keychain bundle on the far end. See secrets across devices.
See browser profiles for attaching a bundle to a browser profile so agents can sign into sites without seeing the credentials.