Agent config files are the new .env: secrets in Claude settings and opencode.json
For a decade, the canonical secret leak was the .env file: plaintext keys
in a project directory, accidentally committed, synced to a dotfile repo, or
pasted into a support thread. We built ignore rules, scanners, and git
history rewrites to deal with it.
The AI coding agent ecosystem has quietly recreated the same problem with a
new filename. Claude Code, OpenCode, and similar agents now encourage you to
put API keys directly into their configuration files — and those files are
plaintext, version-controlled, and shared more casually than .env ever
was.
The config formats that now hold secrets
The patterns differ per agent, but they share a shape:
- Claude Code reads a
settings.jsonwith an"env"block, and project-scoped.claude/settings.jsonfiles that live inside the repo itself. The quick-start path for many integrations is literally “add your key to the env block.” - OpenCode uses
opencode.json, which has anenvsection and per-agent environment blocks. Example configs in docs and blog posts show real-looking keys. - The generic
.envis still auto-loaded by most agents, so the old problem did not go away — it gained new siblings.
None of these files are encrypted, and all are read by the agent — so the keys inside end up in its context window, session transcripts, and anything it echoes back.
Why these are worse than .env
.env had conventions on its side: it was a known filename with a known
.gitignore entry, and scanners had rules for it. Agent config files are
newer, fewer ignore rules exist for them, and they are committed eagerly —
opencode.json is meant to be shared with teammates so everyone’s agent
behaves the same way. The same file gets synced to dotfile repos, pasted
into gists for troubleshooting, and attached to GitHub issues. The file is
machine-readable and human-pasteable, which is a bad combination.
Finding the leaks
Before fixing anything, you need to know where the values are. A few practical sweeps:
- Run a scan for env-style files.
trustless doctorincludes an.envscan that walks your projects and reports files that parse asKEY=VALUE— the same shape used by agent config env blocks. grep -ryour config directories forapi[_-]?key,sk-, and provider key prefixes (ANTHROPIC_,OPENAI_,GITHUB_).- Check git history:
git log -S "sk-" --allacross your repos, plus GitHub’s secret scanning results for anything that was pushed. - Search your dotfile repo and any shared configs, not just project trees.
What to do instead
The fix is to stop storing values and start storing names:
- Import what you have into your existing password store.
trustless setupscans directories for env-style files, parses them, imports the entries, and backs up the originals before touching them. - Remove the plaintext values from settings.json, opencode.json, and
.env. The agent config references secrets by name only. - Inject at runtime.
trustless run -s OPENAI_API_KEY -- opencodeor an equivalent wrapper resolves the value frompassor Bitwarden and injects it into the subprocess environment. The agent gets the value it needs; no file on disk contains it. - Rotate anything that was committed. If a value ever reached git, a gist, or a transcript, treat it as public — rotation is the only step that actually unsends it.
Config files are the new .env, but the fix is the one that worked before:
values in the store, names in the files, injection at the process boundary.
The agent still works; the plaintext is gone.
trustless implements exactly this import-and-inject workflow — one static binary, existing pass or Bitwarden backends, no migration. The command reference lives at /docs/commands/.
When was the last time you grepped your dotfiles and agent configs for a key that should not be there?