Stop Claude Code from deleting your files
Claude tidied 214 files away, a tax return included. This guide: a deny rule that makes delete commands impossible.
The fix
Create .claude/settings.json in your project and add a deny rule. Claude Code enforces permission rules, not the model; CLAUDE.md instructions do not change what it allows. Order is deny, then ask, then allow, and the first match wins. A deny blocks the command outright. Want to be asked instead, so you can say no? Put the pattern under ask. Bash(rm:*) is another way to write Bash(rm *); both mean the same.
{
"permissions": {
"deny": ["Bash(rm *)", "Bash(rmdir *)"],
"ask": ["Bash(git clean *)"]
}
}Which file?
~/.claude/settings.json applies to you in every project. .claude/settings.json applies to everyone in the repo once you commit it. .claude/settings.local.json is yours only, for one project; if you create it by hand, add it to .gitignore. Lists like permissions.deny merge across files, and a tool denied at any level cannot be allowed by another. The file must be strict JSON: no comments, no trailing commas.
Check it worked
Run /permissions to see your allow, ask and deny rules by scope. Edits to settings files apply to the running session, no restart needed. Then ask Claude to create a scratch file and delete it with rm. The call must be blocked.
/permissionsPro tip: protect secrets, and Windows
A Read deny rule keeps Claude out of a file or folder (it also blocks Edit and Write on that path). If Claude runs commands through the PowerShell tool, PowerShell rules have the same shape.
{
"permissions": {
"deny": [
"PowerShell(Remove-Item *)",
"Read(./.env)",
"Read(./secrets/**)"
]
}
}Pro tip: add an OS-level wall
Permission rules are not a sandbox. For filesystem limits that hold for every process Claude starts, turn on the sandbox with /sandbox. It is off by default and runs on macOS, Linux and WSL2; on native Windows, commands run unsandboxed.
/sandboxCommon mistake
Treating Bash(rm *) as a wall around deletion. It matches the command text Claude writes. /bin/rm -rf build/ and bash -c 'rm -rf build/' are different text and are not stopped by it. Cover the gap with the sandbox, or with a PreToolUse hook that inspects the command and exits 2 to block.
Official docs
One fix of twenty: the whole Claude Code survival kit.
Follow @whyshouldaicareA new disaster and its fix every day. Comment the word under a reel to get its guide.