Before you start
How to stop Claude Code from committing secrets
This tutorial
What you’ll set up: cckit ships a secret guard that scans every staged change for keys, .env
files, private-key blocks, and your own private terms. Turn it into a git pre-commit hook and the
commit is blocked the moment a secret is staged — whether you typed it or Claude Code did. It takes
one command.
-
Turn on the pre-commit hook. cckit ships the hook in
githooks/; point git at it once.Terminal window git config core.hooksPath githooksFrom now on git runs cckit’s guard on every
git commit, before anything reaches a remote. -
Prove it blocks a secret. Stage a fake
.envand try to commit — the guard fails the commit.Terminal window echo "API_KEY=sk-not-a-real-key" > .envgit add -f .env && git commit -m "test"# ✗ blocked: forbidden file .env — commit abortedNothing was committed. Delete the test file:
rm .env. -
Declare your own private terms (optional). Beyond keys and env files, add anything private to you — org names, internal hosts, emails — one per line.
Terminal window cp privacy-denylist.example .cckit/privacy-denylist # the target is gitignored# …add your terms, one per line…The guard now also fails a commit if any of those terms appears in a tracked file.
How it works
Section titled “How it works”The guard checks code, docs, the cookbook, examples, and templates — every commit, every time. It
runs in two places: the local check suite (scripts/check.sh) and the pre-commit hook you just
enabled. A finding blocks the commit; it is not optional and is not waved through by permission
consent. Because it fires at commit time, a leaked key is caught before it can reach a remote,
so Claude Code cannot commit a secret even when it’s driving git for you.
Troubleshooting
Section titled “Troubleshooting”The guard didn’t run on my commit. The hook path isn’t set. Re-run
git config core.hooksPath githooks in the repo, and confirm with git config core.hooksPath.
It blocked a placeholder that isn’t a real secret. Placeholders like <...>, ${...}, and
YOUR_… are allowed by design. If a real placeholder still trips it, rephrase it to one of those
forms rather than disabling the guard.
My teammate’s clone doesn’t enforce it. core.hooksPath is per-clone local config. Each person
runs the one-time command once, or you wire it in your setup script — the hook itself is committed in
githooks/.
Related tutorials
Section titled “Related tutorials”Independent, educational project — not affiliated with or endorsed by Anthropic. Claude and Claude Code are trademarks of Anthropic PBC. Disclaimer & trademarks
From Mexico with love by josegtz