Skip to content
| Marketplace
Sign in
Visual Studio Code>Other>Pi OrchestratorNew to Visual Studio Code? Get it now.
Pi Orchestrator

Pi Orchestrator

Martin Colley

|
13 installs
| (0) | Free
Manage multiple named pi terminals from a VS Code sidebar.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Pi Orchestrator

Pi Orchestrator manages multiple pi coding-agent terminals from a VS Code sidebar. Pi still runs as its normal interactive TUI in a real integrated terminal; the extension adds names, lifecycle visibility, Git/worktree context, and diff links.

Version 0.6 adds proactive delivery management, focused transcript views, and an optional authenticated task home at pi-orchestrator-worker.martinacolley.workers.dev. Capability-scoped external row/thread messaging remains available through a local fake or strictly preconfigured Worker transport; see Hooks integration and customization.

Requirements

  • VS Code 1.100 or newer.
  • pi 0.80.7 or newer installed in the environment where the VS Code extension host runs.
  • git for branch, worktree, origin, and change information.
  • For WSL, open a Remote–WSL window first. Install/enable Pi Orchestrator in WSL when prompted; pi and git must be available inside WSL.

Use

  1. Open Pi Orchestrator in the Activity Bar.
  2. Select +.
  3. Enter an optional name (empty uses the folder name).
  4. Select any filesystem folder accessible to the current extension host.
  5. For Git repositories, choose the selected checkout, the main checkout, an existing worktree, or Create a new worktree with Pi Orchestrator. The last option uses the bundled portable /pio-wt new command and supported Pi session handoff.
  6. Work with pi normally in its terminal. Create as many sessions as required.

Select a live session to focus its terminal. Select the Markdown button immediately before the rename pencil to open its short Context page: a glanceable explanation of why the session exists, its intended outcome, and important constraints. The agent seeds and maintains this page without adding files to the repository. Use the session context menu to rename its sidebar entry and terminal title, stop, remove, or relaunch it. The reporter links each entry to pi's exact persisted session file and updates that link when /pio-wt new or /pio-wt join switches into the target worktree session. Relaunch resumes that conversation with pi --session, preserving its conversation tree and worktree context. If the linked file was deleted, Orchestrator falls back to its saved Pi session ID when available; otherwise it asks before starting fresh. Definitions are saved across reloads, but agents are deliberately not relaunched automatically. A restored definition is shown as stopped until you choose Relaunch.

Optional account task home

Select the Pi local status-bar item (or run Pi Orchestrator: Connect Account) to authorize the extension through Better Auth OAuth. OAuth tokens stay in VS Code SecretStorage. Right-click a parent and choose Link Parent to Cloud Task, or use the account menu, to connect an existing local owner to a durable task.

The extension synchronizes only the latest message typed by the human, the latest final agent reply visible to that human, runtime state, and a generic activity line such as Editing project files. It never uploads full Pi transcripts, thinking, prompts, source code, file contents, command arguments/output, tool arguments/results, absolute local paths, or secrets. Messages written in the account app are delivered to the exact linked session. Questions retain their originating session ID so an answer can go directly to the child that asked rather than consuming manager context.

Managers receive a narrow pi_orchestrator_account tool for concise project/task listing, idempotent legacy migration, lifecycle updates, and linking existing parents. A task can exist without a parent; linking is only needed when actionable work should start or resume. The browser app remains the durable task view, while the complete local conversation stays inside its Pi session.

Managers, parents, and children

Pi Orchestrator supports an explicit three-level delivery hierarchy:

Manager → Parent → Child

A manager is a technically enforced, orchestration-only Pi session. It cannot use project file, shell, heavy-work, review, worktree-handoff, or merge tools. Its job is to keep accepted agendas moving: allocate the minimum useful parents, route remediation, surface only genuine user blockers, prepare dependency-safe merge order, and drive work through PR review, Merge ready, Pending release, and verified Live delivery. A parent can complete its agenda directly or create children for useful parallelism.

