Skip to content

fix(codex): detect proxy shims that pass which() but fail on invoke - #155

Open
vanvasten wants to merge 1 commit into
mainfrom
fix/codex-shim-detection
Open

fix(codex): detect proxy shims that pass which() but fail on invoke#155
vanvasten wants to merge 1 commit into
mainfrom
fix/codex-shim-detection

Conversation

@vanvasten

Copy link
Copy Markdown
Contributor

What this does

Fresh ./setup.sh crashes with a stack trace on machines where a codex proxy shim sits on PATH — most commonly cmux, which drops a shim at \$TMPDIR/cmux-cli-shims/<uuid>/codex. The shim exists (so Bun.which returns it), but invoking it just prints Error: codex not found in PATH and exits non-zero — so readCodexPluginState throws that raw error and takes setup down.

After this fix, codexCliAvailable() actually verifies codex runs before trusting it. On the reproducing machine, setup now exits cleanly with the existing friendly "Codex CLI is required for a full Codex install" message instead of a stack trace.

Summary

  • `src/lib/codex-install.ts` — `codexCliAvailable()` gains a memoized `codex --version` probe (3s timeout) after the `hasCommand` check. Fast path unchanged when nothing named `codex` is on PATH. New `resetCodexCliAvailabilityMemoForTests()` export lets PATH-mutating tests force a re-probe.
  • `tests/codex-install.test.ts` — two new tests in a `describe.skipIf(win32)` block: a POSIX shim that exits non-zero (mimics cmux), and an empty-PATH fast path.
  • No call sites of `codexCliAvailable()` touched (still sync, still `boolean`). No changes to `runCommand`, `readCodexPluginState`, `hasCommand`, or any downstream install code.

Repro

```
$ which codex
/var/folders/.../cmux-cli-shims//codex # cmux shim
$ ./setup.sh
✗ Setup failed: Codex plugin state query failed: Error: codex not found in PATH
at readCodexPluginState (src/lib/codex-install.ts:1516:15)
at async assertFirstInstallDestinationsAbsent (src/lib/codex-install.ts:1147:31)
at async installCodex (src/lib/codex-install.ts:1987:11)
```

After the fix, same machine:

```
$ ./setup.sh
✗ Codex CLI is required for a full Codex install
```

(User then re-runs with `--light` to skip Codex, or installs real codex.)

Test Plan

  • `bun run typecheck` — clean
  • `bun test tests/codex-install.test.ts -t "codexCliAvailable"` — 2 pass, 0 fail
  • Full `bun test` — 1767 pass. 6 pre-existing failures verified via `git stash` (identical output on unmodified main), none introduced by this change
  • `bun run lint` — clean (3 pre-existing warnings, unchanged lines)
  • `bash setup.sh` on reproducing machine — no stack trace, exits cleanly on friendly message

Setup crashed on fresh installs where a codex proxy shim lives on PATH
(e.g. cmux CLI shims at $TMPDIR/cmux-cli-shims/.../codex). Bun.which
resolved the shim, so codexCliAvailable() returned true; then
readCodexPluginState invoked `codex plugin list --json`, the shim exited
non-zero with "Error: codex not found in PATH", and the raw error surfaced
as a stack trace instead of falling through to the friendly
"Codex CLI is required for a full Codex install" message.

- codexCliAvailable now probes `codex --version` (3s timeout) after the
  hasCommand check, memoized per process to avoid re-probing across the
  ~15 call sites. Non-zero exit or spawn failure -> unavailable.
- resetCodexCliAvailabilityMemoForTests exported so tests that mutate
  PATH can force a re-probe.
- Two new tests: POSIX shim that exits non-zero (mimics cmux) and empty
  PATH fast path. Windows-gated via describe.skipIf since the shim uses
  #!/bin/sh.

bash setup.sh on the reproducing machine now prints the friendly
"Codex CLI is required for a full Codex install" and exits 1 cleanly,
with no stack trace.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant