Gemini CLI Permissions and Policy Engine

Updated by

Independent reference, not affiliated with Google. Tables are generated from the Gemini CLI source at v0.62.0 (v0.62.0). Official documentation: geminicli.com.

Gemini CLI decides whether a tool call runs, prompts or fails with a policy engine: TOML rules that pair a tool with a decision (allow, deny or ask_user) and a priority, stacked in five tiers from bundled defaults to admin policies. The approval mode selects which rules apply, and an optional sandbox limits what an approved command can reach.

What approval modes does Gemini CLI have?#

--approval-modemodes = [...] in TOMLBehaviorNotes
defaultdefaultprompt for approval—
auto_editautoEditauto-approve edit toolsforced to default in untrusted folders
yoloyoloauto-approve all toolsnot accepted from general.defaultApprovalMode; --yolo and --approval-mode cannot be combined; forced to default in untrusted folders
planplanread-only modefalls back to default when general.plan.enabled is false; forced to default in untrusted folders

The CLI flag and the policy files spell one mode differently: --approval-mode auto_edit on the command line, modes = ["autoEdit"] in TOML. A rule written with modes = ["auto_edit"] fails schema validation and its whole file is skipped. In a session, Shift+Tab cycles default, auto_edit and plan, and Ctrl+Y toggles YOLO; in an untrusted folder only default and plan can be selected. general.defaultApprovalMode sets the starting mode.

FlagTypeDescription
--yolo, -ybooleanAutomatically accept all actions (YOLO mode)?
--approval-modedefault | auto_edit | yolo | planSet the approval mode: default (prompt for approval), auto_edit (auto-approve edit tools), yolo (auto-approve all tools), plan (read-only mode)
--policystring[]Additional policy files or directories to load (comma-separated or multiple --policy)
--admin-policystring[]Additional admin policy files or directories to load (comma-separated or multiple --admin-policy)
--sandbox, -sbooleanRun in sandbox?
--skip-trustbooleanTrust the current workspace for this session.
--allowed-toolsstring[][DEPRECATED: Use Policy Engine instead] Tools that are allowed to run without confirmation
--allowed-mcp-server-namesstring[]Allowed MCP server names

How do I enable YOLO mode in Gemini CLI?#

Start with gemini --yolo (or -y), or gemini --approval-mode=yolo; the two flags cannot be combined. Ctrl+Y switches YOLO on and off inside a running session. YOLO cannot be the saved default: general.defaultApprovalMode accepts only default, auto_edit and plan, and a yolo value there is ignored. security.disableYoloMode or the admin setting secureModeEnabled turns the flag into a startup error and blocks Ctrl+Y, and in an untrusted folder the mode silently drops back to default.

YOLO is not a bypass of the policy engine. It is a bundled rule, toolName = "*", decision = "allow" at priority 1.998, so every user and admin rule still outranks it: a deny in ~/.gemini/policies/ or in tools.exclude keeps blocking in YOLO mode, and the ask_user tool still asks.

What is the Gemini CLI policy engine?#

Every tool call is checked against all loaded rules from the highest effective priority down; the first rule that matches decides. A rule matches when its tool name, MCP server, approval modes, interactive flag, annotations and argument pattern all fit. With no match, interactive sessions ask and headless runs (-p) deny.

# ~/.gemini/policies/shell.toml
[[rule]]
toolName = "run_shell_command"
commandPrefix = ["git status", "git diff", "npm test"]
decision = "allow"
priority = 100

[[rule]]
toolName = "run_shell_command"
commandRegex = "rm -rf .*"
decision = "deny"
priority = 200
denyMessage = "Recursive deletes are blocked by policy."
KeyTypeRequiredMeaning
toolNamestring | string[]yesTool name, list of names, or wildcard (`*`, `mcp_<server>_*`). The old `server__tool` MCP form only draws a deprecation warning; use mcpName.
subagentstringnoOnly matches calls made by this subagent.
mcpNamestringnoMCP server name; `*` matches any MCP tool.
argsPatternstringnoRegex tested against the tool arguments as stable-sorted JSON.
commandPrefixstring | string[]norun_shell_command only: allowed command prefix(es).
commandRegexstringnorun_shell_command only: regex over the command.
decisionallow | deny | ask_useryesallow, deny or ask_user.
priorityinteger 0-999yesEffective priority is tier + priority/1000. A missing or out-of-range value fails schema validation and the whole file is skipped.
modesstring[]noApproval modes the rule applies to (`default`, `autoEdit`, `yolo`, `plan`); omitted means all.
interactivebooleannotrue: interactive sessions only; false: headless only; omitted: both.
toolAnnotationstablenoMatch MCP tool annotations, e.g. `{ readOnlyHint = true }`.
allowRedirectionbooleannoKeep ALLOW for shell commands with redirection (otherwise downgraded to ask_user).
denyMessagestringnoAppended to "Tool execution denied by policy."