Managers include a trusted transcript viewer even though arbitrary extension discovery remains disabled. Use /focus (or /transcript) to open the user-and-agent conversation without orchestration calls and results. /focus report shows only agent text, /focus user shows only user text, and /focus all includes thinking, tools, and metadata. In the viewer, keys 1–5 toggle individual categories. The persistent presets are c chat, f full, r agent only, u user only, and t tools only.

Select New Manager from the view title. Choose a named Markdown persona from piOrchestrator.managerProfiles, enter an ad-hoc delivery policy, or use the built-in manager contract. Persona content is injected into the manager’s system prompt on every turn and survives relaunch. The built-in contract acts before narrating, avoids repeated transcript relays, keeps partial-question work moving, and uses independent verification only when policy, the user, or concrete risk requires it.

Multiple managers can coexist. Right-click an existing parent and choose Assign Parent to Manager to assign, move, or unassign it. Each parent has at most one manager. Parents created by a manager are always managed ownership sessions, so their questions and settled results wake the manager. The manager can list and inspect children transitively for oversight, but sends instructions through their direct parent rather than bypassing ownership.

Worktrees are reserved for code delivery expected to produce a commit or PR. Intake, research, consultation, external MCP work, and deployment operations use direct no-worktree parents. Review should inspect an existing exact candidate read-only rather than create another persistent checkout. Independent verification is available when explicitly required or justified by concrete risk, but is not the routine default.

The sidebar nests managers, their parents, and each parent’s children. A separate ↳N active marker on manager and parent rows aggregates working descendants without changing the row’s own state icon; for example, an idle parent can display idle · ↳4 active while four children are working.

Spawn tasks from a parent pi

Every parent managed pi exposes generic local tools: pi_orchestrator_spawn, pi_orchestrator_resume, pi_orchestrator_relaunch, pi_orchestrator_list, pi_orchestrator_inspect, pi_orchestrator_send, pi_orchestrator_wait, pi_orchestrator_accept_outcome, pi_orchestrator_remove, and pi_orchestrator_close. After discussing any set of tasks, explicitly ask the parent to “spin these up in Pi Orchestrator.” The parent supplies normalized names and complete prompts; Orchestrator creates one real terminal per task and, by default, runs each through its bundled /pio-wt new handoff. Task sources are deliberately irrelevant—conversation, issue tracker, or pasted text all behave identically.

Spawn mode worktree is the default and requires a Git repository. Explicit mode nt (“no tree”) launches directly in the requested absolute directory, creates that directory when missing, and does not require Git. Agents may use nt only when the user explicitly requests a direct/no-worktree folder; this keeps isolated worktrees as the safe default.

Supply only the task to perform. Do not instruct the child to create a worktree or invoke /pio-wt or /wt; Orchestrator performs that handoff automatically. Spawned children cannot recursively spawn more sessions by default. Recursive orchestration requires the explicit piOrchestrator.allowRecursiveSpawning opt-in.

Ownership is selected per task:

  • user (default): launch and hand the unique terminal to the user.
  • supervised: preserve the parent/child relationship so the parent can list, inspect, and message the child when asked.
  • managed: also notify and wake the parent when a child settles or needs an answer. The parent is instructed to relay user questions rather than invent answers.

Terminal status and work outcome are separate. Settled, idle, waiting, exited, and failed sessions are not implicitly complete. Owned sessions record unfinished, blocked, or completed outcomes with evidence; the direct owner explicitly accepts completed evidence or assigns unfinished work to a direct successor. Close is rejected until that durable acceptance/handoff exists, and always remains blocked for working or waiting terminals. Blocked sibling dependencies wake the parent when the dependency clears. A recurring parent-owned watchdog rearms while an inactive child remains unaccepted, without requiring any child to inspect siblings. Follow-up, close, and relaunch delivery IDs are durably acknowledged so timeout retries are idempotent.

