Skip to content

fix: make orchestration work when wmux isn't on PATH (fall back to $WMUX_CLI) - #5

Open
tawman wants to merge 2 commits into
amirlehmam:masterfrom
tawman:feature/wmux-resolve-cli
Open

fix: make orchestration work when wmux isn't on PATH (fall back to $WMUX_CLI)#5
tawman wants to merge 2 commits into
amirlehmam:masterfrom
tawman:feature/wmux-resolve-cli

Conversation

@tawman

@tawman tawman commented Jul 7, 2026

Copy link
Copy Markdown

The problem we hit

We use this plugin heavily for Claude Code orchestration on Windows. On a fresh wmux install, orchestration silently degrades: spawn-agents.sh warns "wmux not found in PATH" and drops to subagent mode, and the dashboard/notify hooks are skipped. Until now the only fix was hand-installing wmux shims into ~/.local/bin on every machine.

Root cause

The plugin's scripts run as non-interactive bash (Claude Code hooks / Bash tool) and call bare wmux, guarded by command -v wmux. But wmux only provides the wmux command as an interactive shell function (via shell-integration), which doesn't propagate to bash -c children — so the guard fails even though wmux is running and reachable. What those shells do always have is $WMUX_CLI: wmux injects the CLI-script path into every shell it spawns.

The fix

scripts/wmux-resolve.sh (new, 3 lines of logic):

if ! command -v wmux >/dev/null 2>&1 && [ -n "${WMUX_CLI:-}" ]; then
  wmux() { node "$WMUX_CLI" "$@"; }
fi

Sourced from orchestration-state.sh (which every wmux-calling script already sources) and from the standalone detect-wmux.sh. Defining a function makes the existing command -v wmux guards pass, so no other call sites change. No-op when a real wmux is on PATH; Node is guaranteed (Claude Code runs on it).

Also adds .gitattributes with *.sh text eol=lf — on a Windows clone with core.autocrlf=true, checkout otherwise flips the scripts to CRLF and breaks their shebangs. Existing blobs are already LF, so this renormalizes nothing.

Verification

  • With wmux absent from PATH and $WMUX_CLI set (any wmux-spawned shell), detect-wmux.sh now prints available and wmux pingpong through the fallback.
  • Running daily with real orchestrations: agents spawn into panes, hooks update the dashboard — no ~/.local/bin shims installed.

Related: amirlehmam/wmux#75 fixes the same gap at the root (wmux putting a cli-bin shim dir on spawned shells' PATH). This fallback makes the plugin work on current and older wmux releases without waiting for that.

Also: orchestration lessons learned, folded into the distributed skills

We have been running heavy multi-agent Claude Code orchestrations on wmux, and this PR also contributes that operating knowledge back into the distributed skills so they match how orchestration actually behaves:

  • skills/orchestrate Phase 7 (monitoring) corrected — the completion signal is the agent's result file, not process exit: launch-agent.js runs agents interactively, so a finished agent idles at its TUI and never exits, and the previous "poll wmux agent list for exited" loop never terminates. The skill now polls result files, and documents that the coordinator owns state.json (Claude Code Stop/SubagentStop hooks don't fire for wmux-spawned agents) using the status vocabulary the sidebar actually counts (exited for agents, complete for waves/run).
  • Consistent agent ids — bare ids ("a", not "agent-a"): the scripts prefix agent- themselves, so the old schema example produced double-prefixed prompt/result filenames the launcher couldn't find.
  • Windows reliability notes — align TMPDIR with the temp dir the sidebar watches (Git Bash), forward-slash paths in state.json (backslashes are invalid JSON escapes and freeze the cockpit), retry reads that race the app's 1 s poller.
  • Pane hygiene — start each run from a single coordinator pane (re-gridding over leftover panes orphans their surfaces as dead tabs), collapse after; wmux send targets the caller's own surface by default (use --surface); agent kill doesn't kill agents' child processes (sweep orphaned dev-server ports).
  • New skills/orchestrate/references/browser-driving.md — field recipes for agents driving the browser panel: bare eN refs, the single persistent eval scope (IIFE), snapshot parsing, React/Radix synthetic-event input recipes, the transient-UI polling caveat, and the port-9222 CDP collision warning.

tawman added 2 commits July 7, 2026 01:47
The orchestrator calls bare wmux from non-interactive shells (Claude Code's Bash
tool, hook scripts). A patched wmux puts a wmux shim on those shells' PATH; on an
un-patched/upstream wmux it isn't there. Add scripts/wmux-resolve.sh (defines a
wmux() -> node $WMUX_CLI fallback), sourced from orchestration-state.sh (covers
all callers that use it) and directly in the standalone detect-wmux.sh. Defining
the function makes existing 'command -v wmux' guards pass, so no other call sites
change. Mirrors the app-bundled copy in tawman/wmux.
… skills

Corrections and additions from running real Claude Code orchestrations,
so the skills match how orchestration actually behaves:

- orchestrate Phase 7: completion signal is the RESULT FILE, not process
  exit — launch-agent.js runs agents interactively, so a finished agent
  idles at its TUI and never exits; the old "poll agent list for exited"
  loop never terminates. Also: the coordinator owns state.json (Stop/
  SubagentStop hooks don't fire for wmux-spawned agents), and the sidebar
  only counts status vocabulary exited (agents) / complete (waves, run).
- orchestrate Phase 6b: bare agent ids ("a", not "agent-a" — scripts
  prefix agent- themselves; the old schema was self-inconsistent),
  forward-slash paths in state.json, TMPDIR alignment on Git Bash so the
  sidebar cockpit sees the run.
- Pane hygiene: start from a single coordinator pane (re-gridding over
  leftover panes orphans their surfaces as dead tabs), collapse after.
- Nudging workers: wmux send targets the CALLER's surface by default —
  always pass --surface; agent kill doesn't kill agents' child processes.
- New references/browser-driving.md: CLI sharp edges for the browser
  panel (bare refs, single persistent eval scope, snapshot parsing,
  React/Radix synthetic-event recipes, transient-UI polling caveat,
  port-9222 CDP collision).
- wmux-detect: note the $WMUX_CLI fallback.
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