commandPrefix and commandRegex work only with toolName = "run_shell_command" (a single name, not a list) and cannot be combined with each other or with argsPattern. A shell command with output redirection is downgraded from allow to ask unless the rule sets allowRedirection = true.

How do policy priority tiers resolve?#

Effective priority = tier + priority/1000, so any admin rule outranks any user rule.
TierNameLoaded from
1defaultpolicies bundled with the CLI (table below)
2extensionpolicies/ directory of each active extension
3workspace<project>/.gemini/policies/*.toml (not loaded in this release: workspace policies are switched off in code)
4user~/.gemini/policies/*.toml, replaced by policyPaths / --policy when set
5admin/Library/Application Support/GeminiCli/policies (macOS), C:\ProgramData\gemini-cli\policies (Windows), /etc/gemini-cli/policies (Linux), plus adminPolicyPaths / --admin-policy (ignored when the system directory already holds .toml files)

Each file's priority (0 to 999) is divided by 1000 and added to its tier, so an admin rule at priority 0 (5.000) beats a user rule at 999 (4.999). Project-level .gemini/policies/ files are not loaded in 0.62.0: the workspace-policy switch in the CLI is off by default and nothing turns it on, so project rules have to go in a user or admin directory. The system directory is also skipped with a "Security Warning" if its permissions are not secure.

Several settings keys become rules in the user tier:

SettingDecisionEffective priority
"Always allow" answer, user scopeallow4.95
mcp.excludeddeny4.9
tools.excludedeny4.4
tools.confirmationRequiredask_user4.35
tools.allowed / --allowed-toolsallow4.3
tools.core (everything else denied)allow4.25
mcpServers.<name>.trust = trueallow4.2
mcp.allowed / --allowed-mcp-server-namesallow4.1
"Always allow" answer, workspace scopeallow3.95

Narrowed entries behave differently from plain names. "tools.allowed": ["run_shell_command(git status)"] allows git status and adds a deny rule just below it, so every other shell command is denied rather than prompted. tools.core works the same way for the whole tool list: anything not named is denied outside plan mode.

Which policy rules ship by default?#

FiletoolNameDecisionPriorityModesConditions
agents.tomlinvoke_agentallow1.050default, autoEdit, yolonone
discovered.tomldiscovered_tool_*ask_user1.010allinteractive only
discovered.tomldiscovered_tool_*deny1.010allheadless only
non-interactive.tomlask_userdeny1.999allheadless only
plan.tomlenter_plan_modeask_user1.050allinteractive only
plan.tomlenter_plan_modeallow1.050allheadless only
plan.tomlenter_plan_modedeny1.070plannone
plan.tomlexit_plan_modeask_user1.070planinteractive only
plan.tomlexit_plan_modeallow1.070planheadless only
plan.tomlexit_plan_modedeny1.050allnone
plan.toml*deny1.040plannone
plan.toml*ask_user1.050planmcpName=*; annotations readOnlyHint=true; interactive only
plan.tomlinvoke_agentallow1.050planargsPattern
plan.tomlask_user, web_fetch, activate_skillask_user1.050planinteractive only
plan.tomlwrite_file, replaceallow1.070planargsPattern
plan.tomlwrite_file, replacedeny1.065plannone
read-only.tomlglob, grep_search, list_directory, read_file, google_web_search, codebase_investigator, cli_help, get_internal_docs, tracker_create_task, tracker_update_task, tracker_get_task, tracker_list_tasks, tracker_add_dependency, tracker_visualize, update_topic, complete_task, read_mcp_resource, list_mcp_resourcesallow1.050allnone
write.tomlreplaceask_user1.010allinteractive only
write.tomlreplaceallow1.015autoEditnone
write.tomlrun_shell_commandask_user1.010allinteractive only
write.tomlwrite_fileask_user1.010allinteractive only
write.tomlactivate_skillask_user1.010allinteractive only
write.tomlwrite_fileallow1.015autoEditnone
write.tomlweb_fetchallow1.015autoEditnone
write.tomlweb_fetchask_user1.010allinteractive only
write.tomlreplace, run_shell_command, write_file, activate_skill, web_fetchdeny1.010allheadless only
yolo.tomlask_userask_user1.999yolointeractive only
yolo.tomlenter_plan_mode, exit_plan_modedeny1.999yolointeractive only
yolo.toml*allow1.998yolonone

Read-only tools are allowed, file writes, shell commands, skills and web fetches ask, autoEdit allows replace, write_file and web_fetch, and headless runs deny anything that would have asked. Plan mode denies everything at 1.040 and then carves out read-only tools, the codebase_investigator and cli_help subagents, prompts for ask_user, web_fetch, activate_skill and read-only MCP tools, and allows writing Markdown plan files.

Why does Gemini CLI say "Tool execution denied by policy"?#

No matching rule: ask_user interactively, deny headless. Rules are checked from highest priority down; the first match wins.
MessageCause
Tool execution denied by policy. <denyMessage>the highest-priority matching rule has decision = "deny"; its denyMessage, if any, is appended
Tool execution for "<tool>" requires user confirmation, which is not supported in non-interactive mode.a rule resolved to ask_user in a headless run (-p)
Tool execution blocked: <reason>a BeforeTool hook returned decision block or deny (hook, not policy)

The denial comes from the highest-priority matching deny rule. Common sources: a deny in ~/.gemini/policies/ or an admin policy, tools.exclude or mcp.excluded in settings, a narrowed tools.allowed entry that denies every other command, tools.core denying unlisted tools, plan mode, or a headless run where a rule would have asked. Set GEMINI_DEBUG_LOG_FILE=/tmp/gemini.log before starting to log every check; the deciding rule appears as [PolicyEngine.check] MATCHED rule.

How does the Gemini CLI sandbox work?#

--sandbox (-s), tools.sandbox in settings or the GEMINI_SANDBOX environment variable runs the CLI inside a sandbox. tools.sandbox also takes an object with enabled, command, image, allowedPaths and networkAccess. Policy decides whether a call runs; the sandbox limits what an allowed call can touch.

Set with --sandbox / -s, tools.sandbox in settings.json, or GEMINI_SANDBOX (true, false or a command name), which takes precedence.
Sandbox commandNotes
dockercontainer; used for sandbox = true when sandbox-exec is unavailable
podmancontainer; used for sandbox = true when neither sandbox-exec nor docker exists
sandbox-execmacOS Seatbelt; the pick for sandbox = true on macOS
runscgVisor; Linux only and needs Docker
lxcLXC container
windows-nativeWindows only

On macOS the default is Seatbelt (sandbox-exec) with the permissive-open profile. Choose another with SEATBELT_PROFILE:

Every shipped profile starts from (deny default). Any other name loads ~/.gemini/sandbox-macos-<name>.sb, else .gemini/sandbox-macos-<name>.sb in the project.
SEATBELT_PROFILEFile readsOutbound networkInbound network
permissive-open (default)anywhereall*:*
permissive-closedno profile file ships in this release——
permissive-proxiedanywhereproxy only (localhost:8877)localhost:9229
restrictive-openanywherealllocalhost:9229
restrictive-closedno profile file ships in this release——
restrictive-proxiedanywhereproxy only (localhost:8877)localhost:9229
strict-openworking directory, system and selected user pathsalllocalhost:9229
strict-proxiedworking directory, system and selected user pathsproxy only (localhost:8877)localhost:9229

What are trusted folders in Gemini CLI?#

Trust decides how much a project may configure Gemini CLI. Until a folder is trusted, its .gemini/settings.json, its hooks and any approval mode other than default are ignored.

ItemRule
File~/.gemini/trustedFolders.json (path override: GEMINI_CLI_TRUSTED_FOLDERS_PATH), a map of path to trust level
Defaultfolder trust is on (security.folderTrust.enabled = true) and a folder with no matching rule counts as untrusted
EnvironmentGEMINI_CLI_TRUST_WORKSPACE=true trusts the workspace and false distrusts it, ahead of the file and the IDE
--skip-trustsets GEMINI_CLI_TRUST_WORKSPACE=true for the session
Untrusted folderworkspace .gemini/settings.json is ignored, hooks from settings.json do not run, and the approval mode is forced to default
When several rules cover a path, the rule with the longest path wins.
Value in trustedFolders.jsonMeaning
TRUST_FOLDERthe folder and everything under it is trusted
TRUST_PARENTthe folder's parent and everything under it is trusted
DO_NOT_TRUSTthe folder and everything under it is untrusted

Security settings#

KeyTypeDefaultDescription
general.defaultApprovalModedefault | auto_edit | plan"default"The default approval mode for tool execution. 'default' prompts for approval, 'auto_edit' auto-approves edit tools, and 'plan' is read-only mode. YOLO mode (auto-approve all actions) can only be enabled via command line (--yolo or --approval-mode=yolo).
security.toolSandboxingbooleanfalseTool-level sandboxing. Isolates individual tools instead of the entire CLI process.
security.disableYoloModebooleanfalseDisable YOLO mode, even if enabled by a flag.
security.disableAlwaysAllowbooleanfalseDisable "Always allow" options in tool confirmation dialogs.
security.enablePermanentToolApprovalbooleanfalseEnable the "Allow for all future sessions" option in tool confirmation dialogs.
security.autoAddToPolicyByDefaultbooleanfalseWhen enabled, the "Allow for all future sessions" option becomes the default choice for low-risk tools in trusted workspaces.
security.enableConsecabooleanfalseEnable the context-aware security checker. This feature uses an LLM to dynamically generate and enforce security policies for tool use based on your prompt, providing an additional layer of protection against unintended actions.
admin.secureModeEnabledbooleanfalseIf true, disallows YOLO mode and "Always allow" options from being used.

Frequently asked questions#

What is the Gemini CLI policy engine?#

The component that decides whether each tool call is allowed, denied or needs confirmation. Rules live in TOML files with toolName, decision and priority, plus optional matchers for MCP server, arguments, shell command prefix, approval mode and interactivity. Rules are layered in default, extension, workspace, user and admin tiers, and the highest-priority match wins.

Is there a Gemini CLI equivalent of --dangerously-skip-permissions?#

Yes: gemini --yolo or gemini --approval-mode=yolo. It adds an allow-everything rule near the top of the default tier, so it approves any call your own rules do not deny. It cannot be set as the default in settings.json, is refused when security.disableYoloMode is on, and is dropped to default in untrusted folders.

How do I auto-approve only specific shell commands in Gemini CLI?#

Add a rule in ~/.gemini/policies/ with toolName = "run_shell_command", commandPrefix = ["git status", "npm test"], decision = "allow" and a priority. Other shell commands keep asking. Listing run_shell_command(git status) in tools.allowed also works but denies every other shell command instead of asking, and --allowed-tools is deprecated.

Why does Gemini CLI say "Tool execution denied by policy"?#

A matching rule with decision = "deny" outranked every allow rule for that call, and any denyMessage is appended to the error. Check ~/.gemini/policies/ and admin policies, tools.exclude, mcp.excluded, a narrowed tools.allowed or tools.core list, plan mode, and headless runs, where calls that would ask are denied. GEMINI_DEBUG_LOG_FILE logs the matching rule.

How do Gemini CLI policy priority tiers work?#

Five tiers: default (1), extension (2), workspace (3), user (4) and admin (5). A rule's effective priority is its tier plus priority / 1000, so any admin rule beats any user rule, which beats extension and default rules. Settings such as tools.exclude become user-tier rules; "Always allow" answers land at 4.95 or 3.95.

What approval modes does Gemini CLI have?#

Four: default prompts for writes and shell commands, auto_edit also approves file edits, plan is read-only apart from writing plan files, and yolo approves everything your rules do not deny. Select one with --approval-mode, Shift+Tab or Ctrl+Y. In TOML policy files auto_edit is spelled autoEdit.

Why do my .gemini/policies files in the project do nothing?#

Gemini CLI 0.62.0 does not load workspace policy files. The CLI keeps workspace policies switched off by default and no command or setting turns them on, so rules in a project's .gemini/policies/ are ignored. Put them in ~/.gemini/policies/, pass them with --policy, or list their paths in policyPaths.

Sources

Release-by-release changes: Gemini CLI version tracker. All Gemini CLI pages: Gemini CLI reference index.