AI Workspace Builder
← Blog

October 16, 2026

Claude Code permissions for teams: a shared settings.json that is safe by default

Which file to commit, which rules to put in it, and where permission rules stop being enough

When one developer uses Claude Code, permissions are a personal habit. They click "yes" on the commands they trust and "no" on the ones they don't, and over a few weeks their setup settles into something that works for them.

On a team, that habit doesn't scale. Every developer ends up with a different set of approvals, nobody knows what anyone else's agent is allowed to run, and the new hire clicks through prompts on day one without knowing which ones matter.

The fix is a shared permissions file, committed to the repository, that every developer's Claude Code session starts from.

The three files that matter

Claude Code reads settings from several places. For a team, three of them matter:

File Who it applies to Commit it?
.claude/settings.json Everyone working in the repository Yes
.claude/settings.local.json One developer, in this repository No
~/.claude/settings.json One developer, in every project Not in the repo

The shared file is where team rules go. The local file is for personal exceptions, so a developer who wants one extra command approved doesn't have to change the team file. When Claude Code creates the local file itself, it keeps it out of git; if someone creates it by hand, they need to add it to .gitignore.

Organizations that need rules nobody can override can also use managed settings, which sit above all three.

What goes in the shared file

A good starting point is short:

{
  "permissions": {
    "allow": [
      "Bash(npm run lint)",
      "Bash(npm run test *)",
      "Bash(git status)",
      "Bash(git diff *)"
    ],
    "ask": [
      "Bash(git push *)"
    ],
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)"
    ]
  }
}

Replace the commands with your project's own. The pattern is what matters:

  • Allow the commands developers run dozens of times a day and that can't do damage: tests, lint, type checks, read-only git. Every prompt you remove here is a prompt nobody learns to click through without reading.
  • Ask for actions that are fine but deserve a human glance: pushing, publishing, running a migration locally.
  • Deny reads of secrets, and any command your team never wants an agent to run.

Lists from different files are combined, not replaced. A developer's personal allow rules add to the team's list; they don't remove the team's deny rules.

Rule order: deny wins

Claude Code checks deny rules first, then ask, then allow. The first match in that order decides, and a more specific rule doesn't change the order.

That means an allow rule can't carve an exception out of a deny rule. If the team file denies Bash(aws *), a developer adding Bash(aws s3 ls) to their local allow list still gets blocked. This is what makes the shared file safe to rely on: a team deny rule holds no matter what anyone adds locally.

Writing rules that match what you mean

A few details decide whether a rule does what you expect:

  • The * matches any text in its place. Bash(npm run test *) matches npm run test with any arguments.
  • The space before a trailing * matters. Bash(ls *) matches ls and ls -la but not lsof. Bash(ls*) matches lsof too.
  • Compound commands are split. An allow rule for Bash(npm run test *) does not approve npm run test && rm -rf build. Each part has to be allowed on its own, and a deny rule applies if any part matches it.
  • File rules use paths. Read(./.env) covers one file; Read(./secrets/**) covers everything under that folder.

Where permission rules stop

Permission rules shape what the agent does. They are not a security boundary on their own.

A Bash rule matches the command text the agent writes. The same program run a different way (through a variable, a script, or sh -c) may not match. The Claude Code documentation is direct about this: rules that try to restrict command arguments, such as limiting curl to one domain, are fragile.

For things that must never happen, add a second layer:

  • Sandboxing enforces filesystem and network limits that don't depend on how a command is written.
  • A PreToolUse hook runs your own check on every command before it executes, and can block it. Hooks live in the same shared settings file, so the whole team gets them.
  • Real access control still applies. If an agent should never touch production, the developer's machine shouldn't hold production credentials.

Rolling it out

  1. Start with deny rules for secrets and allow rules for tests and lint. That alone removes most prompts and the riskiest reads.
  2. Commit the file in a normal PR, so the team reviews it like code.
  3. Ask developers to note any prompt they approve more than twice in a week. Those are candidates for the shared allow list.
  4. Run /status in Claude Code to confirm the file loaded. It lists the settings sources in use.

Review changes to .claude/settings.json with the same care as changes to CI configuration. It decides what every developer's agent can do without asking.

Starting from the docs you already have

Permissions are one part of a team setup. The other part is the instructions: the commands, the conventions and the ownership rules your agent needs to follow. Most teams already have those written down in an onboarding guide or engineering handbook.

That is what we built AI Workspace Builder for. You upload the docs your team already has, and it generates the CLAUDE.md, a profile for each role, and an install script in 15 to 30 seconds. There's one free trial workspace, no card required. If you'd rather start by hand, our free templates include a shared settings file.