Agent IndexAgent Permissions Index

Guides / Claude Code

How to stop Claude Code from reading your .env file

Add Read(./.env) and Read(./.env.*) to the permissions.deny array in .claude/settings.json. Deny rules are checked before allow rules, so the read is blocked even if something broader is allowed. Also deny Edit and Write on .claude/** so the agent can't remove the rule.

Stats from the 2026-10-20 snapshot of public GitHub configs (methodology). Behavior checked against the official docs linked below.

The rules

{
  "permissions": {
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)",
      "Read(~/.aws/**)",
      "Edit(./.claude/**)",
      "Write(./.claude/**)"
    ]
  }
}

Read rules don't cover the shell

A Read deny stops the Read tool. It doesn't stop a Bash command like cat .env if you've allowed broad shell access. Avoid wildcard rules such as Bash(cat *) or Bash(python3 *), or add matching Bash denies. For stronger isolation, run Claude Code in a sandbox or container that doesn't have the secrets mounted.

Where to put it

Use .claude/settings.json if the whole team should get the rule (commit it). Use ~/.claude/settings.json to apply it to every project on your machine.

How many configs do this

Of 4,831 unique public Claude Code configs with a permissions block, 339 (7%) deny reading .env files. Even among the 694 configs that have any deny rule, only 48.8% cover .env.

FAQ

Does .gitignore stop Claude Code from reading .env?

No. .gitignore controls what git tracks. Claude Code can still read an ignored file unless a deny rule blocks it.

Should I deny .env.example too?

Read(./.env.*) also matches .env.example. That's usually fine. If you want the agent to see the example file, add an explicit deny for each real env file instead (.env.local, .env.production).

Sources