Skip to content

fix(claude-bridge): recover login-shell PATH for bare CLI launches#477

Merged
artemgetmann merged 1 commit into
mainfrom
codex/claude-runtime-path-fix-main-20260416
Apr 17, 2026
Merged

fix(claude-bridge): recover login-shell PATH for bare CLI launches#477
artemgetmann merged 1 commit into
mainfrom
codex/claude-runtime-path-fix-main-20260416

Conversation

@artemgetmann
Copy link
Copy Markdown
Owner

Review Fast Path

  • User path fixed: isolated Telegram/launchd-style runtimes can find and launch bare claude again even when the inherited PATH is only system bins.
  • Proof: pnpm exec vitest run src/agents/claude-bridge.test.ts passed; direct stripped-env repro still shows bare claude fails with ENOENT, and the new bridge test proves the spawn env now merges login-shell PATH before launch.
  • Shared-state footgun removed: claude-bridge no longer assumes the service/runtime PATH already includes user-installed CLI bins like /Users/user/.local/bin.
  • Still hurts: this does not claim live Telegram claude-bridge/sonnet is fixed end-to-end yet; it only fixes the bridge executable lookup boundary.

Why This Matters

  • The active blocker is isolated runtime execution context, not Telegram transport and not continuity logic.
  • In clean runtime envs, bare claude can disappear even though it works in the operator login shell.
  • Recovering login-shell PATH at the bridge spawn point keeps the fix narrow and avoids dragging unrelated runtime/auth changes into this slice.

Scope Boundary

  • Changed: src/agents/claude-bridge.ts, src/agents/claude-bridge.test.ts
  • Did not change: Telegram transport, continuity/session handling, service env bootstrap, or tester-runtime config scripts.

Verification

  • pnpm exec vitest run src/agents/claude-bridge.test.ts
  • Direct stripped-env repro before fix shape:
    • env -i HOME="$HOME" USER="$USER" LOGNAME="$LOGNAME" TMPDIR="${TMPDIR:-/tmp}" PATH="/usr/bin:/bin:/usr/sbin:/sbin" /opt/homebrew/bin/node -e 'const { spawnSync } = require("node:child_process"); const before = spawnSync("claude", ["--version"], { encoding: "utf8" }); console.log(JSON.stringify({ beforeError: before.error ? { code: before.error.code, message: before.error.message } : null, beforeStatus: before.status ?? null }));'
    • observed: {"beforeError":{"code":"ENOENT","message":"spawnSync claude ENOENT"},"beforeStatus":null}
  • Test proof of the fix:
    • bridge test asserts spawn env PATH becomes /Users/user/.local/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin when login-shell PATH is available and runtime PATH is stripped

AI Assistance

  • AI-assisted
  • Testing degree: targeted

- what: merge login-shell PATH into claude-bridge spawn env when the backend launches a bare command without an explicit PATH override
- why: isolated runtime and launchd-style environments can drop user PATH entries, so bare `claude` fails with ENOENT even though it works in the operator login shell
- risk: bridge launches now consult login-shell PATH on non-Windows hosts; test coverage keeps the merge scoped to bare-command launches only
@artemgetmann artemgetmann marked this pull request as ready for review April 17, 2026 07:07
@artemgetmann artemgetmann merged commit d474a82 into main Apr 17, 2026
3 of 10 checks passed
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