core-agent-ide/codex-rs/core
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
..
src feat: run zsh fork shell tool via shell-escalation (#12649) 2026-02-24 10:31:08 -08:00
templates memories: tighten memory lookup guidance and citation requirements (#12635) 2026-02-24 11:46:28 +00:00
tests feat(core) Introduce Feature::RequestPermissions (#11871) 2026-02-24 09:48:57 -08:00
BUILD.bazel Add feature-gated freeform js_repl core runtime (#10674) 2026-02-11 12:05:02 -08:00
Cargo.toml feat: run zsh fork shell tool via shell-escalation (#12649) 2026-02-24 10:31:08 -08:00
config.schema.json feat(core) Introduce Feature::RequestPermissions (#11871) 2026-02-24 09:48:57 -08:00
gpt-5.1-codex-max_prompt.md Assemble sandbox/approval/network prompts dynamically (#8961) 2026-01-12 23:12:59 +00:00
gpt-5.2-codex_prompt.md Assemble sandbox/approval/network prompts dynamically (#8961) 2026-01-12 23:12:59 +00:00
gpt_5_1_prompt.md Assemble sandbox/approval/network prompts dynamically (#8961) 2026-01-12 23:12:59 +00:00
gpt_5_2_prompt.md Assemble sandbox/approval/network prompts dynamically (#8961) 2026-01-12 23:12:59 +00:00
gpt_5_codex_prompt.md Assemble sandbox/approval/network prompts dynamically (#8961) 2026-01-12 23:12:59 +00:00
hierarchical_agents_message.md Add hierarchical agent prompt (#8996) 2026-01-09 13:47:37 -08:00
models.json Update models.json (#11408) 2026-02-23 18:37:31 -08:00
prompt.md Assemble sandbox/approval/network prompts dynamically (#8961) 2026-01-12 23:12:59 +00:00
prompt_with_apply_patch_instructions.md Assemble sandbox/approval/network prompts dynamically (#8961) 2026-01-12 23:12:59 +00:00
README.md [feat] add seatbelt permission files (#11639) 2026-02-12 23:30:22 +00:00
review_prompt.md docs: Fix markdown list item spacing in codex-rs/core/review_prompt.md (#4144) 2025-10-30 17:39:21 -07:00

codex-core

This crate implements the business logic for Codex. It is designed to be used by the various Codex UIs written in Rust.

Dependencies

Note that codex-core makes some assumptions about certain helper utilities being available in the environment. Currently, this support matrix is:

macOS

Expects /usr/bin/sandbox-exec to be present.

When using the workspace-write sandbox policy, the Seatbelt profile allows writes under the configured writable roots while keeping .git (directory or pointer file), the resolved gitdir: target, and .codex read-only.

Network access and filesystem read/write roots are controlled by SandboxPolicy. Seatbelt consumes the resolved policy and enforces it.

Seatbelt also supports macOS permission-profile extensions layered on top of SandboxPolicy:

  • no extension profile provided: keeps legacy default preferences read access (user-preference-read).
  • extension profile provided with no macos_preferences grant: does not add preferences access clauses.
  • macos_preferences = "readonly": enables cfprefs read clauses and user-preference-read.
  • macos_preferences = "readwrite": includes readonly clauses plus user-preference-write and cfprefs shm write clauses.
  • macos_automation = true: enables broad Apple Events send permissions.
  • macos_automation = ["com.apple.Notes", ...]: enables Apple Events send only to listed bundle IDs.
  • macos_accessibility = true: enables com.apple.axserver mach lookup.
  • macos_calendar = true: enables com.apple.CalendarAgent mach lookup.

Linux

Expects the binary containing codex-core to run the equivalent of codex sandbox linux (legacy alias: codex debug landlock) when arg0 is codex-linux-sandbox. See the codex-arg0 crate for details.

All Platforms

Expects the binary containing codex-core to simulate the virtual apply_patch CLI when arg1 is --codex-run-as-apply-patch. See the codex-arg0 crate for details.