Claude Code and Secrets Management

Published Aug 6, 2026

Real rules, not vague advice — what to check for API keys, tokens, and passwords, and how to catch a leak before it ever ships.

Rule 1: Environment Variables, Not Hardcoded Values

Every secret belongs in an environment variable, documented in .env.example with a placeholder, never a real value. This should be stated explicitly in CLAUDE.md, not assumed — see the e-commerce CLAUDE.md template for a real example of this convention written out.

Rule 2: Check Git History, Not Just Current Files

A secret removed in a later commit is often still recoverable from git history unless it's actually purged — a quick search of the current codebase isn't enough to confirm nothing ever leaked.

Rule 3: .gitignore Alone Isn't Proof of Safety

.env in .gitignore is necessary but not sufficient — check whether an earlier commit already included it before .gitignore was added, and confirm .env.example never has real values swapped in "just for now."

Rule 4: Treat It as a Standing Pre-Deploy Check

A one-time check isn't enough on an active project — make it a routine part of shipping, not a one-off audit. See the full security checklist for the broader pre-deploy pass this fits into.

New to Claude Code? Start With the Basics

The free guide covers the permission model — the foundation these conventions build on.

Get the Free Guide →

Frequently Asked Questions

Will Claude Code ever commit a secret on its own?

It shouldn't if the project follows real environment-variable conventions, but it depends entirely on those conventions actually being in place and documented — not on the tool guessing what's sensitive.

How do I check if a secret already leaked into git history?

Search the full commit history, not just the current file state — a secret removed in a later commit is still recoverable from history unless it's actually purged.

Is .env in .gitignore enough?

It's necessary but not sufficient — also check that no earlier commit already included it before .gitignore was added, and that .env.example never has real values instead of placeholders.