Claude Code reads settings from more than one file, and most teams only use one of them. If you've ever committed your own allow-list tweak by accident, or argued about whose model choice goes in the repo, the fix is to split shared rules from personal ones.
The three files
-
~/.claude/settings.jsonholds your user settings, applied in every project on your machine. -
.claude/settings.jsonholds project settings. Commit this one so the whole team gets the same rules. -
.claude/settings.local.jsonholds your personal settings for this project. Claude Code configures git to ignore it when it creates the file, so it stays on your machine.
When the same setting appears in more than one file, the more specific one wins: local beats project, and project beats user. Managed enterprise policy, if your company uses it, sits above all three.
A split that works
Shared, in .claude/settings.json:
{
"permissions": {
"allow": ["Bash(npm test:*)", "Bash(git diff:*)"],
"ask": ["Bash(git push:*)"],
"deny": ["Read(./.env)", "Read(./.env.*)"]
}
}
Personal, in .claude/settings.local.json:
{
"permissions": {
"allow": ["Bash(docker compose up:*)"]
}
}
The team keeps the safety rails, and you get your extra command without a pull request.
Tips
- Put deny rules in the project file. A teammate's local file shouldn't be where
.envprotection lives. - Check
.gitignoreonce if you createdsettings.local.jsonby hand rather than through Claude Code. - Run
/permissionsinside Claude Code to see which rules are active and where each one came from.
The project-side file, plus a short CLAUDE.md, a risky-git hook and a read-only reviewer subagent, ships in Vildanden Agent Config. The free sample is enough to set this up today.
Top comments (1)
Nice breakdown of the local-vs-project split. The tip about keeping deny rules in the project file is a good one, since it means .env protection doesn't depend on each teammate's setup. Do you also review changes to .claude/settings.json in pull requests like any other config, so a loosened allow-list gets noticed?