Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Settings Precedence

Four settings files contribute to the final permission set. Higher-priority files win when keys conflict. tool-gates respects every explicit rule before applying its own gate decisions. One enterprise flag narrows that set to a single file.

File priority

Where rules live.

Top of the list wins. The same precedence applies on macOS and Linux.

PriorityLocationUse case
1 highest /etc/claude-code/managed-settings.json (Linux)
/Library/Application Support/ClaudeCode/managed-settings.json (macOS)
C:\Program Files\ClaudeCode\managed-settings.json (Windows)
Enterprise managed. Locked by IT; overrides everything below, and can exclude it entirely.
2 .claude/settings.local.json Local project overrides. Per-developer, not committed.
3 .claude/settings.json Shared project rules. Committed; team baseline.
4 lowest ~/.claude/settings.json Personal defaults across every project on this machine.

Managed-only resolution

When the enterprise file is the whole ruleset.

When the managed settings document sets allowManagedPermissionRulesOnly to boolean true, tool-gates evaluates Claude against that document alone. The user, project, and local files are not loaded into the effective permission set at all.

AspectBehavior
What is excluded Every lower-scope entry: allow, ask, deny, and additionalDirectories. The flag draws a source boundary, not a grants-only filter, so a personal deny rule stops participating alongside a personal allow.
Allowed directories The invocation cwd plus the managed document's additionalDirectories. A directory listed only in a lower scope does not become writable or auto-approvable.
Empty managed permissions Resolve to no rules. tool-gates does not fall back to a lower scope because the managed file has nothing to say.
Malformed managed permissions Resolve to no rules. A document that is valid JSON and asserts the flag keeps the boundary even when its permissions block cannot be parsed.
Who can set it Only the managed document at the platform path above. The same key in a user, project, or local file has no authority to turn managed-only resolution on or off, and a non-boolean value leaves the four-source merge in place.
Other clients Codex, Antigravity, and deprecated Gemini keep the four-source merge whatever the flag says. The flag is a Claude Code setting, and tool-gates only applies it to Claude.
Safety floor Unchanged. A managed allow does not unlock a destructive command or a raw-string pattern such as pipe-to-shell.

Nested evaluation inherits the same boundary. Mise task expansion, package-script expansion, compound sub-command checks, and the acceptEdits directory check all resolve settings under the client that started the invocation, so none of them can reload a lower scope mid-decision.

With the flag absent or false, everything below applies exactly as it always has.

Interaction

How tool-gates respects your rules.

Your explicit settings.json rules override tool-gates' built-in decision in every case but one: a dangerous call stays blocked even if a rule allows it.

settings.jsontool-gatesResult
deny rule any Deny   explicit deny respected.
ask rule any Ask   two-button prompt (Yes / No).
allow rule dangerous Deny   tool-gates still blocks the dangerous floor.
allow or none safe Allow
none unknown Defer in default / acceptEdits; Ask in auto; Block in plan unless the gate proves the command is read-only.

When a permissions.deny rule matches, the decision reason names the exact Bash(...) pattern. This lets the agent identify the configured boundary that rejected the command instead of receiving a generic settings denial.

Pattern formats

How rules match commands.

PatternTypeMatches
Bash(git:*)Word-boundary prefixThe : splits on spaces. Matches git, git status, git push; NOT github.
Bash(cat /dev/zero*)Glob prefixMatches anything that starts with the literal prefix.
Bash(pwd)ExactOnly the exact command, no trailing args.
Bash(uv run $HOME/scripts/*)$HOME expansiontool-gates expands $HOME in a pattern to the home directory before matching. (Claude Code itself natively expands the ~/ form.)

Specificity resolution

When ask and allow both match.

Specificity is the length of the non-wildcard prefix. The more specific pattern wins; exact matches are highest. Ties go to ask, the safer default. Bash(mytool --verbose:*) (length 16) beats Bash(mytool:*) (length 6), so a narrow allow can override a broad ask. Deny rules are checked first and use simple matching with no specificity comparison.

When a permissions.ask rule in settings.json matches, Claude Code's resolver shows a two-button prompt instead of three (the "don't ask again for X" button is suppressed). tool-gates rules ask-audit categorises each rule by what tool-gates would do without it (gate-covered, safety floor, indeterminate) and offers per-rule removal.

tool-gates · permission gate hook for Claude Code, Codex CLI, and Antigravity CLI, with deprecated Gemini CLI support. github.com/camjac251/tool-gates

13 gates · 400+ commands · built from rules/*.toml