fixes https://github.com/openai/codex/issues/10160 and some more.
## Description
Hardens Git command safety to prevent approval bypasses for destructive
or write-capable invocations (branch delete, risky push forms,
output/config-override flags), so these commands no longer auto-run as
“safe.”
- `git branch -d` variants (especially in worktrees / with global
options like -C / -c)
- `git show|diff|log --output` ... style file-write flags
- risky Git config override flags (-c, --config-env) that can trigger
external execution
- dangerous push forms that weren’t fully caught (`--force*`,
`--delete`, `+refspec`, `:refspec`)
- grouped short-flag delete forms (e.g. stacked branch flags containing
`d/D`)
will fast follow with a common git policy to bring windows to parity.
---------
Co-authored-by: Eric Traut <etraut@openai.com>
Adding a `--experimental` flag to the `generate-ts` fct in the
app-sever.
It can be called through one of those 2 command
```
just write-app-server-schema --experimental
codex app-server generate-ts --experimental
```
## Summary
- Make typed slash commands become text elements when the user hits
space, including paste‑burst spaces.
- Enable `/plan` to accept inline args and submit them in plan mode,
mirroring `/review` behavior and blocking submission while a task is
running.
- Preserve text elements/attachments for slash commands that take args.
<img width="1510" height="500" alt="image"
src="https://github.com/user-attachments/assets/446024df-b69a-4249-85db-1a85110e07f1"
/>
## Changes
- Add safe helper to insert element ranges in the textarea.
- Extend command‑with‑args pipeline to carry text elements and reuse
submission prep.
- Update `/plan` dispatch to switch to plan mode then submit prompt +
elements.
- Document new composer behavior and add tests.
## Notes
- `/plan` is blocked during active tasks (same as `/review`).
- Slash‑command elementization recognizes built‑ins and `/prompts:`
custom commands only.
## Codex author
`codex fork 019c16d3-4520-7bb0-9b9d-48720d40a8ab`
## Problem being solved
- We need a single, reliable way to mark app-server API surface as
experimental so that:
1. the runtime can reject experimental usage unless the client opts in
2. generated TS/JSON schemas can exclude experimental methods/fields for
stable clients.
Right now that’s easy to drift or miss when done ad-hoc.
## How to declare experimental methods and fields
- **Experimental method**: add `#[experimental("method/name")]` to the
`ClientRequest` variant in `client_request_definitions!`.
- **Experimental field**: on the params struct, derive `ExperimentalApi`
and annotate the field with `#[experimental("method/name.field")]` + set
`inspect_params: true` for the method variant so
`ClientRequest::experimental_reason()` inspects params for experimental
fields.
## How the macro solves it
- The new derive macro lives in
`codex-rs/codex-experimental-api-macros/src/lib.rs` and is used via
`#[derive(ExperimentalApi)]` plus `#[experimental("reason")]`
attributes.
- **Structs**:
- Generates `ExperimentalApi::experimental_reason(&self)` that checks
only annotated fields.
- The “presence” check is type-aware:
- `Option<T>`: `is_some_and(...)` recursively checks inner.
- `Vec`/`HashMap`/`BTreeMap`: must be non-empty.
- `bool`: must be `true`.
- Other types: considered present (returns `true`).
- Registers each experimental field in an `inventory` with `(type_name,
serialized field name, reason)` and exposes `EXPERIMENTAL_FIELDS` for
that type. Field names are converted from `snake_case` to `camelCase`
for schema/TS filtering.
- **Enums**:
- Generates an exhaustive `match` returning `Some(reason)` for annotated
variants and `None` otherwise (no wildcard arm).
- **Wiring**:
- Runtime gating uses `ExperimentalApi::experimental_reason()` in
`codex-rs/app-server/src/message_processor.rs` to reject requests unless
`InitializeParams.capabilities.experimental_api == true`.
- Schema/TS export filters use the inventory list and
`EXPERIMENTAL_CLIENT_METHODS` from `client_request_definitions!` to
strip experimental methods/fields when `experimental_api` is false.
- shows names of threads in the ResumePicker used by `/resume` and
`codex resume` if set, default to preview (previous behaviour) if none
- adds a `find_thread_names_by_ids` that maps names to IDs in
`codex-rs/core/src/rollout/session_index.rs`. It reads sequentially in
normal (instead of reverse order in `codex resume <name>`) the index
mapping file. This function is called from a list of session (default
page is 25, pages loaded depends of height of terminal), for which most
of them will always have at least one session unnamed and require the
whole file to be read therefore. Could be better and sqlite integration
will make this better
- those reads won't be needed when leveraging sqlite
Opened questions:
- We could rename the TUI "Conversation" column to "Name" or "Thread"
that would feel more accurate. Could be a fast-follow if we implement
auto-naming as it'll always be a name instead?
Similar to what @sayan-oai did in openai/codex#8956 for
`config.schema.json`, this PR updates the repo so that it includes the
output of `codex app-server generate-json-schema` and `codex app-server
generate-ts` and adds a test to verify it is in sync with the current
code.
Motivation:
- This makes any schema changes introduced by a PR transparent during
code review.
- In particular, this should help us catch PRs that would introduce a
non-backwards-compatible change to the app schema (eventually, this
should also be enforced by tooling).
- Once https://github.com/openai/codex/pull/10231 is in to formalize the
notion of "experimental" fields, we can work on ensuring the
non-experimental bits are backwards-compatible.
`codex-rs/app-server-protocol/tests/schema_fixtures.rs` was added as the
test and `just write-app-server-schema` can be use to generate the
vendored schema files.
Incidentally, when I run:
```
rg _ codex-rs/app-server-protocol/schema/typescript/v2
```
I see a number of `snake_case` names that should be `camelCase`.
## Summary
We ideally shouldn't make it to this point in the first place, but if we
do try to append a rule that already exists, we shouldn't append the
same rule twice.
## Testing
- [x] Added unit test for this case
## Summary
We should probably warn users that they have a million rules, and help
clean them up. But for now, we should handle this unbounded case.
Limit rules listed in conversations, with shortest / broadest rules
first.
## Testing
- [x] Updated unit tests
Updated system skills bundled with Codex were not correctly replacing
the user's skills in their .system folder.
- Fix `.codex-system-skills.marker` not updating by hashing embedded
system skills recursively (nested dirs + file contents), so updates
trigger a reinstall.
- Added a build Cargo hook to rerun if there are changes in
`src/skills/assets/samples/*`, ensuring embedded skill updates rebuild
correctly under caching.
- Add a small unit test to ensure nested entries are included in the
fingerprint.
## Summary
- Touch restored rollout files on `thread/unarchive` so `updatedAt`
reflects the unarchive time.
- Add a regression test to ensure unarchiving bumps `updated_at` from an
old mtime.
## Notes
This fixes the UX issue where unarchived old threads don’t reappear near
the top of recent threads.
## Summary
- Replace the “Hard interaction rule” with a clearer “Response
constraints” section that enumerates the allowed exceptions for Plan
Mode replies.
- Remove the stray Phase 1 exception line about simple questions.
- Update plan content requirements to ask for a brief summary section
and generalize API/type wording.
Summary
- expose websocket telemetry hooks through the responses client so
request durations and event processing can be reported
- record websocket request/event metrics and emit runtime telemetry
events that the history UI now surfaces
- improve tests to cover websocket telemetry reporting and guard runtime
summary updates
<img width="824" height="79" alt="Screenshot 2026-01-31 at 5 28 12 PM"
src="https://github.com/user-attachments/assets/ea9a7965-d8b4-4e3c-a984-ef4fdc44c81d"
/>
# External (non-OpenAI) Pull Request Requirements
Before opening this Pull Request, please read the dedicated
"Contributing" markdown file or your PR may be closed:
https://github.com/openai/codex/blob/main/docs/contributing.md
If your PR conforms to our contribution guidelines, replace this text
with a detailed and high quality description of your changes.
Include a link to a bug report or enhancement request.
# External (non-OpenAI) Pull Request Requirements
Before opening this Pull Request, please read the dedicated
"Contributing" markdown file or your PR may be closed:
https://github.com/openai/codex/blob/main/docs/contributing.md
If your PR conforms to our contribution guidelines, replace this text
with a detailed and high quality description of your changes.
Include a link to a bug report or enhancement request.
### Motivation
- The image referenced in the package README was 404ing on the npm
package page because it used a relative file path that doesn't resolve
on npm, so the splash image needs a GitHub-hosted URL to render
correctly.
### Description
- Update `README.md` to replace the relative image path
`./.github/codex-cli-splash.png` with the GitHub-hosted URL
`https://github.com/openai/codex/blob/main/.github/codex-cli-splash.png`.
### Testing
- No automated tests were run because this is a docs-only change and
does not affect code or test behavior.
------
[Codex
Task](https://chatgpt.com/codex/tasks/task_i_697e58dbce34832d87c7847779e8f4a5)
## Summary
I have read the contribution guidelines.
All changes in this PR are limited to text corrections and do not modify
any business logic, runtime behavior, or user-facing functionality.
## Details
This PR fixes several minor typos, including:
- `create` -> `crate`
- `analagous` -> `analogous`
- `apply-patch` -> `apply_patch`
- `codecs` -> `codex`
- ` '/" ` -> ` '/' `
- `Respesent` -> `Represent`
Summary
- require `CODEX_HOME` to point to an existing directory before
canonicalizing and surface clear errors otherwise
- share the same helper logic in both `core` and `rmcp-client` and add
unit tests that cover missing, non-directory, valid, and default paths
This addresses #9222
## Summary
Fixes#9041
- Adds update_search_dir() method to FileSearchManager to allow updating
the search directory after initialization
- Calls this method when the session CWD changes: new session, resume,
or fork
## Problem
The FileSearchManager was created once with the initial search_dir and
never updated. When a user:
1. Starts Codex in a non-git directory (e.g., /tmp/random)
2. Resumes or forks a session from a different workspace
3. The @filename lookup still searched the original directory
This caused no matches to be returned even when files existed in the
current workspace.
## Solution
Update FileSearchManager.search_dir whenever the session working
directory changes:
- AppEvent::NewSession: Use current config CWD
- SessionSelection::Resume: Use resumed session CWD
- SessionSelection::Fork: Use forked session CWD
## Test plan
- [ ] Start Codex in /tmp/test-dir (non-git)
- [ ] Resume a session from a project with actual files
- [ ] Verify @filename returns matches from the resumed session
directory
---------
Co-authored-by: Eric Traut <etraut@openai.com>
seeing issues with azure after default-enabling web search: #10071,
#10257.
need to work with azure to fix api-side, for now turning off
default-enable of web_search for azure.
diff is big because i moved logic to reuse
Fixes#9559.
When `shell_snapshot` runs, it may execute user startup files (e.g.
`.bashrc`). If those files read from stdin (or if stdin is an
interactive TTY under job control), the snapshot subprocess can block or
receive `SIGTTIN` (as reported over SSH).
This change explicitly sets `stdin` to `Stdio::null()` for the snapshot
subprocess, so it can't read from the terminal.
Regression test added that would hang/timeout without this change.
Tests: `ulimit -n 4096 && cargo test -p codex-core`.
cc @dongdongbh @etraut-openai
---------
Co-authored-by: Skylar Graika <sgraika127@gmail.com>
Summary:
- Fixes issue #9932: https://github.com/openai/codex/issues/9932
- Prevents `$CODEX_HOME` (typically `~/.codex`) from being discovered as
a project `.codex` layer by skipping it during project layer traversal.
We compare both normalized absolute paths and best-effort canonicalized
paths to handle symlinks.
- Adds regression tests for home-directory invocation and for the case
where `CODEX_HOME` points to a project `.codex` directory (e.g.,
worktrees/editor integrations).
Testing:
- `cargo build -p codex-cli --bin codex`
- `cargo build -p codex-rmcp-client --bin test_stdio_server`
- `cargo test -p codex-core`
- `cargo test --all-features`
- Manual: ran `target/debug/codex` from `~` and confirmed the
disabled-folder warning and trust prompt no longer appear.
# External (non-OpenAI) Pull Request Requirements
Before opening this Pull Request, please read the dedicated
"Contributing" markdown file or your PR may be closed:
https://github.com/openai/codex/blob/main/docs/contributing.md
If your PR conforms to our contribution guidelines, replace this text
with a detailed and high quality description of your changes.
Include a link to a bug report or enhancement request.
# External (non-OpenAI) Pull Request Requirements
Before opening this Pull Request, please read the dedicated
"Contributing" markdown file or your PR may be closed:
https://github.com/openai/codex/blob/main/docs/contributing.md
If your PR conforms to our contribution guidelines, replace this text
with a detailed and high quality description of your changes.
Include a link to a bug report or enhancement request.
When using ChatGPT in names of types, we should be consistent, so this
renames some types with `ChatGpt` in the name to `Chatgpt`. From
https://rust-lang.github.io/api-guidelines/naming.html:
> In `UpperCamelCase`, acronyms and contractions of compound words count
as one word: use `Uuid` rather than `UUID`, `Usize` rather than `USize`
or `Stdin` rather than `StdIn`. In `snake_case`, acronyms and
contractions are lower-cased: `is_xid_start`.
This PR updates existing uses of `ChatGpt` and changes them to
`Chatgpt`. Though in all cases where it could affect the wire format, I
visually inspected that we don't change anything there. That said, this
_will_ change the codegen because it will affect the spelling of type
names.
For example, this renames `AuthMode::ChatGPT` to `AuthMode::Chatgpt` in
`app-server-protocol`, but the wire format is still `"chatgpt"`.
This PR also updates a number of types in `codex-rs/core/src/auth.rs`.
Title
Hide Code mode footer label/cycle hint; add Plan footer-collapse
snapshots
Summary
- Keep Code mode internal naming but suppress the footer mode label +
cycle hint when Code is active.
- Only show the cycle hint when a non‑Code mode indicator is present.
- Add Plan-mode footer collapse snapshot coverage (empty + queued,
across widths) and update existing footer collapse snapshots for the new
Code behavior.
Notes
- The test run currently fails in codex-cloud-requirements on
origin/main due to a stale auth.mode field; no fix is included in this
PR to keep the diff minimal.
Codex author
`codex resume 019c0296-cfd4-7193-9b0a-6949048e4546`
## Summary
- Stream proposed plans in Plan Mode using `<proposed_plan>` tags parsed
in core, emitting plan deltas plus a plan `ThreadItem`, while stripping
tags from normal assistant output.
- Persist plan items and rebuild them on resume so proposed plans show
in thread history.
- Wire plan items/deltas through app-server protocol v2 and render a
dedicated proposed-plan view in the TUI, including the “Implement this
plan?” prompt only when a plan item is present.
## Changes
### Core (`codex-rs/core`)
- Added a generic, line-based tag parser that buffers each line until it
can disprove a tag prefix; implements auto-close on `finish()` for
unterminated tags. `codex-rs/core/src/tagged_block_parser.rs`
- Refactored proposed plan parsing to wrap the generic parser.
`codex-rs/core/src/proposed_plan_parser.rs`
- In plan mode, stream assistant deltas as:
- **Normal text** → `AgentMessageContentDelta`
- **Plan text** → `PlanDelta` + `TurnItem::Plan` start/completion
(`codex-rs/core/src/codex.rs`)
- Final plan item content is derived from the completed assistant
message (authoritative), not necessarily the concatenated deltas.
- Strips `<proposed_plan>` blocks from assistant text in plan mode so
tags don’t appear in normal messages.
(`codex-rs/core/src/stream_events_utils.rs`)
- Persist `ItemCompleted` events only for plan items for rollout replay.
(`codex-rs/core/src/rollout/policy.rs`)
- Guard `update_plan` tool in Plan Mode with a clear error message.
(`codex-rs/core/src/tools/handlers/plan.rs`)
- Updated Plan Mode prompt to:
- keep `<proposed_plan>` out of non-final reasoning/preambles
- require exact tag formatting
- allow only one `<proposed_plan>` block per turn
(`codex-rs/core/templates/collaboration_mode/plan.md`)
### Protocol / App-server protocol
- Added `TurnItem::Plan` and `PlanDeltaEvent` to core protocol items.
(`codex-rs/protocol/src/items.rs`, `codex-rs/protocol/src/protocol.rs`)
- Added v2 `ThreadItem::Plan` and `PlanDeltaNotification` with
EXPERIMENTAL markers and note that deltas may not match the final plan
item. (`codex-rs/app-server-protocol/src/protocol/v2.rs`)
- Added plan delta route in app-server protocol common mapping.
(`codex-rs/app-server-protocol/src/protocol/common.rs`)
- Rebuild plan items from persisted `ItemCompleted` events on resume.
(`codex-rs/app-server-protocol/src/protocol/thread_history.rs`)
### App-server
- Forward plan deltas to v2 clients and map core plan items to v2 plan
items. (`codex-rs/app-server/src/bespoke_event_handling.rs`,
`codex-rs/app-server/src/codex_message_processor.rs`)
- Added v2 plan item tests.
(`codex-rs/app-server/tests/suite/v2/plan_item.rs`)
### TUI
- Added a dedicated proposed plan history cell with special background
and padding, and moved “• Proposed Plan” outside the highlighted block.
(`codex-rs/tui/src/history_cell.rs`, `codex-rs/tui/src/style.rs`)
- Only show “Implement this plan?” when a plan item exists.
(`codex-rs/tui/src/chatwidget.rs`,
`codex-rs/tui/src/chatwidget/tests.rs`)
<img width="831" height="847" alt="Screenshot 2026-01-29 at 7 06 24 PM"
src="https://github.com/user-attachments/assets/69794c8c-f96b-4d36-92ef-c1f5c3a8f286"
/>
### Docs / Misc
- Updated protocol docs to mention plan deltas.
(`codex-rs/docs/protocol_v1.md`)
- Minor plumbing updates in exec/debug clients to tolerate plan deltas.
(`codex-rs/debug-client/src/reader.rs`, `codex-rs/exec/...`)
## Tests
- Added core integration tests:
- Plan mode strips plan from agent messages.
- Missing `</proposed_plan>` closes at end-of-message.
(`codex-rs/core/tests/suite/items.rs`)
- Added unit tests for generic tag parser (prefix buffering, non-tag
lines, auto-close). (`codex-rs/core/src/tagged_block_parser.rs`)
- Existing app-server plan item tests in v2.
(`codex-rs/app-server/tests/suite/v2/plan_item.rs`)
## Notes / Behavior
- Plan output no longer appears in standard assistant text in Plan Mode;
it streams via `PlanDelta` and completes as a `TurnItem::Plan`.
- The final plan item content is authoritative and may diverge from
streamed deltas (documented as experimental).
- Reasoning summaries are not filtered; prompt instructs the model not
to include `<proposed_plan>` outside the final plan message.
## Codex Author
`codex fork 019bec2d-b09d-7450-b292-d7bcdddcdbfb`
## Summary
- Tightens Plan Mode to encourage exploration-first behavior and more
back-and-forth alignment.
- Adds a required TL;DR checkpoint before drafting the full plan.
- Clarifies client behavior that can cause premature “Implement this
plan?” prompts.
## What changed
- Require at least one targeted non-mutating exploration pass before the
first user question.
- Insert a TL;DR checkpoint between Phase 2 (intent) and Phase 3
(implementation).
- TL;DR checkpoint guidance:
- Label: “Proposed Plan (TL;DR)”
- Format: 3–5 bullets using `- `
- Options: exactly one option, “Approve”
- `isOther: true`, with explicit guidance that “None of the above” is
the edit path in the current UI.
- Require the final plan to include a TL;DR consistent with the approved
checkpoint.
## Why
- In Plan Mode, any normal assistant message at turn completion is
treated as plan content by the client. This can trigger premature
“Implement this plan?” prompts.
- The TL;DR checkpoint aligns on direction before Codex drafts a long,
decision-complete plan.
## Testing
- Manual: built the local CLI and verified the flow now explores first,
presents a TL;DR checkpoint, and only drafts the full plan after
approval.
---------
Co-authored-by: Nick Baumann <@openai.com>
`requirements.toml` should be able to specify rules which always run.
My intention here was that these rules could only ever be restrictive,
which means the decision can be "prompt" or "forbidden" but never
"allow". A requirement of "you must always allow this command" didn't
make sense to me, but happy to be gaveled otherwise.
Rules already applies the most restrictive decision, so we can safely
merge these with rules found in other config folders.
Previously, `CodexAuth` was defined as follows:
d550fbf41a/codex-rs/core/src/auth.rs (L39-L46)
But if you looked at its constructors, we had creation for
`AuthMode::ApiKey` where `storage` was built using a nonsensical path
(`PathBuf::new()`) and `auth_dot_json` was `None`:
d550fbf41a/codex-rs/core/src/auth.rs (L212-L220)
By comparison, when `AuthMode::ChatGPT` was used, `api_key` was always
`None`:
d550fbf41a/codex-rs/core/src/auth.rs (L665-L671)https://github.com/openai/codex/pull/10012 took things further because
it introduced a new `ChatgptAuthTokens` variant to `AuthMode`, which is
important in when invoking `account/login/start` via the app server, but
most logic _internal_ to the app server should just reason about two
`AuthMode` variants: `ApiKey` and `ChatGPT`.
This PR tries to clean things up as follows:
- `LoginAccountParams` and `AuthMode` in `codex-rs/app-server-protocol/`
both continue to have the `ChatgptAuthTokens` variant, though it is used
exclusively for the on-the-wire messaging.
- `codex-rs/core/src/auth.rs` now has its own `AuthMode` enum, which
only has two variants: `ApiKey` and `ChatGPT`.
- `CodexAuth` has been changed from a struct to an enum. It is a
disjoint union where each variant (`ApiKey`, `ChatGpt`, and
`ChatGptAuthTokens`) have only the associated fields that make sense for
that variant.
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/10208).
* #10224
* __->__ #10208
Load requirements from Codex Backend. It only does this for enterprise
customers signed in with ChatGPT.
Todo in follow-up PRs:
* Add to app-server and exec too
* Switch from fail-open to fail-closed on failure
Session renaming:
- `/rename my_session`
- `/rename` without arg and passing an argument in `customViewPrompt`
- AppExitInfo shows resume hint using the session name if set instead of
uuid, defaults to uuid if not set
- Names are stored in `CODEX_HOME/sessions.jsonl`
Session resuming:
- codex resume <name> lookup for `CODEX_HOME/sessions.jsonl` first entry
matching the name and resumes the session
---------
Co-authored-by: jif-oai <jif@openai.com>
## Summary
- add startup tooltip for OpenAI community Discord
- add startup tooltip for Codex community forum
## Testing
- not run (text-only tooltip change)
## Summary
Let's dial in this api contract in a bit more with more robust fallback
behavior when model_instructions_template is false.
Switches to a more explicit template / variables structure, with more
fallbacks.
## Testing
- [x] Adding unit tests
- [x] Tested locally
## Problem
OpenAI employees were sent to the public GitHub issue flow after
`/feedback`, which is the wrong follow-up path internally.
## Mental model
After feedback upload completes, we render a follow-up link/message.
That link should be audience-aware but must not change the upload
pipeline itself.
## Non-goals
- Changing how feedback is captured or uploaded
- Changing external user behavior
## Tradeoffs
We detect employees via the authenticated account email suffix
(`@openai.com`). If the email is unavailable (e.g., API key auth), we
default to the external behavior.
## Architecture
- Introduce `FeedbackAudience` and thread it from `App` -> `ChatWidget`
-> `FeedbackNoteView`
- Gate internal messaging/links on `FeedbackAudience::OpenAiEmployee`
- Internal follow-up link is now `http://go/codex-feedback-internal`
- External GitHub URL remains byte-for-byte identical
## Observability
No new telemetry; this only changes rendered follow-up instructions.
## Tests
- `just fmt`
- `cargo test -p codex-tui --lib`
Add dynamic tools to rollout file for persistence & read from rollout on
resume. Ran a real example and spotted the following in the rollout
file:
```
{"timestamp":"2026-01-29T01:27:57.468Z","type":"session_meta","payload":{"id":"019c075d-3f0b-77e3-894e-c1c159b04b1e","timestamp":"2026-01-29T01:27:57.451Z","...."dynamic_tools":[{"name":"demo_tool","description":"Demo dynamic tool","inputSchema":{"additionalProperties":false,"properties":{"city":{"type":"string"}},"required":["city"],"type":"object"}}],"git":{"commit_hash":"ebc573f15c01b8af158e060cfedd401f043e9dfa","branch":"dev/cc/dynamic-tools","repository_url":"https://github.com/openai/codex.git"}}}
```
## Summary
Adds a simple `/plan` slash command in the TUI that switches the active
collaboration mode to Plan mode. The command is only available when the
`collaboration_modes` feature is enabled.
## Changes
- Add `plan_mask` helper in `codex-rs/tui/src/collaboration_modes.rs`
- Add `SlashCommand::Plan` metadata in
`codex-rs/tui/src/slash_command.rs`
- Implement and hard-gate `/plan` dispatch in
`codex-rs/tui/src/chatwidget.rs`
- Hide `/plan` when collaboration modes are disabled in
`codex-rs/tui/src/bottom_pane/slash_commands.rs`
- Update command popup tests in
`codex-rs/tui/src/bottom_pane/command_popup.rs`
- Add a focused unit test for `/plan` in
`codex-rs/tui/src/chatwidget/tests.rs`
## Behavior notes
- `/plan` is now a no-op if `Feature::CollaborationModes` is disabled.
- When enabled, `/plan` switches directly to Plan mode without opening
the picker.
## Codex author
`codex resume 019c05da-d7c3-7322-ae2c-3ca38d0ef702`
This enables a new use case where `codex app-server` is embedded into a
parent application that will directly own the user's ChatGPT auth
lifecycle, which means it owns the user’s auth tokens and refreshes it
when necessary. The parent application would just want a way to pass in
the auth tokens for codex to use directly.
The idea is that we are introducing a new "auth mode" currently only
exposed via app server: **`chatgptAuthTokens`** which consist of the
`id_token` (stores account metadata) and `access_token` (the bearer
token used directly for backend API calls). These auth tokens are only
stored in-memory. This new mode is in addition to the existing `apiKey`
and `chatgpt` auth modes.
This PR reuses the shape of our existing app-server account APIs as much
as possible:
- Update `account/login/start` with a new `chatgptAuthTokens` variant,
which will allow the client to pass in the tokens and have codex
app-server use them directly. Upon success, the server emits
`account/login/completed` and `account/updated` notifications.
- A new server->client request called
`account/chatgptAuthTokens/refresh` which the server can use whenever
the access token previously passed in has expired and it needs a new one
from the parent application.
I leveraged the core 401 retry loop which typically triggers auth token
refreshes automatically, but made it pluggable:
- **chatgpt** mode refreshes internally, as usual.
- **chatgptAuthTokens** mode calls the client via
`account/chatgptAuthTokens/refresh`, the client responds with updated
tokens, codex updates its in-memory auth, then retries. This RPC has a
10s timeout and handles JSON-RPC errors from the client.
Also some additional things:
- chatgpt logins are blocked while external auth is active (have to log
out first. typically clients will pick one OR the other, not support
both)
- `account/logout` clears external auth in memory
- Ensures that if `forced_chatgpt_workspace_id` is set via the user's
config, we respect it in both:
- `account/login/start` with `chatgptAuthTokens` (returns a JSON-RPC
error back to the client)
- `account/chatgptAuthTokens/refresh` (fails the turn, and on next
request app-server will send another `account/chatgptAuthTokens/refresh`
request to the client).
###### Problem
Users get generic 429s with no guidance when a model is at capacity.
###### Solution
Detect model-cap headers, surface a clear “try a different model”
message, and keep behavior non‑intrusive (no auto‑switch).
###### Scope
CLI/TUI only; protocol + error mapping updated to carry model‑cap info.
###### Tests
- just fmt
- cargo test -p codex-tui
- cargo test -p codex-core --lib
shell_snapshot::tests::try_new_creates_and_deletes_snapshot_file --
--nocapture (ran in isolated env)
- validate local build with backend
<img width="719" height="845" alt="image"
src="https://github.com/user-attachments/assets/1470b33d-0974-4b1f-b8e6-d11f892f4b54"
/>
## Summary
- add `codex features enable <feature>` and `codex features disable
<feature>`
- persist feature flag changes to `config.toml` (respecting profile)
- print the under-development feature warning when enabling prerelease
features
- keep `features list` behavior unchanged and add unit/integration tests
## Testing
- cargo test -p codex-cli
An experimental flow for env var skill dependencies. Skills can now
declare required env vars in SKILL.md; if missing, the CLI prompts the
user to get the value, and Core will store it in memory (eventually to a
local persistent store)
<img width="790" height="169" alt="image"
src="https://github.com/user-attachments/assets/cd928918-9403-43cb-a7e7-b8d59bcccd9a"
/>
On the back of:
https://github.com/openai/codex/pull/10138
Let's ensure that every folder with a `package.json` is listed in
`pnpm-workspace.yaml` (not sure why `docs` was in there...) and that we
are using `pnpm` over `npm` consistently (which is why this PR deletes
`codex-cli/package-lock.json`).
```
just log -h
if [ "${1:-}" = "--" ]; then shift; fi; cargo run -p codex-state --bin logs_client -- "$@"
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.21s
Running `target/debug/logs_client -h`
Tail Codex logs from state.sqlite with simple filters
Usage: logs_client [OPTIONS]
Options:
--codex-home <CODEX_HOME> Path to CODEX_HOME. Defaults to $CODEX_HOME or ~/.codex [env: CODEX_HOME=]
--db <DB> Direct path to the SQLite database. Overrides --codex-home
--level <LEVEL> Log level to match exactly (case-insensitive)
--from <RFC3339|UNIX> Start timestamp (RFC3339 or unix seconds)
--to <RFC3339|UNIX> End timestamp (RFC3339 or unix seconds)
--module <MODULE> Substring match on module_path
--file <FILE> Substring match on file path
--backfill <BACKFILL> Number of matching rows to show before tailing [default: 200]
--poll-ms <POLL_MS> Poll interval in milliseconds [default: 500]
-h, --help Print help
```
Currently, our `npm publish` logic is failing.
There were a number of things that were merged recently that seemed to
contribute to this situation, though I think we have fixed most of them,
but this one stands out:
https://github.com/openai/codex/pull/10115
As best I can tell, we tried to fix the pnpm version to a specific hash,
but we did not do it consistently (though `shell-tool-mcp/package.json`
had it specified twice...), so for this PR, I ran:
```
$ git ls-files | grep package.json
codex-cli/package.json
codex-rs/responses-api-proxy/npm/package.json
package.json
sdk/typescript/package.json
shell-tool-mcp/package.json
```
and ensured that all of them now have this line:
```json
"packageManager": "pnpm@10.28.2+sha512.41872f037ad22f7348e3b1debbaf7e867cfd448f2726d9cf74c08f19507c31d2c8e7a11525b983febc2df640b5438dee6023ebb1f84ed43cc2d654d2bc326264"
```
I also went and deleted all of the `corepack` stuff that was added by
https://github.com/openai/codex/pull/10115.
If someone can explain why we need it and verify it does not break `npm
publish`, then we can bring it back.
## Summary
- guard onboarding key handling to ignore KeyEventKind::Release
- handle key events at the onboarding screen boundary to avoid
double-triggering widgets
## Related
- https://github.com/ratatui/ratatui/issues/347
## Testing
- cd codex-rs && just fmt
- cd codex-rs && cargo test -p codex-tui
- [x] Support `/apps` slash command to browse the apps in tui.
- [x] Support inserting apps to prompt using `$`.
- [x] Lots of simplification/renaming from connectors to apps.
## Summary
Add personality instructions so we can let users try it out, in tandem
with making it an experimental feature
## Testing
- [x] Tested locally
## Summary
Sets up an explicit Feature flag for `/personality`, so users can now
opt in to it via `/experimental`. #10114 also updates the config
## Testing
- [x] Tested locally
we can't use runfiles directory on Windows due to path lengths, so swap
to manifest strategy. Parsing the manifest is a bit complex and the
format is changing in Bazel upstream, so pull in the official Rust
library (via a small hack to make it importable...) and cleanup all the
associated logic to work cleanly in both bazel and cargo without extra
confusion
This updates the CI workflows for shell-tool-mcp to use the pnpm version
from package.json and print it in the build for verification.
I have read the CLA Document and I hereby sign the CLA
This PR adds a new `tui.notifications_method` config option that accepts
values of "auto", "osc9" and "bel". It defaults to "auto", which
attempts to auto-detect whether the terminal supports OSC 9 escape
sequences and falls back to BEL if not.
The PR also removes the inconsistent handling of notifications on
Windows when WSL was used.
# External (non-OpenAI) Pull Request Requirements
Before opening this Pull Request, please read the dedicated
"Contributing" markdown file or your PR may be closed:
https://github.com/openai/codex/blob/main/docs/contributing.md
If your PR conforms to our contribution guidelines, replace this text
with a detailed and high quality description of your changes.
Include a link to a bug report or enhancement request.
deprecate all old web search flags and aliases, including:
- `[features].web_search_request` and `[features].web_search_cached`
- `[tools].web_search`
- `[features].web_search`
slightly rework `legacy_usages` to enable pointing to non-features from
deprecated features; we need to point to `web_search` (not under
`[features]`) from things like `[features].web_search_cached` and
`[features].web_search_request`.
Added integration tests to confirm deprecation notice is shown on
explicit enablement and disablement of deprecated flags.
I needed to upgrade bazel one to get gnullvm artifacts and then noticed
monorepo had drifted forward. They should move in lockstep. Also 1.93
already shipped so we can try that instead.
## Summary
Overhaul the ask‑user‑questions TUI to support “Other/None” answers,
better notes handling, improved option selection
UX, and a safer submission flow with confirmation for unanswered
questions.
Multiple choice (number keys for quick selection, up/down or jk for
cycling through options):
<img width="856" height="169" alt="Screenshot 2026-01-27 at 7 22 29 PM"
src="https://github.com/user-attachments/assets/cabd1b0e-25e0-4859-bd8f-9941192ca274"
/>
Tab to add notes:
<img width="856" height="197" alt="Screenshot 2026-01-27 at 7 22 45 PM"
src="https://github.com/user-attachments/assets/a807db5e-e966-412c-af91-6edc60062f35"
/>
Freeform (also note enter tooltip is highlighted on last question to
indicate questions UI will be exited upon submission):
<img width="854" height="112" alt="Screenshot 2026-01-27 at 7 23 13 PM"
src="https://github.com/user-attachments/assets/2e7b88bf-062b-4b9f-a9da-c9d8c8a59643"
/>
Confirmation dialogue (submitting with unanswered questions):
<img width="854" height="126" alt="Screenshot 2026-01-27 at 7 23 29 PM"
src="https://github.com/user-attachments/assets/93965c8f-54ac-45bc-a660-9625bcd101f8"
/>
## Key Changes
- **Options UI refresh**
- Render options as numbered entries; allow number keys to select &
submit.
- Remove “Option X/Y” header and allow the question UI height to expand
naturally.
- Keep spacing between question, options, and notes even when notes are
visible.
- Hide the title line and render the question prompt in cyan **only when
uncommitted**.
- **“Other / None of the above” support**
- Wire `isOther` to add “None of the above”.
- Add guidance text: “Optionally, add details in notes (tab).”
- **Notes composer UX**
- Remove “Notes” heading; place composer directly under the selected
option.
- Preserve pending paste placeholders across question navigation and
after submission.
- Ctrl+C clears notes **only when the notes composer has focus**.
- Ctrl+C now triggers an immediate redraw so the clear is visible.
- **Committed vs uncommitted state**
- Introduce a unified `answer_committed` flag per question.
- Editing notes (including adding text or pastes) marks the answer
uncommitted.
- Changing the option highlight (j/k, up/down) marks the answer
uncommitted.
- Clearing options (Backspace/Delete) also clears pending notes.
- Question prompt turns cyan only when the answer is uncommitted.
- **Submission safety & confirmation**
- Only submit notes/freeform text once explicitly committed.
- Last-question submit with unanswered questions shows a confirmation
dialog.
- Confirmation options:
1. **Proceed** (default)
2. **Go back**
- Description reflects count: “Submit with N unanswered question(s).”
- Esc/Backspace in confirmation returns to first unanswered question.
- Ctrl+C in confirmation interrupts and exits the overlay.
- **Footer hints**
- Cyan highlight restored for “enter to submit answer” / “enter to
submit all”.
## Codex author
`codex fork 019c00ed-323a-7000-bdb5-9f9c5a635bd9`
Add a `.sqlite` database to be used to store rollout metatdata (and
later logs)
This PR is phase 1:
* Add the database and the required infrastructure
* Add a backfill of the database
* Persist the newly created rollout both in files and in the DB
* When we need to get metadata or a rollout, consider the `JSONL` as the
source of truth but compare the results with the DB and show any errors
**Summary**
- Up/Down input history now restores image attachments and text elements
for local entries.
- Composer history stores rich local entries (text + text elements +
local image paths) while persistent history remains text-only.
- Added tests to verify history recall rehydrates image placeholders and
attachments in both `tui` and `tui2`.
**Changes**
- `tui/src/bottom_pane/chat_composer_history.rs`: store `HistoryEntry`
(text + elements + image paths) for local history; adapt navigation +
tests.
- `tui2/src/bottom_pane/chat_composer_history.rs`: same as above.
- `tui/src/bottom_pane/chat_composer.rs`: record rich history entries
and restore them on Up/Down; update Ctrl+C history and tests.
- `tui2/src/bottom_pane/chat_composer.rs`: same as above.
web_search can now be updated per-turn, for things like changes to
sandbox policy.
`SandboxPolicy::DangerFullAccess` now sets web_search to `live`, and the
default is still `cached`.
Added integration tests.
Fixes#9361
## Context
Split out from #9059 per review:
https://github.com/openai/codex/pull/9059#issuecomment-3757859033
## Summary
The shortcut overlay renders different paste-image bindings on WSL
(Ctrl+Alt+V) vs non-WSL (Ctrl+V), which makes snapshot tests
non-deterministic when run under WSL.
## Changes
- Gate WSL detection behind `cfg(not(test))` so snapshot tests are
deterministic across environments.
- Add a focused unit test that still asserts the WSL-specific
paste-image binding.
## Testing
- `just fmt`
- `just fix -p codex-tui`
- `just fix -p codex-tui2`
- `cargo test -p codex-tui`
- `cargo test -p codex-tui2`
## Summary
Polishes the `request_user_input` TUI overlay
Question 1 (unanswered)
<img width="853" height="167" alt="Screenshot 2026-01-27 at 1 30 09 PM"
src="https://github.com/user-attachments/assets/3c305644-449e-4e8d-a47b-d689ebd8702c"
/>
Tab to add notes
<img width="856" height="198" alt="Screenshot 2026-01-27 at 1 30 25 PM"
src="https://github.com/user-attachments/assets/0d2801b0-df0c-49ae-85af-e6d56fc2c67c"
/>
Question 2 (unanswered)
<img width="854" height="168" alt="Screenshot 2026-01-27 at 1 30 55 PM"
src="https://github.com/user-attachments/assets/b3723062-51f9-49c9-a9ab-bb1b32964542"
/>
Ctrl+p or h to go back to q1 (answered)
<img width="853" height="195" alt="Screenshot 2026-01-27 at 1 31 27 PM"
src="https://github.com/user-attachments/assets/c602f183-1c25-4c51-8f9f-e565cb6bd637"
/>
Unanswered freeform
<img width="856" height="126" alt="Screenshot 2026-01-27 at 1 31 42 PM"
src="https://github.com/user-attachments/assets/7e3d9d8b-820b-4b9a-9ef2-4699eed484c5"
/>
## Key changes
- Footer tips wrap at tip boundaries (no truncation mid‑tip); footer
height scales to wrapped tips.
- Keep tooltip text as Esc: interrupt in all states.
- Make the full Tab: add notes tip cyan/bold when applicable; hide notes
UI by default.
- Notes toggling/backspace:
- Tab opens notes when an option is selected; Tab again clears notes and
hides the notes UI.
- Backspace in options clears the current selection.
- Backspace in empty notes closes notes and returns to options.
- Selection/answering behavior:
- Option questions highlight a default option but are not answered until
Enter.
- Enter no longer auto‑selects when there’s no selection (prevents
accidental answers).
- Notes submission can commit the selected option when present.
- Freeform questions require Enter with non‑empty text to mark answered;
drafts are not submitted unless committed.
- Unanswered cues:
- Skipped option questions count as unanswered.
- Unanswered question titles are highlighted for visibility.
- Typing/navigation in options:
- Typing no longer opens notes; notes are Tab‑only.
- j/k move option selection; h/l switch questions (Ctrl+n/Ctrl+p still
work).
## Tests
- Added unit coverage for:
- tip‑level wrapping
- focus reset when switching questions with existing drafts
- backspace clearing selection
- backspace closing empty notes
- typing in options does not open notes
- freeform draft submission gating
- h/l question navigation in options
- Updated snapshots, including narrow footer wrap.
## Why
These changes make the ask‑user‑question overlay:
- safer (no silent auto‑selection or accidental freeform submission),
- clearer (tips wrap cleanly and unanswered states stand out),
- more ergonomic (Tab explicitly controls notes; backspace acts like
undo/close).
## Codex author
`codex fork 019bfc3c-2c42-7982-9119-fee8b9315c2f`
---------
Co-authored-by: Ahmed Ibrahim <aibrahim@openai.com>
### Motivation
- Improve UX by making it explicit that `VISUAL`/`EDITOR` must be set
before launching Codex, not during a running session.
### Description
- Update the external editor error text in `codex-rs/tui/src/app.rs` to:
`"Cannot open external editor: set $VISUAL or $EDITOR before starting
Codex."` and run `just fmt` to apply formatting.
### Testing
- Ran `just fmt` successfully; attempted `cargo test -p codex-tui` but
it failed due to network errors when fetching git dependencies (tests
did not complete).
------
[Codex
Task](https://chatgpt.com/codex/tasks/task_i_6972c2c984948329b1a37d5c5839aff3)
### Motivation
- The local OAuth callback server returned a generic "Invalid OAuth
callback" on failures even when the query contained an
`error_description`, making it hard to debug OAuth failures.
### Description
- Update `codex-rs/rmcp-client/src/perform_oauth_login.rs` to surface
`error_description` values from the callback query in the HTTP response.
- Introduce a `CallbackOutcome` enum and change `parse_oauth_callback`
to return it, parsing `code`, `state`, and `error_description` from the
query string.
- Change `spawn_callback_server` to match on `CallbackOutcome` and
return `OAuth error: <description>` with a 400 status when
`error_description` is present, while preserving the existing success
and invalid flows.
- Use inline formatting for the error response string.
### Testing
- Ran `just fmt` in the `codex-rs` workspace to format changes
successfully.
- Ran `cargo test -p codex-rmcp-client` and all tests passed.
------
[Codex
Task](https://chatgpt.com/codex/tasks/task_i_6971aadc68d0832e93159efea8cd48a9)
## What?
- Render an MCP image output cell whenever a decodable image block
exists in `CallToolResult.content` (including text-before-image or
malformed image before valid image).
## Why?
- Tool results that include caption text before the image currently drop
the image output cell.
- A malformed image block can also suppress later valid image output.
## How?
- Iterate `content` and return the first successfully decoded image
instead of only checking the first block.
- Add unit tests that cover text-before-image ordering and
invalid-image-before-valid.
## Before
```rust
let image = match result {
Ok(mcp_types::CallToolResult { content, .. }) => {
if let Some(mcp_types::ContentBlock::ImageContent(image)) = content.first() {
// decode image (fails -> None)
} else {
None
}
}
_ => None,
}?;
```
## After
```rust
let image = result
.as_ref()
.ok()?
.content
.iter()
.find_map(decode_mcp_image)?;
```
## Risk / Impact
- Low: only affects image cell creation for MCP tool results; no change
for non-image outputs.
## Tests
- [x] `just fmt`
- [x] `cargo test -p codex-tui`
- [x] Rerun after branch update (2026-01-27): `just fmt`, `cargo test -p
codex-tui`
Manual testing
# Manual testing: MCP image tool result rendering (Codex TUI)
# Build the rmcp stdio test server binary:
cd codex-rs
cargo build -p codex-rmcp-client --bin test_stdio_server
# Register the server as an MCP server (absolute path to the built binary):
codex mcp add mcpimg -- /Users/joshka/code/codex-pr-review/codex-rs/target/debug/test_stdio_server
# Then in Codex TUI, ask it to call:
- mcpimg.image_scenario({"scenario":"image_only"})
- mcpimg.image_scenario({"scenario":"text_then_image","caption":"Here is the image:"})
- mcpimg.image_scenario({"scenario":"invalid_base64_then_image"})
- mcpimg.image_scenario({"scenario":"invalid_image_bytes_then_image"})
- mcpimg.image_scenario({"scenario":"multiple_valid_images"})
- mcpimg.image_scenario({"scenario":"image_then_text","caption":"Here is the image:"})
- mcpimg.image_scenario({"scenario":"text_only","caption":"Here is the image:"})
# Expected:
# - You should see an extra history cell: "tool result (image output)" when the
# tool result contains at least one decodable image block (even if earlier
# blocks are text or invalid images).
Fixes#9814
---------
Co-authored-by: Josh McKinney <joshka@openai.com>
Auto-enable live `web_search` tool when sandbox policy is
`DangerFullAccess`.
Explicitly setting `web_search` (canonical setting), or enabling
`web_search_cached` or `web_search_request` still takes precedence over
this sandbox-policy-driven enablement.
Constructors with long param lists can be hard to reason about when a
number of the args are `None`, in practice. Introducing a struct to use
as the args type helps make things more self-documenting.
Updates the `CodexOptions` passed to the `Codex()` constructor in the
SDK to support a `config` property that is a map of configuration data
that will be transformed into `--config` flags passed to the invocation
of `codex`.
Therefore, something like this:
```typescript
const codex = new Codex({
config: {
show_raw_agent_reasoning: true,
sandbox_workspace_write: { network_access: true },
},
});
```
would result in the following args being added to the invocation of
`codex`:
```shell
--config show_raw_agent_reasoning=true --config sandbox_workspace_write.network_access=true
```
### Overview
Currently calling `thread/resume` will always bump the thread's
`updated_at` timestamp. This PR makes it the `updated_at` timestamp
changes only if a turn is triggered.
### Additonal context
What we typically do on resuming a thread is **always** writing “initial
context” to the rollout file immediately. This initial context includes:
- Developer instructions derived from sandbox/approval policy + cwd
- Optional developer instructions (if provided)
- Optional collaboration-mode instructions
- Optional user instructions (if provided)
- Environment context (cwd, shell, etc.)
This PR defers writing the “initial context” to the rollout file until
the first `turn/start`, so we don't inadvertently bump the thread's
`updated_at` timestamp until a turn is actually triggered.
This works even though both `thread/resume` and `turn/start` accept
overrides (such as `model`, `cwd`, etc.) because the initial context is
seeded from the effective `TurnContext` in memory, computed at
`turn/start` time, after both sets of overrides have been applied.
**NOTE**: This is a very short-lived solution until we introduce sqlite.
Then we can remove this.
### Summary
- Adds an optional SOCKS5 listener via `rama-socks5`
- SOCKS5 is disabled by default and gated by config
- Reuses existing policy enforcement and blocked-request recording
- Blocks SOCKS5 in limited mode to prevent method-policy bypass
- Applies bind clamping to the SOCKS5 listener
### Config
New/used fields under `network_proxy`:
- `enable_socks5`
- `socks_url`
- `enable_socks5_udp`
### Scope
- Changes limited to `codex-rs/network-proxy` (+ `codex-rs/Cargo.lock`)
### Testing
```bash
cd codex-rs
just fmt
cargo test -p codex-network-proxy --offline
## Summary
Refines the bottom footer layout to keep `% context left` right-aligned
while making the left side degrade cleanly
## Behavior with empty textarea
Full width:
<img width="607" height="62" alt="Screenshot 2026-01-26 at 2 59 59 PM"
src="https://github.com/user-attachments/assets/854f33b7-d714-40be-8840-a52eb3bda442"
/>
Less:
<img width="412" height="66" alt="Screenshot 2026-01-26 at 2 59 48 PM"
src="https://github.com/user-attachments/assets/9c501788-c3a2-4b34-8f0b-8ec4395b44fe"
/>
Min width:
<img width="218" height="77" alt="Screenshot 2026-01-26 at 2 59 33 PM"
src="https://github.com/user-attachments/assets/0bed2385-bdbf-4254-8ae4-ab3452243628"
/>
## Behavior with message in textarea and agent running (steer enabled)
Full width:
<img width="753" height="63" alt="Screenshot 2026-01-26 at 4 33 54 PM"
src="https://github.com/user-attachments/assets/1856b352-914a-44cf-813d-1cb50c7f183b"
/>
Less:
<img width="353" height="61" alt="Screenshot 2026-01-26 at 4 30 12 PM"
src="https://github.com/user-attachments/assets/d951c4d5-f3e7-4116-8fe1-6a6c712b3d48"
/>
Less:
<img width="304" height="64" alt="Screenshot 2026-01-26 at 4 30 51 PM"
src="https://github.com/user-attachments/assets/1433e994-5cbc-4e20-a98a-79eee13c8699"
/>
Less:
<img width="235" height="61" alt="Screenshot 2026-01-26 at 4 30 56 PM"
src="https://github.com/user-attachments/assets/e216c3c6-84cd-40fc-ae4d-83bf28947f0e"
/>
Less:
<img width="165" height="59" alt="Screenshot 2026-01-26 at 4 31 08 PM"
src="https://github.com/user-attachments/assets/027de5de-7185-47ce-b1cc-5363ea33d9b1"
/>
## Notes / Edge Cases
- In steer mode while typing, the queue hint no longer replaces the mode
label; it renders as `tab to queue message · {Mode}`.
- Collapse priorities differ by state:
- With the queue hint active, `% context left` is hidden before
shortening or dropping the queue hint.
- In the empty + non-running state, `? for shortcuts` is dropped first,
and `% context left` is only shown if `(shift+tab to
cycle)` can also fit.
- Transient instructional states (`?` overlay, Esc hint, Ctrl+C/D
reminders, and flash/override hints) intentionally suppress the
mode label (and context) to focus the next action.
## Implementation Notes
- Renamed the base footer modes to make the state explicit:
`ComposerEmpty` and `ComposerHasDraft`, and compute the base mode
directly from emptiness.
- Unified collapse behavior in `single_line_footer_layout` for both base
modes, with:
- Queue-hint behavior that prefers keeping the queue hint over context.
- A cycle-hint guard that prevents context from reappearing after
`(shift+tab to cycle)` is dropped.
- Kept rendering responsibilities explicit:
- `single_line_footer_layout` decides what fits.
- `render_footer_line` renders a chosen line.
- `render_footer_from_props` renders the canonical mode-to-text mapping.
- Expanded snapshot coverage:
- Added `footer_collapse_snapshots` in `chat_composer.rs` to lock the
distinct collapse states across widths.
- Consolidated the width-aware snapshot helper usage (e.g.,
`snapshot_composer_state_with_width`,
`snapshot_footer_with_mode_indicator`).
Updates pnpm to 10.28.2. to address security issues in prior versions of
pnpm that can allow deps to execute lifecycle scripts against policy.
I have read the CLA Document and I hereby sign the CLA
# External (non-OpenAI) Pull Request Requirements
Before opening this Pull Request, please read the dedicated
"Contributing" markdown file or your PR may be closed:
https://github.com/openai/codex/blob/main/docs/contributing.md
If your PR conforms to our contribution guidelines, replace this text
with a detailed and high quality description of your changes.
Include a link to a bug report or enhancement request.
# External (non-OpenAI) Pull Request Requirements
Before opening this Pull Request, please read the dedicated
"Contributing" markdown file or your PR may be closed:
https://github.com/openai/codex/blob/main/docs/contributing.md
If your PR conforms to our contribution guidelines, replace this text
with a detailed and high quality description of your changes.
Include a link to a bug report or enhancement request.
Fix resume --last prompt parsing by dropping the clap conflict on the
codex resume subcommand so a positional prompt is accepted when --last
is set. This aligns interactive resume behavior with exec-mode logic and
avoids the “--last cannot be used with SESSION_ID” error.
This addresses #6717
# External (non-OpenAI) Pull Request Requirements
Before opening this Pull Request, please read the dedicated
"Contributing" markdown file or your PR may be closed:
https://github.com/openai/codex/blob/main/docs/contributing.md
If your PR conforms to our contribution guidelines, replace this text
with a detailed and high quality description of your changes.
Include a link to a bug report or enhancement request.
# External (non-OpenAI) Pull Request Requirements
Before opening this Pull Request, please read the dedicated
"Contributing" markdown file or your PR may be closed:
https://github.com/openai/codex/blob/main/docs/contributing.md
If your PR conforms to our contribution guidelines, replace this text
with a detailed and high quality description of your changes.
Include a link to a bug report or enhancement request.
### Summary
- Parse all `web_search` tool actions (`search`, `find_in_page`,
`open_page`).
- Previously we only parsed + displayed `search`, which made the TUI
appear to pause when the other actions were being used.
- Show in progress `web_search` calls as `Searching the web`
- Previously we only showed completed tool calls
<img width="308" height="149" alt="image"
src="https://github.com/user-attachments/assets/90a4e8ff-b06a-48ff-a282-b57b31121845"
/>
### Tests
Added + updated tests, tested locally
### Follow ups
Update VSCode extension to display these as well
Reuse the shared chat composer for notes and freeform answers in
request_user_input.
- Build the overlay composer with ChatComposerConfig::plain_text.
- Wire paste-burst flushing + menu surface sizing through the bottom
pane.
## Context
Previous work in https://github.com/openai/codex/pull/9560 only rejected
`request_user_input` in Execute and Custom modes. Since then, additional
modes
(e.g., Code) were added, so the guard should be mode-agnostic.
## What changed
- Switch the handler to an allowlist: only Plan and PairProgramming are
allowed
- Return the same error for any other mode (including Code)
- Add a Code-mode rejection test alongside the existing Execute/Custom
tests
## Why
This prevents `request_user_input` from being used in modes where it is
not
intended, even as new modes are introduced.
Fixes a TUI freeze caused by awaiting `mpsc::Sender::send()` that blocks
the tokio thread, stopping the consumption runtime and creating a
deadlock. This could happen if the server was producing enough chunks to
fill the `mpsc` fast enough. To solve this we try on insert using a
`try_send()` (not requiring an `await`) and delegate to a tokio task if
this does not work
This is a temporary solution as it can contain races for delta elements
and a stronger design should come here
Fixes#9822
### Summary
Make the Homebrew upgrade command explicit by using `brew upgrade --cask
codex`.
### Motivation
During the Codex self-update, Homebrew can emit an avoidable warning
because the
name `codex` resolves to a cask:
```
Warning: Formula codex was renamed to homebrew/cask/codex.
````
While the upgrade succeeds, this relies on implicit name resolution and
produces
unnecessary output during the update flow.
### Why `--cask`
* Eliminates warning/noise for users
* Explicitly matches how Codex is distributed via Homebrew
* Avoids reliance on name resolution behavior
* Makes the command more robust if a `codex` formula is ever introduced
### Context
This restores the `--cask` flag that was removed in #6238 after being
considered
“not necessary” during review:
[https://github.com/openai/codex/pull/6238#discussion_r2505947880](https://github.com/openai/codex/pull/6238#discussion_r2505947880).
Co-authored-by: Eric Traut <etraut@openai.com>
Bumps [globset](https://github.com/BurntSushi/ripgrep) from 0.4.16 to
0.4.18.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="0b0e013f5a"><code>0b0e013</code></a>
globset-0.4.18</li>
<li><a
href="cac9870a02"><code>cac9870</code></a>
doc: update date in man page template</li>
<li><a
href="24e88dc15b"><code>24e88dc</code></a>
ignore/types: add <code>ssa</code> type</li>
<li><a
href="5748f81bb1"><code>5748f81</code></a>
printer: use <code>doc_cfg</code> instead of
<code>doc_auto_cfg</code></li>
<li><a
href="d47663b1b4"><code>d47663b</code></a>
searcher: fix regression with <code>--line-buffered</code> flag</li>
<li><a
href="38d630261a"><code>38d6302</code></a>
printer: add Cursor hyperlink alias</li>
<li><a
href="b3dc4b0998"><code>b3dc4b0</code></a>
globset: improve debug log</li>
<li><a
href="ca2e34f37c"><code>ca2e34f</code></a>
grep-0.4.0</li>
<li><a
href="a0d61a063f"><code>a0d61a0</code></a>
grep-printer-0.3.0</li>
<li><a
href="c22fc0f13c"><code>c22fc0f</code></a>
deps: bump to grep-searcher 0.1.15</li>
<li>Additional commits viewable in <a
href="https://github.com/BurntSushi/ripgrep/compare/globset-0.4.16...globset-0.4.18">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [tokio-test](https://github.com/tokio-rs/tokio) from 0.4.4 to
0.4.5.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="41d1877689"><code>41d1877</code></a>
chore: prepare tokio-test 0.4.5 (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7831">#7831</a>)</li>
<li><a
href="60b083b630"><code>60b083b</code></a>
chore: prepare tokio-stream 0.1.18 (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7830">#7830</a>)</li>
<li><a
href="9cc02cc88d"><code>9cc02cc</code></a>
chore: prepare tokio-util 0.7.18 (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7829">#7829</a>)</li>
<li><a
href="d2799d791b"><code>d2799d7</code></a>
task: improve the docs of <code>Builder::spawn_local</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7828">#7828</a>)</li>
<li><a
href="4d4870f291"><code>4d4870f</code></a>
task: doc that task drops before JoinHandle completion (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7825">#7825</a>)</li>
<li><a
href="fdb150901a"><code>fdb1509</code></a>
fs: check for io-uring opcode support (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7815">#7815</a>)</li>
<li><a
href="426a562780"><code>426a562</code></a>
rt: remove <code>allow(dead_code)</code> after <code>JoinSet</code>
stabilization (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7826">#7826</a>)</li>
<li><a
href="e3b89bbefa"><code>e3b89bb</code></a>
chore: prepare Tokio v1.49.0 (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7824">#7824</a>)</li>
<li><a
href="4f577b84e9"><code>4f577b8</code></a>
Merge 'tokio-1.47.3' into 'master'</li>
<li><a
href="f320197693"><code>f320197</code></a>
chore: prepare Tokio v1.47.3 (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7823">#7823</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/tokio-rs/tokio/compare/tokio-test-0.4.4...tokio-test-0.4.5">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Currently `apply_patch` will fail on Windows if the file contents happen
to have a multi-byte character at the point where the `preview` function
truncates.
I've used the existing `take_bytes_at_char_boundary` helper and added a
regression test (that fails without the fix).
This is related to #4013 but doesn't fix it.
# External (non-OpenAI) Pull Request Requirements
Before opening this Pull Request, please read the dedicated
"Contributing" markdown file or your PR may be closed:
https://github.com/openai/codex/blob/main/docs/contributing.md
If your PR conforms to our contribution guidelines, replace this text
with a detailed and high quality description of your changes.
Include a link to a bug report or enhancement request.
### Motivation
- Allow MCP OAuth flows to request scopes defined in `config.toml`
instead of requiring users to always pass `--scopes` on the CLI.
CLI/remote parameters should still override config values.
### Description
- Add optional `scopes: Option<Vec<String>>` to `McpServerConfig` and
`RawMcpServerConfig`, and propagate it through deserialization and the
built config types.
- Serialize `scopes` into the MCP server TOML via
`serialize_mcp_server_table` in `core/src/config/edit.rs` and include
`scopes` in the generated config schema (`core/config.schema.json`).
- CLI: update `codex-rs/cli/src/mcp_cmd.rs` `run_login` to fall back to
`server.scopes` when the `--scopes` flag is empty, with explicit CLI
scopes still taking precedence.
- App server: update
`codex-rs/app-server/src/codex_message_processor.rs`
`mcp_server_oauth_login` to use `params.scopes.or_else(||
server.scopes.clone())` so the RPC path also respects configured scopes.
- Update many test fixtures to initialize the new `scopes` field (set to
`None`) so test code builds with the new struct field.
### Testing
- Ran config tooling and formatters: `just write-config-schema`
(succeeded), `just fmt` (succeeded), and `just fix -p codex-core`, `just
fix -p codex-cli`, `just fix -p codex-app-server` (succeeded where
applicable).
- Ran unit tests for the CLI: `cargo test -p codex-cli` (passed).
- Ran unit tests for core: `cargo test -p codex-core` (ran; many tests
passed but several failed, including model refresh/403-related tests,
shell snapshot/timeouts, and several `unified_exec` expectations).
- Ran app-server tests: `cargo test -p codex-app-server` (ran; many
integration-suite tests failed due to mocked/remote HTTP 401/403
responses and wiremock expectations).
If you want, I can split the tests into smaller focused runs or help
debug the failing integration tests (they appear to be unrelated to the
config change and stem from external HTTP/mocking behaviors encountered
during the test runs).
------
[Codex
Task](https://chatgpt.com/codex/tasks/task_i_69718f505914832ea1f334b3ba064553)
We've recently standardized a [feature maturity
model](https://developers.openai.com/codex/feature-maturity) that we're
using in our docs and support forums to communicate expectations to
users. This PR updates the internal stage names and descriptions to
match.
This change involves a simple internal rename and updates to a few
user-visible strings. No functional change.
## Summary
- Adds a new `thread/unarchive` RPC to move archived thread rollouts
back into the active `sessions/` tree.
## What changed
- **Protocol**
- Adds `thread/unarchive` request/response types and wiring.
- **Server**
- Implements `thread_unarchive` in the app server.
- Validates the archived rollout path and thread ID.
- Restores the rollout to `sessions/YYYY/MM/DD/...` based on the rollout
filename timestamp.
- **Core**
- Adds `find_archived_thread_path_by_id_str` helper for archived
rollouts.
- **Docs**
- Documents the new RPC and usage example.
- **Tests**
- Adds an end-to-end server test that:
1) starts a thread,
2) archives it,
3) unarchives it,
4) asserts the file is restored to `sessions/`.
## How to use
```json
{ "method": "thread/unarchive", "id": 24, "params": { "threadId": "<thread-id>" } }
```
## Author Codex Session
`codex resume 019bf158-54b6-7960-a696-9d85df7e1bc1` (soon I'll make this
kind of session UUID forkable by anyone with the right
`session_object_storage_url` line in their config, but for now just
pasting it here for my reference)
# External (non-OpenAI) Pull Request Requirements
Before opening this Pull Request, please read the dedicated
"Contributing" markdown file or your PR may be closed:
https://github.com/openai/codex/blob/main/docs/contributing.md
If your PR conforms to our contribution guidelines, replace this text
with a detailed and high quality description of your changes.
Include a link to a bug report or enhancement request.
Reproduce with a prompt like this with collab enabled:
```
Examine the code at <some subdirectory with a deeply nested project>. Find the most urgent issue to resolve and describe it to me.
```
Existing behavior causes the top-level agent to busy wait on subagents.
### Summary
Add `isOther` to question object from request_user_input tool input and
remove `other` option from the tool prompt to better handle tool input.
I've seen this test fail with:
```
- Mock #1.
Expected range of matching incoming requests: == 2
Number of matched incoming requests: 1
```
This is because we pop the wrong task_complete events and then the test
exits. I think this is because the MCP events are now buffered after
https://github.com/openai/codex/pull/8874.
So:
1. clear the buffer before we do any user message sending
2. additionally listen for task start before task complete
3. use the ID from task start to find the correct task complete event.
Sessions' `updated_at` times are truncated to seconds, with the UUID
session ID used to break ties. If the two test sessions are created in
the same second, AND the session B UUID < session A UUID, the test
fails.
Fix this by mutating the session mtimes, from which we derive the
updated_at time, to ensure session B is updated_at later than session A.
## Summary
Add dynamic tool injection to thread startup in API v2, wire dynamic
tool calls through the app server to clients, and plumb responses back
into the model tool pipeline.
### Flow (high level)
- Thread start injects `dynamic_tools` into the model tool list for that
thread (validation is done here).
- When the model emits a tool call for one of those names, core raises a
`DynamicToolCallRequest` event.
- The app server forwards it to the client as `item/tool/call`, waits
for the client’s response, then submits a `DynamicToolResponse` back to
core.
- Core turns that into a `function_call_output` in the next model
request so the model can continue.
### What changed
- Added dynamic tool specs to v2 thread start params and protocol types;
introduced `item/tool/call` (request/response) for dynamic tool
execution.
- Core now registers dynamic tool specs at request time and routes those
calls via a new dynamic tool handler.
- App server validates tool names/schemas, forwards dynamic tool call
requests to clients, and publishes tool outputs back into the session.
- Integration tests
## Summary
Move `model_instructions_template` config to the experimental slug while
we iterate on this feature
## Testing
- [x] Tested locally, unit tests still pass
## Summary
Adds /personality selector in the TUI, which leverages the new core
interface in #9644
Notes:
- We are doing some of our own state management for model_info loading
here, but not sure if that's ideal. open to opinions on simpler
approach, but would like to avoid blocking on a larger refactor
- Right now, the `/personality` selector just hides when the model
doesn't support it. we can update this behavior down the line
## Testing
- [x] Tested locally
- [x] Added snapshot tests
2026-01-25 21:59:42 -08:00
1054 changed files with 131658 additions and 6555 deletions
@@ -15,10 +15,10 @@ Things to look out for when doing the review:
## Code Organization
- Each create in the Cargo workspace in `codex-rs` has a specific purpose: make a note if you believe new code is not introduced in the correct crate.
- Each crate in the Cargo workspace in `codex-rs` has a specific purpose: make a note if you believe new code is not introduced in the correct crate.
- When possible, try to keep the `core` crate as small as possible. Non-core but shared logic is often a good candidate for `codex-rs/common`.
- Be wary of large files and offer suggestions for how to break things into more reasonably-sized files.
- Rust files should generally be organized such that the public parts of the API appear near the top of the file and helper functions go below. This is analagous to the "inverted pyramid" structure that is favored in journalism.
- Rust files should generally be organized such that the public parts of the API appear near the top of the file and helper functions go below. This is analogous to the "inverted pyramid" structure that is favored in journalism.
- If applicable, add one of the following labels to specify which sub-product or product surface the issue relates to.
1. CLI — the Codex command line interface.
2. extension — VS Code (or other IDE) extension-specific issues.
3. codex-web — Issues targeting the Codex web UI/Cloud experience.
4. github-action — Issues with the Codex GitHub action.
5. iOS — Issues with the Codex iOS app.
3. app - Issues related to the Codex desktop application.
4. codex-web — Issues targeting the Codex web UI/Cloud experience.
5. github-action — Issues with the Codex GitHub action.
6. iOS — Issues with the Codex iOS app.
- Additionally add zero or more of the following labels that are relevant to the issue content. Prefer a small set of precise labels over many broad ones.
1. windows-os — Bugs or friction specific to Windows environments (always when PowerShell is mentioned, path handling, copy/paste, OS-specific auth or tooling failures).
"description":"Use to correlate this with [codex_core::protocol::PatchApplyBeginEvent] and [codex_core::protocol::PatchApplyEndEvent].",
"type":"string"
},
"conversationId":{
"$ref":"#/definitions/ThreadId"
},
"fileChanges":{
"additionalProperties":{
"$ref":"#/definitions/FileChange"
},
"type":"object"
},
"grantRoot":{
"description":"When set, the agent is asking the user to allow writes under this root for the remainder of the session (unclear if this is honored today).",
"type":[
"string",
"null"
]
},
"reason":{
"description":"Optional explanatory reason (e.g. request for extra write access).",
"description":"User has approved this command and wants to automatically approve any future identical instances (`command` and `cwd` match exactly) for the remainder of the session.",
"enum":[
"approved_for_session"
],
"type":"string"
},
{
"description":"User has denied this command and the agent should not execute it, but it should continue the session and try something else.",
"enum":[
"denied"
],
"type":"string"
},
{
"description":"User has denied this command and the agent should not do anything until the user's next command.",
"description":"Codex attempted a backend request and received `401 Unauthorized`.",
"enum":[
"unauthorized"
],
"type":"string"
}
]
}
},
"properties":{
"previousAccountId":{
"description":"Workspace/account identifier that Codex was previously using.\n\nClients that manage multiple accounts/workspaces can use this as a hint to refresh the token for the correct workspace.\n\nThis may be `null` when the prior ID token did not include a workspace identifier (`chatgpt_account_id`) or when the token could not be parsed.",
"description":"User approved the command and future identical commands should run without prompting.",
"enum":[
"acceptForSession"
],
"type":"string"
},
{
"additionalProperties":false,
"description":"User approved the command, and wants to apply the proposed execpolicy amendment so future matching commands can run without prompting.",
"description":"(Best effort) Path to the file being read by the command. When possible, this is an absolute path, though when relative, it should be resolved against the `cwd`` that will be used to run the command to derive the absolute path.",
"type":"string"
},
"type":{
"enum":[
"read"
],
"title":"ReadParsedCommandType",
"type":"string"
}
},
"required":[
"cmd",
"name",
"path",
"type"
],
"title":"ReadParsedCommand",
"type":"object"
},
{
"properties":{
"cmd":{
"type":"string"
},
"path":{
"type":[
"string",
"null"
]
},
"type":{
"enum":[
"list_files"
],
"title":"ListFilesParsedCommandType",
"type":"string"
}
},
"required":[
"cmd",
"type"
],
"title":"ListFilesParsedCommand",
"type":"object"
},
{
"properties":{
"cmd":{
"type":"string"
},
"path":{
"type":[
"string",
"null"
]
},
"query":{
"type":[
"string",
"null"
]
},
"type":{
"enum":[
"search"
],
"title":"SearchParsedCommandType",
"type":"string"
}
},
"required":[
"cmd",
"type"
],
"title":"SearchParsedCommand",
"type":"object"
},
{
"properties":{
"cmd":{
"type":"string"
},
"type":{
"enum":[
"unknown"
],
"title":"UnknownParsedCommandType",
"type":"string"
}
},
"required":[
"cmd",
"type"
],
"title":"UnknownParsedCommand",
"type":"object"
}
]
},
"ThreadId":{
"type":"string"
}
},
"properties":{
"callId":{
"description":"Use to correlate this with [codex_core::protocol::ExecCommandBeginEvent] and [codex_core::protocol::ExecCommandEndEvent].",
"description":"User has approved this command and wants to automatically approve any future identical instances (`command` and `cwd` match exactly) for the remainder of the session.",
"enum":[
"approved_for_session"
],
"type":"string"
},
{
"description":"User has denied this command and the agent should not execute it, but it should continue the session and try something else.",
"enum":[
"denied"
],
"type":"string"
},
{
"description":"User has denied this command and the agent should not do anything until the user's next command.",
"description":"[UNSTABLE] When set, the agent is asking the user to allow writes under this root for the remainder of the session (unclear if this is honored today).",
"type":[
"string",
"null"
]
},
"itemId":{
"type":"string"
},
"reason":{
"description":"Optional explanatory reason (e.g. request for extra write access).",
"description":"Use to correlate this with [codex_core::protocol::PatchApplyBeginEvent] and [codex_core::protocol::PatchApplyEndEvent].",
"type":"string"
},
"conversationId":{
"$ref":"#/definitions/ThreadId"
},
"fileChanges":{
"additionalProperties":{
"$ref":"#/definitions/FileChange"
},
"type":"object"
},
"grantRoot":{
"description":"When set, the agent is asking the user to allow writes under this root for the remainder of the session (unclear if this is honored today).",
"type":[
"string",
"null"
]
},
"reason":{
"description":"Optional explanatory reason (e.g. request for extra write access).",
"type":[
"string",
"null"
]
}
},
"required":[
"callId",
"conversationId",
"fileChanges"
],
"type":"object"
},
"ChatgptAuthTokensRefreshParams":{
"properties":{
"previousAccountId":{
"description":"Workspace/account identifier that Codex was previously using.\n\nClients that manage multiple accounts/workspaces can use this as a hint to refresh the token for the correct workspace.\n\nThis may be `null` when the prior ID token did not include a workspace identifier (`chatgpt_account_id`) or when the token could not be parsed.",
"description":"Codex attempted a backend request and received `401 Unauthorized`.",
"enum":[
"unauthorized"
],
"type":"string"
}
]
},
"CommandAction":{
"oneOf":[
{
"properties":{
"command":{
"type":"string"
},
"name":{
"type":"string"
},
"path":{
"type":"string"
},
"type":{
"enum":[
"read"
],
"title":"ReadCommandActionType",
"type":"string"
}
},
"required":[
"command",
"name",
"path",
"type"
],
"title":"ReadCommandAction",
"type":"object"
},
{
"properties":{
"command":{
"type":"string"
},
"path":{
"type":[
"string",
"null"
]
},
"type":{
"enum":[
"listFiles"
],
"title":"ListFilesCommandActionType",
"type":"string"
}
},
"required":[
"command",
"type"
],
"title":"ListFilesCommandAction",
"type":"object"
},
{
"properties":{
"command":{
"type":"string"
},
"path":{
"type":[
"string",
"null"
]
},
"query":{
"type":[
"string",
"null"
]
},
"type":{
"enum":[
"search"
],
"title":"SearchCommandActionType",
"type":"string"
}
},
"required":[
"command",
"type"
],
"title":"SearchCommandAction",
"type":"object"
},
{
"properties":{
"command":{
"type":"string"
},
"type":{
"enum":[
"unknown"
],
"title":"UnknownCommandActionType",
"type":"string"
}
},
"required":[
"command",
"type"
],
"title":"UnknownCommandAction",
"type":"object"
}
]
},
"CommandExecutionRequestApprovalParams":{
"properties":{
"command":{
"description":"The command to be executed.",
"type":[
"string",
"null"
]
},
"commandActions":{
"description":"Best-effort parsed command actions for friendly display.",
"items":{
"$ref":"#/definitions/CommandAction"
},
"type":[
"array",
"null"
]
},
"cwd":{
"description":"The command's working directory.",
"type":[
"string",
"null"
]
},
"itemId":{
"type":"string"
},
"proposedExecpolicyAmendment":{
"description":"Optional proposed execpolicy amendment to allow similar commands without prompting.",
"items":{
"type":"string"
},
"type":[
"array",
"null"
]
},
"reason":{
"description":"Optional explanatory reason (e.g. request for network access).",
"type":[
"string",
"null"
]
},
"threadId":{
"type":"string"
},
"turnId":{
"type":"string"
}
},
"required":[
"itemId",
"threadId",
"turnId"
],
"type":"object"
},
"DynamicToolCallParams":{
"properties":{
"arguments":true,
"callId":{
"type":"string"
},
"threadId":{
"type":"string"
},
"tool":{
"type":"string"
},
"turnId":{
"type":"string"
}
},
"required":[
"arguments",
"callId",
"threadId",
"tool",
"turnId"
],
"type":"object"
},
"ExecCommandApprovalParams":{
"properties":{
"callId":{
"description":"Use to correlate this with [codex_core::protocol::ExecCommandBeginEvent] and [codex_core::protocol::ExecCommandEndEvent].",
"type":"string"
},
"command":{
"items":{
"type":"string"
},
"type":"array"
},
"conversationId":{
"$ref":"#/definitions/ThreadId"
},
"cwd":{
"type":"string"
},
"parsedCmd":{
"items":{
"$ref":"#/definitions/ParsedCommand"
},
"type":"array"
},
"reason":{
"type":[
"string",
"null"
]
}
},
"required":[
"callId",
"command",
"conversationId",
"cwd",
"parsedCmd"
],
"type":"object"
},
"FileChange":{
"oneOf":[
{
"properties":{
"content":{
"type":"string"
},
"type":{
"enum":[
"add"
],
"title":"AddFileChangeType",
"type":"string"
}
},
"required":[
"content",
"type"
],
"title":"AddFileChange",
"type":"object"
},
{
"properties":{
"content":{
"type":"string"
},
"type":{
"enum":[
"delete"
],
"title":"DeleteFileChangeType",
"type":"string"
}
},
"required":[
"content",
"type"
],
"title":"DeleteFileChange",
"type":"object"
},
{
"properties":{
"move_path":{
"type":[
"string",
"null"
]
},
"type":{
"enum":[
"update"
],
"title":"UpdateFileChangeType",
"type":"string"
},
"unified_diff":{
"type":"string"
}
},
"required":[
"type",
"unified_diff"
],
"title":"UpdateFileChange",
"type":"object"
}
]
},
"FileChangeRequestApprovalParams":{
"properties":{
"grantRoot":{
"description":"[UNSTABLE] When set, the agent is asking the user to allow writes under this root for the remainder of the session (unclear if this is honored today).",
"type":[
"string",
"null"
]
},
"itemId":{
"type":"string"
},
"reason":{
"description":"Optional explanatory reason (e.g. request for extra write access).",
"type":[
"string",
"null"
]
},
"threadId":{
"type":"string"
},
"turnId":{
"type":"string"
}
},
"required":[
"itemId",
"threadId",
"turnId"
],
"type":"object"
},
"ParsedCommand":{
"oneOf":[
{
"properties":{
"cmd":{
"type":"string"
},
"name":{
"type":"string"
},
"path":{
"description":"(Best effort) Path to the file being read by the command. When possible, this is an absolute path, though when relative, it should be resolved against the `cwd`` that will be used to run the command to derive the absolute path.",
"type":"string"
},
"type":{
"enum":[
"read"
],
"title":"ReadParsedCommandType",
"type":"string"
}
},
"required":[
"cmd",
"name",
"path",
"type"
],
"title":"ReadParsedCommand",
"type":"object"
},
{
"properties":{
"cmd":{
"type":"string"
},
"path":{
"type":[
"string",
"null"
]
},
"type":{
"enum":[
"list_files"
],
"title":"ListFilesParsedCommandType",
"type":"string"
}
},
"required":[
"cmd",
"type"
],
"title":"ListFilesParsedCommand",
"type":"object"
},
{
"properties":{
"cmd":{
"type":"string"
},
"path":{
"type":[
"string",
"null"
]
},
"query":{
"type":[
"string",
"null"
]
},
"type":{
"enum":[
"search"
],
"title":"SearchParsedCommandType",
"type":"string"
}
},
"required":[
"cmd",
"type"
],
"title":"SearchParsedCommand",
"type":"object"
},
{
"properties":{
"cmd":{
"type":"string"
},
"type":{
"enum":[
"unknown"
],
"title":"UnknownParsedCommandType",
"type":"string"
}
},
"required":[
"cmd",
"type"
],
"title":"UnknownParsedCommand",
"type":"object"
}
]
},
"RequestId":{
"anyOf":[
{
"type":"string"
},
{
"format":"int64",
"type":"integer"
}
]
},
"ThreadId":{
"type":"string"
},
"ToolRequestUserInputOption":{
"description":"EXPERIMENTAL. Defines a single selectable option for request_user_input.",
"properties":{
"description":{
"type":"string"
},
"label":{
"type":"string"
}
},
"required":[
"description",
"label"
],
"type":"object"
},
"ToolRequestUserInputParams":{
"description":"EXPERIMENTAL. Params sent with a request_user_input event.",
"description":"DEPRECATED APIs below Request to approve a patch. This request is used for Turns started via the legacy APIs (i.e. SendUserTurn, SendUserMessage).",
"properties":{
"id":{
"$ref":"#/definitions/RequestId"
},
"method":{
"enum":[
"applyPatchApproval"
],
"title":"ApplyPatchApprovalRequestMethod",
"type":"string"
},
"params":{
"$ref":"#/definitions/ApplyPatchApprovalParams"
}
},
"required":[
"id",
"method",
"params"
],
"title":"ApplyPatchApprovalRequest",
"type":"object"
},
{
"description":"Request to exec a command. This request is used for Turns started via the legacy APIs (i.e. SendUserTurn, SendUserMessage).",
"description":"Authentication mode for OpenAI-backed providers.",
"oneOf":[
{
"description":"OpenAI API key provided by the caller and stored by Codex.",
"enum":[
"apikey"
],
"type":"string"
},
{
"description":"ChatGPT OAuth managed by Codex (tokens persisted and refreshed by Codex).",
"enum":[
"chatgpt"
],
"type":"string"
},
{
"description":"[UNSTABLE] FOR OPENAI INTERNAL USE ONLY - DO NOT USE.\n\nChatGPT auth tokens are supplied by an external host app and are only stored in memory. Token refresh must be handled by the external host app.",
"enum":[
"chatgptAuthTokens"
],
"type":"string"
}
]
}
},
"description":"Deprecated notification. Use AccountUpdatedNotification instead.",
"description":"A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
"type":"string"
},
"NetworkAccess":{
"description":"Represents whether outbound network access is available to the agent.",
"enum":[
"restricted",
"enabled"
],
"type":"string"
},
"SandboxPolicy":{
"description":"Determines execution restrictions for model shell commands.",
"oneOf":[
{
"description":"No restrictions whatsoever. Use with caution.",
"properties":{
"type":{
"enum":[
"danger-full-access"
],
"title":"DangerFullAccessSandboxPolicyType",
"type":"string"
}
},
"required":[
"type"
],
"title":"DangerFullAccessSandboxPolicy",
"type":"object"
},
{
"description":"Read-only access to the entire file-system.",
"properties":{
"type":{
"enum":[
"read-only"
],
"title":"ReadOnlySandboxPolicyType",
"type":"string"
}
},
"required":[
"type"
],
"title":"ReadOnlySandboxPolicy",
"type":"object"
},
{
"description":"Indicates the process is already in an external sandbox. Allows full disk access while honoring the provided network setting.",
"properties":{
"network_access":{
"allOf":[
{
"$ref":"#/definitions/NetworkAccess"
}
],
"default":"restricted",
"description":"Whether the external sandbox permits outbound network traffic."
},
"type":{
"enum":[
"external-sandbox"
],
"title":"ExternalSandboxSandboxPolicyType",
"type":"string"
}
},
"required":[
"type"
],
"title":"ExternalSandboxSandboxPolicy",
"type":"object"
},
{
"description":"Same as `ReadOnly` but additionally grants write access to the current working directory (\"workspace\").",
"properties":{
"exclude_slash_tmp":{
"default":false,
"description":"When set to `true`, will NOT include the `/tmp` among the default writable roots on UNIX. Defaults to `false`.",
"type":"boolean"
},
"exclude_tmpdir_env_var":{
"default":false,
"description":"When set to `true`, will NOT include the per-user `TMPDIR` environment variable among the default writable roots. Defaults to `false`.",
"type":"boolean"
},
"network_access":{
"default":false,
"description":"When set to `true`, outbound network access is allowed. `false` by default.",
"type":"boolean"
},
"type":{
"enum":[
"workspace-write"
],
"title":"WorkspaceWriteSandboxPolicyType",
"type":"string"
},
"writable_roots":{
"description":"Additional folders (beyond cwd and possibly TMPDIR) that should be writable from within the sandbox.",
"description":"Determines the conditions under which the user is consulted to approve running the command proposed by Codex.",
"oneOf":[
{
"description":"Under this policy, only \"known safe\" commands—as determined by `is_safe_command()`—that **only read files** are auto‑approved. Everything else will ask the user to approve.",
"enum":[
"untrusted"
],
"type":"string"
},
{
"description":"*All* commands are auto‑approved, but they are expected to run inside a sandbox where network access is disabled and writes are confined to a specific set of paths. If the command fails, it will be escalated to the user to approve execution without a sandbox.",
"enum":[
"on-failure"
],
"type":"string"
},
{
"description":"The model decides when to ask the user for approval.",
"enum":[
"on-request"
],
"type":"string"
},
{
"description":"Never ask the user to approve commands. Failures are immediately returned to the model, and never escalated to the user for approval.",
"description":"Authentication mode for OpenAI-backed providers.",
"oneOf":[
{
"description":"OpenAI API key provided by the caller and stored by Codex.",
"enum":[
"apikey"
],
"type":"string"
},
{
"description":"ChatGPT OAuth managed by Codex (tokens persisted and refreshed by Codex).",
"enum":[
"chatgpt"
],
"type":"string"
},
{
"description":"[UNSTABLE] FOR OPENAI INTERNAL USE ONLY - DO NOT USE.\n\nChatGPT auth tokens are supplied by an external host app and are only stored in memory. Token refresh must be handled by the external host app.",
"description":"A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
"type":"string"
},
"AskForApproval":{
"description":"Determines the conditions under which the user is consulted to approve running the command proposed by Codex.",
"oneOf":[
{
"description":"Under this policy, only \"known safe\" commands—as determined by `is_safe_command()`—that **only read files** are auto‑approved. Everything else will ask the user to approve.",
"enum":[
"untrusted"
],
"type":"string"
},
{
"description":"*All* commands are auto‑approved, but they are expected to run inside a sandbox where network access is disabled and writes are confined to a specific set of paths. If the command fails, it will be escalated to the user to approve execution without a sandbox.",
"enum":[
"on-failure"
],
"type":"string"
},
{
"description":"The model decides when to ask the user for approval.",
"enum":[
"on-request"
],
"type":"string"
},
{
"description":"Never ask the user to approve commands. Failures are immediately returned to the model, and never escalated to the user for approval.",
"description":"A summary of the reasoning performed by the model. This can be useful for debugging and understanding the model's reasoning process. See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#reasoning-summaries",
"oneOf":[
{
"enum":[
"auto",
"concise",
"detailed"
],
"type":"string"
},
{
"description":"Option to disable reasoning summaries.",
"enum":[
"none"
],
"type":"string"
}
]
},
"SandboxMode":{
"enum":[
"read-only",
"workspace-write",
"danger-full-access"
],
"type":"string"
},
"SandboxSettings":{
"properties":{
"excludeSlashTmp":{
"type":[
"boolean",
"null"
]
},
"excludeTmpdirEnvVar":{
"type":[
"boolean",
"null"
]
},
"networkAccess":{
"type":[
"boolean",
"null"
]
},
"writableRoots":{
"default":[],
"items":{
"$ref":"#/definitions/AbsolutePathBuf"
},
"type":"array"
}
},
"type":"object"
},
"Tools":{
"properties":{
"viewImage":{
"type":[
"boolean",
"null"
]
},
"webSearch":{
"type":[
"boolean",
"null"
]
}
},
"type":"object"
},
"UserSavedConfig":{
"properties":{
"approvalPolicy":{
"anyOf":[
{
"$ref":"#/definitions/AskForApproval"
},
{
"type":"null"
}
]
},
"forcedChatgptWorkspaceId":{
"type":[
"string",
"null"
]
},
"forcedLoginMethod":{
"anyOf":[
{
"$ref":"#/definitions/ForcedLoginMethod"
},
{
"type":"null"
}
]
},
"model":{
"type":[
"string",
"null"
]
},
"modelReasoningEffort":{
"anyOf":[
{
"$ref":"#/definitions/ReasoningEffort"
},
{
"type":"null"
}
]
},
"modelReasoningSummary":{
"anyOf":[
{
"$ref":"#/definitions/ReasoningSummary"
},
{
"type":"null"
}
]
},
"modelVerbosity":{
"anyOf":[
{
"$ref":"#/definitions/Verbosity"
},
{
"type":"null"
}
]
},
"profile":{
"type":[
"string",
"null"
]
},
"profiles":{
"additionalProperties":{
"$ref":"#/definitions/Profile"
},
"type":"object"
},
"sandboxMode":{
"anyOf":[
{
"$ref":"#/definitions/SandboxMode"
},
{
"type":"null"
}
]
},
"sandboxSettings":{
"anyOf":[
{
"$ref":"#/definitions/SandboxSettings"
},
{
"type":"null"
}
]
},
"tools":{
"anyOf":[
{
"$ref":"#/definitions/Tools"
},
{
"type":"null"
}
]
}
},
"required":[
"profiles"
],
"type":"object"
},
"Verbosity":{
"description":"Controls output length/detail on GPT-5 models via the Responses API. Serialized with lowercase values to match the OpenAI API.",
"description":"Determines the conditions under which the user is consulted to approve running the command proposed by Codex.",
"oneOf":[
{
"description":"Under this policy, only \"known safe\" commands—as determined by `is_safe_command()`—that **only read files** are auto‑approved. Everything else will ask the user to approve.",
"enum":[
"untrusted"
],
"type":"string"
},
{
"description":"*All* commands are auto‑approved, but they are expected to run inside a sandbox where network access is disabled and writes are confined to a specific set of paths. If the command fails, it will be escalated to the user to approve execution without a sandbox.",
"enum":[
"on-failure"
],
"type":"string"
},
{
"description":"The model decides when to ask the user for approval.",
"enum":[
"on-request"
],
"type":"string"
},
{
"description":"Never ask the user to approve commands. Failures are immediately returned to the model, and never escalated to the user for approval.",
"description":"Determines the conditions under which the user is consulted to approve running the command proposed by Codex.",
"oneOf":[
{
"description":"Under this policy, only \"known safe\" commands—as determined by `is_safe_command()`—that **only read files** are auto‑approved. Everything else will ask the user to approve.",
"enum":[
"untrusted"
],
"type":"string"
},
{
"description":"*All* commands are auto‑approved, but they are expected to run inside a sandbox where network access is disabled and writes are confined to a specific set of paths. If the command fails, it will be escalated to the user to approve execution without a sandbox.",
"enum":[
"on-failure"
],
"type":"string"
},
{
"description":"The model decides when to ask the user for approval.",
"enum":[
"on-request"
],
"type":"string"
},
{
"description":"Never ask the user to approve commands. Failures are immediately returned to the model, and never escalated to the user for approval.",
"enum":[
"never"
],
"type":"string"
}
]
},
"ContentItem":{
"oneOf":[
{
"properties":{
"text":{
"type":"string"
},
"type":{
"enum":[
"input_text"
],
"title":"InputTextContentItemType",
"type":"string"
}
},
"required":[
"text",
"type"
],
"title":"InputTextContentItem",
"type":"object"
},
{
"properties":{
"image_url":{
"type":"string"
},
"type":{
"enum":[
"input_image"
],
"title":"InputImageContentItemType",
"type":"string"
}
},
"required":[
"image_url",
"type"
],
"title":"InputImageContentItem",
"type":"object"
},
{
"properties":{
"text":{
"type":"string"
},
"type":{
"enum":[
"output_text"
],
"title":"OutputTextContentItemType",
"type":"string"
}
},
"required":[
"text",
"type"
],
"title":"OutputTextContentItem",
"type":"object"
}
]
},
"FunctionCallOutputContentItem":{
"description":"Responses API compatible content items that can be returned by a tool call. This is a subset of ContentItem with the types we support as function call outputs.",
"description":"The payload we send back to OpenAI when reporting a tool call result.\n\n`content` preserves the historical plain-string payload so downstream integrations (tests, logging, etc.) can keep treating tool output as `String`. When an MCP server returns richer data we additionally populate `content_items` with the structured form that the Responses/Chat Completions APIs understand.",
"description":"A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
"type":"string"
},
"AskForApproval":{
"description":"Determines the conditions under which the user is consulted to approve running the command proposed by Codex.",
"oneOf":[
{
"description":"Under this policy, only \"known safe\" commands—as determined by `is_safe_command()`—that **only read files** are auto‑approved. Everything else will ask the user to approve.",
"enum":[
"untrusted"
],
"type":"string"
},
{
"description":"*All* commands are auto‑approved, but they are expected to run inside a sandbox where network access is disabled and writes are confined to a specific set of paths. If the command fails, it will be escalated to the user to approve execution without a sandbox.",
"enum":[
"on-failure"
],
"type":"string"
},
{
"description":"The model decides when to ask the user for approval.",
"enum":[
"on-request"
],
"type":"string"
},
{
"description":"Never ask the user to approve commands. Failures are immediately returned to the model, and never escalated to the user for approval.",
"enum":[
"never"
],
"type":"string"
}
]
},
"InputItem":{
"oneOf":[
{
"properties":{
"data":{
"properties":{
"text":{
"type":"string"
},
"text_elements":{
"default":[],
"description":"UI-defined spans within `text` used to render or persist special elements.",
"items":{
"$ref":"#/definitions/V1TextElement"
},
"type":"array"
}
},
"required":[
"text"
],
"type":"object"
},
"type":{
"enum":[
"text"
],
"title":"TextInputItemType",
"type":"string"
}
},
"required":[
"data",
"type"
],
"title":"TextInputItem",
"type":"object"
},
{
"properties":{
"data":{
"properties":{
"image_url":{
"type":"string"
}
},
"required":[
"image_url"
],
"type":"object"
},
"type":{
"enum":[
"image"
],
"title":"ImageInputItemType",
"type":"string"
}
},
"required":[
"data",
"type"
],
"title":"ImageInputItem",
"type":"object"
},
{
"properties":{
"data":{
"properties":{
"path":{
"type":"string"
}
},
"required":[
"path"
],
"type":"object"
},
"type":{
"enum":[
"localImage"
],
"title":"LocalImageInputItemType",
"type":"string"
}
},
"required":[
"data",
"type"
],
"title":"LocalImageInputItem",
"type":"object"
}
]
},
"NetworkAccess":{
"description":"Represents whether outbound network access is available to the agent.",
"description":"A summary of the reasoning performed by the model. This can be useful for debugging and understanding the model's reasoning process. See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#reasoning-summaries",
"oneOf":[
{
"enum":[
"auto",
"concise",
"detailed"
],
"type":"string"
},
{
"description":"Option to disable reasoning summaries.",
"enum":[
"none"
],
"type":"string"
}
]
},
"SandboxPolicy":{
"description":"Determines execution restrictions for model shell commands.",
"oneOf":[
{
"description":"No restrictions whatsoever. Use with caution.",
"properties":{
"type":{
"enum":[
"danger-full-access"
],
"title":"DangerFullAccessSandboxPolicyType",
"type":"string"
}
},
"required":[
"type"
],
"title":"DangerFullAccessSandboxPolicy",
"type":"object"
},
{
"description":"Read-only access to the entire file-system.",
"properties":{
"type":{
"enum":[
"read-only"
],
"title":"ReadOnlySandboxPolicyType",
"type":"string"
}
},
"required":[
"type"
],
"title":"ReadOnlySandboxPolicy",
"type":"object"
},
{
"description":"Indicates the process is already in an external sandbox. Allows full disk access while honoring the provided network setting.",
"properties":{
"network_access":{
"allOf":[
{
"$ref":"#/definitions/NetworkAccess"
}
],
"default":"restricted",
"description":"Whether the external sandbox permits outbound network traffic."
},
"type":{
"enum":[
"external-sandbox"
],
"title":"ExternalSandboxSandboxPolicyType",
"type":"string"
}
},
"required":[
"type"
],
"title":"ExternalSandboxSandboxPolicy",
"type":"object"
},
{
"description":"Same as `ReadOnly` but additionally grants write access to the current working directory (\"workspace\").",
"properties":{
"exclude_slash_tmp":{
"default":false,
"description":"When set to `true`, will NOT include the `/tmp` among the default writable roots on UNIX. Defaults to `false`.",
"type":"boolean"
},
"exclude_tmpdir_env_var":{
"default":false,
"description":"When set to `true`, will NOT include the per-user `TMPDIR` environment variable among the default writable roots. Defaults to `false`.",
"type":"boolean"
},
"network_access":{
"default":false,
"description":"When set to `true`, outbound network access is allowed. `false` by default.",
"type":"boolean"
},
"type":{
"enum":[
"workspace-write"
],
"title":"WorkspaceWriteSandboxPolicyType",
"type":"string"
},
"writable_roots":{
"description":"Additional folders (beyond cwd and possibly TMPDIR) that should be writable from within the sandbox.",
"items":{
"$ref":"#/definitions/AbsolutePathBuf"
},
"type":"array"
}
},
"required":[
"type"
],
"title":"WorkspaceWriteSandboxPolicy",
"type":"object"
}
]
},
"ThreadId":{
"type":"string"
},
"V1ByteRange":{
"properties":{
"end":{
"description":"End byte offset (exclusive) within the UTF-8 text buffer.",
"format":"uint",
"minimum":0.0,
"type":"integer"
},
"start":{
"description":"Start byte offset (inclusive) within the UTF-8 text buffer.",
"format":"uint",
"minimum":0.0,
"type":"integer"
}
},
"required":[
"end",
"start"
],
"type":"object"
},
"V1TextElement":{
"properties":{
"byteRange":{
"allOf":[
{
"$ref":"#/definitions/V1ByteRange"
}
],
"description":"Byte range in the parent `text` buffer that this element occupies."
},
"placeholder":{
"description":"Optional human-readable placeholder for the element, displayed in the UI.",
"type":[
"string",
"null"
]
}
},
"required":[
"byteRange"
],
"type":"object"
}
},
"properties":{
"approvalPolicy":{
"$ref":"#/definitions/AskForApproval"
},
"conversationId":{
"$ref":"#/definitions/ThreadId"
},
"cwd":{
"type":"string"
},
"effort":{
"anyOf":[
{
"$ref":"#/definitions/ReasoningEffort"
},
{
"type":"null"
}
]
},
"items":{
"items":{
"$ref":"#/definitions/InputItem"
},
"type":"array"
},
"model":{
"type":"string"
},
"outputSchema":{
"description":"Optional JSON Schema used to constrain the final assistant message for this turn."
"description":"Authentication mode for OpenAI-backed providers.",
"oneOf":[
{
"description":"OpenAI API key provided by the caller and stored by Codex.",
"enum":[
"apikey"
],
"type":"string"
},
{
"description":"ChatGPT OAuth managed by Codex (tokens persisted and refreshed by Codex).",
"enum":[
"chatgpt"
],
"type":"string"
},
{
"description":"[UNSTABLE] FOR OPENAI INTERNAL USE ONLY - DO NOT USE.\n\nChatGPT auth tokens are supplied by an external host app and are only stored in memory. Token refresh must be handled by the external host app.",
"description":"Opaque pagination cursor returned by a previous call.",
"type":[
"string",
"null"
]
},
"limit":{
"description":"Optional page size; defaults to a reasonable server-side value.",
"format":"uint32",
"minimum":0.0,
"type":[
"integer",
"null"
]
}
},
"title":"AppsListParams",
"type":"object"
}
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.