Claude Hookbook

Hooks / safety

Protect .env and secret files

Blocks Claude from writing to .env files, keys, and credential files - unless you say otherwise.

PreToolUseEdit|Writeblocking riskneeds manual check

What it does

Fires before Edit/Write tool calls. The script checks the target file's name against a protected list (.env, .env.*, *.pem, *.key, anything with 'credentials' or 'secrets' in the name) and returns a permissionDecision of deny with a clear reason. Everything else passes through to the normal permission flow. Official-guide pattern, updated to the current JSON decision output.

When it runs

EventPreToolUse
MatcherEdit|Write
Scopeproject or user
Platformsmacos, linux
Timeout10s
Requiresjq
Failure modeblock
Verified againstClaude Code hooks reference, event/matcher schema checked 2026-09-10
Test statusneeds manual check - run the test steps below before relying on it

Config

Merge this into .claude/settings.json (or ~/.claude/settings.json for user scope) - or use the generator to combine hooks.

{
  "hooks": {
    "PreToolUse": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/protect-env-secrets.sh",
            "timeout": 10
          }
        ],
        "matcher": "Edit|Write"
      }
    ]
  }
}

Script

Save as .claude/hooks/protect-env-secrets.sh and chmod +x it.

#!/bin/bash
# protect-env-secrets: deny writes to secret-bearing files.
set -u
file=$(jq -r '.tool_input.file_path // empty')
[ -z "$file" ] && exit 0
base=$(basename "$file")
protected=0
case "$base" in
  .env|.env.*|*.pem|*.key|*.p12|*.pfx) protected=1 ;;
  *credential*|*secret*) protected=1 ;;
esac
if [ "$protected" = "1" ]; then
  jq -n --arg f "$file" '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "deny",
      permissionDecisionReason: ("Writes to secret-bearing files are blocked by the protect-env-secrets hook (" + $f + "). Edit it yourself, or temporarily disable the hook.")
    }
  }'
  exit 0
fi
exit 0

Install

  1. Save the script to .claude/hooks/protect-env-secrets.sh and chmod +x it.
  2. Add the config fragment to .claude/settings.json (project scope) or ~/.claude/settings.json (everywhere).

Test it

If it blocks something you wanted

When Claude is blocked it sees the deny reason and can tell you. To let a specific edit through, make the edit yourself, or remove/disable the hook entry in settings.json for that session.

Sources

Related hooks

Block destructive shell commands

Blocks rm -rf, disk tools, force pushes, and destructive git commands before they run.

PreToolUseBashblocking riskneeds manual check

Secret scan on changed files

Runs gitleaks on every file Claude edits and warns when something looks like a secret.

PostToolUseEdit|Writereview riskneeds manual check

Pro Pack (later)

Framework bundles, cross-platform scripts, tested blocking policies, and a test harness. Free recipes and the generator stay free.

Waitlist opens soon.