Summary
When /codex:rescue routes to the codex:codex-rescue subagent, the subagent's forward command fails because ${CLAUDE_PLUGIN_ROOT} resolves to an empty string in the subagent's Bash environment. The command becomes node "/scripts/codex-companion.mjs" task … → Cannot find module '/scripts/codex-companion.mjs'. The subagent then silently falls back to doing its own grep-based investigation and returns a non-Codex answer, so no Codex job is ever created and the user is unaware Codex was never invoked.
Environment
- Plugin
codex v1.0.4 (marketplace openai/codex-plugin-cc)
- Claude Code 2.1.186 (Agent SDK 0.3.186), VS Code extension
- codex-cli 0.133.0, Node v20.20.2, Linux (WSL2)
- ChatGPT auth, plugin enabled, project trusted, review-gate off
Repro
- Install/enable the plugin; confirm
/codex:setup reports ready.
- Run a substantial
/codex:rescue <multi-file investigation prompt>.
- Observe the subagent returns a plausible answer fairly quickly.
- Run
/codex:status → no job exists (running: [], recent: [], latestFinished: null). The returned answer was authored by the subagent, not Codex.
Root cause
${CLAUDE_PLUGIN_ROOT} is a harness template token that Claude Code substitutes when rendering plugin commands and hooks (textually, per-plugin). It is not exported as a real environment variable into the Bash environment of a spawned subagent.
plugins/codex/agents/codex-rescue.md instructs the subagent to run node "${CLAUDE_PLUGIN_ROOT}/scripts/codex-companion.mjs" task … via Bash.
- In the subagent's shell,
${CLAUDE_PLUGIN_ROOT} expands to empty → module-not-found.
Verified:
- In a subagent Bash,
echo "[${CLAUDE_PLUGIN_ROOT}]" prints [] (empty) by default.
- Running the exact forward command with an empty var reproduces
Cannot find module '/scripts/codex-companion.mjs'.
- Exporting
CLAUDE_PLUGIN_ROOT=<plugin-root> (e.g. via a project env setting) makes the var available in subagent Bash, and /codex:rescue then forwards correctly and creates a real Codex job.
Impact
Silent, dangerous failure mode: the user believes Codex ran when it did not. This directly violates the plugin's own codex-result-handling rule ("if Codex was never successfully invoked, do not generate a substitute answer"), because the substitute is produced by the subagent before any result-handling guidance applies.
Suggested fixes
- Have the subagent resolve the script path robustly instead of relying on
${CLAUDE_PLUGIN_ROOT} being present in the shell env — e.g. pass the absolute companion path into the subagent prompt at command-render time (the slash-command layer already receives the expanded path), or derive it without the env var.
- Alternatively, make the subagent hard-fail (return nothing) when the forward command errors, rather than silently self-investigating — at minimum this surfaces the problem instead of masking it.
Summary
When
/codex:rescueroutes to thecodex:codex-rescuesubagent, the subagent's forward command fails because${CLAUDE_PLUGIN_ROOT}resolves to an empty string in the subagent's Bash environment. The command becomesnode "/scripts/codex-companion.mjs" task …→Cannot find module '/scripts/codex-companion.mjs'. The subagent then silently falls back to doing its own grep-based investigation and returns a non-Codex answer, so no Codex job is ever created and the user is unaware Codex was never invoked.Environment
codexv1.0.4 (marketplaceopenai/codex-plugin-cc)Repro
/codex:setupreports ready./codex:rescue <multi-file investigation prompt>./codex:status→ no job exists (running: [],recent: [],latestFinished: null). The returned answer was authored by the subagent, not Codex.Root cause
${CLAUDE_PLUGIN_ROOT}is a harness template token that Claude Code substitutes when rendering plugin commands and hooks (textually, per-plugin). It is not exported as a real environment variable into the Bash environment of a spawned subagent.plugins/codex/agents/codex-rescue.mdinstructs the subagent to runnode "${CLAUDE_PLUGIN_ROOT}/scripts/codex-companion.mjs" task …via Bash.${CLAUDE_PLUGIN_ROOT}expands to empty → module-not-found.Verified:
echo "[${CLAUDE_PLUGIN_ROOT}]"prints[](empty) by default.Cannot find module '/scripts/codex-companion.mjs'.CLAUDE_PLUGIN_ROOT=<plugin-root>(e.g. via a projectenvsetting) makes the var available in subagent Bash, and/codex:rescuethen forwards correctly and creates a real Codex job.Impact
Silent, dangerous failure mode: the user believes Codex ran when it did not. This directly violates the plugin's own
codex-result-handlingrule ("if Codex was never successfully invoked, do not generate a substitute answer"), because the substitute is produced by the subagent before any result-handling guidance applies.Suggested fixes
${CLAUDE_PLUGIN_ROOT}being present in the shell env — e.g. pass the absolute companion path into the subagent prompt at command-render time (the slash-command layer already receives the expanded path), or derive it without the env var.