Skip to content

Stop a loop whose backend CLI is not on PATH, and say so - #343

Merged
scgopi merged 1 commit into
mainfrom
fix/provider-not-on-path
Sep 12, 2026
Merged

scgopi merged 1 commit into
mainfrom
fix/provider-not-on-path

Conversation

@scgopi

@scgopi scgopi commented Sep 12, 2026

Copy link
Copy Markdown
Owner

What changes

When a loop's backend CLI (claude, copilot, codex, opencode) can't be found, GraphCode now stops the loop and shows a dialog instead of leaving a dead session that reads running — or, when the pane reported the exit, succeeded.

claude is not on your PATH
“Hello” was stopped. GraphCode couldn't find claude, the Claude Code command-line tool, so the loop was stopped instead of left running without an agent. Loops start their agent from a login shell (/bin/zsh -i -l): install Claude Code, or add the folder containing claude to PATH in ~/.zshrc or ~/.zprofile, then restart the loop.

How it's detected

The daemon resolves the executable the way launches do — /bin/zsh -i -l -c 'whence -p -- <exe>' in a PTY (ProviderPath). whence -p rather than command -v, because the launch execs the agent and an alias wouldn't survive that. Bounded at 15s; an undecided probe never stops a loop. Found answers are cached briefly; missing ones never are.

Where Covers
After every GraphStore.ensureSession Daemon launches (ZmxSessionLauncher)
Pane exit report (nodeCheckApproved) App-terminal launches (GhosttyTerminalView) — the exit no longer resolves the loop
Presence reading with exit code 127 Any session no launch checked

Remote projects are skipped — their PATH belongs to another machine.

Stop, dialog, restart

  • The node goes to stopped with LoopNode.launchFailure, which carries the executable, backend, and time. Older apps decode snapshots unchanged. The card shows the reason, and the loop's memory records it.
  • The app raises the dialog when a snapshot carries a failure it hasn't shown yet. Failures a project already had when it first loaded stay on their cards, with no dialog at launch.
  • Restart Session is now allowed for a loop stopped this way. It clears the failure and launches again. A daemon restart doesn't relaunch it.
  • A key pressed on the dead pane no longer deletes such a loop.

Gate (worktree, private DerivedData)

Step Result
xcodebuild test -scheme graphcode exit=0 — 1730 tests in 183 suites passed, including 12 new in ProviderNotOnPathTests
xcodebuild build -scheme graphcode-cli / graphcoded exit=0 / exit=0
swiftlint lint errors 0
swift format lint --strict exit=0
scripts/cli-smoke.sh (fresh SwiftPM build) exit=0, 5/5 verbs
Isolated daemon, claude off the login shell's PATH, goal loop on Claude Code runningstopped; memory: "stopped: claude is not on your PATH — …"; launchFailure persisted

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@scgopi
scgopi merged commit 96a7f45 into main Sep 12, 2026
1 check 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