Repository navigation
Description
Summary
When the plugin is invoked for a write-mode task (e.g. via /codex:rescue or any flow that ends in runAppServerTurn(... { write: true })), codex-companion.mjs hardcodes the sandbox to "workspace-write" at line 460:
sandbox: request.write ? "workspace-write" : "read-only",workspace-write permits filesystem writes inside the workspace but blocks network egress. As a result, any task whose deliverable involves git push (e.g. mechanical sweep PRs, autonomous code-fix PRs) fails inside the Codex shell with:
git push origin <branch>
fatal: unable to access 'https://github.com/<org>/<repo>.git/': Could not resolve host: github.com
The plugin then returns the task as "completed" — the commits exist in a local worktree (typically .claude/worktrees/<branch> of the workspace repo) but they're never pushed and no PR is opened. Recovering the work requires the operator to:
- Read the per-job log under
~/.claude/plugins/data/codex-openai-codex/state/<workspace-hash>/jobs/task-*.log - Discover the worktree path from the log
- Manually push the branch from a shell with working network
- Manually open the PR
Reproduction
- Install the plugin (1.0.2 confirmed; recent versions likely affected).
- Invoke a write-mode task that ends with a push, e.g. via the rescue agent in Claude Code:
"Update the gitignore in this repo to add
<some-path>. Open a PR titledchore: ...." - Codex completes the local work (branch + commit), then attempts
git push. - Push fails with the DNS error above; plugin returns success-shaped output.
Why this matters
Write-mode tasks are the highest-leverage use of the plugin — they're the "fire-and-forget delegation" path that makes the plugin valuable vs the bare CLI. The current behavior turns every push-required task into an archaeology exercise, which removes most of the plugin's UX win over codex exec directly.
Proposed fix
Make the sandbox mode configurable, with safer defaults than danger-full-access but with git push capability. Two options:
Option 1 (minimal): pass through caller-provided sandbox
Allow callers of runWriteTask (or whatever the entry is) to override the sandbox via the request object:
sandbox: request.sandbox ?? (request.write ? "workspace-write" : "read-only"),This lets internal callers (e.g. the rescue agent) opt into danger-full-access for tasks that need push, while leaving the conservative default for everything else.
Option 2 (better): respect ~/.codex/config.toml trust_level
The Codex CLI's config already defines per-project trust_level (e.g. [projects."/Users/og/src/exit"] trust_level = "trusted"). When the workspace root matches a project with trust_level = "trusted", default the sandbox to danger-full-access (or whatever the closest equivalent is that permits network for git push). This makes the trust model explicit and centralized, rather than hardcoded in plugin logic.
Option 3 (fallback): post-Codex push step
If Option 1/2 are too invasive, add a post-completion step in the plugin that runs git push from outside the sandbox (i.e., in the plugin's own shell, which has full network access). This separates "Codex generates commits inside sandbox" from "plugin pushes to remote outside sandbox" — cleaner separation of concerns.
Workaround in use
For now, we're routing push-required tasks through codex exec --sandbox danger-full-access "<prompt>" directly via Bash, bypassing the plugin entirely. This loses the plugin's auto-PR scaffolding but recovers reliable push behavior.
Environment
- Plugin version: 1.0.2 (latest as of 2026-05-07)
- Codex CLI: 0.129.0
- Platform: macOS (Apple Silicon)
- Workspace: trusted in
~/.codex/config.toml
Activity
feat(sandbox)!: inherit user ~/.codex/config.toml sandbox_mode by def…
docs(v2.0.0): sync README + MIGRATION_v2.0.md + TROUBLESHOOTING.md wi…
docs(exploration): Phase B — suminerProxy fork eval + upstream issue …
creatornader commentedon Jul 14, 2026
Corroborating evidence for the hardcoded sandbox override, from a different failure surface: under the forced
workspace-writeseatbelt on macOS, vitest's defaultforkspool cannot create its child-process IPC channel (socketpair), so delegated test runs hang indefinitely rather than failing. Workaround that unblocked us: pass--pool=threadsto vitest for any run under the companion. Also confirming the quoted expression is still present in plugin v1.0.6 (the line number has drifted from the one cited here; it sits near line 491 in that version), and that a user-levelsandbox_mode = "danger-full-access"in~/.codex/config.tomlis still ignored by the companion path while honored by directcodex exec. If honoring the user config is unacceptable as a default for safety reasons, an explicit per-invocation opt-in flag would resolve both the write-scope and the test-IPC failure classes.ZalmyAI commentedon Aug 3, 2026
Confirming this is still live on plugin v1.0.5, reproduced independently today across 4 separate
/codex:rescue-dispatched write-mode jobs in the same session (all hitCould not resolve host: github.cominside the Codex shell after doing real, correctly-tested work in an isolated worktree — none could push or open a PR themselves). Root cause matches #482's more general framing (sandboxis always explicitly set onthread/start/thread/resume, so~/.codex/config.toml'ssandbox_mode = "danger-full-access"never applies to plugin-dispatched jobs) rather than being specific to one code path.Workaround we're using in the meantime: treat every write-mode dispatch that ends in a PR as "build in the sandbox, then have the orchestrating Claude Code session (which has real network access) push the worktree branch and open/merge the PR" rather than expecting the job to self-publish. Worth noting for anyone hitting this: the job's own
codex-companion.mjs result <job-id>output still reports the worktree path and commit SHAs even when publication fails, so the work isn't lost — just needs a manual handoff.