Commit Graph
3356 Commits
Author SHA1 Message Date
jif-oai a7eda6a29b ## New Features
- The TUI now syntax-highlights fenced code blocks and diffs, adds a `/theme` picker with live preview, and uses better theme-aware diff colors for light and dark terminals. (#11447, #12581)
- You can now dictate prompts by holding the spacebar to record and transcribe voice input directly in the TUI. (#3381)
- Multi-agent workflows are easier to run and track: `spawn_agents_on_csv` can fan out work from a CSV with built-in progress/ETA, and sub-agents are easier to follow with nicknames, a cleaner picker, and visible child-thread approval prompts. (#10935, #12320, #12327, #12332, #12570, #12767)
- The TUI picked up new convenience commands: `/copy` copies the latest complete assistant reply, while `/clear` and `Ctrl-L` clear the screen without losing thread context, with `/clear` also able to start a fresh chat. (#12444, #12520, #12613, #12628)
- Approval controls are more flexible: Codex can now ask for extra sandbox permissions for a command, and you can auto-reject specific approval prompt types without turning approvals off entirely. (#11871, #12087)
- App-server clients can do more with threads: `thread/list` can search by title, thread status is exposed in read/list responses and notifications, and `thread/resume` returns the latest turn inline so reconnects are less lossy. (#11776, #11786, #12578)

## Bug Fixes
- Long links in the TUI stay clickable when wrapped, which also fixes related clipping and layout issues in several views. (#12067)
- Several TUI interaction edge cases were fixed: queued-message editing now works in more terminals, follow-up prompts no longer get stuck if you press Enter while a final answer is still streaming, and approval dialogs now respond with the correct request id. (#12240, #12569, #12746)
- `@` parsing in the chat composer is more reliable, so commands like `npx -y @scope/pkg@latest` no longer accidentally open the file picker or block submission. (#12643)
- App-server websocket handling is more robust: thread listeners survive disconnects, Ctrl-C waits for in-flight turns before restarting, and websocket clients that send `permessage-deflate` can connect successfully. (#12373, #12517, #12629)
- Linux sandboxed commands now get a minimal `/dev`, fixing failures in tools that need entropy or other standard device nodes. (#12081)
- `js_repl` now reports uncaught kernel failures more clearly, recovers cleanly afterward, and correctly attaches `view_image` results from nested tool calls. (#12636, #12725)

## Documentation
- Added a public security policy with Bugcrowd reporting guidance. (#12193)
- Updated install and local workflow docs to use `cargo install --locked cargo-nextest` and to avoid routine `--all-features` builds unless you specifically need full feature coverage. (#12377, #12429)

## Changelog

Full Changelog: https://github.com/openai/codex/compare/rust-v0.104.0...rust-v0.105.0

- #12071 Use V2 websockets if feature enabled @pakrym-oai
- #12052 feat(core): zsh exec bridge @owenlin0
- #12072 Add message phase to agent message thread item @mousseau-oai
- #12077 got rid of experimental_mode for configtoml @won-openai
- #12036 codex-api: realtime websocket session.create + typed inbound events @aibrahim-oai
- #12073 Add model-visible context layout snapshot tests @charley-oai
- #12096 Updated issue labeler script to include safety-check label @etraut-openai
- #11944 [js_repl] paths for node module resolution can be specified for js_repl @aaronl-openai
- #11798 fix: Restricted Read: /System is too permissive for macOS platform de… @leoshimo-oai
- #12015 Enable default status line indicators in TUI config @jif-oai
- #12124 feat: phase 1 and phase 2 e2e latencies @jif-oai
- #12121 feat: phase 2 usage @jif-oai
- #12120 feat: memory usage metrics @jif-oai
- #12133 feat: validate agent config file paths @jif-oai
- #12137 nit: change model for phase 1 @jif-oai
- #12069 Stop filtering model tools in js_repl_tools_only mode @fjord-oai
- #12135 feat: better slug for rollout summaries @jif-oai
- #12157 Disable collab tools during review delegation @jif-oai
- #11802 Fixed a hole in token refresh logic for app server @etraut-openai
- #12105 fix: file watcher @jif-oai
- #12167 memories: bump rollout summary slug cap to 60 @zuxin-oai
- #12177 js_repl: canonicalize paths for node_modules boundary checks @fjord-oai
- #12025 app-server support for Windows sandbox setup. @iceweasel-oai
- #12187 fix: Remove citation @zuxin-oai
- #12180 [apps] Temporary app block. @mzeng-openai
- #11786 app-server: expose loaded thread status via read/list and notifications @euroelessar
- #12038 state: enforce 10 MiB log caps for thread and threadless process logs @charley-oai
- #12203 Stabilize app-server detached review and running-resume tests @charley-oai
- #12211 [apps] Update apps allowlist. @mzeng-openai
- #12081 fix(linux-sandbox): mount /dev in bwrap sandbox @viyatb-oai
- #12164 Update docs links for feature flag notice @etraut-openai
- #12231 Adjust memories rollout defaults @jif-oai
- #12152 feat: sub-agent injection @jif-oai
- #12233 feat: add shell snapshot failure reason @jif-oai
- #12193 docs: add codex security policy @viyatb-oai
- #12228 feat: add configurable write_stdin timeout @jif-oai
- #11787 Adjust MCP tool approval handling for custom servers @colby-oai
- #12179 Move previous turn context tracking into ContextManager history @charley-oai
- #12244 Restore phase when loading from history @mousseau-oai
- #12101 client side modelinfo overrides @sayan-oai
- #12251 Add configurable agent spawn depth @jif-oai
- #12254 chore: increase stack size for everyone @jif-oai
- #12250 feat: no timeout mode on ue @jif-oai
- #12255 chore: consolidate new() and initialize() for McpConnectionManager @bolinfest
- #12256 Revert "feat: no timeout mode on ue" @jif-oai
- #12258 Undo stack size Bazel test hack @charley-oai
- #12264 Fix flaky test @jif-oai
- #12087 feat: add Reject approval policy with granular prompt rejection controls @bolinfest
- #12253 Skip removed features during metrics emission @jif-oai
- #12265 Clarify cumulative proposed_plan behavior in Plan mode @charley-oai
- #12266 app-server tests: reduce intermittent nextest LEAK via graceful child shutdown @bolinfest
- #11953 ws turn metadata via client_metadata @pash-openai
- #11778 fix(bazel): replace askama templates with include_str! in memories @rupurt
- #11382 Add configurable MCP OAuth callback URL for MCP login @dkumar-oai
- #12274 [bazel] Fix proc_macro_dep libs @zbarsky-openai
- #12054 feat(config): add permissions.network proxy config wiring @viyatb-oai
- #12269 tests(thread_resume): interrupt running turns in resume error-path tests @bolinfest
- #12009 Update pnpm versions to fix cve-2026-24842 @mjr-openai
- #12080 skill-creator: lazy-load PyYAML in frontmatter parsing @xl-openai
- #12271 tests: centralize in-flight turn cleanup helper @bolinfest
- #12286 app-server: fix flaky list_apps_returns_connectors_with_accessible_flags test @bolinfest
- #11776 app-server: improve thread resume rejoin flow @maxj-oai
- #11822 [apps] Store apps tool cache in disk to reduce startup time. @mzeng-openai
- #12221 memories: add rollout_summary_file header to raw memories and tune prompts @zuxin-oai
- #12309 Set memories phase reasoning effort constants @jif-oai
- #12315 chore: nit explorer @jif-oai
- #12320 feat: add nick name to sub-agents @jif-oai
- #12328 chore: better agent names @jif-oai
- #12326 disable collab for phase 2 @jif-oai
- #12267 Add MCP server context to otel tool_result logs @colby-oai
- #12327 feat: cleaner TUI for sub-agents @jif-oai
- #12332 feat: better agent picker in TUI @jif-oai
- #12344 feat: do not enqueue phase 2 if not necessary @jif-oai
- #12340 fix: simplify macOS sleep inhibitor FFI @yvolovich-cyber
- #12347 fix: nick name at thread/read @jif-oai
- #12294 Reuse connection between turns @pakrym-oai
- #12287 app-server: add JSON tracing logs @maxj-oai
- #12140 Refactor network approvals to host/protocol/port scope @viyatb-oai
- #12300 js_repl: block wrapped payload prefixes in grammar @fjord-oai
- #11368 fix(network-proxy): add unix socket allow-all and update seatbelt rules @viyatb-oai
- #12275 js_repl: remove codex.state helper references @fjord-oai
- #12289 CODEX-4927: Surface local login entitlement denials in browser @daniel-oai
- #12205 ci(bazel): install Node from node-version.txt in remote image @fjord-oai
- #12312 feat: add config `allow_login_shell` @jif-oai
- #12086 [apps] Implement apps configs. @mzeng-openai
- #12353 fix(core): require approval for destructive MCP tool calls @colby-oai
- #12218 app-server: harden disconnect cleanup paths @maxj-oai
- #12291 core tests: use hermetic mock server in review suite @viyatb-oai
- #12374 [apps] Enforce simple logo url format. @mzeng-openai
- #12377 docs: use --locked when installing cargo-nextest @derekf-oai
- #12370 Add ability to attach extra files to feedback @pakrym-oai
- #12306 Move sanitizer into codex-secrets @viyatb-oai
- #12379 clarify model_catalog_json only applied on startup @sayan-oai
- #12307 Show model/reasoning hint when switching modes @charley-oai
- #12403 [apps] Fix gateway url. @mzeng-openai
- #12240 fix(tui): queued-message edit shortcut unreachable in some terminals @fcoury
- #12405 [apps] Bump MCP tool call timeout. @mzeng-openai
- #12406 fix: explicitly list name collisions in JSON schema generation @bolinfest
- #12301 Add field to Thread object for the latest rename set for a given thread @natea-oai
- #12268 Wire realtime api to core @aibrahim-oai
- #12415 fix(nix): include libcap dependency on linux builds @rgodha24
- #12416 Add experimental realtime websocket URL override @aibrahim-oai
- #12303 Improve Plan mode reasoning selection flow @charley-oai
- #12418 Add experimental realtime websocket overrides and text mirroring @aibrahim-oai
- #12381 fix: address flakiness in thread_resume_rejoins_running_thread_even_with_override_mismatch @bolinfest
- #12422 feat: use OAI Responses API MessagePhase type directly in App Server v2 @bolinfest
- #12376 test(app-server): wait for turn/completed in turn_start tests @yvolovich-cyber
- #12408 ignore v1 in JSON schema codegen @bolinfest
- #12314 fix(core) Filter non-matching prefix rules @dylan-hurd-oai
- #12429 feat: discourage the use of the --all-features flag @bolinfest
- #12252 Fix compaction context reinjection and model baselines @charley-oai
- #12427 chore: move config diagnostics out of codex-core @bolinfest
- #12430 Collapse waited message @pakrym-oai
- #12432 chore: remove codex-core public protocol/shell re-exports @bolinfest
- #12434 fix: codex-arg0 no longer depends on codex-core @bolinfest
- #12435 refactor(core): move embedded system skills into codex-skills crate @bolinfest
- #12440 chore: delete empty codex-rs/code file @bolinfest
- #12441 Delete AggregatedStream @pakrym-oai
- #11293 feat(linux-sandbox): implement proxy-only egress via TCP-UDS-TCP bridge @viyatb-oai
- #12410 profile-level model_catalog_json overrie @sayan-oai
- #12420 Prevent replayed runtime events from forcing active status @etraut-openai
- #12428 Prefer v2 websockets if available @pakrym-oai
- #12419 Improve token usage estimate for images @etraut-openai
- #12474 fix: make skills loader tests hermetic with ~/.agents skills @bolinfest
- #12473 core: preserve constrained approval/sandbox policies in TurnContext @bolinfest
- #12067 fix(tui): preserve URL clickability across all TUI views @fcoury
- #12469 Route inbound realtime text into turn start or steer @aibrahim-oai
- #12479 Revert "Route inbound realtime text into turn start or steer" @aibrahim-oai
- #12475 fix: make realtime conversation flake test order-insensitive @bolinfest
- #12476 Make shell detection tests
     robust to Nix shell paths @rupurt
- #11447 feat(tui): syntax highlighting via syntect with theme picker @fcoury
- #12373 app-server: retain thread listener across disconnects @maxj-oai
- #12444 feat(tui) /clear @won-openai
- #12485 fix(core) exec policy parsing 3 @dylan-hurd-oai
- #12423 Send events to realtime api @aibrahim-oai
- #12364 feat: monitor role @jif-oai
- #12313 Handle orphan exec ends without clobbering active exploring cell @jif-oai
- #12455 feat(tui): support Alt-d delete-forward-word @dougEfresh
- #12480 Revert "Revert "Route inbound realtime text into turn start or steer"" @aibrahim-oai
- #12509 Sort themes case-insensitively in picker @etraut-openai
- #12511 Add C# syntax option to highlight selections @etraut-openai
- #12513 Add PR babysitting skill for this repo @etraut-openai
- #12518 test: vendor zsh fork via DotSlash and stabilize zsh-fork tests @bolinfest
- #12553 Return image content from view_image @pakrym-oai
- #12555 refactor: decouple MCP policy construction from escalate server @bolinfest
- #12559 chore: nit name @jif-oai
- #12562 chore: awaiter @jif-oai
- #12565 chore: add doc to memories @jif-oai
- #12568 chore: phase 2 name @jif-oai
- #12571 fix: TUI constraint @jif-oai
- #12570 feat: keep dead agents in the agent picker @jif-oai
- #12575 feat: agent nick names to model @jif-oai
- #12500 feat: add uuid helper @jif-oai
- #12580 chore: rename memory feature flag @jif-oai
- #12541 Allow exec resume to parse output-last-message flag after command @etraut-openai
- #12579 feat: role metrics multi-agent @jif-oai
- #12141 feat: land sqlite @jif-oai
- #12576 chore: better bazel test logs @jif-oai
- #12028 remove feature flag collaboration modes @aibrahim-oai
- #12520 tweaked /clear to support clear + new chat, also fix minor bug for macos terminal @won-openai
- #12556 refactor: normalize unix module layout for exec-server and shell-escalation @bolinfest
- #12421 app-server: box request dispatch future to reduce stack pressure @charley-oai
- #12528 chore(deps): bump libc from 0.2.180 to 0.2.182 in /codex-rs @dependabot
- #12529 chore(deps): bump syn from 2.0.114 to 2.0.117 in /codex-rs @dependabot
- #12583 Use Arc-based ToolCtx in tool runtimes @bolinfest
- #12540 fix: add ellipsis for truncated status indicator @sayan-oai
- #12609 fix(tui): recover on owned wrap mapping mismatch @fcoury
- #12569 fix(tui): queue steer Enter while final answer is still streaming to prevent dead state @guidedways
- #12530 chore(deps): bump owo-colors from 4.2.3 to 4.3.0 in /codex-rs @dependabot
- #12549 fix: show command running in background terminal in details under status indicator @sayan-oai
- #3381 voice transcription @nornagon-openai
- #12619 Handle realtime spawn_transcript delegation @aibrahim-oai
- #11408 Update models.json @github-actions
- #12629 app-server: fix connecting via websockets with `Sec-WebSocket-Extensions: permessage-deflate` @JaviSoto
- #12632 refactor: delete exec-server and move execve wrapper into shell-escalation @bolinfest
- #12638 refactor: decouple shell-escalation from codex-core @bolinfest
- #12357 feat(core): persist network approvals in execpolicy @viyatb-oai
- #12648 fix(exec) Patch resume test race condition @dylan-hurd-oai
- #12049 Support implicit skill invocation analytics events @alexsong-oai
- #12647 Avoid `AbsolutePathBuf::parent()` panic under `EMFILE` by skipping re-absolutization @etraut-openai
- #12633 Add skill approval event/response @pakrym-oai
- #12650 chore: rm hardcoded PRESETS list @sayan-oai
- #12652 Simplify skill tracking @pakrym-oai
- #12653 memories: tighten consolidation prompt schema and indexing guidance @zuxin-oai
- #12667 feat: mutli agents persist config overrides @jif-oai
- #12635 memories: tighten memory lookup guidance and citation requirements @zuxin-oai
- #12663 fix: replay after `/agent` @jif-oai
- #11258 Send warmup request @pakrym-oai
- #12688 feat: use process group to kill the PTY @jif-oai
- #11871 feat(core) Introduce Feature::RequestPermissions @dylan-hurd-oai
- #12628 ctrl-L (clears terminal but does not start a new chat)  @won-openai
- #9859 feat(network-proxy): add MITM support and gate limited-mode CONNECT @viyatb-oai
- #12649 feat: run zsh fork shell tool via shell-escalation @bolinfest
- #12643 Fix @mention token parsing in chat composer @etraut-openai
- #12658 fix: also try matching namespaced prefix for modelinfo candidate @sayan-oai
- #11766 feat(sleep-inhibitor): add Linux and Windows idle-sleep prevention @yvolovich-cyber
- #12581 feat(tui): add theme-aware diff backgrounds with capability-graded palettes @fcoury
- #12697 Ensure shell command skills trigger approval @pakrym-oai
- #12707 refactor: remove unused seatbelt unix socket arg @bolinfest
- #12687 Add TUI realtime conversation mode @aibrahim-oai
- #12639 Honor `project_root_markers` when discovering `AGENTS.md` @etraut-openai
- #10935 Agent jobs (spawn_agents_on_csv) + progress UI @daveaitel-openai
- #12700 revert audio scope @nornagon-openai
- #12711 fix: temp remove citation @zuxin-oai
- #12613 feat(tui) - /copy @won-openai
- #12695 Add app-server event tracing @pakrym-oai
- #12717 Raise image byte estimate for compaction token accounting @etraut-openai
- #12724 fix: make EscalateServer public and remove shell escalation wrappers @bolinfest
- #12517 codex-rs/app-server: graceful websocket restart on Ctrl-C @maxj-oai
- #12636 fix(js_repl): surface uncaught kernel errors and reset cleanly @fjord-oai
- #12729 fix: clarify the value of SkillMetadata.path @bolinfest
- #12719 feat: pass helper executable paths via Arg0DispatchPaths @bolinfest
- #12720 add AWS_LC_SYS_NO_JITTER_ENTROPY=1 to release musl build step to unblock releases @sayan-oai
- #12725 Fix js_repl view_image attachments in nested tool calls @fjord-oai
- #12656 chore: change catalog mode to enum @sayan-oai
- #12731 chore: migrate additional permissions to PermissionProfile @celia-oai
- #12407 tests(js_repl): stabilize CI runtime test execution @fjord-oai
- #12737 feat:  add experimental additionalPermissions to v2 command execution approval requests @celia-oai
- #12372 feat: update Docker image digest to reflect #12205 @fjord-oai
- #12746 fix: chatwidget was not honoring approval_id for an ExecApprovalRequestEvent @bolinfest
- #12185 tests(js_repl): remove node-related skip paths from js_repl tests @fjord-oai
- #12358 feat(ui): add network approval persistence plumbing @viyatb-oai
- #12730 feat: zsh-fork forces scripts/**/* for skills to trigger a prompt @bolinfest
- #12750 fix: keep shell escalation exec paths absolute @bolinfest
- #12753 Surface skill permission profiles in zsh-fork exec approvals @celia-oai
- #12319 feat: add service name to app-server @jif-oai
- #12692 fix: flaky test due to second-resolution for thread ordering @jif-oai
- #12578 feat: add search term to thread list @jif-oai
- #12660 Support external agent config detect and import @alexsong-oai
- #12756 feat: record whether a skill script is approved for the session @bolinfest
- #12767 Display pending child-thread approvals in TUI @jif-oai
- #12768 feat: add large stack test macro @jif-oai
- #12666 feat: adding stream parser @jif-oai
- #12761 feat: record memory usage @jif-oai
- #12772 nit: migration @jif-oai
- #12352 otel: add host.name resource attribute to logs/traces via gethostname @mcgrew-oai
- #12770 chore: unify max depth parameter @jif-oai
- #12787 feat: fix sqlite home @jif-oai
2026-02-25 16:36:36 +00:00
jif-oai 8362b79cb4 feat: fix sqlite home (#12787) 2026-02-25 15:52:55 +00:00
jif-oai 01f25a7b96 chore: unify max depth parameter (#12770)
Users were confused
2026-02-25 15:20:24 +00:00
mcgrew-oai bccce0d75f otel: add host.name resource attribute to logs/traces via gethostname (#12352)
**PR Summary**

This PR adds the OpenTelemetry `host.name` resource attribute to Codex
OTEL exports so every OTEL log (and trace, via the shared resource)
carries the machine hostname.

**What changed**

- Added `host.name` to the shared OTEL `Resource` in
`/Users/michael.mcgrew/code/codex/codex-rs/otel/src/otel_provider.rs`
  - This applies to both:
    - OTEL logs (`SdkLoggerProvider`)
    - OTEL traces (`SdkTracerProvider`)
- Hostname is now resolved via `gethostname::gethostname()`
(best-effort)
  - Value is trimmed
  - Empty values are omitted (non-fatal)
- Added focused unit tests for:
  - including `host.name` when present
  - omitting `host.name` when missing/empty

**Why**

- `host.name` is host/process metadata and belongs on the OTEL
`resource`, not per-event attributes.
- Attaching it in the shared resource is the smallest change that
guarantees coverage across all exported OTEL logs/traces.

**Scope / Non-goals**

- No public API changes
- No changes to metrics behavior (this PR only updates log/trace
resource metadata)

**Dependency updates**

- Added `gethostname` as a workspace dependency and `codex-otel`
dependency
- `Cargo.lock` updated accordingly
- `MODULE.bazel.lock` unchanged after refresh/check

**Validation**

- `just fmt`
- `cargo test -p codex-otel`
- `just bazel-lock-update`
- `just bazel-lock-check`
2026-02-25 09:54:45 -05:00
jif-oai 8d49e0d0c4 nit: migration (#12772) 2026-02-25 13:56:52 +00:00
jif-oai e4bfa763f6 feat: record memory usage (#12761) 2026-02-25 13:48:40 +00:00
jif-oai 5441130e0a feat: adding stream parser (#12666)
Add a stream parser to extract citations (and others) from a stream.
This support cases where markers are split in differen tokens.

Codex never manage to make this code work so everything was done
manually. Please review correctly and do not touch this part of the code
without a very clear understanding of it
2026-02-25 13:27:58 +00:00
jif-oai 5a9a5b51b2 feat: add large stack test macro (#12768)
This PR adds the macro `#[large_stack_test]`

This spawns the tests in a dedicated tokio runtime with a larger stack.
It is useful for tests that needs the full recursion on the harness
(which is now too deep for windows for example)
2026-02-25 13:19:21 +00:00
jif-oai bcd6e68054 Display pending child-thread approvals in TUI (#12767)
Summary
- propagate approval policy from parent to spawned agents and drop the
Never override so sub-agents respect the caller’s request
- refresh the pending-approval list whenever events arrive or the active
thread changes and surface the list above the composer for inactive
threads
- add widgets, helpers, and tests covering the new pending-thread
approval UI state

![Uploading Screenshot 2026-02-25 at 11.02.18.png…]()
2026-02-25 11:40:11 +00:00
Michael Bolin 93efcfd50d feat: record whether a skill script is approved for the session (#12756)
## Why

`unix_escalation.rs` checks a session-scoped approval cache before
prompting again for an execve-intercepted skill script. Without also
recording `ReviewDecision::ApprovedForSession`, that cache never gets
populated, so the same skill script can still trigger repeated approval
prompts within one session.

## What Changed

- Add `execve_session_approvals` to `SessionServices` so the session can
track approved skill script paths.
- Record the script path when a skill-script prompt returns
`ReviewDecision::ApprovedForSession`, but only for the skill-script path
rather than broader prefix-rule approvals.
- Reuse the cached approval on later execve callbacks by treating an
already-approved skill script as `Decision::Allow`.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/12756).
* #12758
* __->__ #12756
2026-02-25 10:17:22 +00:00
alexsong-oai 6d6570d89d Support external agent config detect and import (#12660)
Migration Behavior

* Config
  *  Migrates settings.json into config.toml
* Only adds fields when config.toml is missing, or when those fields are
missing from the existing file
  *  Supported mappings:
    env -> shell_environment_policy
     sandbox.enabled = true -> sandbox_mode = "workspace-write"

* Skills
  *  Copies home and repo .claude/skills into .agents/skills
  *  Existing skill directories are not overwritten
  *  SKILL.md content is rewritten from Claude-related terms to Codex

* AgentsMd
  *  Repo only
  *  Migrates CLAUDE.md into AGENTS.md
* Detect/import only proceed when AGENTS.md is missing or present but
empty
  *  Content is rewritten from Claude-related terms to Codex
2026-02-25 02:11:51 -08:00
jif-oai f46b767b7e feat: add search term to thread list (#12578)
Add `searchTerm` to `thread/list` that will search for a match in the
titles (the condition being `searchTerm` $$\in$$ `title`)
2026-02-25 09:59:41 +00:00
jif-oai a046849438 fix: flaky test due to second-resolution for thread ordering (#12692) 2026-02-25 09:59:25 +00:00
jif-oai 10c04e11b8 feat: add service name to app-server (#12319)
Add service name to the app-server so that the app can use it's own
service name

This is on thread level because later we might plan the app-server to
become a singleton on the computer
2026-02-25 09:51:42 +00:00
Celia Chen 6a3233da64 Surface skill permission profiles in zsh-fork exec approvals (#12753)
## Summary

- Preserve each skill’s raw permissions block as a permission_profile on
SkillMetadata during skill loading.
- Keep compiling that same metadata into the existing runtime
Permissions object, so current enforcement
    behavior stays intact.
- When zsh-fork intercepts execution of a script that belongs to a
skill, include the skill’s
    permission_profile in the exec approval request.
- This lets approval UIs show the extra filesystem access the skill
declared when prompting for approval.
2026-02-25 01:23:10 -08:00
Michael Bolin c4ec6be4ab fix: keep shell escalation exec paths absolute (#12750)
## Why

In the `shell_zsh_fork` flow, `codex-shell-escalation` receives the
executable path exactly as the shell passed it to `execve()`. That path
is not guaranteed to be absolute.

For commands such as `./scripts/hello-mbolin.sh`, if the shell was
launched with a different `workdir`, resolving the intercepted `file`
against the server process working directory makes policy checks and
skill matching inspect the wrong executable. This change pushes that fix
a step further by keeping the normalized path typed as `AbsolutePathBuf`
throughout the rest of the escalation pipeline.

That makes the absolute-path invariant explicit, so later code cannot
accidentally treat the resolved executable path as an arbitrary
`PathBuf`.

## What Changed

- record the wrapper process working directory as an `AbsolutePathBuf`
- update the escalation protocol so `workdir` is explicitly absolute
while `file` remains the raw intercepted exec path
- resolve a relative intercepted `file` against the request `workdir` as
soon as the server receives the request
- thread `AbsolutePathBuf` through `EscalationPolicy`,
`CoreShellActionProvider`, and command normalization helpers so the
resolved executable path stays type-checked as absolute
- replace the `path-absolutize` dependency in `codex-shell-escalation`
with `codex-utils-absolute-path`
- add a regression test that covers a relative `file` with a distinct
`workdir`

## Verification

- `cargo test -p codex-shell-escalation`
2026-02-24 23:52:36 -08:00
Michael Bolin 59398125f6 feat: zsh-fork forces scripts/**/* for skills to trigger a prompt (#12730)
Direct skill-script matches force `Decision::Prompt`, so skill-backed
scripts require explicit approval before they run. (Note "allow for
session" is not supported in this PR, but will be done in a follow-up.)

In the process of implementing this, I fixed an important bug:
`ShellZshFork` is supposed to keep ordinary allowed execs on the
client-side `Run` path so later `execve()` calls are still intercepted
and reviewed. After the shell-escalation port, `Decision::Allow` still
mapped to `Escalate`, which moved `zsh` to server-side execution too
early. That broke the intended flow for skill-backed scripts and made
the approval prompt depend on the wrong execution path.

## What changed
- In `codex-rs/core/src/tools/runtimes/shell/unix_escalation.rs`,
`Decision::Allow` now returns `Run` unless escalation is actually
required.
- Removed the zsh-specific `argv[0]` fallback. With the `Allow -> Run`
fix in place, zsh's later `execve()` of the script is intercepted
normally, so the skill match happens on the script path itself.
- Kept the skill-path handling in `determine_action()` focused on the
direct `program` match path.

## Verification
- Updated `shell_zsh_fork_prompts_for_skill_script_execution` in
`codex-rs/core/tests/suite/skill_approval.rs` (gated behind `cfg(unix)`)
to:
- run under `SandboxPolicy::new_workspace_write_policy()` instead of
`DangerFullAccess`
  - assert the approval command contains only the script path
- assert the approved run returns both stdout and stderr markers in the
shell output
- Ran `cargo test -p codex-core
shell_zsh_fork_prompts_for_skill_script_execution -- --nocapture`

## Manual Testing

Run the dev build:

```
just codex --config zsh_path=/Users/mbolin/code/codex2/codex-rs/app-server/tests/suite/zsh --enable shell_zsh_fork
```

I have created `/Users/mbolin/.agents/skills/mbolin-test-skill` with:

```
├── scripts
│   └── hello-mbolin.sh
└── SKILL.md
```

The skill:

```
---
name: mbolin-test-skill
description: Used to exercise various features of skills.
---

When this skill is invoked, run the `hello-mbolin.sh` script and report the output.
```

The script:

```
set -e

# Note this script will fail if run with network disabled.
curl --location openai.com
```

Use `$mbolin-test-skill` to invoke the skill manually and verify that I
get prompted to run `hello-mbolin.sh`.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/12730).
* #12750
* __->__ #12730
2026-02-24 23:51:26 -08:00
viyatb-oai c086b36b58 feat(ui): add network approval persistence plumbing (#12358)
## Summary
- add TUI approval options for persistent network host rules
- add app-server v2 approval payload plumbing for network approval
context + proposed network policy amendments
- add app-server handling to translate `applyNetworkPolicyAmendment`
decisions back into core review decisions
- update docs/test client output and generated app-server schemas/types
2026-02-25 07:06:19 +00:00
Curtis 'Fjord' Hawthorne 9501669a24 tests(js_repl): remove node-related skip paths from js_repl tests (#12185)
## Summary
Remove js_repl/node test-skip paths and make Node setup explicit in CI
so js_repl tests always run instead of silently skipping.

## Why
We had multiple “expediency” skip paths that let js_repl tests pass
without actually exercising Node-backed behavior. This reduced CI signal
and hid runtime/environment regressions.

## What changed

### CI
- Added Node setup using `codex-rs/node-version.txt` in:
  - `.github/workflows/rust-ci.yml`
  - `.github/workflows/bazel.yml`
- Added a Unix PATH copy step in Bazel workflow to expose the setup-node
binary in common paths.

### js_repl test harness
- Added explicit js_repl sandbox test configuration helpers in:
  - `codex-rs/core/src/tools/js_repl/mod.rs`
  - `codex-rs/core/src/tools/handlers/js_repl.rs`
- Added Linux arg0 dispatch glue for js_repl tests so sandbox subprocess
entrypoint behavior is correct under Linux test execution.

### Removed skip behavior
- Deleted runtime guard function and early-return skips in js_repl tests
(`can_run_js_repl_runtime_tests` and related per-test short-circuits).
- Removed view_image integration test skip behavior:
  - dropped `skip_if_no_network!(Ok(()))`
- removed “skip on Node missing/too old” branch after js_repl output
inspection.

## Impact
- js_repl/node tests now consistently execute and fail loudly when the
environment is not correctly provisioned.
- CI has stronger signal for js_repl regressions instead of false green
from conditional skips.

## Testing
- `cargo test -p codex-core` (locally) to validate js_repl
unit/integration behavior with skips removed.
- CI expected to surface any remaining environment/runtime gaps directly
(rather than masking them).


#### [git stack](https://github.com/magus/git-stack-cli)
- ✅ `1` https://github.com/openai/codex/pull/12300
- ✅ `2` https://github.com/openai/codex/pull/12275
- ✅ `3` https://github.com/openai/codex/pull/12205
- ✅ `4` https://github.com/openai/codex/pull/12407
- ✅ `5` https://github.com/openai/codex/pull/12372
- 👉 `6` https://github.com/openai/codex/pull/12185
- ⏳ `7` https://github.com/openai/codex/pull/10673
2026-02-24 22:52:14 -08:00
Michael Bolin ddfa032eb8 fix: chatwidget was not honoring approval_id for an ExecApprovalRequestEvent (#12746)
## Why

`ExecApprovalRequestEvent` can carry a distinct `approval_id` for
subcommand approvals, including the `execve`-intercepted zsh-fork path.

The session registers the pending approval callback under `approval_id`
when one is present, but `ChatWidget` was stashing `call_id` in the
approval modal state. When the user approved the command in the TUI, the
response was sent back with the wrong identifier, so the pending
approval could not be matched and the approval callback would not
resolve.

Note `approval_id` was introduced in
https://github.com/openai/codex/pull/12051.

## What changed

- In `tui/src/chatwidget.rs`, `ChatWidget` now uses
`ExecApprovalRequestEvent::effective_approval_id()` when constructing
`ApprovalRequest::Exec`.
- That preserves the existing behavior for normal shell and
`unified_exec` approvals, where `approval_id` is absent and the
effective id still falls back to `call_id`.
- For subcommand approvals that provide a distinct `approval_id`, the
TUI now sends back the same key that
`Session::request_command_approval()` registered.

## Verification

- Traced the approval flow end to end to confirm the same effective
approval id is now used on both sides of the round trip:
- `Session::request_command_approval()` registers the pending callback
under `approval_id.unwrap_or(call_id)`.
- `ChatWidget` now emits `Op::ExecApproval` with that same effective id.
2026-02-24 22:27:05 -08:00
Celia Chen 1151972fb2 feat: add experimental additionalPermissions to v2 command execution approval requests (#12737)
This adds additionalPermissions to the app-server v2
item/commandExecution/requestApproval payload as an experimental field.

The field is now exposed on CommandExecutionRequestApprovalParams and is
populated from the existing core approval event when a command requests
additional sandbox permissions.

This PR also contains changes to make server requests to support
experiment API.

A real app server test client test:

sample payload with experimental flag off:
```
 {
<   "id": 0,
<   "method": "item/commandExecution/requestApproval",
<   "params": {
<     "command": "/bin/zsh -lc 'mkdir -p ~/some/test && touch ~/some/test/file'",
<     "commandActions": [
<       {
<         "command": "mkdir -p '~/some/test'",
<         "type": "unknown"
<       },
<       {
<         "command": "touch '~/some/test/file'",
<         "type": "unknown"
<       }
<     ],
<     "cwd": "/Users/celia/code/codex/codex-rs",
<     "itemId": "call_QLp0LWkQ1XkU6VW9T2vUZFWB",
<     "proposedExecpolicyAmendment": [
<       "mkdir",
<       "-p",
<       "~/some/test"
<     ],
<     "reason": "Do you want to allow creating ~/some/test/file outside the workspace?",
<     "threadId": "019c9309-e209-7d82-a01b-dcf9556a354d",
<     "turnId": "019c9309-e27a-7f33-834f-6011e795c2d6"
<   }
< }
```
with experimental flag on: 
```
< {
<   "id": 0,
<   "method": "item/commandExecution/requestApproval",
<   "params": {
<     "additionalPermissions": {
<       "fileSystem": null,
<       "macos": null,
<       "network": true
<     },
<     "command": "/bin/zsh -lc 'install -D /dev/null ~/some/test/file'",
<     "commandActions": [
<       {
<         "command": "install -D /dev/null '~/some/test/file'",
<         "type": "unknown"
<       }
<     ],
<     "cwd": "/Users/celia/code/codex/codex-rs",
<     "itemId": "call_K3U4b3dRbj3eMCqslmncbGsq",
<     "proposedExecpolicyAmendment": [
<       "install",
<       "-D"
<     ],
<     "reason": "Do you want to allow creating the file at ~/some/test/file outside the workspace sandbox?",
<     "threadId": "019c9303-3a8e-76e1-81bf-d67ac446d892",
<     "turnId": "019c9303-3af1-7143-88a1-73132f771234"
<   }
< }
```
2026-02-25 05:16:35 +00:00
Curtis 'Fjord' Hawthorne 8f3f2c3c02 tests(js_repl): stabilize CI runtime test execution (#12407)
## Summary

Stabilize `js_repl` runtime test setup in CI and move tool-facing
`js_repl` behavior coverage into integration tests.

This is a test/CI change only. No production `js_repl` behavior change
is intended.

## Why

- Bazel test sandboxes (especially on macOS) could resolve a different
`node` than the one installed by `actions/setup-node`, which caused
`js_repl` runtime/version failures.
- `js_repl` runtime tests depend on platform-specific
sandbox/test-harness behavior, so they need explicit gating in a
base-stability commit.
- Several tests in the `js_repl` unit test module were actually
black-box/tool-level behavior tests and fit better in the integration
suite.

## Changes

- Add `actions/setup-node` to the Bazel and Rust `Tests` workflows,
using the exact version pinned in the repo’s Node version file.
- In Bazel (non-Windows), pass `CODEX_JS_REPL_NODE_PATH=$(which node)`
into test env so `js_repl` uses the `actions/setup-node` runtime inside
Bazel tests.
- Add a new integration test suite for `js_repl` tool behavior and
register it in the core integration test suite module.
- Move black-box `js_repl` behavior tests into the integration suite
(persistence/TLA, builtin tool invocation, recursive self-call
rejection, `process` isolation, blocked builtin imports).
- Keep white-box manager/kernel tests in the `js_repl` unit test module.
- Gate `js_repl` runtime tests to run only on macOS and only when a
usable Node runtime is available (skip on other platforms / missing Node
in this commit).

## Impact

- Reduces `js_repl` CI failures caused by Node resolution drift in
Bazel.
- Improves test organization by separating tool-facing behavior tests
from white-box manager/kernel tests.
- Keeps the base commit stable while expanding `js_repl` runtime
coverage.


#### [git stack](https://github.com/magus/git-stack-cli)
- ✅ `1` https://github.com/openai/codex/pull/12372
- 👉 `2` https://github.com/openai/codex/pull/12407
- ⏳ `3` https://github.com/openai/codex/pull/12185
- ⏳ `4` https://github.com/openai/codex/pull/10673
2026-02-24 21:04:34 -08:00
Celia Chen 16ca527c80 chore: migrate additional permissions to PermissionProfile (#12731)
This PR replaces the old `additional_permissions.fs_read/fs_write` shape
with a shared `PermissionProfile`
model and wires it through the command approval, sandboxing, protocol,
and TUI layers. The schema is adopted from the
`SkillManifestPermissions`, which is also refactored to use this unified
struct. This helps us easily expose permission profiles in app
server/core as a follow-up.
2026-02-25 03:35:28 +00:00
sayan-oai e6bb5d8553 chore: change catalog mode to enum (#12656)
make presence of custom catalog more clear by changing to enum instead
of bool.
2026-02-24 19:33:32 -08:00
Curtis 'Fjord' Hawthorne 125fbec317 Fix js_repl view_image attachments in nested tool calls (#12725)
## Summary

- Fix `js_repl` so `await codex.tool("view_image", { path })` actually
attaches the image to the active turn when called from inside the JS
REPL.
- Restore the behavior expected by the existing `js_repl`
image-attachment test.
- This is a follow-up to
[#12553](https://github.com/openai/codex/pull/12553), which changed
`view_image` to return structured image content.

## Root Cause

- [#12553](https://github.com/openai/codex/pull/12553) changed
`view_image` from directly injecting a pending user image message to
returning structured `function_call_output` content items.
- The nested tool-call bridge inside `js_repl` serialized that tool
response back to the JS runtime, but it did not mirror returned image
content into the active turn.
- As a result, `view_image` appeared to succeed inside `js_repl`, but no
`input_image` was actually attached for the outer turn.

## What Changed

- Updated the nested tool-call path in `js_repl` to inspect function
tool responses for structured content items.
- When a nested tool response includes `input_image` content, `js_repl`
now injects a corresponding user `Message` into the active turn before
returning the raw tool result back to the JS runtime.
- Kept the normal JSON result flow intact, so `codex.tool(...)` still
returns the original tool output object to JavaScript.

## Why

- `js_repl` documentation and tests already assume that `view_image` can
be used from inside the REPL to attach generated images to the model.
- Without this fix, the nested call path silently dropped that
attachment behavior.
2026-02-24 18:23:53 -08:00
Michael Bolin e88f74d140 feat: pass helper executable paths via Arg0DispatchPaths (#12719)
## Why

`codex-rs/core/src/tools/runtimes/shell/unix_escalation.rs` previously
located `codex-execve-wrapper` by scanning `PATH` and sibling
directories. That lookup is brittle and can select the wrong binary when
the runtime environment differs from startup assumptions.

We already pass `codex-linux-sandbox` from `codex-arg0`;
`codex-execve-wrapper` should use the same startup-driven path plumbing.

## What changed

- Introduced `Arg0DispatchPaths` in `codex-arg0` to carry both helper
executable paths:
  - `codex_linux_sandbox_exe`
  - `main_execve_wrapper_exe`
- Updated `arg0_dispatch_or_else()` to pass `Arg0DispatchPaths` to
top-level binaries and preserve helper paths created in
`prepend_path_entry_for_codex_aliases()`.
- Threaded `Arg0DispatchPaths` through entrypoints in `cli`, `exec`,
`tui`, `app-server`, and `mcp-server`.
- Added `main_execve_wrapper_exe` to core configuration plumbing
(`Config`, `ConfigOverrides`, and `SessionServices`).
- Updated zsh-fork shell escalation to consume the configured
`main_execve_wrapper_exe` and removed path-sniffing fallback logic.
- Updated app-server config reload paths so reloaded configs keep the
same startup-provided helper executable paths.

## References

- [`Arg0DispatchPaths`
definition](https://github.com/openai/codex/blob/e355b43d5c2a771f045296a6deae10d7c9c36ec6/codex-rs/arg0/src/lib.rs#L20-L24)
- [`arg0_dispatch_or_else()` forwarding both
paths](https://github.com/openai/codex/blob/e355b43d5c2a771f045296a6deae10d7c9c36ec6/codex-rs/arg0/src/lib.rs#L145-L176)
- [zsh-fork escalation using configured wrapper
path](https://github.com/openai/codex/blob/e355b43d5c2a771f045296a6deae10d7c9c36ec6/codex-rs/core/src/tools/runtimes/shell/unix_escalation.rs#L109-L150)

## Testing

- `cargo check -p codex-arg0 -p codex-core -p codex-exec -p codex-tui -p
codex-mcp-server -p codex-app-server`
- `cargo test -p codex-arg0`
- `cargo test -p codex-core tools::runtimes::shell::unix_escalation:: --
--nocapture`
2026-02-24 17:44:38 -08:00
Michael Bolin 448fb6ac22 fix: clarify the value of SkillMetadata.path (#12729)
Rename `SkillMetadata.path` to `SkillMetadata.path_to_skills_md` for
clarity.

Would ideally change the type to `AbsolutePathBuf`, but that can be done
later.
2026-02-24 17:15:54 -08:00
Curtis 'Fjord' Hawthorne 63c2ac96cd fix(js_repl): surface uncaught kernel errors and reset cleanly (#12636)
## Summary

Improve `js_repl` behavior when the Node kernel hits a process-level
failure (for example, an uncaught exception or unhandled Promise
rejection).

Instead of only surfacing a generic `js_repl kernel exited unexpectedly`
after stdout EOF, `js_repl` now returns a clearer exec error for the
active request, then resets the kernel cleanly.

## Why

Some sandbox-denied operations can trigger Node errors that become
process-level failures (for example, an unhandled EventEmitter `'error'`
event). In that case:

- the kernel process exits,
- the host sees stdout EOF,
- the user gets a generic kernel-exit error,
- and the next request can briefly race with stale kernel state.

This change improves that failure mode without monkeypatching Node APIs.

## Changes

### Kernel-side (`js_repl` Node process)
- Add process-level handlers for:
  - `uncaughtException`
  - `unhandledRejection`
- When one of these fires:
  - best-effort emit a normal `exec_result` error for the active exec
- include actionable guidance to catch/handle async errors (including
Promise rejections and EventEmitter `'error'` events)
  - exit intentionally so the host can reset/restart the kernel

### Host-side (`JsReplManager`)
- Clear dead kernel state as soon as the stdout reader observes
unexpected kernel exit/EOF.
- This lets the next `js_repl` exec start a fresh kernel instead of
hitting a stale broken-pipe path.

### Tests
- Add regression coverage for:
- uncaught async exception -> exec error + kernel recovery on next exec
- Update forced-kernel-exit test to validate recovery behavior (next
exec restarts cleanly)

## Impact

- Better user-facing error for kernel crashes caused by
uncaught/unhandled async failures.
- Cleaner recovery behavior after kernel exit.

## Validation

- `cargo test -p codex-core --lib
tools::js_repl::tests::js_repl_uncaught_exception_returns_exec_error_and_recovers
-- --exact`
- `cargo test -p codex-core --lib
tools::js_repl::tests::js_repl_forced_kernel_exit_recovers_on_next_exec
-- --exact`
- `just fmt`
2026-02-24 17:12:02 -08:00
Max JohnsonandCodex 5163850025 codex-rs/app-server: graceful websocket restart on Ctrl-C (#12517)
## Summary
- add graceful websocket app-server restart on Ctrl-C by draining until
no assistant turns are running
- stop the websocket acceptor and disconnect existing connections once
the drain condition is met
- add a websocket integration test that verifies Ctrl-C waits for an
in-flight turn before exit

## Verification
- `cargo check -p codex-app-server --quiet`
- `cargo test -p codex-app-server --test all
suite::v2::connection_handling_websocket`
- I (maxj) tested remote and local Codex.app

---------

Co-authored-by: Codex <noreply@openai.com>
2026-02-24 16:27:59 -08:00
Michael Bolin 3d356723c4 fix: make EscalateServer public and remove shell escalation wrappers (#12724)
## Why

`codex-shell-escalation` exposed a `codex-core`-specific adapter layer
(`ShellActionProvider`, `ShellPolicyFactory`, and `run_escalate_server`)
that existed only to bridge `codex-core` to `EscalateServer`. That
indirection increased API surface and obscured crate ownership without
adding behavior.

This change moves orchestration into `codex-core` so boundaries are
clearer: `codex-shell-escalation` provides reusable escalation
primitives, and `codex-core` provides shell-tool policy decisions.

Admittedly, @pakrym rightfully requested this sort of cleanup as part of
https://github.com/openai/codex/pull/12649, though this avoids moving
all of `codex-shell-escalation` into `codex-core`.

## What changed

- Made `EscalateServer` public and exported it from `shell-escalation`.
- Removed the adapter layer from `shell-escalation`:
  - deleted `shell-escalation/src/unix/core_shell_escalation.rs`
- removed exports for `ShellActionProvider`, `ShellPolicyFactory`,
`EscalationPolicyFactory`, and `run_escalate_server`
- Updated `core/src/tools/runtimes/shell/unix_escalation.rs` to:
  - create `Stopwatch`/cancellation in `codex-core`
  - instantiate `EscalateServer` directly
  - implement `EscalationPolicy` directly on `CoreShellActionProvider`

Net effect: same escalation flow with fewer wrappers and a smaller
public API.

## Verification

- Manually reviewed the old vs. new escalation call flow to confirm
timeout/cancellation behavior and approval policy decisions are
preserved while removing wrapper types.
2026-02-24 16:20:08 -08:00
Eric Traut 8da40c9251 Raise image byte estimate for compaction token accounting (#12717)
Increase `IMAGE_BYTES_ESTIMATE` from 340 bytes to 7,373 bytes so the
existing 4-bytes/token heuristic yields an image estimate of ~1,844
tokens instead of ~85. This makes auto-compaction more conservative for
image-heavy transcripts and avoids underestimating context usage, which
can otherwise cause compaction to fail when there is not enough free
context remaining. The new value was chosen because that's the image
resolution cap used for our latest models.

Follow-up to [#12419](https://github.com/openai/codex/pull/12419).
Refs [#11845](https://github.com/openai/codex/issues/11845).
2026-02-24 16:11:38 -08:00
pakrym-oai 5571a022eb Add app-server event tracing (#12695)
To help with debugging
2026-02-24 14:45:50 -08:00
Won Park ee1520e79e feat(tui) - /copy (#12613)
# /copy!

/copy allows you to copy the latest **complete** message from Codex on
the TUI.
2026-02-24 14:17:01 -08:00
zuxin-oai 61cd3a9700 fix: temp remove citation (#12711)
- **temp remove citation**
2026-02-24 22:07:30 +00:00
Jeremy Rose fefdc03b25 revert audio scope (#12700) 2026-02-24 13:38:28 -08:00
daveaitel-openai dcab40123f Agent jobs (spawn_agents_on_csv) + progress UI (#10935)
## Summary
- Add agent job support: spawn a batch of sub-agents from CSV, auto-run,
auto-export, and store results in SQLite.
- Simplify workflow: remove run/resume/get-status/export tools; spawn is
deterministic and completes in one call.
- Improve exec UX: stable, single-line progress bar with ETA; suppress
sub-agent chatter in exec.

## Why
Enables map-reduce style workflows over arbitrarily large repos using
the existing Codex orchestrator. This addresses review feedback about
overly complex job controls and non-deterministic monitoring.

## Demo (progress bar)
```
./codex-rs/target/debug/codex exec \
  --enable collab \
  --enable sqlite \
  --full-auto \
  --progress-cursor \
  -c agents.max_threads=16 \
  -C /Users/daveaitel/code/codex \
  - <<'PROMPT'
Create /tmp/agent_job_progress_demo.csv with columns: path,area and 30 rows:
path = item-01..item-30, area = test.

Then call spawn_agents_on_csv with:
- csv_path: /tmp/agent_job_progress_demo.csv
- instruction: "Run `python - <<'PY'` to sleep a random 0.3–1.2s, then output JSON with keys: path, score (int). Set score = 1."
- output_csv_path: /tmp/agent_job_progress_demo_out.csv
PROMPT
```

## Review feedback addressed
- Auto-start jobs on spawn; removed run/resume/status/export tools.
- Auto-export on success.
- More descriptive tool spec + clearer prompts.
- Avoid deadlocks on spawn failure; pending/running handled safely.
- Progress bar no longer scrolls; stable single-line redraw.

## Tests
- `cd codex-rs && cargo test -p codex-exec`
- `cd codex-rs && cargo build -p codex-cli`
2026-02-24 21:00:19 +00:00
Eric Traut bd192b54cd Honor project_root_markers when discovering AGENTS.md (#12639)
Fixes #12128

The docs indicates that `project_root_markers` are used to discover the
project root for local config as well as `AGENTS.md`. It looks like it
was never wired up to support the latter.

Summary
- resolve project docs by walking to the configured
`project_root_markers` (or defaults) instead of assuming the Git root,
while honoring CLI overrides and handling malformed configs
- fall back to the project’s canonical path chain and add a test that
makes sure custom markers upstream of `.git` are respected
2026-02-24 12:55:48 -08:00
Ahmed IbrahimandCodex b6ab2214e3 Add TUI realtime conversation mode (#12687)
- Add a hidden `realtime_conversation` feature flag and `/realtime`
slash command for start/stop live voice sessions.
- Reuse transcription composer/footer UI for live metering, stream mic
audio, play assistant audio, render realtime user text events, and
force-close on feature disable.

---------

Co-authored-by: Codex <noreply@openai.com>
2026-02-24 12:54:30 -08:00
Michael Bolin 3b5fc7547e refactor: remove unused seatbelt unix socket arg (#12707)
https://github.com/openai/codex/pull/12052 introduced an
`allowed_unix_socket_paths` parameter to
`create_seatbelt_command_args()`, but
https://github.com/openai/codex/pull/12649 removed the abstraction that
#12052 introduced, so this parameter is no longer necessary as it is
always an empty slice.
2026-02-24 12:30:26 -08:00
pakrym-oai daf0f03ac8 Ensure shell command skills trigger approval (#12697)
Summary
- detect skill-invoking shell commands based on the original command
string, request approvals when needed, and cache positive decisions per
session
- keep implicit skill invocation emitted after approval and keep skill
approval decline messaging centralized to the shell handler
- expand and adjust skill approval tests to cover shell-based skill
scripts while matching the new detection expectations

Testing
- Not run (not requested)
2026-02-24 12:13:20 -08:00
Felipe Coury 061d1d3b5e feat(tui): add theme-aware diff backgrounds with capability-graded palettes (#12581)
## Problem

Diff lines used only foreground colors (green/red) with no background
tinting, making them hard to scan. The gutter (line numbers) also had no
theme awareness — dimmed text was fine on dark terminals but unreadable
on light ones.

## Mental model

Each diff line now has four styled layers: **gutter** (line number),
**sign** (`+`/`-`), **content** (text), and **line background** (full
terminal width). A `DiffTheme` enum (`Dark` / `Light`) is selected once
per render by probing the terminal's queried background via
`default_bg()`. A companion `DiffColorLevel` enum (`TrueColor` /
`Ansi256` / `Ansi16`) is derived from `stdout_color_level()` and gates
which palette is used. All style helpers dispatch on `(theme,
DiffLineType, color_level)` to pick the right colors.

| Theme Picker Wide | Theme Picker Narrow |
|---|---|
| <img width="1552" height="1012" alt="image"
src="https://github.com/user-attachments/assets/231b21b7-32d4-4727-80ed-7d01924954be"
/> | <img width="795" height="1012" alt="image"
src="https://github.com/user-attachments/assets/549cacdf-daec-43c9-ad64-2a28d16d140e"
/> |

| Dark BG - 16 colors | Dark BG - 256 colors | Dark BG - True Colors |
|---|---|---|
| <img width="1552" height="1012" alt="dark-16colors"
src="https://github.com/user-attachments/assets/fba36de3-c101-47d4-9e63-88cdd00410d0"
/> | <img width="1552" height="1012" alt="dark-256colors"
src="https://github.com/user-attachments/assets/f39e4307-c6b0-49c4-b4fe-bd26d3d8e41c"
/> | <img width="1552" height="1012" alt="dark-truecolor"
src="https://github.com/user-attachments/assets/1af4ec57-04bf-4dfb-8a44-0ab5e5aaaf18"
/> |

| Light BG - 16 colors | Light BG - 256 colors | Light BG - True Colors
|
|---|---|---|
| <img width="1552" height="1012" alt="light-16colors"
src="https://github.com/user-attachments/assets/2b5423d1-74b4-4b1e-8123-7c2488ff436b"
/> | <img width="1552" height="1012" alt="light-256colors"
src="https://github.com/user-attachments/assets/c94cff9a-8d3e-42c9-bbe7-079da39953a8"
/> | <img width="1552" height="1012" alt="light-truecolor"
src="https://github.com/user-attachments/assets/f73da626-725f-4452-99ee-69ef706df2c6"
/> |

## Non-goals

- No runtime theme switching beyond what `default_bg()` already
provides.
- No change to syntax highlighting theme selection or the highlight
module.

## Tradeoffs

- Three fixed palettes (truecolor RGB, 256-color indexed, 16-color
named) are maintained rather than using `best_color` nearest-match. This
is deliberate: `supports_color::on_cached(Stream::Stdout)` can misreport
capabilities once crossterm enters the alternate screen, so hand-picked
palette entries give better visual results than automatic quantization.
- Delete lines in the syntax-highlighted path get `Modifier::DIM` to
visually recede compared to insert lines. This trades some readability
of deleted code for scan-ability of additions.
- The theme picker's diff preview sets `preserve_side_content_bg: true`
on `ListSelectionView` so diff background tints survive into the side
panel. Other popups keep the default (`false`) to preserve their
reset-background look.

## Architecture

- **Color constants** are module-level `const` items grouped by palette
tier: `DARK_TC_*` / `LIGHT_TC_*` (truecolor RGB tuples), `DARK_256_*` /
`LIGHT_256_*` (xterm indexed), with named `Color` variants used for the
16-color tier.
- **`DiffTheme`** is a private enum; `diff_theme()` probes the terminal
and `diff_theme_for_bg()` is the testable pure-function version.
- **`DiffColorLevel`** is a private enum derived from `StdoutColorLevel`
via `diff_color_level()`.
- **Palette helpers** (`add_line_bg`, `del_line_bg`, `light_gutter_fg`,
`light_add_num_bg`, `light_del_num_bg`) each take `(DiffTheme,
DiffColorLevel)` or just `DiffColorLevel` and return a `Color`.
- **Style helpers** (`style_line_bg_for`, `style_gutter_for`,
`style_sign_add`, `style_sign_del`, `style_add`, `style_del`) each take
`(DiffLineType, DiffTheme, DiffColorLevel)` or `(DiffTheme,
DiffColorLevel)` and return a `Style`.
- **`push_wrapped_diff_line_inner_with_theme_and_color_level`** is the
innermost renderer, accepting both theme and color level so tests can
exercise any combination without depending on the terminal.
- **Line-level background** is applied via
`RtLine::from(...).style(line_bg)` so the tint extends across the full
terminal width, not just the text content.
- **Theme picker integration**: `ListSelectionView` gained a
`preserve_side_content_bg` flag. When `true`, the side panel skips
`force_bg_to_terminal_bg`, letting diff preview backgrounds render
faithfully.

## Observability

No new logging. Theme selection is deterministic from `default_bg()`,
which is already queried and cached at TUI startup.

## Tests

1. **`DiffTheme` is determined per `render_change` call** — if
`default_bg()` changes mid-render (e.g. `requery_default_colors()`
fires), different file chunks could render with different themes. Low
risk in practice since re-query only happens on explicit user action.
2. **16-color tier uses named `Color` variants** (`Color::Green`,
`Color::Red`, etc.) which the terminal maps to its own palette. On
unusual terminal themes these could clash with the background.
Acceptable since 16-color terminals already have unpredictable color
rendering.
3. **Light-theme `style_add` / `style_del` set bg but no fg** — on light
terminals, non-syntax-highlighted content uses the terminal's default
foreground against a pastel background. If the terminal's default fg
happens to be very light, contrast could suffer. This is an edge case
since light-terminal users typically have dark default fg.
4. **`preserve_side_content_bg` is a general-purpose flag but only used
by the theme picker** — if other popups start using side content with
intentional backgrounds they'll need to opt in explicitly. Not a real
risk today, just a note for future callers.
2026-02-24 11:55:01 -08:00
Yaroslav Volovich 67d9261e2c feat(sleep-inhibitor): add Linux and Windows idle-sleep prevention (#11766)
## Background
- follow-up to previous macOS-only PR:
https://github.com/openai/codex/pull/11711
- follow-up macOS refactor PR (current structural approach used here):
https://github.com/openai/codex/pull/12340

## Summary
- extend `codex-utils-sleep-inhibitor` with Linux and Windows backends
while preserving existing macOS behavior
- Linux backend:
  - use `systemd-inhibit` (`--what=idle --mode=block`) when available
- fall back to `gnome-session-inhibit` (`--inhibit idle`) when available
  - keep no-op behavior if neither backend exists on host
- Windows backend:
- use Win32 power request handles (`PowerCreateRequest` +
`PowerSetRequest` / `PowerClearRequest`) with
`PowerRequestSystemRequired`
- make `prevent_idle_sleep` Experimental on macOS/Linux/Windows; keep
under development on other targets

## Testing
- `just fmt`
- `cargo test -p codex-utils-sleep-inhibitor`
- `cargo test -p codex-core features::tests::`
- `cargo test -p codex-tui chatwidget::tests::`
- `just fix -p codex-utils-sleep-inhibitor`
- `just fix -p codex-core`

## Semantics and API references
- Goal remains: prevent idle system sleep while a turn is running.
- Linux:
  - `systemd-inhibit` / login1 inhibitor model:
-
https://www.freedesktop.org/software/systemd/man/latest/systemd-inhibit.html
-
https://www.freedesktop.org/software/systemd/man/org.freedesktop.login1.html
    - https://systemd.io/INHIBITOR_LOCKS/
  - xdg-desktop-portal Inhibit (relevant for sandboxed apps):
-
https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.Inhibit.html
- Windows:
  - `PowerCreateRequest`:
-
https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-powercreaterequest
  - `PowerSetRequest`:
-
https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-powersetrequest
  - `PowerClearRequest`:
-
https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-powerclearrequest
  - `SetThreadExecutionState` (alternative baseline API):
-
https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setthreadexecutionstate

## Chromium vs this PR
- Chromium Linux backend:
-
https://github.com/chromium/chromium/blob/main/services/device/wake_lock/power_save_blocker/power_save_blocker_linux.cc
- Chromium Windows backend:
-
https://github.com/chromium/chromium/blob/main/services/device/wake_lock/power_save_blocker/power_save_blocker_win.cc
- Electron powerSaveBlocker entry point:
-
https://github.com/electron/electron/blob/main/shell/browser/api/electron_api_power_save_blocker.cc

## Why we differ from Chromium
- Linux implementation mechanism:
- Chromium uses in-process D-Bus APIs plus UI-integrated screen-saver
suspension.
- This PR uses command-based inhibitor backends (`systemd-inhibit`,
`gnome-session-inhibit`) instead of linking a Linux D-Bus client in this
crate.
- Reason: keep `codex-utils-sleep-inhibitor` dependency-light and avoid
Linux CI/toolchain fragility from new native D-Bus linkage, while
preserving the same runtime intent (hold an inhibitor while a turn
runs).
- Linux UI integration scope:
- Chromium also uses `display::Screen::SuspendScreenSaver()` in its UI
stack.
- Codex `codex-rs` does not have that display abstraction in this crate,
so this PR scopes Linux behavior to process-level sleep inhibition only.
- Windows wake-lock type breadth:
- Chromium supports both display/system wake-lock types and extra
display-specific handling for some pre-Win11 scenarios.
- Codex’s feature is scoped to turn execution continuity (not forcing
display on), so this PR uses `PowerRequestSystemRequired` only.
2026-02-24 11:51:44 -08:00
sayan-oai 0b6c2e5652 fix: also try matching namespaced prefix for modelinfo candidate (#12658)
#### What
Try matching `\w+`-namespaced model after `longest prefix` as heuristic
to match `ModelInfo` from list of candidates.

This shouldn't regress existing behavior:
- `gpt-5.2-codex` -> `gpt-5.2` if `gpt-5.2-codex` not present
- `gpt-5.3` -> `gpt-5` if `gpt-5.3` not present
- `gpt-9` still doesn't match anything

while being more forgiving for custom prefixes:
- `oai/gpt-5.3-codex` -> `gpt-5.3-codex`

#### Tests
Added unit test.
2026-02-24 10:57:26 -08:00
Eric Traut 74cebceed7 Fix @mention token parsing in chat composer (#12643)
Fixes #12175

If a user types an npm package name with multiple `@` symbols like `npx
-y @foo/bar@latest`, the TUI currently treats this as though it's
attempting to invoke the file picker.

### What changed

- **Generalized `@` token parsing**
- `current_prefixed_token(...)` now treats `@` as a token start **only
at a whitespace boundary** (or start-of-line).
- If the cursor is on a nested `@` inside an existing
whitespace-delimited token (for example `@scope/pkg@latest`), it keeps
the surrounding token active instead of starting a new token at the
second `@`.
- It also avoids misclassifying mid-word usages like `foo@bar` as an `@`
file token.

- **Enter behavior with file popup**
- If the file-search popup is open but has **no selected match**,
pressing `Enter` now closes the popup and falls through to normal submit
behavior.
- This prevents pasted strings containing `@...` from blocking
submission just because file-search was active with no actionable
selection.

### Testing
I manually built and tested the scenarios involved with the bug report
and related use of `@` mentions to verify no regressions
2026-02-24 10:50:00 -08:00
Michael Bolin 3ca0e7673b feat: run zsh fork shell tool via shell-escalation (#12649)
## Why

This PR switches the `shell_command` zsh-fork path over to
`codex-shell-escalation` so the new shell tool can use the shared
exec-wrapper/escalation protocol instead of the `zsh_exec_bridge`
implementation that was introduced in
https://github.com/openai/codex/pull/12052. `zsh_exec_bridge` relied on
UNIX domain sockets, which is not as tamper-proof as the FD-based
approach in `codex-shell-escalation`.

## What Changed

- Added a Unix zsh-fork runtime adapter in `core`
(`core/src/tools/runtimes/shell/unix_escalation.rs`) that:
- runs zsh-fork commands through
`codex_shell_escalation::run_escalate_server`
  - bridges exec-policy / approval decisions into `ShellActionProvider`
- executes escalated commands via a `ShellCommandExecutor` that calls
`process_exec_tool_call`
- Updated `ShellRuntime` / `ShellCommandHandler` / tool spec wiring to
select a `shell_command` backend (`classic` vs `zsh-fork`) while leaving
the generic `shell` tool path unchanged.
- Removed the `zsh_exec_bridge`-based session service and deleted
`core/src/zsh_exec_bridge/mod.rs`.
- Moved exec-wrapper entrypoint dispatch to `arg0` by handling the
`codex-execve-wrapper` arg0 alias there, and removed the old
`codex_core::maybe_run_zsh_exec_wrapper_mode()` hooks from `cli` and
`app-server` mains.
- Added the needed `codex-shell-escalation` dependencies for `core` and
`arg0`.

## Tests

- `cargo test -p codex-core
shell_zsh_fork_prefers_shell_command_over_unified_exec`
- `cargo test -p codex-app-server turn_start_shell_zsh_fork --
--nocapture`
- verifies zsh-fork command execution and approval flows through the new
backend
- includes subcommand approve/decline coverage using the shared zsh
DotSlash fixture in `app-server/tests/suite/zsh`
- To test manually, I added the following to `~/.codex/config.toml`:

```toml
zsh_path = "/Users/mbolin/code/codex3/codex-rs/app-server/tests/suite/zsh"

[features]
shell_zsh_fork = true
```

Then I ran `just c` to run the dev build of Codex with these changes and
sent it the message:

```
run `echo $0`
```

And it replied with:

```
  echo $0 printed:

  /Users/mbolin/code/codex3/codex-rs/app-server/tests/suite/zsh

  In this tool context, $0 reflects the script path used to invoke the shell, not just zsh.
```

so the tool appears to be wired up correctly.

## Notes

- The zsh subcommand-decline integration test now uses `rm` under a
`WorkspaceWrite` sandbox. The previous `/usr/bin/true` scenario is
auto-allowed by the new `shell-escalation` policy path, which no longer
produces subcommand approval prompts.
2026-02-24 10:31:08 -08:00
viyatb-oai 8d3d58f992 feat(network-proxy): add MITM support and gate limited-mode CONNECT (#9859)
## Description
- Adds MITM support (CA load/issue, TLS termination, optional body
inspection).
- Adds `codex-network-proxy init` to create
`CODEX_HOME/network_proxy/mitm`.
- Enforces limited-mode HTTPS correctly: `CONNECT` requires MITM,
otherwise blocked with `mitm_required`.
- Keeps `origin/main` layering/reload semantics (managed layers included
in reload checks).
- Centralizes block reasons (`REASON_MITM_REQUIRED`) and removes
`println!`.
- Scope is MITM-only (no SOCKS changes).

gated by `mitm=false` (default)
2026-02-24 18:15:15 +00:00
Won Park ca556fa313 ctrl-L (clears terminal but does not start a new chat) (#12628)
# ctrl-L

- Clears your terminal window
- Does not start a new chat
2026-02-24 10:03:42 -08:00
Dylan Hurd f6053fdfb3 feat(core) Introduce Feature::RequestPermissions (#11871)
## Summary
Introduces the initial implementation of Feature::RequestPermissions.
RequestPermissions allows the model to request that a command be run
inside the sandbox, with additional permissions, like writing to a
specific folder. Eventually this will include other rules as well, and
the ability to persist these permissions, but this PR is already quite
large - let's get the core flow working and go from there!

<img width="1279" height="541" alt="Screenshot 2026-02-15 at 2 26 22 PM"
src="https://github.com/user-attachments/assets/0ee3ec0f-02ec-4509-91a2-809ac80be368"
/>

## Testing
- [x] Added tests
- [x] Tested locally
- [x] Feature
2026-02-24 09:48:57 -08:00
jif-oai 9a8adbf6e5 feat: use process group to kill the PTY (#12688)
Use the process group kill logic to kill the PTY
2026-02-24 16:55:23 +00:00
pakrym-oaiandCodex 97d0068658 Send warmup request (#11258)
Send a request with `generate: falls` but a full set of tools and
instructions to pre-warm inference.

---------

Co-authored-by: Codex <noreply@openai.com>
2026-02-24 08:15:47 -08:00