Show HN: A 60-line PreToolUse hook that stops Claude Code from editing your .env

gaiinmaster1 pts0 comments

claude-code-survival-kr/guard at main · avenna01-ceo/claude-code-survival-kr · GitHub

//files/disambiguate" data-turbo-transient="true" />

Skip to content

Search or jump to...

Search code, repositories, users, issues, pull requests...

-->

Search

Clear

Search syntax tips

Provide feedback

--><br>We read every piece of feedback, and take your input very seriously.

Include my email address so I can be contacted

Cancel

Submit feedback

Saved searches

Use saved searches to filter your results more quickly

-->

Name

Query

To see all available qualifiers, see our documentation.

Cancel

Create saved search

Sign in

//files/disambiguate;ref_cta:Sign up;ref_loc:header logged out"}"<br>Sign up

Appearance settings

Resetting focus

You signed in with another tab or window. Reload to refresh your session.<br>You signed out in another tab or window. Reload to refresh your session.<br>You switched accounts on another tab or window. Reload to refresh your session.

Dismiss alert

{{ message }}

avenna01-ceo

claude-code-survival-kr

Public

Notifications<br>You must be signed in to change notification settings

Fork

Star

FilesExpand file tree

main

/guard<br>Copy path

Directory actions

More options<br>More options

Directory actions

More options<br>More options

Latest commit

History<br>History<br>History

main

/guard<br>Copy path

Top

Folders and files<br>NameNameLast commit message<br>Last commit date<br>parent directory<br>..<br>README.md

README.md

guard.py

guard.py

protected.txt

protected.txt

settings.json

settings.json

View all files

README.md<br>Outline<br>guard.py — stop it from touching the files that matter

CLAUDE.md is advice. The model reads it, the conversation gets long, the rule<br>loses priority, and it edits the file anyway.

That is not a prompting problem. No wording fixes it.

This is not advice. It runs before the tool call and refuses it.

Blocked by guard.py: .env<br>It matches the pattern '.env' listed in .claude/protected.txt.

The model never gets to write. It gets told why, and moves on.

Install (2 minutes)

mkdir -p .claude<br>curl -o .claude/guard.py https://raw.githubusercontent.com/avenna01-ceo/claude-code-survival-kr/main/guard/guard.py<br>curl -o .claude/protected.txt https://raw.githubusercontent.com/avenna01-ceo/claude-code-survival-kr/main/guard/protected.txt<br>curl -o .claude/settings.json https://raw.githubusercontent.com/avenna01-ceo/claude-code-survival-kr/main/guard/settings.json

Already have a .claude/settings.json? Merge this in instead of overwriting:

"hooks": {<br>"PreToolUse": [<br>"matcher": "Edit|Write|MultiEdit|NotebookEdit",<br>"hooks": [{ "type": "command", "command": "python3 .claude/guard.py" }]

On Windows use python instead of python3.

Restart Claude Code. That's it — no dependencies, Python 3.8+.

Choose what to protect

Edit .claude/protected.txt. One pattern per line.

.env<br>.env.*<br>*.pem<br>*.key<br>credentials.json

migrations/**<br>legacy/**

.claude/guard.py<br>.claude/protected.txt<br>.claude/settings.json

A bare filename matches anywhere in the tree , because that's what you mean<br>when you type it. .env blocks ./.env and api/.env both. dir/** blocks<br>everything under that directory.

Keep the last three lines. They are what stops the model from disabling its own<br>guard when it gets stuck.

Check it works

echo '{"tool_name":"Edit","tool_input":{"file_path":".env"},"cwd":"'"$PWD"'"}' | python3 .claude/guard.py; echo "exit=$?"

exit=2 means it's live. exit=0 on a protected path means the pattern didn't match.

What it does and doesn't do

Does

Blocks Edit, Write, MultiEdit, NotebookEdit on paths you list

Reads every path in a MultiEdit batch, not just the first

Returns the reason on stderr, so the model stops instead of retrying

Fails open — if the hook itself errors, your work continues. A guard that<br>breaks everything when it breaks is worse than no guard.

Doesn't

Doesn't block Bash. rm -rf still goes through. Gate that separately, or<br>add a Bash matcher and inspect the command string.

Doesn't protect against a user who edits protected.txt themselves. It's a<br>guardrail, not a permission system.

Why a hook and not a rule

Where it lives<br>When it loses

CLAUDE.md<br>in the prompt<br>context gets long, priority drops

hook<br>in your machine<br>never — it isn't the model's decision

Rules are advisory. Hooks are enforcement. Use both: CLAUDE.md for why,<br>guard.py for can't.

Part of claude-code-survival-kr —<br>rules and prompts that stop AI from breaking working code. MIT.

You can’t perform that action at this time.

claude guard code protected settings survival

Related Articles