TECHDEV Β· Open-source tool

keymap

In October 2026, a breach at an agent-tool vendor exposed provider API keys stored in its console workspaces β€” and every affected developer faced the same awkward question: which keys do I have, where are they stored, and which ones do I need to rotate? A provider key gets pasted into a Claude Code config, then a Codex config, then an .env file, then shell history β€” and every copy is another place it can leak from, another line on the bill if it's abused. keymap answers the question locally, in seconds:

python -m keymap

It scans the config files your agent tools, CLIs and shells actually read β€” ~/.claude.json, ~/.codex/config.toml, ~/.env, shell rc files and history, ~/.aws/credentials, and friends β€” and reports where each provider key sits, whether the same key is sprawled across files, whether its file is world-readable, whether it landed in shell history, and whether it's one careless git add . away from a commit. It finishes with a rotation checklist: the exact revoke pages for every provider it found.

Python 3.10+ Β· Standard library only Β· MIT

What it never does

Copied verbatim from the keymap README ("What it never does").

The report: a fake-home demo

The repo ships examples/demo-home/, a fake home directory with the same Anthropic key in two files, an OpenAI key in .env and shell history, a GitHub token in ~/.claude.json, and a world-readable .env. Real output of sh examples/run-demo.sh:

keymap β€” API key footprint report
Files scanned: 5  Skipped: 0

Keys found: 5 across 5 file(s) β€” providers: openai, github, anthropic

Occurrences (prefix + fingerprint only β€” no key material):
  .claude.json:1  github  (unknown)  ghp_…685d57433a9e  [GitHub classic personal access token]
  .codex/config.toml:5  anthropic  api_key  sk-ant-…776a5e869d89  [Anthropic API key]
  .config/app.json:1  anthropic  (unknown)  sk-ant-…776a5e869d89  [Anthropic API key]
  .env:3  openai  OPENAI_API_KEY  sk-proj-…29289fad0238  [OpenAI project API key]
  .zsh_history:1  openai  OPENAI_API_KEY  sk-proj-…29289fad0238  [OpenAI project API key]

Findings:
  [HIGH] world-readable β€” .env
      File is mode 0o644 β€” anyone on this machine can read it. Run: chmod 600 .env
  [HIGH] history β€” .zsh_history
      openai key (…29289fad0238) was typed into shell history. Rotate the key, then clear that history entry.
  [MEDIUM] sprawl β€” .env, .zsh_history
      Same openai key (…29289fad0238) lives in 2 files. Keep one canonical home for it and delete the copies.
  [MEDIUM] sprawl β€” .codex/config.toml, .config/app.json
      Same anthropic key (…776a5e869d89) lives in 2 files. Keep one canonical home for it and delete the copies.

Rotation checklist (revoke at the provider, then replace):
  - openai: https://platform.openai.com/api-keys
  - github: https://github.com/settings/tokens
  - anthropic: https://console.anthropic.com/settings/keys

After rotating: delete the old value from every file above, clear it from shell history, and re-run keymap to confirm.

Demo output copied exactly from the keymap README ("Demo (all values fake)" β€” matches examples/expected-output.txt).

Quick start

# No dependencies β€” Python 3.10+ standard library only.
git clone https://github.com/techdevfun/keymap
cd keymap
python -m keymap

Or install the keymap command:

pip install .
keymap --help

Commands copied exactly from the keymap README ("Install").

Usage

python -m keymap                  # scan your home directory
python -m keymap --root ~/work    # scan a different root
python -m keymap .env .codex/config.toml   # scan specific files
python -m keymap --json           # machine-readable output for CI/scripts

Exit codes: 0 = no keys found Β· 1 = keys/findings found Β· 2 = usage or I/O error.

Commands and exit codes copied exactly from the keymap README ("Usage").

What it checks

CheckSeverityMeaning
world-readablehighFile holding a key is readable by anyone on the machine (chmod 600 it)
historyhighKey was typed into shell history β€” rotate it, then clear the entry
git-trackedhighKey is already tracked by git β€” rotate now, history rewrites don't un-leak it
not-ignoredmediumKey sits in a git repo and is not gitignored β€” one git add . from a commit
sprawlmediumSame key lives in 2+ files β€” keep one canonical home, delete the copies

Table copied from the keymap README ("What it checks").

Recognised providers

Anthropic, OpenAI, Google, GitHub (classic, fine-grained, OAuth, server-to-server), AWS access key IDs, Slack, Stripe. Anything assigned to a *_API_KEY / *_TOKEN / *_SECRET / *_PASSWORD variable that matches no known pattern is reported as unrecognized instead of ignored. Placeholder values (your-token-here, ${OPENAI_API_KEY}, xxx…) are skipped.

From the keymap README ("Recognised providers").

Honest comparison

Secret scanners like gitleaks / trufflehog hunt for leaked secrets in repos. keymap answers a different question: the keys you own, on your own machine, right now β€” which agent tools hold them, how many copies exist, and what to rotate first after a vendor breach. It complements a repo scanner; it doesn't replace one.

From the keymap README ("How it's different").

Roadmap β€” not shipped yet

Roadmap copied from the keymap README; none of these have shipped yet (2026-10-30).

License

MIT β€” see LICENSE in the repository.

Related tools

More open-source tools from TECHDEV: sessguard, runverdict, gheist-guard, vetgate, context-diet, ci-failure-detective, agent-seatbelt, devsecops-os, env-doctor, skill-audit, logtrim, testguard, breakcheck, memgraph, ggufit, leaseguard, factfence, jsonfold

Have a say

Vote for this tool, suggest a feature, or discuss it with other operators on the community board.