When a manager, parent, or child has nothing useful to do until another update, it uses pi_orchestrator_wait as its only final tool call. The tool settles the turn immediately, leaving user and Orchestrator messages unblocked. An optional seconds value schedules a fallback status recheck, which is cancelled if another message arrives first. Waiting also records an unfinished outcome rather than implying completion. Standalone passive bash sleep tool calls are rejected; compound commands that happen to contain a short sleep are not treated as Orchestrator waiting.

The control transport is an authenticated-by-possession, instance-private atomic file queue under VS Code global storage; no public port or terminal text injection is used. External references are optional and deduplicate repeated spawn requests from the same parent. Programmatic spawn, resume, and relaunch operations start terminals in the background without changing the active terminal, so they cannot redirect typing from your current conversation. Select a sidebar row whenever you want to focus the new terminal. Parent and manager sessions can close an inactive direct child/parent terminal even when its Pi process has already disconnected; closure is idempotent, retains the sidebar definition and saved conversation, and permits a later relaunch. After explicit user approval, pi_orchestrator_remove permanently removes selected inactive direct sessions and their complete descendant lineages. Starting, working, and waiting-for-answer sessions are protected from agent-directed closure and removal.

Sidebar cleanup supports both Children and Parents groups. Removing a parent recursively stops and removes its full lineage. Removing a manager offers a choice between keeping its parents as unmanaged sessions or permanently removing the complete managed lineage. Runtime control directories use live process markers, and stale runtime/context artifacts are garbage-collected conservatively.

Restart an existing lineage

After shutting down all terminals, manually relaunch only the manager from the sidebar and explicitly ask it to restart the existing work that is still needed. pi_orchestrator_relaunch reuses stopped definitions and saved conversations without creating duplicate sidebar entries: the manager relaunches its direct parents, then messages those parents to inspect and relaunch only their needed direct children. Ownership boundaries remain enforced, already-running sessions are harmless no-ops, and individual launch failures are reported without preventing other selected sessions from starting.

Recover conversations as children

Use pi_orchestrator_resume when a conversation has no existing Orchestrator definition. When the exact Pi session file or ID is known, it launches directly with no human selection. Otherwise Orchestrator opens Pi’s startup resume picker (pi -r) in the original project/worktree cwd. Once linked, the reporter preserves the parent/child ownership relationship and marks it as a resumed child rather than a newly spawned task.

The same flow is available without an agent tool: right-click the intended parent in the sidebar and choose Resume Conversation as Child, then select the folder where the conversation appears in /resume. Cancelling the picker leaves a stopped/exited recovery definition that can be relaunched to try again. Stable externalRef values deduplicate retried recovery requests.

Bundled worktree handoff

Every non-manager Orchestrator terminal loads a portable /pio-wt Pi command in addition to the status reporter. Managers deliberately do not load it:

/pio-wt new <task>
/pio-wt join <directory, branch, or absolute path>

new asks the agent to create a registered worktree using repository-local conventions, then switches to a new Pi session rooted there before starting the task. join resolves only registered Git worktrees and forks the current conversation into the selected checkout. The command is loaded with Orchestrator’s -e argument, so it is visible only in managed terminals and does not install globally or replace an existing /wt command. It has no fixed home directory, repository name, base branch, package manager, setup command, or port assumptions.

Heavy-work capacity and enforced leases

Orchestrator enforces a shared semaphore for expensive child work. Select the server-process button in the Pi Sessions view title to set the limit, pause/resume admission, manage named reservations, or inspect active and queued work. The view title always shows used/limit, plus queue and paused indicators. The same controls are available through Pi slash commands:

/orch capacity 5
/orch status
/orch pause
/orch resume
/orch reserve 1 deploy
/orch reserve 0 deploy   # remove the reservation

piOrchestrator.majorProcessLimit persists capacity at workspace scope (or globally when no workspace is open). Pause and named external reservations are live for the current Orchestrator instance. Reservations subtract from child capacity.

