mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
1822ffe870e65da2b3fc596bc75296dc5acf8422
33 Commits
-
codex-exec: allow resume --last to read prompt #6717 (#6719)
### Description - codex exec --json resume --last "<prompt>" bailed out because clap treated the prompt as SESSION_ID. I removed the conflicts_with flag and reinterpret that positional as a prompt when --last is set, so the flow now keeps working in JSON mode. (codex-rs/exec/src/cli.rs:84-104, codex-rs/exec/src/lib.rs:75-130) - Added a regression test that exercises resume --last in JSON mode to ensure the prompt is accepted and the rollout file is updated. (codex-rs/exec/tests/suite/resume.rs:126-178) ### Testing - just fmt - cargo test -p codex-exec - just fix -p codex-exec - cargo test -p codex-exec #6717 Signed-off-by: Dmitri Khokhlov <dkhokhlov@cribl.io>
Dmitri Khokhlov ·
2025-11-20 13:10:49 -08:00 -
LM Studio OSS Support (#2312)
## Overview Adds LM Studio OSS support. Closes #1883 ### Changes This PR enhances the behavior of `--oss` flag to support LM Studio as a provider. Additionally, it introduces a new flag`--local-provider` which can take in `lmstudio` or `ollama` as values if the user wants to explicitly choose which one to use. If no provider is specified `codex --oss` will auto-select the provider based on whichever is running. #### Additional enhancements The default can be set using `oss-provider` in config like: ``` oss_provider = "lmstudio" ``` For non-interactive users, they will need to either provide the provider as an arg or have it in their `config.toml` ### Notes For best performance, [set the default context length](https://lmstudio.ai/docs/app/advanced/per-model) for gpt-oss to the maximum your machine can support --------- Co-authored-by: Matt Clayton <matt@lmstudio.ai> Co-authored-by: Eric Traut <etraut@openai.com>
rugvedS07 ·
2025-11-17 11:49:09 -08:00 -
feat: Add support for --add-dir to exec and TypeScript SDK (#6565)
## Summary Adds support for specifying additional directories in the TypeScript SDK through a new `additionalDirectories` option in `ThreadOptions`. ## Changes - Added `additionalDirectories` parameter to `ThreadOptions` interface - Updated `CodexExec` to accept and pass through additional directories via the `--config` flag for `sandbox_workspace_write.writable_roots` - Added comprehensive test coverage for the new functionality ## Test plan - Added test case that verifies `additionalDirectories` is correctly passed as repeated flags - Existing tests continue to pass --------- Co-authored-by: Claude <noreply@anthropic.com>
Dan Hernandez ·
2025-11-13 13:47:10 -08:00 -
Update full-auto description with on-request (#6523)
This PR fixes #6522 by correcting the comment for `full-auto` in both `codex-rs/exec/src/cli.rs` and `codex-rs/tui/src/cli.rs` from `-a on-failure` to `-a on-request` to make it coherent with `codex-rs/tui/src/lib.rs:97-105`: ```rust pub async fn run_main( mut cli: Cli, codex_linux_sandbox_exe: Option<PathBuf>, ) -> std::io::Result<AppExitInfo> { let (sandbox_mode, approval_policy) = if cli.full_auto { ( Some(SandboxMode::WorkspaceWrite), Some(AskForApproval::OnRequest), ) ``` Running `just codex --help` or `just codex exec --help` should now yield the correct description of `full-auto` CLI argument. Signed-off-by: lionelchg <lionel.cheng@hotmail.fr>
Lionel Cheng ·
2025-11-11 15:59:20 -08:00 -
Enable plan tool by default (#5384)
## Summary - make the plan tool available by default by removing the feature flag and always registering the handler - drop plan-tool CLI and API toggles across the exec, TUI, MCP server, and app server code paths - update tests and configs to reflect the always-on plan tool and guard workspace restriction tests against env leakage ## Testing Manually tested the extension. ------ https://chatgpt.com/codex/tasks/task_i_68f67a3ff2d083209562a773f814c1f9
pakrym-oai ·
2025-10-21 16:25:05 +00:00 -
pakrym-oai ·
2025-10-20 11:05:55 -07:00 -
cli: fix zsh completion (#4692)
Before this change: ``` tamird@L03G26TD12 codex-rs % codex zsh: do you wish to see all 3864 possibilities (1285 lines)? ``` After this change: ``` tamird@L03G26TD12 codex-rs % codex app-server -- [experimental] Run the app server apply a -- Apply the latest diff produced by Codex agent as a `git apply` to your local working tree cloud -- [EXPERIMENTAL] Browse tasks from Codex Cloud and apply changes locally completion -- Generate shell completion scripts debug -- Internal debugging commands exec e -- Run Codex non-interactively generate-ts -- Internal: generate TypeScript protocol bindings help -- Print this message or the help of the given subcommand(s) login -- Manage login logout -- Remove stored authentication credentials mcp -- [experimental] Run Codex as an MCP server and manage MCP servers mcp-server -- [experimental] Run the Codex MCP server (stdio transport) responses-api-proxy -- Internal: run the responses API proxy resume -- Resume a previous interactive session (picker by default; use --last to continue the most recent) ```
Tamir Duberstein ·
2025-10-07 08:07:31 -07:00 -
feat:
codex execwrites only the final message to stdout (#4644)This updates `codex exec` so that, by default, most of the agent's activity is written to stderr so that only the final agent message is written to stdout. This makes it easier to pipe `codex exec` into another tool without extra filtering. I introduced `#![deny(clippy::print_stdout)]` to help enforce this change and renamed the `ts_println!()` macro to `ts_msg()` because (1) it no longer calls `println!()` and (2), `ts_eprintln!()` seemed too long of a name. While here, this also adds `-o` as an alias for `--output-last-message`. Fixes https://github.com/openai/codex/issues/1670
Michael Bolin ·
2025-10-03 16:22:12 +00:00 -
Remove legacy codex exec --json format (#4525)
`codex exec --json` now maps to the behavior of `codex exec --experimental-json` with new event and item shapes. Thread events: - thread.started - turn.started - turn.completed - turn.failed - item.started - item.updated - item.completed Item types: - assistant_message - reasoning - command_execution - file_change - mcp_tool_call - web_search - todo_list - error Sample output: <details> `codex exec "list my assigned github issues" --json | jq` ``` { "type": "thread.started", "thread_id": "01999ce5-f229-7661-8570-53312bd47ea3" } { "type": "turn.started" } { "type": "item.completed", "item": { "id": "item_0", "item_type": "reasoning", "text": "**Planning to list assigned GitHub issues**" } } { "type": "item.started", "item": { "id": "item_1", "item_type": "mcp_tool_call", "server": "github", "tool": "search_issues", "status": "in_progress" } } { "type": "item.completed", "item": { "id": "item_1", "item_type": "mcp_tool_call", "server": "github", "tool": "search_issues", "status": "completed" } } { "type": "item.completed", "item": { "id": "item_2", "item_type": "reasoning", "text": "**Organizing final message structure**" } } { "type": "item.completed", "item": { "id": "item_3", "item_type": "assistant_message", "text": "**Assigned Issues**\n- openai/codex#3267 – “stream error: stream disconnected before completion…” (bug) – last update 2025-09-08\n- openai/codex#3257 – “You've hit your usage limit. Try again in 4 days 20 hours 9 minutes.” – last update 2025-09-23\n- openai/codex#3054 – “reqwest SSL panic (library has no ciphers)” (bug) – last update 2025-09-03\n- openai/codex#3051 – “thread 'main' panicked at linux-sandbox/src/linux_run_main.rs:53:5:” (bug) – last update 2025-09-10\n- openai/codex#3004 – “Auto-compact when approaching context limit” (enhancement) – last update 2025-09-26\n- openai/codex#2916 – “Feature request: Add OpenAI service tier support for cost optimization” – last update 2025-09-12\n- openai/codex#1581 – “stream error: stream disconnected before completion: stream closed before response.complete; retrying...” (bug) – last update 2025-09-17" } } { "type": "turn.completed", "usage": { "input_tokens": 34785, "cached_input_tokens": 12544, "output_tokens": 560 } } ``` </details>pakrym-oai ·
2025-09-30 17:21:37 -07:00 -
Add explicit codex exec events (#4177)
This pull request add a new experimental format of JSON output. You can try it using `codex exec --experimental-json`. Design takes a lot of inspiration from Responses API items and stream format. # Session and items Each invocation of `codex exec` starts or resumes a session. Session contains multiple high-level item types: 1. Assistant message 2. Assistant thinking 3. Command execution 4. File changes 5. To-do lists 6. etc. # Events Session and items are going through their life cycles which is represented by events. Session is `session.created` or `session.resumed` Items are `item.added`, `item.updated`, `item.completed`, `item.require_approval` (or other item types like `item.output_delta` when we need streaming). So a typical session can look like: <details> ``` { "type": "session.created", "session_id": "01997dac-9581-7de3-b6a0-1df8256f2752" } { "type": "item.completed", "item": { "id": "itm_0", "item_type": "assistant_message", "text": "I’ll locate the top-level README and remove its first line. Then I’ll show a quick summary of what changed." } } { "type": "item.completed", "item": { "id": "itm_1", "item_type": "command_execution", "command": "bash -lc ls -la | sed -n '1,200p'", "aggregated_output": "pyenv: cannot rehash: /Users/pakrym/.pyenv/shims isn't writable\ntotal 192\ndrwxr-xr-x@ 33 pakrym staff 1056 Sep 24 14:36 .\ndrwxr-xr-x 41 pakrym staff 1312 Sep 24 09:17 ..\n-rw-r--r--@ 1 pakrym staff 6 Jul 9 16:16 .codespellignore\n-rw-r--r--@ 1 pakrym staff 258 Aug 13 09:40 .codespellrc\ndrwxr-xr-x@ 5 pakrym staff 160 Jul 23 08:26 .devcontainer\n-rw-r--r--@ 1 pakrym staff 6148 Jul 22 10:03 .DS_Store\ndrwxr-xr-x@ 15 pakrym staff 480 Sep 24 14:38 .git\ndrwxr-xr-x@ 12 pakrym staff 384 Sep 2 16:00 .github\n-rw-r--r--@ 1 pakrym staff 778 Jul 9 16:16 .gitignore\ndrwxr-xr-x@ 3 pakrym staff 96 Aug 11 09:37 .husky\n-rw-r--r--@ 1 pakrym staff 104 Jul 9 16:16 .npmrc\n-rw-r--r--@ 1 pakrym staff 96 Sep 2 08:52 .prettierignore\n-rw-r--r--@ 1 pakrym staff 170 Jul 9 16:16 .prettierrc.toml\ndrwxr-xr-x@ 5 pakrym staff 160 Sep 14 17:43 .vscode\ndrwxr-xr-x@ 2 pakrym staff 64 Sep 11 11:37 2025-09-11\n-rw-r--r--@ 1 pakrym staff 5505 Sep 18 09:28 AGENTS.md\n-rw-r--r--@ 1 pakrym staff 92 Sep 2 08:52 CHANGELOG.md\n-rw-r--r--@ 1 pakrym staff 1145 Jul 9 16:16 cliff.toml\ndrwxr-xr-x@ 11 pakrym staff 352 Sep 24 13:03 codex-cli\ndrwxr-xr-x@ 38 pakrym staff 1216 Sep 24 14:38 codex-rs\ndrwxr-xr-x@ 18 pakrym staff 576 Sep 23 11:01 docs\n-rw-r--r--@ 1 pakrym staff 2038 Jul 9 16:16 flake.lock\n-rw-r--r--@ 1 pakrym staff 1434 Jul 9 16:16 flake.nix\n-rw-r--r--@ 1 pakrym staff 10926 Jul 9 16:16 LICENSE\ndrwxr-xr-x@ 465 pakrym staff 14880 Jul 15 07:36 node_modules\n-rw-r--r--@ 1 pakrym staff 242 Aug 5 08:25 NOTICE\n-rw-r--r--@ 1 pakrym staff 578 Aug 14 12:31 package.json\n-rw-r--r--@ 1 pakrym staff 498 Aug 11 09:37 pnpm-lock.yaml\n-rw-r--r--@ 1 pakrym staff 58 Aug 11 09:37 pnpm-workspace.yaml\n-rw-r--r--@ 1 pakrym staff 2402 Jul 9 16:16 PNPM.md\n-rw-r--r--@ 1 pakrym staff 4393 Sep 12 14:36 README.md\ndrwxr-xr-x@ 4 pakrym staff 128 Sep 18 09:28 scripts\ndrwxr-xr-x@ 2 pakrym staff 64 Sep 11 11:34 tmp\n", "exit_code": 0, "status": "completed" } } { "type": "item.completed", "item": { "id": "itm_2", "item_type": "reasoning", "text": "**Reviewing README.md file**\n\nI've located the README.md file at the root, and it’s 4393 bytes. Now, I need to remove the first line, but first, I should check its content to make sure I’m patching it correctly. I’ll use sed to display the first 20 lines. By reviewing those lines, I can determine exactly what needs to be removed before I proceed with the editing. Let's do this carefully!" } } { "type": "item.completed", "item": { "id": "itm_3", "item_type": "command_execution", "command": "bash -lc sed -n '1,40p' README.md", "aggregated_output": "<h1 align=\"center\">OpenAI Codex CLI</h1>\n\n<p align=\"center\"><code>npm i -g @openai/codex</code><br />or <code>brew install codex</code></p>\n\n<p align=\"center\"><strong>Codex CLI</strong> is a coding agent from OpenAI that runs locally on your computer.\n</br>\n</br>If you want Codex in your code editor (VS Code, Cursor, Windsurf), <a href=\"https://developers.openai.com/codex/ide\">install in your IDE</a>\n</br>If you are looking for the <em>cloud-based agent</em> from OpenAI, <strong>Codex Web</strong>, go to <a href=\"https://chatgpt.com/codex\">chatgpt.com/codex</a></p>\n\n<p align=\"center\">\n <img src=\"./.github/codex-cli-splash.png\" alt=\"Codex CLI splash\" width=\"80%\" />\n </p>\n\n---\n\n## Quickstart\n\n### Installing and running Codex CLI\n\nInstall globally with your preferred package manager. If you use npm:\n\n```shell\nnpm install -g @openai/codex\n```\n\nAlternatively, if you use Homebrew:\n\n```shell\nbrew install codex\n```\n\nThen simply run `codex` to get started:\n\n```shell\ncodex\n```\n\n<details>\n<summary>You can also go to the <a href=\"https://github.com/openai/codex/releases/latest\">latest GitHub Release</a> and download the appropriate binary for your platform.</summary>\n\n", "exit_code": 0, "status": "completed" } } { "type": "item.completed", "item": { "id": "itm_4", "item_type": "reasoning", "text": "**Updating README file**\n\nThe user wants to update the README by removing the first line, which is an HTML h1 tag. I'll proceed to delete that line while keeping the rest intact. To do this, I need to use the apply_patch tool and create a patch in the diff format. I’ll take care to include context lines around the change. After removing the header, I’m considering whether to delete the following blank line as well to keep it tidy." } } { "type": "item.completed", "item": { "id": "itm_5", "item_type": "reasoning", "text": "**Crafting the patch**\n\nThe user has asked to remove just the first line, without mentioning the blank lines. Technically, leaving a blank line at the start is acceptable, but it's not ideal. Ideally, I'd prefer to remove the first line while maintaining the subsequent blank line. However, if I can also remove that blank line, it could tidy things up even more. Still, since the user's request is strictly to remove only the first line, I'll stick to that and craft the patch accordingly." } } { "type": "item.completed", "item": { "id": "itm_6", "item_type": "assistant_message", "text": "Applying the change by removing the first line from `README.md`." } } { "type": "item.completed", "item": { "id": "itm_7", "item_type": "file_change", "changes": [ { "path": "/Users/pakrym/code/codex/README.md", "kind": "update" } ], "status": "completed" } } { "type": "item.completed", "item": { "id": "itm_8", "item_type": "reasoning", "text": "**Validating README Update**\n\nI updated the README.md and now I need to validate that the first line has been successfully removed. To do this, I'll check the first 10 lines of the document to ensure everything looks correct. It’s always good to double-check these kinds of changes, so I’m going to take that extra step to make sure the update was executed properly. Let's see what those initial lines say!" } } { "type": "item.completed", "item": { "id": "itm_9", "item_type": "command_execution", "command": "bash -lc sed -n '1,20p' README.md", "aggregated_output": "\n<p align=\"center\"><code>npm i -g @openai/codex</code><br />or <code>brew install codex</code></p>\n\n<p align=\"center\"><strong>Codex CLI</strong> is a coding agent from OpenAI that runs locally on your computer.\n</br>\n</br>If you want Codex in your code editor (VS Code, Cursor, Windsurf), <a href=\"https://developers.openai.com/codex/ide\">install in your IDE</a>\n</br>If you are looking for the <em>cloud-based agent</em> from OpenAI, <strong>Codex Web</strong>, go to <a href=\"https://chatgpt.com/codex\">chatgpt.com/codex</a></p>\n\n<p align=\"center\">\n <img src=\"./.github/codex-cli-splash.png\" alt=\"Codex CLI splash\" width=\"80%\" />\n </p>\n\n---\n\n## Quickstart\n\n### Installing and running Codex CLI\n\nInstall globally with your preferred package manager. If you use npm:\n\n", "exit_code": 0, "status": "completed" } } { "type": "item.completed", "item": { "id": "itm_10", "item_type": "assistant_message", "text": "- Updated `README.md:1` by removing the opening H1 line.\n- The README now starts with the install instructions paragraph.\n\nWant me to also remove the leading blank line at the top?" } } ``` </details> The idea is to give users fully formatted items they can use directly in their rendering/application logic and avoid having them building up items manually based on events (unless they want to for streaming). This PR implements only the `item.completed` payload for some event types, more event types and item types to come. --------- Co-authored-by: Michael Bolin <mbolin@openai.com>pakrym-oai ·
2025-09-25 17:47:09 +00:00 -
[exec] add include-plan-tool flag and print it nicely (#3461)
### Summary Sometimes in exec runs, we want to allow the model to use the `update_plan` tool, but that's not easily configurable. This change adds a feature flag for this, and formats the output so it's human-readable ## Test Plan <img width="1280" height="354" alt="Screenshot 2025-09-11 at 12 39 44 AM" src="https://github.com/user-attachments/assets/72e11070-fb98-47f5-a784-5123ca7333d9" />
Dylan ·
2025-09-23 16:50:59 -07:00 -
Add exec output-schema parameter (#4079)
Adds structured output to `exec` via the `--structured-output` parameter.
pakrym-oai ·
2025-09-23 13:59:16 -07:00 -
enable-resume (#3537)
Adding the ability to resume conversations. we have one verb `resume`. Behavior: `tui`: `codex resume`: opens session picker `codex resume --last`: continue last message `codex resume <session id>`: continue conversation with `session id` `exec`: `codex resume --last`: continue last conversation `codex resume <session id>`: continue conversation with `session id` Implementation: - I added a function to find the path in `~/.codex/sessions/` with a `UUID`. This is helpful in resuming with session id. - Added the above mentioned flags - Added lots of testing
Ahmed Ibrahim ·
2025-09-14 19:33:19 -04:00 -
[exec] Fix exec sandbox arg (#2034)
## Summary From codex-cli 😁 `-s/--sandbox` now correctly affects sandbox mode. What changed - In `codex-rs/exec/src/cli.rs`: - Added `value_enum` to the `--sandbox` flag so Clap parses enum values into ` SandboxModeCliArg`. - This ensures values like `-s read-only`, `-s workspace-write`, and `-s dange r-full-access` are recognized and propagated. Why this fixes it - The enum already derives `ValueEnum`, but without `#[arg(value_enum)]` Clap ma y not map the string into the enum, leaving the option ineffective at runtime. W ith `value_enum`, `sandbox_mode` is parsed and then converted to `SandboxMode` i n `run_main`, which feeds into `ConfigOverrides` and ultimately into the effecti ve `sandbox_policy`.Dylan ·
2025-08-08 18:19:40 -07:00 -
ae ·
2025-08-06 22:54:54 -07:00 -
Introduce
--ossflag to use gpt-oss models (#1848)This adds support for easily running Codex backed by a local Ollama instance running our new open source models. See https://github.com/openai/gpt-oss for details. If you pass in `--oss` you'll be prompted to install/launch ollama, and it will automatically download the 20b model and attempt to use it. We'll likely want to expand this with some options later to make the experience smoother for users who can't run the 20b or want to run the 120b. Co-authored-by: Michael Bolin <mbolin@openai.com>
easong-openai ·
2025-08-05 11:31:11 -07:00 -
feat: add --json flag to
codex exec(#1603)This is designed to facilitate programmatic use of Codex in a more lightweight way than using `codex mcp`. Passing `--json` to `codex exec` will print each event as a line of JSON to stdout. Note that it does not print the individual tokens as they are streamed, only full messages, as this is aimed at programmatic use rather than to power UI. <img width="1348" height="1307" alt="image" src="https://github.com/user-attachments/assets/fc7908de-b78d-46e4-a6ff-c85de28415c7" /> I changed the existing `EventProcessor` into a trait and moved the implementation to `EventProcessorWithHumanOutput`. Then I introduced an alternative implementation, `EventProcessorWithJsonOutput`. The `--json` flag determines which implementation to use.
Michael Bolin ·
2025-07-17 15:10:15 -07:00 -
feat: add support for --sandbox flag (#1476)
On a high-level, we try to design `config.toml` so that you don't have to "comment out a lot of stuff" when testing different options. Previously, defining a sandbox policy was somewhat at odds with this principle because you would define the policy as attributes of `[sandbox]` like so: ```toml [sandbox] mode = "workspace-write" writable_roots = [ "/tmp" ] ``` but if you wanted to temporarily change to a read-only sandbox, you might feel compelled to modify your file to be: ```toml [sandbox] mode = "read-only" # mode = "workspace-write" # writable_roots = [ "/tmp" ] ``` Technically, commenting out `writable_roots` would not be strictly necessary, as `mode = "read-only"` would ignore `writable_roots`, but it's still a reasonable thing to do to keep things tidy. Currently, the various values for `mode` do not support that many attributes, so this is not that hard to maintain, but one could imagine this becoming more complex in the future. In this PR, we change Codex CLI so that it no longer recognizes `[sandbox]`. Instead, it introduces a top-level option, `sandbox_mode`, and `[sandbox_workspace_write]` is used to further configure the sandbox when when `sandbox_mode = "workspace-write"` is used: ```toml sandbox_mode = "workspace-write" [sandbox_workspace_write] writable_roots = [ "/tmp" ] ``` This feels a bit more future-proof in that it is less tedious to configure different sandboxes: ```toml sandbox_mode = "workspace-write" [sandbox_read_only] # read-only options here... [sandbox_workspace_write] writable_roots = [ "/tmp" ] [sandbox_danger_full_access] # danger-full-access options here... ``` In this scheme, you never need to comment out the configuration for an individual sandbox type: you only need to redefine `sandbox_mode`. Relatedly, previous to this change, a user had to do `-c sandbox.mode=read-only` to change the mode on the command line. With this change, things are arguably a bit cleaner because the equivalent option is `-c sandbox_mode=read-only` (and now `-c sandbox_workspace_write=...` can be set separately). Though more importantly, we introduce the `-s/--sandbox` option to the CLI, which maps directly to `sandbox_mode` in `config.toml`, making config override behavior easier to reason about. Moreover, as you can see in the updates to the various Markdown files, it is much easier to explain how to configure sandboxing when things like `--sandbox read-only` can be used as an example. Relatedly, this cleanup also made it straightforward to add support for a `sandbox` option for Codex when used as an MCP server (see the changes to `mcp-server/src/codex_tool_config.rs`). Fixes https://github.com/openai/codex/issues/1248.
Michael Bolin ·
2025-07-07 22:31:30 -07:00 -
feat: add --dangerously-bypass-approvals-and-sandbox (#1384)
This PR reworks `assess_command_safety()` so that the combination of `AskForApproval::Never` and `SandboxPolicy::DangerFullAccess` ensures that commands are run without _any_ sandbox and the user should never be prompted. In turn, it adds support for a new `--dangerously-bypass-approvals-and-sandbox` flag (that cannot be used with `--approval-policy` or `--full-auto`) that sets both of those options. Fixes https://github.com/openai/codex/issues/1254
Michael Bolin ·
2025-06-25 12:36:10 -07:00 -
chore: improve docstring for --full-auto (#1379)
Reference `-c sandbox.mode=workspace-write` in the docstring and users can read the config docs for `sandbox` for more information.
Michael Bolin ·
2025-06-25 09:13:36 -07:00 -
feat: redesign sandbox config (#1373)
This is a major redesign of how sandbox configuration works and aims to fix https://github.com/openai/codex/issues/1248. Specifically, it replaces `sandbox_permissions` in `config.toml` (and the `-s`/`--sandbox-permission` CLI flags) with a "table" with effectively three variants: ```toml # Safest option: full disk is read-only, but writes and network access are disallowed. [sandbox] mode = "read-only" # The cwd of the Codex task is writable, as well as $TMPDIR on macOS. # writable_roots can be used to specify additional writable folders. [sandbox] mode = "workspace-write" writable_roots = [] # Optional, defaults to the empty list. network_access = false # Optional, defaults to false. # Disable sandboxing: use at your own risk!!! [sandbox] mode = "danger-full-access" ``` This should make sandboxing easier to reason about. While we have dropped support for `-s`, the way it works now is: - no flags => `read-only` - `--full-auto` => `workspace-write` - currently, there is no way to specify `danger-full-access` via a CLI flag, but we will revisit that as part of https://github.com/openai/codex/issues/1254 Outstanding issue: - As noted in the `TODO` on `SandboxPolicy::is_unrestricted()`, we are still conflating sandbox preferences with approval preferences in that case, which needs to be cleaned up.
Michael Bolin ·
2025-06-24 16:59:47 -07:00 -
feat: for
codex exec, if PROMPT is not specified, read from stdin if not a TTY (#1178)This attempts to make `codex exec` more flexible in how the prompt can be passed: * as before, it can be passed as a single string argument * if `-` is passed as the value, the prompt is read from stdin * if no argument is passed _and stdin is a tty_, prints a warning to stderr that no prompt was specified an exits non-zero. * if no argument is passed _and stdin is NOT a tty_, prints `Reading prompt from stdin...` to stderr to let the user know that Codex will wait until it reads EOF from stdin to proceed. (You can repro this case by doing `yes | just exec` since stdin is not a TTY in that case but it also never reaches EOF).
Michael Bolin ·
2025-05-30 14:41:55 -07:00 -
feat: add support for -c/--config to override individual config items (#1137)
This PR introduces support for `-c`/`--config` so users can override individual config values on the command line using `--config name=value`. Example: ``` codex --config model=o4-mini ``` Making it possible to set arbitrary config values on the command line results in a more flexible configuration scheme and makes it easier to provide single-line examples that can be copy-pasted from documentation. Effectively, it means there are four levels of configuration for some values: - Default value (e.g., `model` currently defaults to `o4-mini`) - Value in `config.toml` (e.g., user could override the default to be `model = "o3"` in their `config.toml`) - Specifying `-c` or `--config` to override `model` (e.g., user can include `-c model=o3` in their list of args to Codex) - If available, a config-specific flag can be used, which takes precedence over `-c` (e.g., user can specify `--model o3` in their list of args to Codex) Now that it is possible to specify anything that could be configured in `config.toml` on the command line using `-c`, we do not need to have a custom flag for every possible config option (which can clutter the output of `--help`). To that end, as part of this PR, we drop support for the `--disable-response-storage` flag, as users can now specify `-c disable_response_storage=true` to get the equivalent functionality. Under the hood, this works by loading the `config.toml` into a `toml::Value`. Then for each `key=value`, we create a small synthetic TOML file with `value` so that we can run the TOML parser to get the equivalent `toml::Value`. We then parse `key` to determine the point in the original `toml::Value` to do the insert/replace. Once all of the overrides from `-c` args have been applied, the `toml::Value` is deserialized into a `ConfigToml` and then the `ConfigOverrides` are applied, as before.
Michael Bolin ·
2025-05-27 23:11:44 -07:00 -
feat: experimental --output-last-message flag to exec subcommand (#1037)
This introduces an experimental `--output-last-message` flag that can be used to identify a file where the final message from the agent will be written. Two use cases: - Ultimately, we will likely add a `--quiet` option to `exec`, but even if the user does not want any output written to the terminal, they probably want to know what the agent did. Writing the output to a file makes it possible to get that information in a clean way. - Relatedly, when using `exec` in CI, it is easier to review the transcript written "normally," (i.e., not as JSON or something with extra escapes), but getting programmatic access to the last message is likely helpful, so writing the last message to a file gets the best of both worlds. I am calling this "experimental" because it is possible that we are overfitting and will want a more general solution to this problem that would justify removing this flag.
Michael Bolin ·
2025-05-19 16:08:18 -07:00 -
feat: introduce --profile for Rust CLI (#921)
This introduces a much-needed "profile" concept where users can specify a collection of options under one name and then pass that via `--profile` to the CLI. This PR introduces the `ConfigProfile` struct and makes it a field of `CargoToml`. It further updates `Config::load_from_base_config_with_overrides()` to respect `ConfigProfile`, overriding default values where appropriate. A detailed unit test is added at the end of `config.rs` to verify this behavior. Details on how to use this feature have also been added to `codex-rs/README.md`.
Michael Bolin ·
2025-05-13 16:52:52 -07:00 -
chore: introduce codex-common crate (#843)
I started this PR because I wanted to share the `format_duration()` utility function in `codex-rs/exec/src/event_processor.rs` with the TUI. The question was: where to put it? `core` should have as few dependencies as possible, so moving it there would introduce a dependency on `chrono`, which seemed undesirable. `core` already had this `cli` feature to deal with a similar situation around sharing common utility functions, so I decided to: * make `core` feature-free * introduce `common` * `common` can have as many "special interest" features as it needs, each of which can declare their own deps * the first two features of common are `cli` and `elapsed` In practice, this meant updating a number of `Cargo.toml` files, replacing this line: ```toml codex-core = { path = "../core", features = ["cli"] } ``` with these: ```toml codex-core = { path = "../core" } codex-common = { path = "../common", features = ["cli"] } ``` Moving `format_duration()` into its own file gave it some "breathing room" to add a unit test, so I had Codex generate some tests and new support for durations over 1 minute.Michael Bolin ·
2025-05-06 17:38:56 -07:00 -
feat: make cwd a required field of Config so we stop assuming std::env::current_dir() in a session (#800)
In order to expose Codex via an MCP server, I realized that we should be taking `cwd` as a parameter rather than assuming `std::env::current_dir()` as the `cwd`. Specifically, the user may want to start a session in a directory other than the one where the MCP server has been started. This PR makes `cwd: PathBuf` a required field of `Session` and threads it all the way through, though I think there is still an issue with not honoring `workdir` for `apply_patch`, which is something we also had to fix in the TypeScript version: https://github.com/openai/codex/pull/556. This also adds `-C`/`--cd` to change the cwd via the command line. To test, I ran: ``` cargo run --bin codex -- exec -C /tmp 'show the output of ls' ``` and verified it showed the contents of my `/tmp` folder instead of `$PWD`.
Michael Bolin ·
2025-05-04 10:57:12 -07:00 -
Michael Bolin ·
2025-04-29 18:42:52 -07:00 -
fix: overhaul SandboxPolicy and config loading in Rust (#732)
Previous to this PR, `SandboxPolicy` was a bit difficult to work with: https://github.com/openai/codex/blob/237f8a11e11fdcc793a09e787e48215676d9b95b/codex-rs/core/src/protocol.rs#L98-L108 Specifically: * It was an `enum` and therefore options were mutually exclusive as opposed to additive. * It defined things in terms of what the agent _could not_ do as opposed to what they _could_ do. This made things hard to support because we would prefer to build up a sandbox config by starting with something extremely restrictive and only granting permissions for things the user as explicitly allowed. This PR changes things substantially by redefining the policy in terms of two concepts: * A `SandboxPermission` enum that defines permissions that can be granted to the agent/sandbox. * A `SandboxPolicy` that internally stores a `Vec<SandboxPermission>`, but externally exposes a simpler API that can be used to configure Seatbelt/Landlock. Previous to this PR, we supported a `--sandbox` flag that effectively mapped to an enum value in `SandboxPolicy`. Though now that `SandboxPolicy` is a wrapper around `Vec<SandboxPermission>`, the single `--sandbox` flag no longer makes sense. While I could have turned it into a flag that the user can specify multiple times, I think the current values to use with such a flag are long and potentially messy, so for the moment, I have dropped support for `--sandbox` altogether and we can bring it back once we have figured out the naming thing. Since `--sandbox` is gone, users now have to specify `--full-auto` to get a sandbox that allows writes in `cwd`. Admittedly, there is no clean way to specify the equivalent of `--full-auto` in your `config.toml` right now, so we will have to revisit that, as well. Because `Config` presents a `SandboxPolicy` field and `SandboxPolicy` changed considerably, I had to overhaul how config loading works, as well. There are now two distinct concepts, `ConfigToml` and `Config`: * `ConfigToml` is the deserialization of `~/.codex/config.toml`. As one might expect, every field is `Optional` and it is `#[derive(Deserialize, Default)]`. Consistent use of `Optional` makes it clear what the user has specified explicitly. * `Config` is the "normalized config" and is produced by merging `ConfigToml` with `ConfigOverrides`. Where `ConfigToml` contains a raw `Option<Vec<SandboxPermission>>`, `Config` presents only the final `SandboxPolicy`. The changes to `core/src/exec.rs` and `core/src/linux.rs` merit extra special attention to ensure we are faithfully mapping the `SandboxPolicy` to the Seatbelt and Landlock configs, respectively. Also, take note that `core/src/seatbelt_readonly_policy.sbpl` has been renamed to `codex-rs/core/src/seatbelt_base_policy.sbpl` and that `(allow file-read*)` has been removed from the `.sbpl` file as now this is added to the policy in `core/src/exec.rs` when `sandbox_policy.has_full_disk_read_access()` is `true`.
Michael Bolin ·
2025-04-29 15:01:16 -07:00 -
Michael Bolin ·
2025-04-29 09:59:35 -07:00 -
feat: load defaults into Config and introduce ConfigOverrides (#677)
This changes how instantiating `Config` works and also adds `approval_policy` and `sandbox_policy` as fields. The idea is: * All fields of `Config` have appropriate default values. * `Config` is initially loaded from `~/.codex/config.toml`, so values in `config.toml` will override those defaults. * Clients must instantiate `Config` via `Config::load_with_overrides(ConfigOverrides)` where `ConfigOverrides` has optional overrides that are expected to be settable based on CLI flags. The `Config` should be defined early in the program and then passed down. Now functions like `init_codex()` take fewer individual parameters because they can just take a `Config`. Also, `Config::load()` used to fail silently if `~/.codex/config.toml` had a parse error and fell back to the default config. This seemed really bad because it wasn't clear why the values in my `config.toml` weren't getting picked up. I changed things so that `load_with_overrides()` returns `Result<Config>` and verified that the various CLIs print a reasonable error if `config.toml` is malformed. Finally, I also updated the TUI to show which **sandbox** value is being used, as we do for other key values like **model** and **approval**. This was also a reminder that the various values of `--sandbox` are honored on Linux but not macOS today, so I added some TODOs about fixing that.
Michael Bolin ·
2025-04-27 21:47:50 -07:00 -
feat: add ZDR support to Rust implementation (#642)
This adds support for the `--disable-response-storage` flag across our multiple Rust CLIs to support customers who have opted into Zero-Data Retention (ZDR). The analogous changes to the TypeScript CLI were: * https://github.com/openai/codex/pull/481 * https://github.com/openai/codex/pull/543 For a client using ZDR, `previous_response_id` will never be available, so the `input` field of an API request must include the full transcript of the conversation thus far. As such, this PR changes the type of `Prompt.input` from `Vec<ResponseInputItem>` to `Vec<ResponseItem>`. Practically speaking, `ResponseItem` was effectively a "superset" of `ResponseInputItem` already. The main difference for us is that `ResponseItem` includes the `FunctionCall` variant that we have to include as part of the conversation history in the ZDR case. Another key change in this PR is modifying `try_run_turn()` so that it returns the `Vec<ResponseItem>` for the turn in addition to the `Vec<ResponseInputItem>` produced by `try_run_turn()`. This is because the caller of `run_turn()` needs to record the `Vec<ResponseItem>` when ZDR is enabled. To that end, this PR introduces `ZdrTranscript` (and adds `zdr_transcript: Option<ZdrTranscript>` to `struct State` in `codex.rs`) to take responsibility for maintaining the conversation transcript in the ZDR case.
Michael Bolin ·
2025-04-25 12:08:18 -07:00 -
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`: Today, Codex CLI is written in TypeScript and requires Node.js 22+ to run it. For a number of users, this runtime requirement inhibits adoption: they would be better served by a standalone executable. As maintainers, we want Codex to run efficiently in a wide range of environments with minimal overhead. We also want to take advantage of operating system-specific APIs to provide better sandboxing, where possible. To that end, we are moving forward with a Rust implementation of Codex CLI contained in this folder, which has the following benefits: - The CLI compiles to small, standalone, platform-specific binaries. - Can make direct, native calls to [seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and [landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in order to support sandboxing on Linux. - No runtime garbage collection, resulting in lower memory consumption and better, more predictable performance. Currently, the Rust implementation is materially behind the TypeScript implementation in functionality, so continue to use the TypeScript implmentation for the time being. We will publish native executables via GitHub Releases as soon as we feel the Rust version is usable.
Michael Bolin ·
2025-04-24 13:31:40 -07:00