# Permissions Reference This reference describes the rule format understood by Amp's permissions plugin, which supports legacy permissions syntax for backwards compatibility. Custom policy plugins can use the same `tool.call` plugin hook directly, and we recommend moving to custom plugins for enforcing permissions due to the changes in how models work (see https://ampcode.com/news/neo). ## How Permissions Work When the permissions plugin is active, it evaluates tool calls through these steps: 1. **Find matching rule**: The first rule that matches the tool _and_ its arguments wins 2. **Determine action**: The matching rule tells Amp to: - `allow` - run the tool silently - `reject` - block the call (optionally with custom message) - `ask` - prompt the operator for approval - `delegate` - delegate decision to an external program 3. **Examine default rules**: If no user rule matches, the plugin falls back to its bundled default rules (for example, allowing `ls` via Bash) 4. **Return a plugin result**: The plugin returns `allow`, `reject-and-continue`, or `error` to the executor. If you want a default-deny or default-ask policy, add a catch-all rule such as `ask '*'` or `reject '*'` at the end of your rules. ## Configuration Rules are defined in the `amp.permissions` setting. Each rule is a JSON object with these properties: | Key | Type | Required | Description | | --------- | ----------------------------------------------- | ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | | `tool` | string (glob) | Yes | Name of the tool this rule applies to. Supports globs (`Bash`, `mcp__playwright__*`, `**/my-tool`) | | `matches` | object | – | Map of _tool-argument → condition_. If omitted, the rule matches _all_ calls to the tool | | `action` | `"allow"` / `"reject"` / `"ask"` / `"delegate"` | Yes | What Amp should do if the rule matches | | `context` | `"thread"` / `"subagent"` | – | Restrict the rule to the main thread or to sub-agents. Omit to apply everywhere | | `to` | string (program) | only when `action = "delegate"` | Program that decides. Must be on `$PATH` | | `message` | string | only when `action = "reject"` | Message returned to the model. If set, the rejection continues the conversation instead of halting it | ## Match Conditions Each `matches` key corresponds to a tool argument. Values can be: - **string** – glob pattern (`*` = any characters) or regex pattern (`/pattern/`) - **array** – OR of each entry (`["rm -rf *", "git commit *"]`) - **boolean/number/null/undefined** – literal value match - **object** – nested structure matching ### Regular Expression Patterns Strings that start and end with `/` are treated as regular expressions: ```jsonc { "tool": "Bash", "matches": { "cmd": "/^git (status|log|diff)$/" }, "action": "allow" } ``` This matches exactly `git status`, `git log`, or `git diff` but not `git commit`. ### Value Type Matching - **String patterns** only match string values using glob syntax - **Literal values** (boolean, number, null, undefined) require exact matches - **Array conditions** provide OR logic across multiple patterns - **Nested objects** enable deep property matching with dot notation for objects and numeric strings for array indices ## Examples ### Basic Permission Rules Allow all Bash commands in main thread, but restrict sub-agents: ```jsonc { "tool": "Bash", "action": "allow", "context": "thread" }, { "tool": "Bash", "matches": { "cmd": ["rm -rf *", "find *", "git commit *"] }, "action": "reject", "context": "subagent" } // In text form: // allow --context thread Bash // reject --context subagent Bash --cmd "rm -rf *" --cmd "find *" --cmd "git commit *" ``` Ask for approval on greps in the home directory: ```jsonc { "tool": "Grep", "matches": { "path": "$HOME/*" }, "action": "ask" } // In text form: // ask Grep --path '$HOME/*' ``` Forbid editing dotfiles: ```jsonc { "tool": "edit_file", "matches": { "path": ".*" }, "action": "reject" } // In text form: // reject edit_file --path '.*' ``` Reject destructive git commands with a helpful message (allows the model to continue): ```jsonc { "tool": "Bash", "matches": { "cmd": ["*git checkout*", "*git reset*"] }, "action": "reject", "message": "Do not use git checkout or git reset. Use edit_file to make manual changes instead." } ``` ### Delegation Delegate GitHub CLI calls to external validator: ```jsonc { "tool": "Bash", "matches": { "cmd": "gh *" }, "action": "delegate", "to": "my-gh-permission-helper" } // In text form: // delegate --to my-gh-permission-helper Bash --cmd "gh *" ``` When instructed to delegate, Amp will: - Execute the program named in `to` (must be on `$PATH`, or an absolute path) - Export `AMP_THREAD_ID`, `AGENT_TOOL_NAME=nameOfInvokedTool` and `AGENT=amp` environment variables - Pipe tool parameters to **stdin** as JSON - Interpret exit status: - `0` → allow - `1` → ask operator - `≥ 2` → reject (stderr is surfaced to the model) Amp's permission behavior is moving to a plugin so that it's easier to customize. Different teams have different standards for which tool calls should be allowed, rejected, or require approval, and a plugin-based permission system lets each team adapt Amp to its own workflow. For new permission hooks, prefer the [Plugin API](/manual/plugin-api). ## Text Format For editing many rules conveniently, you can use the text format with the `amp permissions` shell commands: ``` [-- ...] [--[:] ] ... ``` The text format is designed to be compatible with UNIX shell syntax, allowing you to copy/paste rules from and to the command line without further editing. ```bash # Basic allow/reject rules allow Bash --cmd 'git *' reject Bash --cmd 'python *' # Multiple conditions allow Bash --cmd 'git diff*' --cmd 'git commit*' # Delegation delegate --to amp-git-permissions Bash --cmd '*' ``` - Single- and double-quoted strings are supported - unquoted true, false, null and numeric words are interpreted as JSON literals - Any value containing `*` must be quoted ## Listing Rules ```bash amp permissions list # Show user rules amp permissions list --builtin # Show default rules ``` ## Testing Rules For example, testing if it would ask on a git commit: ```shell-session $ amp permissions test Bash --cmd "git commit -m 'test'" tool: Bash arguments: {"cmd":"git commit -m 'test'"} action: ask matched-rule: 12 source: built-in ``` or testing if it would ask to edit .env in the current directory ```shell-session $ amp permissions test edit_file --path "$PWD/README.md" tool: edit_file arguments: {"path":"/Users/your/project/README.md"} action: allow matched-rule: 29 source: built-in ``` The test subcommand allows you to test permission rules without actually running any tools or hoping that the agent will generate the right parameters. ## Editing Rules You can use `$EDITOR` to edit rules interactively in the text format: ```shell-session $ amp permissions edit ``` And you can edit from STDIN: ```shell-session $ amp permissions edit <<'EOF' # Ask for approval on every tool use ask '*' EOF ``` ## Add Rules For example, reject all web searches: ```shell-session $ amp permissions add reject web_search ``` or ask for approval on searches about node.js or npm packages: ```shell-session $ amp permissions add ask web_search --query "*node*" --query "*npm*" ``` ## Matching multiple tools with a single rule Tool names support glob patterns for managing groups of tools: - `Bash` - matches only the Bash tool - `mcp__playwright__*` - matches all Playwright MCP tools ### Context Restrictions Use the `context` field to restrict rules to the main agent or subagents - `"context": "thread"` - only applies in main conversation thread - `"context": "subagent"` - only applies to sub-agent tool calls - Omit `context` - applies everywhere