Before heavy work, an agent calls pi_orchestrator_request_lease with kind, estimatedMinutes, commands, and an optional preferredPort. The result is either granted with a unique allocated port or queued with its FIFO position. A queued child is notified automatically when promoted. It must tear down exact PIDs/browser resources and call pi_orchestrator_release_lease; a granted lease is also released when the agent settles. Heartbeats and a TTL recover capacity after crashes. Idle sessions do not send coordination heartbeats. If an extension reload leaves an older terminal attached to an obsolete control instance while it owns or queues coordination work, the reporter stops retrying after repeated short timeouts and asks you to relaunch the session instead of logging an endless timeout loop.

The bundled child extension blocks matching bash tool calls, interactive ! commands, browser tools, and /drp without a granted lease. Built-in categories cover dependency installs, dev servers, builds/typechecks, broad tests, emulators, browsers, and /drp. Control those categories with piOrchestrator.heavyCommandPresets; remove presets that do not apply to the workspace. Add project-specific case-insensitive regular expressions with piOrchestrator.heavyCommandPatterns.

Repository merge slots

Orchestrator also provides a FIFO merge mutex scoped to each repository. Before git merge, an agent calls pi_orchestrator_request_merge with a short purpose and optional target branch. The first requester receives the slot immediately; later requesters remain queued and must hold off. As soon as the holder releases the slot, exits, or loses its heartbeat, the next requester receives an automatic follow-up telling it that the merge slot is available.

The bundled reporter blocks git merge from both the bash tool and interactive ! commands unless that session owns its repository’s slot. Unlike a heavy-work lease, a merge slot is not released merely because an agent turn settles: the holder calls pi_orchestrator_release_merge with outcome merged after success or aborted when the merge does not complete. A merged outcome gives the session a durable green checkmark—even after it stops—while idle sessions use a neutral circle and stopped, unconcluded sessions retain the stop icon. piOrchestrator.mergeLockTtlMs recovers abandoned slots after crashes.

Delivery board

Open Delivery Board below the session tree to track delivery independently from terminal activity. The default portfolio board shows every visible parent; choose a parent from the scope selector to drill into its direct children. Cards move through In progress, Awaiting review, PR created, PR merged, Pending release, Blocked, and Closed.

Select a card to edit its stage, generic ticket reference, pull-request reference, release reference, links, and delivery note. References are provider-agnostic: they may point to GitHub, GitLab, Linear, Jira, an internal tracker, or no URL at all. The card’s runtime dot continues to show whether Pi is working, idle, waiting, stopped, or failed. Settling or stopping a session never closes its delivery card automatically.

Managed Pi sessions can also call pi_orchestrator_update_delivery when review, PR, release, blocking, or closure milestones change. Delivery state and successful merge conclusions persist across extension reloads. Select Focus terminal on a card to return to the associated Pi conversation.

Sidebar information

If a pi command such as /pio-wt new or /pio-wt join moves the live session into a worktree, the bundled reporter sends pi's updated working directory and the sidebar automatically switches its folder, branch, worktree, origin, task, and change metadata to that location.

The sidebar is repository-scoped: it shows lineages owned by the current workspace’s repositories. A child explicitly spawned into another repository remains with its originating parent, while unrelated roots from other workspaces stay hidden. Sessions are nested as Managers → Parents → Children, with parents that have no manager under Unmanaged parent sessions. The colored state icon always represents that session itself. The description shows state · ↳active-descendants · Δchanged-files · branch; the descendant segment appears only when work is active below that session. Select a row to focus its terminal, or use the inline actions to open context, rename, or remove it. Each Children header has a close-all action. Hover for exact additions/deletions, descendant activity, and task details. Disable icon colors with piOrchestrator.colorizeStatusIcons if you prefer theme-neutral icons.

A session shows one of:

  • starting — terminal created and reporter starting
  • working — pi is processing
  • idle — pi settled and awaits normal input (neutral circle unless a merge concluded)
  • merged display — the session successfully released a merge slot with outcome merged; its green checkmark persists after stopping
  • waiting-question — a question tool or final question was detected
  • stopped — no live terminal, usually explicitly stopped or restored
  • exited — the observed terminal closed
  • failed — pi reported an agent error or launch failed

