Paths Subjects Questions Quizzes Pricing Search
Intermediate Open Free

Scoping Permission Rules Across a Team

A team's repository has the following requirements:

  • Every contributor should be able to run the project's linter and test suite without being prompted, since these are safe, frequently run commands.
  • Nobody's Claude Code session — regardless of mode — should ever be able to read or edit the secrets/ directory, which holds locally-decrypted credentials for local development.
  • One senior engineer personally wants Claude Code to also auto-approve a private local script she uses for smoke-testing deploys, but this shouldn't be forced on the rest of the team.
  1. For each of the three requirements, specify which settings file (and roughly what rule) should hold it, and explain why that scope is the correct one.
  2. Suppose the senior engineer accidentally puts her personal smoke-test rule in the project-level settings file and commits it. What concretely goes wrong, and for whom?
  3. Explain why the secrets/ rule needs to be a deny rule rather than simply "don't add an allow rule for it and trust the default behavior."
Solution

1. Correct scoping for each requirement:

  • Linter and test suite for everyone: this belongs in the project-level .claude/settings.json, which is committed to git and applies to every collaborator on the repo. Something like "allow": ["Bash(npm run lint)", "Bash(npm run test *)"]. Project scope is correct because the requirement is explicitly "every contributor" — a shared team policy, not a personal preference — and committing it to git is how that policy propagates to everyone without each person configuring it individually.

  • Blocking secrets/ for everyone, in every mode: this also belongs in the project-level .claude/settings.json (or, if the organization wants to guarantee it can never be overridden even by a rogue project-level edit, in managed settings deployed by IT). Something like "deny": ["Read(./secrets/**)"]. Deny rules apply across every permission mode, including otherwise-permissive ones, so this is the one mechanism that gives an unconditional guarantee regardless of which mode any individual contributor happens to be running in that day.

  • The senior engineer's personal smoke-test script: this belongs in her own .claude/settings.local.json, which is gitignored and applies only to her, in this repo. It should explicitly not go in the project-level file, because the requirement explicitly says it "shouldn't be forced on the rest of the team" — local scope is what keeps a personal convenience from becoming everyone's default.

2. What goes wrong if it lands in project settings:

Because .claude/settings.json is committed and shared, every contributor who pulls that change now has the senior engineer's private smoke-test script silently auto-approved in their own Claude Code sessions too — including engineers who don't know the script exists, don't understand what it does, and never asked for it to run without a prompt. This is a concrete instance of the same "overly broad permissions" risk discussed elsewhere: a rule intended for one trusted, informed person now silently applies to everyone, including people with less context about what that script actually touches. The fix is simply to move the rule to her local settings file and, ideally, add .claude/settings.local.json review to catch this kind of scope mistake before it's merged.

3. Why secrets/ needs an explicit deny, not just "no allow rule":

Absence of an allow rule only prevents automatic approval — it does not prevent access outright. In Manual mode, Claude Code would still prompt to read a file in secrets/ if it ever decided reading one was relevant to a task, and a developer half-paying-attention could approve that prompt without registering what they just approved. More importantly, in a more permissive mode like Accept Edits or Auto, a "no rule either way" file might get auto-approved as an ordinary in-scope read with no prompt at all, since only edits and specific risky categories are gated by default — reads generally aren't. A deny rule is categorically different: it blocks the action outright, in every mode, and deny always takes precedence over an allow rule if one somehow conflicts. For something whose entire purpose is holding credentials, "prevented by default, in every mode, no matter what mode someone happens to be in that day" is the actual guarantee the team needs — and only an explicit deny rule provides that guarantee.

Share this question

← Back to Claude Code Fundamentals practice

We use cookies for product analytics to improve OmniAtlas. See our Privacy Policy.