# Policy engine The Gemini CLI includes a powerful policy engine that provides fine-grained control over tool execution. It allows users and administrators to define rules that determine whether a tool call should be allowed, denied, or require user confirmation. ## Quick start To create your first policy: 1. **Create the policy directory** if it doesn't exist: ```bash mkdir -p ~/.gemini/policies ``` 2. **Create a new policy file** (e.g., `~/.gemini/policies/my-rules.toml`). You can use any filename ending in `.toml`; all such files in this directory will be loaded and combined: ```toml [[rule]] toolName = "run_shell_command" commandPrefix = "git status" decision = "allow" priority = 100 ``` 3. **Run a command** that triggers the policy (e.g., ask Gemini CLI to `git status`). The tool will now execute automatically without prompting for confirmation. ## Core concepts The policy engine operates on a set of rules. Each rule is a combination of conditions and a resulting decision. When a large language model wants to execute a tool, the policy engine evaluates all rules to find the highest-priority rule that matches the tool call. A rule consists of the following main components: - **Conditions**: Criteria that a tool call must meet for the rule to apply. This can include the tool's name, the arguments provided to it, or the current approval mode. - **Decision**: The action to take if the rule matches (`allow`, `deny`, or `ask_user`). - **Priority**: A number that determines the rule's precedence. Higher numbers win. For example, this rule will ask for user confirmation before executing any `git` command. ```toml [[rule]] toolName = "run_shell_command" commandPrefix = "git " decision = "ask_user" priority = 100 ``` ### Conditions Conditions are the criteria that a tool call must meet for a rule to apply. The primary conditions are the tool's name and its arguments. #### Tool Name The `toolName` in the rule must match the name of the tool being called. - **Wildcards**: For Model-hosting-protocol (MCP) servers, you can use a wildcard. A `toolName` of `my-server__*` will match any tool from the `my-server` MCP. #### Arguments pattern If `argsPattern` is specified, the tool's arguments are converted to a stable JSON string, which is then tested against the provided regular expression. If the arguments don't match the pattern, the rule does not apply. ### Decisions There are three possible decisions a rule can enforce: - `allow`: The tool call is executed automatically without user interaction. - `deny`: The tool call is blocked and is not executed. - `ask_user`: The user is prompted to approve or deny the tool call. (In non-interactive mode, this is treated as `deny`.) ### Priority system and tiers The policy engine uses a sophisticated priority system to resolve conflicts when multiple rules match a single tool call. The core principle is simple: **the rule with the highest priority wins**. To provide a clear hierarchy, policies are organized into three tiers. Each tier has a designated number that forms the base of the final priority calculation. | Tier | Base | Description | | :------ | :--- | :------------------------------------------------------------------------- | | Default | 1 | Built-in policies that ship with the Gemini CLI. | | User | 2 | Custom policies defined by the user. | | Admin | 3 | Policies managed by an administrator (e.g., in an enterprise environment). | Within a TOML policy file, you assign a priority value from **0 to 999**. The engine transforms this into a final priority using the following formula: `final_priority = tier_base + (toml_priority / 1000)` This system guarantees that: - Admin policies always override User and Default policies. - User policies always override Default policies. - You can still order rules within a single tier with fine-grained control. For example: - A `priority: 50` rule in a Default policy file becomes `1.050`. - A `priority: 100` rule in a User policy file becomes `2.100`. - A `priority: 20` rule in an Admin policy file becomes `3.020`. ### Approval modes Approval modes allow the policy engine to apply different sets of rules based on the CLI's operational mode. A rule can be associated with one or more modes (e.g., `yolo`, `autoEdit`, `plan`). The rule will only be active if the CLI is running in one of its specified modes. If a rule has no modes specified, it is always active. - `default`: The standard interactive mode where most write tools require confirmation. - `autoEdit`: Optimized for automated code editing; some write tools may be auto-approved. - `plan`: A strict, read-only mode for research and design. See [Customizing Plan Mode Policies]. - `yolo`: A mode where all tools are auto-approved (use with extreme caution). ## Rule matching When a tool call is made, the engine checks it against all active rules, starting from the highest priority. The first rule that matches determines the outcome. A rule matches a tool call if all of its conditions are met: 1. **Tool name**: The `toolName` in the rule must match the name of the tool being called. - **Wildcards**: For Model-hosting-protocol (MCP) servers, you can use a wildcard. A `toolName` of `my-server__*` will match any tool from the `my-server` MCP. 2. **Arguments pattern**: If `argsPattern` is specified, the tool's arguments are converted to a stable JSON string, which is then tested against the provided regular expression. If the arguments don't match the pattern, the rule does not apply. ## Configuration Policies are defined in `.toml` files. The CLI loads these files from Default, User, and (if configured) Admin directories. ### Policy locations | Tier | Type | Location | | :-------- | :----- | :-------------------------- | | **User** | Custom | `~/.gemini/policies/*.toml` | | **Admin** | System | _See below (OS specific)_ | #### System-wide policies (Admin) Administrators can enforce system-wide policies (Tier 3) that override all user and default settings. These policies must be placed in specific, secure directories: | OS | Policy Directory Path | | :---------- | :------------------------------------------------ | | **Linux** | `/etc/gemini-cli/policies` | | **macOS** | `/Library/Application Support/GeminiCli/policies` | | **Windows** | `C:\ProgramData\gemini-cli\policies` | **Security Requirements:** To prevent privilege escalation, the CLI enforces strict security checks on admin directories. If checks fail, system policies are **ignored**. - **Linux / macOS:** Must be owned by `root` (UID 0) and NOT writable by group or others (e.g., `chmod 755`). - **Windows:** Must be in `C:\ProgramData`. Standard users (`Users`, `Everyone`) must NOT have `Write`, `Modify`, or `Full Control` permissions. _Tip: If you see a security warning, use the folder properties to remove write permissions for non-admin groups. You may need to "Disable inheritance" in Advanced Security Settings._ ### TOML rule schema Here is a breakdown of the fields available in a TOML policy rule: ```toml [[rule]] # A unique name for the tool, or an array of names. toolName = "run_shell_command" # (Optional) The name of an MCP server. Can be combined with toolName # to form a composite name like "mcpName__toolName". mcpName = "my-custom-server" # (Optional) A regex to match against the tool's arguments. argsPattern = '"command":"(git|npm)' # (Optional) A string or array of strings that a shell command must start with. # This is syntactic sugar for `toolName = "run_shell_command"` and an `argsPattern`. commandPrefix = "git " # (Optional) A regex to match against the entire shell command. # This is also syntactic sugar for `toolName = "run_shell_command"`. # Note: This pattern is tested against the JSON representation of the arguments (e.g., `{"command":""}`). # Because it prepends `"command":"`, it effectively matches from the start of the command. # Anchors like `^` or `$` apply to the full JSON string, so `^` should usually be avoided here. # You cannot use commandPrefix and commandRegex in the same rule. commandRegex = "git (commit|push)" # The decision to take. Must be "allow", "deny", or "ask_user". decision = "ask_user" # The priority of the rule, from 0 to 999. priority = 10 # (Optional) A custom message to display when a tool call is denied by this rule. # This message is returned to the model and user, useful for explaining *why* it was denied. deny_message = "Deletion is permanent" # (Optional) An array of approval modes where this rule is active. modes = ["autoEdit"] ``` ### Using arrays (lists) To apply the same rule to multiple tools or command prefixes, you can provide an array of strings for the `toolName` and `commandPrefix` fields. **Example:** This single rule will apply to both the `write_file` and `replace` tools. ```toml [[rule]] toolName = ["write_file", "replace"] decision = "ask_user" priority = 10 ``` ### Special syntax for `run_shell_command` To simplify writing policies for `run_shell_command`, you can use `commandPrefix` or `commandRegex` instead of the more complex `argsPattern`. - `commandPrefix`: Matches if the `command` argument starts with the given string. - `commandRegex`: Matches if the `command` argument matches the given regular expression. **Example:** This rule will ask for user confirmation before executing any `git` command. ```toml [[rule]] toolName = "run_shell_command" commandPrefix = "git " decision = "ask_user" priority = 100 ``` ### Special syntax for MCP tools You can create rules that target tools from Model-hosting-protocol (MCP) servers using the `mcpName` field or a wildcard pattern. **1. Using `mcpName`** To target a specific tool from a specific server, combine `mcpName` and `toolName`. ```toml # Allows the `search` tool on the `my-jira-server` MCP [[rule]] mcpName = "my-jira-server" toolName = "search" decision = "allow" priority = 200 ``` **2. Using a wildcard** To create a rule that applies to _all_ tools on a specific MCP server, specify only the `mcpName`. ```toml # Denies all tools from the `untrusted-server` MCP [[rule]] mcpName = "untrusted-server" decision = "deny" priority = 500 deny_message = "This server is not trusted by the admin." ``` ## Default policies The Gemini CLI ships with a set of default policies to provide a safe out-of-the-box experience. - **Read-only tools** (like `read_file`, `glob`) are generally **allowed**. - **Agent delegation** defaults to **`ask_user`** to ensure remote agents can prompt for confirmation, but local sub-agent actions are executed silently and checked individually. - **Write tools** (like `write_file`, `run_shell_command`) default to **`ask_user`**. - In **`yolo`** mode, a high-priority rule allows all tools. - In **`autoEdit`** mode, rules allow certain write operations to happen without prompting. [Customizing Plan Mode Policies]: /docs/cli/plan-mode.md#customizing-policies