fix(agent-setup): stop agent wrappers from resolving to themselves

TH
1d ago
+56-1

What & why

The agent wrappers in ~/.paradev/bin can resolve to themselves and recurse forever. find_real_binary skips the wrapper's own bin dir only through the case patterns, and every pattern except getBinDir() is built from $HOME. So the wrapper finds itself again when:

  • a process runs with a different HOME (test runners and sandboxes routinely set one), or
  • the bin dir is on PATH under another spelling. After the Superset to Paradev rename, ~/.superset is a symlink to ~/.paradev, and PATH still lists ~/.superset/bin.

In either case REAL_BIN is the wrapper. It runs itself with --enable hooks added, the copy does the same, and so on until the process table is full.

On my machine a single codex --version from a test suite with a temporary HOME grew to about 3,500 processes in under an hour. With a fake HOME, 175 copies spawned within 3 seconds.

The fix adds two checks in find_real_binary, after a candidate passes the executable test:

  • [ "$dir/$name" -ef "${BASH_SOURCE[0]}" ]: skip the running wrapper itself, however its path is spelled (same device and inode).
  • Skip any file whose first lines carry WRAPPER_MARKER, so another profile's wrapper (~/.paradev-*/bin) is never treated as the real binary either.

The existing case patterns stay as they are.

How I tested it

  • New test: never resolves to itself when its bin dir is on PATH under another spelling. It reaches the wrapper through a symlinked bin dir with HOME pointing elsewhere. Without the fix it times out at 5 s; with the fix it prints the real binary's output. The test starts the wrapper in its own process group and kills the group on timeout, so a failure can't leak the recursion into the test machine. I checked the process count before and after a failing run.
  • bun test src/agent-wrappers.test.ts in packages/agent-setup: 96 pass, 0 fail.
  • bun run typecheck in packages/agent-setup passes, and biome check on both changed files is clean.
  • I applied the same change by hand to all 16 installed wrappers on macOS and ran each with --version, with my real HOME and with a fake one. None recursed. Tools that are installed printed their version, and the missing ones gave the usual "not found" exit 127.

Not run: the full monorepo bun run lint / bun run test, and Linux.

Checklist

  • PR title follows conventional commits (type(scope): subject)
  • bun run typecheck passes for packages/agent-setup; biome check is clean on the changed files (full bun run lint not run)
  • "Allow edits from maintainers" is checked on fork PRs
  • I have signed the CLA (the bot asks on your first PR)
    🤖 Generated with Claude Code

Summary by cubic

Fixes agent wrappers resolving to themselves and recursing until the process table fills when the wrapper runs with a different HOME or the bin dir is on PATH under another spelling (the ~/.superset symlink to ~/.paradev).

  • find_real_binary now skips candidates that are the same file as the running wrapper and candidates carrying the managed-wrapper marker.
  • Adds a regression test that reaches the wrapper through a symlinked bin dir with HOME set elsewhere; it times out on the old behavior and kills the process group.

Summary by CodeRabbit

  • Bug Fixes
    • Fixed a case where Copilot could fail to launch its real executable when the wrapper was reached through a symlink and the home directory differed. Copilot now correctly starts the real executable in this setup and displays its output, improving reliability for users whose PATH includes a symlink to the wrapper.