Vibe Coding for Production
Getting startedFirst steps

Permissions

How Claude Code limits tools and shell commands with allow, ask, and deny rules, including safe Git boundaries.

Claude Code from Anthropic uses a permission system so you control what the agent may run automatically, what must be confirmed, and what is blocked. Settings can live in team settings files and be shared through version control. Use Anthropic’s Configure permissions doc for the full matrix; what follows is a short orientation.

Allow, ask, and deny

From the docs:

  • Allow rules let Claude Code use the matching tool without manual approval (for that match).
  • Ask rules prompt you when Claude tries to use the tool.
  • Deny rules prevent the tool use.

Evaluation order is deny, then ask, then allow. The first matching rule wins, and deny takes precedence over the others. That is how a single pattern can hard-stop a dangerous command even if something else would have allowed broader access.

Use the /permissions UI in Claude Code to inspect rules and see which settings.json (or layered settings) they come from.

Permission modes (high level)

Claude Code also has permission modes (default, acceptEdits, plan, auto, dontAsk, bypassPermissions) that change how aggressively it prompts or auto-approves. Modes interact with your rules; the full table lives under Configure permissions and Permission modes. For automation in CI-style environments, dontAsk auto-denies anything not covered by explicit allow rules, which pairs well with a tight deny list.

Rule shape: Tool and Tool(specifier)

Rules use the form Tool or Tool(specifier). For shell commands, Bash(...) specifiers support glob * wildcards in the command string. The docs note that a space before * enforces a word boundary (for example Bash(ls *) matches ls -la but not lsof).

The documentation’s stock example allows routine npm and git commit flows while denying any git push:

{
  "permissions": {
    "allow": [
      "Bash(npm run *)",
      "Bash(git commit *)",
      "Bash(* --version)",
      "Bash(* --help *)"
    ],
    "deny": ["Bash(git push *)"]
  }
}

That Bash(git push *) line is already a strong guardrail: git push is how history gets published, and you often want either a human in the loop or narrower allow-lists than "any push."

Example: put every push behind a boundary

git push --force (or git push -f) is especially risky: it can rewrite history on the remote and remove commits other people rely on. For workshop discussion it is a clear deny candidate.

Do not try to enumerate only --force spellings and argument positions. Git global options, aliases, and reordered flags make that boundary easy to miss. If publishing is not part of the agent's job, deny all direct pushes:

{
  "permissions": {
    "deny": ["Bash(git push *)"]
  }
}

If normal pushes should be possible only with approval, put the same rule under ask instead. For a security-critical boundary, also account for aliases and commands such as git -c ...; permission globs are not a substitute for remote branch protection.

Managed and team settings

Organizations can ship managed settings so developers cannot weaken certain rules. The same permissions doc covers allowManagedPermissionRulesOnly, disabling bypassPermissions, and related controls.

Example prompts

Review rules you are about to commit:

Here is our .claude/settings.json `permissions` section. Flag any allow rule that is too broad for day-to-day use, suggest three deny lines we are missing for git and secrets, and explain each fix in one sentence.

[paste JSON]

Check for force-push holes (stay read-only if you use Plan mode):

In plan mode only: find every file under .claude/ that sets permissions. Could `git push --force` or `git push -f` run without matching a deny? Quote the relevant lines or say what to add.

Takeaway

Permissions are not optional sugar. They are the contract between your repo and the agent: what runs silently, what stops for a click, and what never runs. Treat git push --force-class operations as deny-by-default unless you have a narrow, reviewed exception list.

On this page