manaflow-ai / manaflow-ai/cmux

Claude session resume fails ("claude not found in PATH") when the binary isn't on the GUI base PATH

Open
#8,317 0 comments 0 reactions 1 assignee View on GitHub

@lawrencecchen is already working on this.

Since Aug 1, 2026.

bug
Dominant language
Swift
Stars
27.2k
Forks
2.4k
Avg merge
11h 59m
Merged PRs (30d)
559

Description

### cmux version

0.64.19

### macOS version

Tahoe 26.5.2

### Mac chip

Apple Silicon (M1/M2/M3/M4)

### Installation method

Homebrew

### Can you reproduce this on cmux NIGHTLY?

I could not test NIGHTLY

### Bug description

After quitting and relaunching cmux, every restored Claude tab comes back as a bare shell showing `Error: claude not found in PATH`, and the session does not resume. Codex tabs in the same window resume fine.

This happens when `claude` is installed in a directory that is added to `PATH` only by an interactive shell rc file (e.g. `~/.zshrc`), rather than being on the system's GUI base PATH. A representative case is a version manager or a custom install dir like `~/.local/bin` or `~/some-tool/bin` that you add in your shell profile.

Root cause: the Claude resume command is built with a bare `claude` executable instead of the captured absolute path. In `AgentResumeArgv.claudeResumeArgv(...)` the executable is hardcoded to `"claude"` (the captured `executablePath` is ignored), then rendered through `claudeWrapperShellExecutableToken`:

```
"$([ -x "${CMUX_CLAUDE_WRAPPER_SHIM:-}" ] && printf '%s' "$CMUX_CLAUDE_WRAPPER_SHIM" || printf claude)"
```

On relaunch this runs `cmux-claude-wrapper`, whose `find_real_claude()` walks the resume shell's PATH. That shell inherits only the GUI base PATH (`/etc/paths` + `/etc/paths.d`, via `path_helper`) and sources no interactive rc files, so a `claude` that lives in a dir added only by `~/.zshrc` is absent; the wrapper's shim is also gone (its temp dir does not survive a restart), so the lookup exits 127.

Why codex is unaffected: the codex resume command runs the captured absolute path directly, so PATH resolution never matters.

Suggested fix: have `claudeResumeArgv` embed the captured absolute `executablePath` (as the codex path does) instead of hardcoding `"claude"`. cmux already has the correct path at registration time (`CMUX_AGENT_LAUNCH_EXECUTABLE`).

### Expected behavior

After a restart, restored Claude tabs should resume their sessions (run `claude --resume `) using the same binary they were launched with, regardless of whether that binary is on the GUI base PATH - the same way codex tabs already resume correctly.

### Steps to reproduce

1. Install `claude` somewhere that is on your interactive shell PATH but NOT on the macOS GUI base PATH (i.e. a dir added only in `~/.zshrc`/`~/.zprofile`, not present in `/etc/paths` or `/etc/paths.d`). Example: a version manager shim dir or a custom `~/some-tool/bin`.
2. In cmux, start a Claude Code session in a tab and use it.
3. Quit cmux (Cmd-Q) and relaunch it (with session restore / autoResumeAgentSessions on).
4. The restored Claude tab shows `Error: claude not found in PATH` instead of resuming.

### Shell and environment

zsh. `claude` is resolved on the interactive PATH via a dir added in a shell rc file, and cmux's own shell integration wraps `claude` as a shell function pointing at its wrapper. No custom prompt/tmux involvement needed to reproduce.

### Relevant logs or crash reports

```text
No crash. The restored tab prints exactly:

Error: claude not found in PATH

This string is emitted by `find_real_claude()` in `cmux-claude-wrapper` (exit 127) when its PATH walk finds no non-shim `claude`.
```

### Screenshots or screen recordings

_No response_

### Additional context

Still present on `main`: `find_real_claude()` and `claudeResumeArgv()` are unchanged, so this should reproduce on current/nightly builds. Note `SurfaceResumeCommandCanonicalizer+PortableAgentExecutable.swift` already routes *stale* PATH-managed executables through the wrapper token (`isPATHManagedAgentExecutablePath` recognizes `.local/bin`, `.asdf`, `.nvm`, `.bun`, `.volta`, `.fnm`, `mise` shims, etc.), but (a) that path only triggers when the resume command already carries an absolute path whose file is now gone, not the common case where the command was built with bare `claude` from the start, and (b) install dirs outside that recognized list still slip through.

Workaround: set Automation -> Claude Binary Path (`claudeCodeCustomClaudePath`) to the real binary; `find_real_claude()` honors it before the PATH walk. Confirmed this fixes resume across restarts.

Possibly related: #7391 (resume-binding drift), #7655 (custom claude binaries), #5639 (stale PATH-managed codex executable).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.