Skip to main content
CodeMode gives the model an exec tool that runs a JavaScript program. Inside the program, o4’s other tools are functions, so the model can make many tool calls in one step: read ten files, filter the results, and return only what matters. This saves turns and keeps large intermediate results out of the conversation. CodeMode is experimental and off by default.
Every tool call a program makes goes through the same checks as a direct call from the model: your approval mode, permission rules, hooks and the sandbox all still apply. The program itself has no file, network or shell access; it can only act through o4’s tools.

Turn it on

Add this to ~/.o4/config.toml, or to ~/.o4/managed/config.toml:
o4 reads this when it starts, so restart o4 afterwards. A key in the managed file wins over the same key in your own file. o4 ignores a [codemode] section in a project’s .o4/config.toml or .o4/config.local.toml, even in a trusted workspace, so a repository can’t turn it on for you. It logs a codemode_project_config_ignored warning when it does. When it’s on, the main agent gets exec in interactive sessions and in print mode (o4 -p). Subagents and campaign workers don’t get it. o4 also only offers exec with these providers: With any other provider, including Amazon Bedrock and OpenAI-compatible endpoints, the model doesn’t get exec, and o4 logs codemode_provider_unsupported to ~/.o4/o4.log.

What a program looks like

The model writes the program; you don’t need to. A program runs as an async JavaScript module, so it can use await:
Each tool call returns an object with ok, the tool’s text output, details, and an error when ok is false. A program can use: There’s no console, import, eval, Date, setInterval, file system or network access in a program. These tools can’t be called from a program, only directly by the model: enter_plan_mode, exit_plan_mode, enter_worktree, exit_worktree, ask_user_question, undo and checkpoint_restore. A program can’t call exec or wait either. Every other tool in the session is callable from a program. The [codemode] key direct_only_tools is meant to keep more tools out, but it has no effect in 0.2.74: o4 drops the list while loading the config. To keep a tool away from programs, block it with a deny permission rule, which applies inside programs too. In the interactive UI you can also leave it out of the session with disabled_tools in the project’s [scout] section.

Approvals

The exec call itself doesn’t ask for approval, because turning CodeMode on is your approval to run programs. Each tool call inside a program asks just as it would if the model called the tool directly. If you deny a call, that call’s result comes back with ok: false and an error, and the program can carry on or stop. The program’s time limit keeps running while o4 waits for your answer. In print mode nobody can answer, so a call that would ask is refused and the program gets an error. In plan mode, a program can only call the tools plan mode allows.

Options

The other keys set limits: program size, run time, memory, and the number, concurrency and size of tool calls. A program runs for up to 30 seconds by default. wall_time_ms can raise that to 120 seconds, but o4 also stops a program 2 seconds before its 120-second tool timeout, so the real maximum is 118 seconds. Each limit has a built-in ceiling, and a value of 0 or above the ceiling is replaced with the default. See the configuration reference for every key, default and maximum. Two keys have no effect in 0.2.74: direct_only_tools (see above) and max_return_bytes, which o4 checks but never applies.