I let coding agents write a lot of my commits now. They write what they see, and what they see is my machine: /Users/<me>/... in a README, me@my-laptop ~ % in a pasted test log, a claude.ai/code/session_... link at the bottom of a PR body.
None of that is a credential, so secret scanners don't flag it. I wanted one that knows who I am.
- Source: https://github.com/kanywst/kwangmyong
- Install:
brew install --cask kanywst/tap/kwangmyongorgo install github.com/kanywst/kwangmyong/cmd/kwangmyong@latest
Same repository, two scanners
The demo is a four-commit repository for a made-up developer, Taro Yamada (login tyamada, laptop Taros-MacBook-Pro):
-
README.mdmentions/Users/tyamada/src/app/log -
NOTES.mdmentions~/.claude/projects/-Users-tyamada-src-app/memory -
test.loghastyamada@Taros-MacBook-Pro app % make test - one commit message ends with a Claude Code session URL
-
AUTHORSwith山田 太郎was added in one commit and deleted in the next
gitleaks 8.30.1:
$ gitleaks git . --no-banner
INF 3 commits scanned.
INF scanned ~204 bytes (204 bytes) in 36.2ms
INF no leaks found
Correct. There are no secrets in it.
What kwangmyong shows
On a terminal, kwangmyong scan --history . sweeps the repository with a live count, then opens this:
Every value is masked as a prefix and a fingerprint (ty…[b35fc2ee]), so a screenshot or a CI log is not a new leak. r reveals values on that screen only. Search only sees masked text, so typing your own name into it finds nothing.
ALSO lists the other places the same value turns up. FIX depends on where it is: a file needs an edit, a deleted file or a commit message needs a history rewrite, and p drafts that rewrite (git filter-repo inputs plus a checklist of what a rewrite cannot reach) without leaving the screen.
Quit, and the verdict stays in the scrollback:
╭────────────────────────────────────────────────────────────────────────────╮
│ ✗ TARGET EXPOSED 6 pieces of intel on you, from 5 places │
│ 4 to fix in files · 2 baked into history │
│ threat level ■■■■□ HIGH │
│ swept 3 files · 4 commits · 1 deleted blob │
│ looked for 2 names · 1 login · 1 host · home paths · agent session links │
│ values are masked · --reveal shows them │
│ next ▸ kwangmyong plan . drafts the history rewrite for you to review │
╰────────────────────────────────────────────────────────────────────────────╯
A clean repository gets ✓ TARGET DARK with what was swept and what was looked for, so "nothing found" also says how hard it looked. Piped, in CI, or with --format json|sarif, the same report prints without the UI.
It starts from who you are
The profile lives in ~/.config/kwangmyong/config.toml, never in the repository, and kwangmyong init fills it in from the machine: login, home directory, full name, hostname, global git identity.
[identity]
names = ["Taro Yamada", "山田 太郎"]
logins = ["tyamada"]
hosts = ["Taros-MacBook-Pro"]
Each value is expanded into the forms it actually shows up in: tyamada, t.yamada, Yamada Taro, -Users-tyamada-, Taro's MacBook Pro. Session links from Claude Code and Codex are flagged without any config.
Stop the agent, not just the commit
The part I use most is the hooks. kwangmyong hook install sets up pre-commit, commit-msg and pre-push for a repository. For agents, the pre-tool hook gets the tool call before it runs:
| Agent | Hook |
|---|---|
| Claude Code | kwangmyong hook claude |
| Codex CLI | kwangmyong hook codex |
| Gemini CLI | kwangmyong hook gemini |
| Cursor | kwangmyong hook cursor |
| GitHub Copilot | kwangmyong hook copilot |
| Windsurf, Kiro, Devin |
kwangmyong hook windsurf, kiro, devin
|
It checks git commit, git push, gh bodies and body files, file writes into the repository and GitHub MCP writes, and exits 2 to block. The agent gets the reason back, masked:
✗ TRANSMISSION BLOCKED. kwangmyong stopped this command: it would hand out intel on you.
[HIGH] command gh:3
3 │ ht…[bf572e0c]'
│ ^^^^^^^^^^^^^ your agent's session link
fix ▸ use ~/ or repo-relative paths, your public handle instead of a real name,
the GitHub noreply address as the commit email, and no agent session links.
CI
- uses: kanywst/kwangmyong@v0
with:
identity: ${{ secrets.KWANGMYONG_IDENTITY }}
sarif: kwangmyong.sarif
The identity comes from a secret as TOML. The Action checks the release binary against its signed checksums, and the SARIF is masked no matter what.
Not covered yet
Wikis, Actions logs, Discussions.
Source and issues: https://github.com/kanywst/kwangmyong


Top comments (0)