2025-12-01 11:38:48 -08:00
# Policy engine
2025-10-31 11:11:19 -07:00
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.
2025-12-15 12:17:48 -08:00
## 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.
2025-10-31 11:11:19 -07:00
## 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.
2025-12-01 11:38:48 -08:00
#### Arguments pattern
2025-10-31 11:11:19 -07:00
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` .)
2025-12-01 11:38:48 -08:00
### Priority system and tiers
2025-10-31 11:11:19 -07:00
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` ). 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.
## 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:
2025-12-01 11:38:48 -08:00
1. **Tool name ** : The `toolName` in the rule must match the name of the tool
2025-10-31 11:11:19 -07:00
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.
2025-12-01 11:38:48 -08:00
2. **Arguments pattern ** : If `argsPattern` is specified, the tool's arguments
2025-10-31 11:11:19 -07:00
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.
2026-01-26 19:27:49 -05:00
### 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._
2025-10-31 11:11:19 -07:00
### 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":"<your_command>"}`), so anchors like `^` or `$` will apply to the full JSON string, not just the command text.
# 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
2026-01-28 10:52:48 -08:00
# (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"
2025-10-31 11:11:19 -07:00
# (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
```
2025-12-01 11:38:48 -08:00
**2. Using a wildcard**
2025-10-31 11:11:19 -07:00
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
2026-01-28 10:52:48 -08:00
deny_message = "This server is not trusted by the admin."
2025-10-31 11:11:19 -07:00
```
## 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 ** .
2026-01-12 03:55:16 -05:00
- **Agent delegation** (like `delegate_to_agent` ) defaults to * * `ask_user` ** to
ensure remote agents can prompt for confirmation, but local sub-agent actions
are executed silently and checked individually.
2025-10-31 11:11:19 -07:00
- **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.