A question icon and Activity Bar badge highlight sessions that need an answer. Expand a session for its folder, current goal/task or latest prompt, branch/detached commit, main-checkout/worktree classification, inferred Git origin, and changed-file totals. Child sessions also show their parent and whether the relationship came from a task spawn or conversation resume. Select a changed file to open VS Code's native diff.

Diffs show the net HEAD ↔ working tree state. This includes both staged and unstaged changes. Untracked files compare with an empty document; deleted files compare their HEAD version with an empty document.

Configuration

Setting Default Purpose
piOrchestrator.accountUrl hosted account service Better Auth OAuth and structured task-sync origin.
piOrchestrator.piPath pi Executable name or absolute path in the current local/remote extension host.
piOrchestrator.extraArguments [] Argument array appended when launching pi.
piOrchestrator.questionToolNames common pi question tools Tool names treated as structured waiting signals.
piOrchestrator.statusPollIntervalMs 500 Reporter snapshot polling interval in milliseconds.
piOrchestrator.reporterStartTimeoutMs 15000 Time allowed for the reporter's first valid snapshot.
piOrchestrator.managerProfiles {} Named manager personas mapped to absolute Markdown file paths.
piOrchestrator.allowRecursiveSpawning false Explicitly permit child sessions to create a deeper level; manager-owned parents can always create their normal children.
piOrchestrator.majorProcessLimit 5 Persisted maximum simultaneous heavy-work leases.
piOrchestrator.leaseTtlMs 120000 Recover a lease after this long without a heartbeat.
piOrchestrator.mergeLockTtlMs 120000 Recover an abandoned repository merge slot after this long without a heartbeat.
piOrchestrator.heavyCommandPresets all categories Built-in lease categories: dependency install, build/typecheck, dev server, broad test, emulator, browser, and /drp.
piOrchestrator.heavyCommandPatterns [] Additional case-insensitive regex patterns requiring a lease.
piOrchestrator.colorizeStatusIcons true Color compact session icons by state.

Arguments are transported as an array, not composed into a shell string, so folders and arguments containing spaces or shell metacharacters remain intact.

Status integration

Every managed terminal is launched with the bundled pi-extension/status-reporter.ts through pi's supported -e option. The reporter listens to documented pi lifecycle events and atomically writes a small per-session status snapshot under VS Code extension storage. It also exposes pi_orchestrator_update_context, which keeps the session’s extension-owned Markdown context concise and current without dirtying the working tree. It does not consume terminal input.

Structured agent and question-tool events are high confidence. When pi ends with ordinary assistant text asking a question, a narrow final-message heuristic supplies a lower-confidence waiting-question fallback. VS Code does not expose integrated terminal output, so raw ANSI/output scraping is not used. If the reporter cannot load, the extension can still observe terminal creation/closure but cannot reliably identify working or question states.

See docs/architecture.md for design details and limitations.

Development

npm install
npm run build
npm run typecheck
npm run lint
npm test
npm run test:integration
npm run test:real-pi
npm run package

Press F5 in this repository to open an Extension Development Host. A manual smoke-test checklist is in docs/smoke-test.md.

For the 0.5.2 candidate, npm audit --omit=dev reports zero runtime vulnerabilities. The full development-tree audit reports three transitive toolchain advisories (high: brace-expansion, fast-uri; moderate: protobufjs) through Pi/VSCE/ESLint dependencies. They do not enter the dependency-free runtime bundle; update the owning development tools and lockfile in a separately approved dependency-install change rather than applying an unreviewed audit-force upgrade.

Known limitations

  • Parent/base is explicitly inferred: upstream is preferred, then a merge-base with main or master; it may remain unknown.
  • Plain assistant questions are heuristic and may be missed or misclassified.
  • VS Code/WSL shutdown does not guarantee terminal process survival.
  • The first release targets local and Remote–WSL filesystem workspaces, not arbitrary virtual filesystem providers.
  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft