Pi integration

evolving Use & automate

Pi integration

TL;DR. @phux/pi lets Pi select and operate a pane in an external local phux server while preserving the target in Pi’s session history. It provides nineteen bounded terminal tools, three human commands, branch-local named targets, and best-effort Pi lifecycle metadata. It does not embed a terminal, provide remote authentication, or own the phux server.


Requirements and installation

The package requires Node.js 20 or newer, Pi, and an external phux executable on PATH. It does not bundle phux or start a separate implementation. The minimum compatible binary is phux 0.1.0; check it before loading the package:

phux --version

From a checkout of this repository, install the package directory, not the git root:

pi install ./integrations/pi

The repository root is not a Pi package, so a git source that resolves to that root is not an installation method for this integration. @phux/pi is also not published to npm today. Do not use npm:@phux/pi unless a future release is actually present in the registry.

A packed artifact can be tested or moved to another machine without implying registry publication:

cd integrations/pi
npm ci
npm pack
mkdir -p phux-pi-packed
tar -xzf phux-pi-0.1.0.tgz -C phux-pi-packed
pi install ./phux-pi-packed/package

npm pack runs the package build. Pi installs the extracted package directory; it does not load the .tgz file as an extension. The artifact remains dependent on a compatible external phux binary on the destination machine.

The extension inherits PHUX_SOCKET; set it before starting Pi when the server uses a non-default local Unix socket. There is no package command for choosing an alternate executable. Library consumers can construct PhuxCli with an absolute executable, but the installed Pi extension expects phux on PATH.

Surface

The extension registers exactly these nineteen model tools:

ToolOperation
phux_listList phux sessions.
phux_createCreate a named session without attaching and select its seed pane.
phux_snapshotRead a pane’s bounded, side-effect-free screen projection.
phux_send_keysSend named keys or literal key text to one pane.
phux_runRun one shell command line and return its exit result.
phux_waitWait for visible text or idleness and return the bounded final screen.
phux_panesInventory pane ownership, agent state, attention, title, cwd, and evidence.
phux_spawnSpawn a pane without attaching, optionally place it beside one exact local pane, and optionally save an alias.
phux_launchLaunch a configured integration from the CLI’s versioned machine result, with optional local placement.
phux_insert_paneInsert one already-created exact local pane beside another.
phux_move_paneMove one exact local pane beside another in the same session.
phux_swap_paneSwap two exact local pane leaves without changing geometry.
phux_killWith an explicit target and confirm:true, destroy a selector, alias, or the validated members of a named group. Selectors and groups may destroy multiple panes.
phux_signalInterrupt, freeze, or resume a pane’s process group; terminate and kill require an explicit target and confirm:true because selectors may affect multiple processes or panes.
phux_tagList, add, or remove terminal tags.
phux_askReport a human-attention ask event.
phux_watch_eventsCollect typed events for 50 ms–30 s, then stop the streaming CLI subprocess.
phux_rendered_snapshotCapture the attached client’s composited frame at bounded dimensions.
phux_targetsList or mutate branch-local named aliases and groups.

It registers exactly these three human commands:

CommandOperation
/phuxInventory panes and choose the default target.
/phux-statusRefresh and report the saved target and its availability.
/phux-attachPrint a human attach argv; it never executes the attach.

The headless phux CLI owns argument syntax, selector rules, JSON, and exit codes. Use the agent CLI guide for that canonical contract rather than treating this adapter as a second CLI definition.

Input-authority control is an upstream blocker rather than a Pi tool. The take lease is scoped to a live CLI connection, and a one-shot CLI invocation disconnects immediately and releases it; give consequently cannot represent a durable paired action either. These tools must remain absent until phux provides a persistent transport/lifetime that Pi can safely own.

Tool output sent to the model is bounded to 200 lines and 12 KiB. CLI stdout and stderr capture are independently bounded, every subprocess accepts Pi cancellation, and targeted CLI tools expose finite local timeouts. The watch adapter requires a finite collection window and returns at most 100 parsed events rather than leaving an indefinitely streaming subprocess. Results state when the adapter truncated output and preserve a separate truncation flag reported by phux.

Selecting and preserving targets

/phux inventories the public agent projection, groups panes by session, and stores the chosen canonical pane selector plus its owning session and window. phux_create stores the same ownership fields for the newly created seed pane. The selection is appended as the existing versioned phux-target custom entry in Pi’s session branch, preserving compatibility with earlier package sessions.

phux_targets adds named aliases and groups in a separate versioned branch entry. Use alias:build anywhere a tool accepts one pane; phux_kill and phux_tag also accept group:workers and expand it to at most 64 canonical pane selectors. Definitions store pane ownership, not only @id. Immediately before every named-target action, the extension refreshes inventory and rejects missing or reused ids; inventory failure fails closed. Spatial operations also require each role to resolve to exactly one distinct local pane and reject named groups and satellite pane selectors. Explicit raw CLI selectors are caller-owned for ownership and are still subject to the canonical CLI’s exact-one validation. Branch navigation reconstructs the latest selection and named-target document on that branch.

Restoration never silently falls back to phux’s focused pane. Before an implicit target is made available to tools or lifecycle reporting, the extension confirms that the saved pane id still belongs to the saved session and window. A missing pane or reused id is stale: the selection remains visible for diagnosis, but an implicit targeted tool refuses it. An inventory failure is unavailable and likewise preserves the saved selection. Pass an explicit target to a tool only when intentionally overriding the selection.

First shared-terminal walkthrough

  1. Start or locate a local phux server outside Pi. For a first local session, phux new work creates and attaches interactively.
  2. Start Pi with the package installed and run /phux.
  3. Choose the pane under work. The Pi status line shows the saved target.
  4. Ask Pi to create or launch a worker beside that target. For example, phux_launch({ integration: "codex", target: "@3", split: "vertical", ratio: 0.4, alias: "worker" }) creates a side-by-side pane. split or ratio requires target; ratios must be finite and strictly between 0 and
    1. vertical means side-by-side and horizontal means stacked.
  5. Shape already-created panes with phux_insert_pane, phux_move_pane, or phux_swap_pane. These mutate persisted topology only: they do not spawn, focus, take, give, or paste. Insert and move accept optional direction and ratio; horizontal is the CLI default. Insert never spawns its new_pane.
  6. Ask Pi to inspect the pane or run a discrete command. Pi can use phux_snapshot, phux_run, and phux_wait without attaching or resizing the human view.
  7. Run /phux-status before a handoff if the pane may have exited or moved.
  8. Run /phux-attach. Pi prints an argv such as ["phux","attach","work"] and identifies the pane to navigate to after attach. Copy the argv into a separate real terminal. The extension does not execute it and does not open a nested terminal inside Pi.

A human attach joins the same terminal state. It is not a read-only monitor: agent input and human input can interleave at the PTY. The package does not serialize independent writers, reserve a prompt, or provide a transaction around snapshot followed by send_keys. Coordinate before typing into a pane that the other participant is actively driving, and use explicit targets when several panes are live.

Lifecycle metadata

When a target is ownership-validated as available, the extension reports a whole phux.agent/v1 record with name=pi, kind=pi, and a Pi-session owner in the session field. Pi’s agent_start event maps to working with normal attention; agent_settled maps to idle with low attention. Writes are serialized, debounced, locally bounded, and best-effort, so a missing server does not break Pi startup or shutdown.

A target switch clears the old declaration only after reading it back and confirming that Pi still owns it. Normal shutdown applies the same ownership check. Extension reload preserves the declaration for the replacement instance, avoiding a clear/set flicker. This is status metadata, not an input lock; it does not prevent the interleaved-input case above.

Current boundaries and security

  • There is no paste tool. The current canonical CLI ships no headless paste verb, so the adapter does not synthesize paste from send-keys or bypass the CLI. phux_send_keys remains key input only; dedicated paste is tracked by bead phux-foir.
  • phux_rendered_snapshot follows the CLI’s snapshot --rendered contract: unlike ordinary snapshot it attaches a headless client and establishes that client’s bounded viewport. Use phux_snapshot for a side-effect-free pane read.
  • phux_launch validates schema version 1, integration id, plugin id, terminal id, and resolved argv. It never returns the resolved argv to the model.
  • Spawn/launch placement is local-only. target, split (horizontal|vertical), and ratio map directly to canonical CLI flags; satellite pane targets and satellite plus placement are rejected.
  • Spatial tools parse the canonical schema-version-1 CLI JSON. Both role selectors are freshly ownership-validated when named aliases are used, and every subprocess preserves Pi cancellation, local timeouts, and output caps.
  • The package is a Node/Pi integration around an external native process. It has no WASM build and does not render or nest a terminal inside Pi.
  • Remote phux attach, pairing, and token transport are not supported. The adapter accepts a local Unix socket path, not --quic, --ws, bearer-token, or certificate arguments.
  • Pairing tokens and certificate material are secrets. Never place them in a Pi prompt, tool argument, saved target, lifecycle record, attach handoff, or smoke-test output. Configure remote access outside this package and expose a suitable local phux endpoint only if its trust boundary is understood.
  • /phux-attach deliberately emits only local attach argv plus session/pane navigation. It neither reads nor prints remote credentials.

A checked-in live-fleet recording shows Pi using this surface to place, drive, verify, and spatially rearrange real Claude Code and OpenAI Codex panes. Package-local development and validation commands live in ../../integrations/pi/README.md.