@mporenta/pi-cmux-orchestrator

extension

Pi extension for orchestrating visible, interactive Pi workers in cmux terminal surfaces.

by · v0.1.1 · published 3w ago

$ pi install npm:@mporenta/pi-cmux-orchestrator
downloads/mo
328
stars
last push
open issues

Signals

license: MITtestspi manifest: missinginstall size: —deps: 0peer deps: 0

Download trend

No downloads in the last 12 weeks.

README

@mporenta/pi-cmux-orchestrator

A Pi package that lets a parent Pi session create and supervise visible, interactive Pi workers in cmux terminal surfaces. Workers stay human-observable and can be prompted, inspected, stopped, or handed over between the orchestrator and a person.

Use it as the visible transport and topology layer for multi-agent coding workflows: the orchestrator owns routing, the workers do the work in their own cmux surfaces, and a human can step into any surface at any time. It does not, by itself, enforce a workflow — the orchestrator's prompts supply the durable handoffs, completion sentinels, and verification described under Building multi-agent workflows.

Requirements

  • macOS with cmux installed and running
  • cmux available on PATH
  • pi available on PATH
  • A parent Pi session launched inside a cmux terminal surface (so CMUX_WORKSPACE_ID is set), unless every worker is spawned with layout: "new-workspace"

Install

pi install npm:@mporenta/pi-cmux-orchestrator

For project-local installation:

pi install -l npm:@mporenta/pi-cmux-orchestrator

Try the package without installing it:

pi -e npm:@mporenta/pi-cmux-orchestrator

After installation, restart Pi. When developing from an auto-discovered extension directory, /reload reloads the extension.

First prompts to try

  • “Spawn a Pi worker to review the current changes.”
  • “List the Pi workers and show their ownership and liveness.”
  • “Ask the worker to run the targeted tests, then report its latest result.”
  • “Spawn a builder and a separate verifier in a new workspace, then route the verifier’s verdict back to me.”

Tools

ToolPurpose
spawn_pi_workerStart a visible interactive Pi worker in the same or a new cmux workspace.
send_worker_promptSend a follow-up or steering prompt to an orchestrator-owned worker.
list_workersList worker ownership, cmux surface, and liveness state.
stop_workerGracefully stop a worker and optionally close its cmux surface.
get_worker_resultRetrieve the worker's latest result.
release_workerReturn a human-taken worker to orchestrator ownership.

Tool parameters

  • spawn_pi_workername?, cwd? (defaults to the parent session cwd), prompt? (delivered once the worker is online), layout? ("same-workspace" default, or "new-workspace"), waitForOnline? (defaults to true; the call blocks up to 30s for the worker to connect back). Returns { success: true, worker } or a typed failure with reason (not_in_cmux, cmux_error, shell_readiness_timeout, worker_online_timeout).
  • send_worker_promptworkerId, prompt, deliverAs? ("followUp" default, queued after the current turn, or "steer" to interrupt). A prompt to a human-owned worker is deferred, not delivered ({ deferred: true }).
  • list_workers — no parameters. Returns every known worker with its state, owner, cmuxSurfaceId, cmuxWorkspaceId, and last heartbeat.
  • stop_workerworkerId, closeSurface? (defaults to false; leaves the surface open for inspection unless set).
  • get_worker_resultworkerId. Returns the latest result inline up to 8 KB; larger results are written to a file under the run directory and returned as { resultId, path }.
  • release_workerworkerId. Clears human ownership so the orchestrator may prompt the worker again.

How it works

The parent extension starts a local Unix-domain socket server under the system temporary directory (pi-cmux-orchestrator-<sessionId>/parent.sock). It creates cmux terminal surfaces, waits for each shell to become ready, and launches a child pi process with worker-specific environment variables. Workers connect back to the parent over the local socket and exchange lifecycle events — online, heartbeat (every 5s), status, result, offline — while staying visible in cmux.

Worker records are persisted as custom session entries, so list_workers and results survive a /reload of the parent session; previously live workers are marked stale on restore until they heartbeat again.

Worker lifecycle

A worker moves through these state values (visible via list_workers):

StateMeaning
pendingSurface created and pi launched; waiting for the worker to connect back.
onlineConnected and idle.
busyRunning a turn, a tool, or a delivered prompt.
staleNo heartbeat for ≥15s; may recover on the next heartbeat.
presumed_deadNo heartbeat for ≥30s.
offlineCleanly stopped or its session shut down.
failedConfiguration or connection error; inspect the visible surface.

