All articles

Writing Permission Rules That Match Commands

Permission modes set the broad posture. Permission rules give you fine control. With allow and deny lists you pre-approve the tools and commands you trust, and block the ones you do not, so you are prompted far less often.

The shape of a rule

Rules are patterns tied to a tool. The tool name comes first, and an optional pattern in parentheses narrows it:

  • Read, Edit, Write, Glob, Grep — the file and search tools
  • Bash(git *) — any git command
  • Bash(npm run test:*) — npm test scripts
  • Write(/tmp/*) — writes limited to a temp folder
  • Edit(src/*) — edits limited to the source tree

The pattern lets you allow a whole family of commands without opening the door to everything.

Setting them in settings.json

Rules live under permissions in a settings file, with allow and deny arrays:

{
  "permissions": {
    "allow": [
      "Read",
      "Grep",
      "Bash(git status)",
      "Bash(npm run test:*)"
    ],
    "deny": [
      "Bash(git push:*)",
      "Write(/etc/*)"
    ]
  }
}

Here Claude can read, search, check git status, and run test scripts without asking, but it can never push or write to system paths.

Where to put them

Project rules go in .claude/settings.json and are checked into git for the whole team. Personal overrides you do not want to commit go in .claude/settings.local.json. You can also open the rules interactively with /permissions.

Match real commands

The goal is to name the commands you actually run. Allow the safe, repeated ones so the prompts disappear, and deny the destructive ones so they are always blocked. Rules that mirror your real workflow cut noise without giving up control.

Comments

Be the first to comment.