Ownership and human handoff

A worker is orchestrator-owned until interactive input is detected directly in its cmux surface, at which point it becomes human-owned. The orchestrator will not prompt a human-owned worker — prompts are deferred — until release_worker returns it to orchestrator ownership. This is what keeps a person able to take over any surface without the orchestrator fighting them for control.

Building multi-agent workflows

The orchestrator supplies transport; a durable, trustworthy workflow comes from the prompts you route through it. When designing one, apply the building-cmux-agent-workflows skill:

  • Choose the smallest honest topology. A single narrow lane wants three roles — lead, builder, verifier. Keep the lead (this orchestrator session) as the sole routing authority; never route by whichever surface happens to be focused. Capture each workerId → surface reference at spawn time (spawn_pi_worker returns it, list_workers re-lists it).
  • Write durable handoffs, not scrollback. Have workers read and write files — .team/REQUEST.md, PLAN.md, ACCEPTANCE.md, round-scoped logs, patches — so state outlives any single terminal. Terminal output is evidence transport, not the source of truth.
  • Dispatch narrowly. Give each worker its role, allowed paths, exact validation commands, a completion sentinel, and a prohibition on unrelated edits, all in the spawn prompt or a send_worker_prompt follow-up.
  • Wait by event, then read once. get_worker_result returns a worker's settled assistant text — treat its arrival as a doorbell, then confirm the agreed sentinel and required artifacts actually exist before accepting completion. Ask each role to print one machine-readable final line, e.g. CMUX-WORK-DONE: <role> | <PASS|FAIL> | <round> | <summary>.
  • Verify independently. Spawn a separate verifier that re-reads the original request and runs fresh checks; a builder running its own tests is not independent verification.
  • Bound the revision loop. On FAIL, send_worker_prompt the exact evidence back to the responsible builder. Stop after a fixed round/time limit or on repeated unchanged failure, and report the blocker instead of looping.
  • Tear down safely. Preserve reports and patches, then stop_worker only the surfaces this workflow owns. Pass closeSurface: false (the default) when a human may still want to inspect a surface; never close or steal focus from a surface you do not own.

Configuration

The extension configures workers internally through these environment variables; users normally do not need to set them:

  • PI_CMUX_ORCH_ROLE — set to worker in spawned sessions; unset (parent) sessions register the tools.
  • PI_CMUX_ORCH_WORKER_ID — the worker's stable id.
  • PI_CMUX_ORCH_PARENT_SOCKET — path to the parent's Unix socket.
  • PI_CMUX_ORCH_RUN_DIR — per-session run directory for sockets and result overflow files.

It also reads cmux's own CMUX_WORKSPACE_ID and CMUX_SURFACE_ID to decide placement and to report each worker's surface.

Security and permissions

Pi packages run with the installing user's full system permissions. This extension:

  • runs cmux commands to create, inspect, focus, and close terminal surfaces;
  • starts local pi worker processes (each inheriting the parent environment);
  • sends text and key events to cmux surfaces;
  • creates Unix sockets and transient runtime files under the system temporary directory;
  • sends prompts and receives agent output over a local Unix socket;
  • inherits the parent environment and therefore may expose available credentials to worker Pi processes.

It does not intentionally contact a remote service itself, but Pi workers may use configured model providers and tools. Review worker prompts and cmux surfaces before granting access to sensitive repositories or credentials.

Remove the package with:

pi remove npm:@mporenta/pi-cmux-orchestrator

Troubleshooting

  • Not running in cmux (not_in_cmux): launch the parent Pi session from a cmux terminal surface, or spawn with layout: "new-workspace".
  • cmux or pi not found: ensure both executables are on the PATH inherited by Pi.
  • Shell never becomes ready (shell_readiness_timeout): the surface's shell did not echo the readiness marker within 10s; inspect the surface for a slow or blocked shell profile.
  • Worker does not come online (worker_online_timeout): inspect its visible surface; startup waits are bounded to 30s and the surface may show an authentication or configuration error.
  • Worker cannot be prompted: check list_workers; if owner is human, release_worker it before prompting.
  • Worker shows stale or presumed_dead: it stopped heartbeating; read its surface, then stop_worker and respawn if needed.

Development

npm install
npm run typecheck
npm run pack:dry-run
pi -e ./index.ts

License

MIT