@jocax/sphere-client-tui
v0.1.0
Published
Agent-powered terminal dashboard for monitoring running Spheres
Readme
@jocax/sphere-client-tui
Agent-powered terminal dashboard for monitoring running Spheres. A Pi agent — "the brain" — answers questions about your Spheres while live panels show status, logs, topology, and alerts across your registered workspaces. Rendered with pi-tui (@earendil-works/pi-*, pinned 0.78.0).
Design & history live elsewhere. The per-PR implementation narrative is in the M22 specs and the git history; the milestone plan is in the ROADMAP; module-level design is in
concept/docs/design/sphere-client-tui-design.md. This README is the user-facing front door only.
Run
Quickstart — boot example Spheres + dashboard (dev.sh)
The dev.sh harness boots an example workspace's Spheres, registers them in
~/.sphere/tui.yaml (with a local Ollama agent), and opens the dashboard — no
manual wiring. Run everything from this package directory
(software/sphere-client-tui/):
# 0. one-time, from the repo root: install + build runtime, CLI, and TUI
pnpm install && pnpm -r build
# 0b. prerequisite — Ollama running with the example model
ollama serve & # if it isn't already running
ollama pull qwen3.6:35b-mlx # tools-capable local model the examples use
# 1. boot the research-loop Spheres + open the dashboard in a new Terminal window
pnpm dev:start # = dev:up (boot + register + build) then dev:tui
# 2. generate live activity — fire one research cycle (research → delegates to expert)
pnpm dev:task # then press r in the TUI to refresh the panels
# 3. housekeeping
pnpm dev:status # what's running: Spheres, ports, registered workspaces
pnpm dev:logs # tail the Sphere logs
pnpm dev:down # stop everything (Spheres, TUI, orchestrator)| Script | What it does |
| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| pnpm dev:up | Boot the example workspace's Spheres (default research-loop), register them in ~/.sphere/tui.yaml, build the TUI |
| pnpm dev:start | dev:up, then open the TUI in a new macOS Terminal window |
| pnpm dev:tui | Open the TUI only (./dev.sh tui --tmux for a headless tmux session instead) |
| pnpm dev:task | Fire one research cycle against research-loop (dispatches via 127.0.0.1) |
| pnpm dev:status · dev:logs · dev:down | Inspect · tail logs · tear down |
For arguments, call the script directly: a different workspace
(./dev.sh start content-pipeline, or an absolute path), more cycles
(./dev.sh task --cycles 3). Env overrides: SPHERE_TUI_MODEL /
SPHERE_TUI_PROVIDER / SPHERE_TUI_ENDPOINT change the agent model;
SKIP_BUILD=1 skips the TUI rebuild. ./dev.sh with no args prints help.
Spheres daemonize, so the live panels poll every 3 s — when you're attached they update on their own;
rforces an immediate refresh.
Advanced — run the TUI directly (no example boot)
pnpm --filter @jocax/sphere-client-tui dev # launch the dashboard
pnpm --filter @jocax/sphere-client-tui dev -- --workspace <name> # open a workspace directly
pnpm --filter @jocax/sphere-client-tui dev -- --pi-tui-demo # fakes dashboard (no live data / no API key)From software/sphere-client-tui/, two workspace-specific shortcuts:
pnpm dev:tui:ws <name> # current terminal, cross-platform — Ctrl/Alt+arrows + h/j/k/l
pnpm dev:tui:iterm <name> # macOS/iTerm2: opens a NEW window; auto-installs the "AE Sphere TUI"
# CSI-u dynamic profile so Ctrl/Alt+arrows work out of the box
# (no manual iTerm2 prefs). Prints a fallback hint on non-macOS
# or when iTerm2 is absent; h/j/k/l works in any terminal.Contributor commands (same pnpm --filter … prefix): typecheck, test, build.
Configuration — ~/.sphere/tui.yaml
theme: dark # dark | light (toggle live with the `t` key)
workspaces:
- { name: research-loop, type: local, path: /path/to/workspace }
- { name: prod, type: remote, endpoints: ["https://sphere-router.example.com"] }
agent:
provider: { type: ollama, model: gemma4:26b-mlx, endpoint: http://localhost:11434 }Hand-edit the file, or manage workspaces in-app: press a on the selector to add (guided name → type → path/endpoints → confirm), d to remove. Per-workspace UI state (focused panel, scroll offsets, last viewed task) persists under ~/.sphere/tui-state/, one file per workspace.
Agent provider
The agent's provider/model/endpoint is fully config-driven via the nested agent.provider block — the same shape as sphere.yaml — so the TUI agent runs on any pi-supported provider, not just Anthropic.
| Field | Required | Description |
| ----------- | -------- | ---------------------------------------------------------------------------------------------- |
| type | yes | Provider type (anthropic, ollama, openai, … — any pi-supported) |
| model | yes | Model id or name |
| endpoint | no | OpenAI-compatible base URL; required for providers not in pi's built-in registry (e.g. Ollama) |
| apiKeyEnv | no | Name of the env var holding the API key; omit entirely for keyless providers (Ollama) |
# Ollama (keyless, local endpoint)
agent:
provider: { type: ollama, model: gemma4:26b-mlx, endpoint: http://localhost:11434 }
# Anthropic (pi built-in registry + key from env)
agent:
provider: { type: anthropic, model: claude-sonnet-5, apiKeyEnv: ANTHROPIC_API_KEY }- No
apiKeyEnv→ keyless (no-auth); the agent starts. Suitable for Ollama / local endpoints. apiKeyEnvset but the env var is empty, or a provider+model unknown to pi's registry with noendpoint→ the agent is disabled and the panel states why.- A legacy flat block
agent: { provider: <str>, model: <str> }is still accepted (auto-lifted to the nested shape); a flat block with nomodelfails (model is required).
Navigation & keys
Navigation stack (max depth 5): Selector → Workspace → Sphere drill-down → Task inspector → Task walkthrough. Esc pops one level at any depth. The agent transcript is the walkthrough's sibling at depth 5, not a sixth level.
| View | Enter from | Keys |
| ----------------- | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Selector | home | ↑↓ select · Enter connect · a add · d remove · q quit |
| Workspace | selector | Tab/Shift+Tab cycle · Ctrl/Alt+↑↓←→ or h/j/k/l move focus · Ctrl+1–3 switch workspace · t theme · r refresh · Esc back |
| Sphere drill-down | Status Enter | ↑↓ tasks · Enter inspect · o ops desk · Esc back |
| Task inspector | drill-down Enter | ↑↓ envelopes · Space/d raw detail · Enter walkthrough · a agent transcript (durable runs only) · Esc back |
| Task walkthrough | inspector Enter / /trace | ↑↓ · PgUp/PgDn scroll · Esc back |
| Agent transcript | inspector a (durable runs) | PgUp/PgDn scroll · ↑↓ select · Space expand · Ctrl+O settings · Esc back. Composer (open agent): Enter send · Alt+Enter newline · Shift+Tab mode · Ctrl+X twice interrupt · Ctrl+R withdraw newest · ↑↓/Space act on the transcript only while the editor is empty. A finished agent shows "The agent has finished — its result is written."; queued lines cap at 3 plus "+N more queued". Reads the Sphere's dashboard read actions, so it needs dashboard.enabled: true in sphere.yaml; otherwise it shows one unavailable line |
| Ops desk | drill-down o | The Agent transcript view on the Sphere's ops desk (header <sphere> › Ops desk · read-only tools · <model>): Enter send · Alt+Enter newline · Shift+Tab mode · Ctrl+X twice interrupt · PgUp/PgDn · Esc back. No settings (Ctrl+O) and no withdraw (Ctrl+R). Durable Spheres only; otherwise one unavailable line |
| Agent settings | transcript Ctrl+O | r read only · ↑↓ move · Space tick · Esc close |
| Approvals | any view Ctrl+G | ↑↓ select · Enter open · then a approve · d decline… (reason) · i i interrupt (second press confirms) · ? ask… (question) · Esc back/close. Needs dashboard.enabled: true |
Panel keys (Workspace view): Logs — ↑↓ pause + scroll, f resume follow. Agent — Enter submit, Alt+Enter newline, / command autocomplete, PgUp/PgDn scroll transcript, Esc cancel an in-flight turn.
The bottom row shows the focused panel's context keys and the workspace global keys at all times. While any approval waits, a one-line ◆ N waiting · … Ctrl+G answer banner sits above it on every preset; it disappears at zero.
Terminal support — Ctrl/Alt+arrows require a kitty-protocol-capable terminal (iTerm2 with CSI-u / "Use libtickit protocol", Ghostty, Kitty, WezTerm). h/j/k/l is the universal fallback that works everywhere, including Apple Terminal.
Slash commands
Type in the Agent panel. / triggers the editor's autocomplete (Tab completes command names; arguments offer layout presets, workspace names, and flag values). /help lists the live registry.
| Command | Usage | Description |
| -------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| /watch | /watch <sphere> [--level warn] | Focus log stream on a Sphere with optional level filter |
| /bus | /bus <sphere> [--task <id>] | Show envelope bus state (tree or stats); latest task when --task omitted |
| /status | /status | Full status refresh across all connected Spheres |
| /workspace | /workspace <name> | Switch to a registered workspace |
| /history | /history <sphere> | Recent task history with outcomes |
| /result | /result <sphere> [--task <id>] | Show the result envelope payload for a task |
| /errors | /errors <sphere> [--task <id>] | Show the error chain (severity glyph + source→target + message + what_to_do) |
| /trace | /trace <sphere> [--task <id>] | Render a task narrative (Request → Agents → Delegations → Results → Answer → Resources) + push the walkthrough view |
| /activity | /activity [--limit <n>] | Most recent tasks across the workspace — glyph + sphere + duration + relative time (default 10) |
| /add | /add | Register a new workspace interactively |
| /remove | /remove <workspace> | Unregister a workspace |
| /layout | /layout <preset> | Switch panel layout (default / logs / topology / alerts / split) |
| /investigate | /investigate <trace-id> | Trace a full envelope chain cross-workspace |
| /alerts | /alerts [--level <level>] | Show active alerts filtered by severity |
| /bookmark | /bookmark [trace] [--note <text>] | Bookmark a trace id with an optional note |
| /help | /help | List all registered commands with usage |
Local-only:
/result,/errors,/trace,/activity,/bus, and/investigaterequire a local workspace connection. Remote workspaces return a"local-only in v1"message.
Agent tools
The agent replies in natural language; under the hood it has 11 read-only tools. Ask it things like "summarize the latest task on research-loop", "why did the writer Sphere fail", or "compare task A and B".
| Tool | Params | Description |
| ------------------ | ------------------------------------------ | --------------------------------------------------------------------------------------- |
| list_workspaces | — | All registered workspaces with health status |
| query_status | workspace?, sphere? | PID, uptime, liveness, memory episodes |
| watch_logs | workspace, sphere?, level?, limit? | Recent log lines with optional filters |
| inspect_bus | workspace, sphere, task? | Envelope tree or stats for a Sphere's task bus |
| read_config | workspace, sphere? | Read a Sphere's sphere.yaml manifest |
| probe_health | workspace?, sphere? | Agent Card health probe |
| follow_trace | trace_id | Stitch a cross-workspace tree of all envelopes with this trace_id |
| find_delegations | workspace?, sphere? | Locate delegate_to_sphere envelopes and resolve targets to workspaces |
| summarize_task | sphere, task? | Narrative of what a task did (request, agents, delegations, results, answer, resources) |
| diagnose_task | sphere, task? | Root-cause a failed task: error chain correlated with recent log lines |
| compare_tasks | sphere, task_a, task_b | Diff two tasks on the same Sphere — topology, duration, errors, resource deltas |
All tools return structured JSON; the agent composes prose from the result.
Testing
Two vitest projects (vitest.config.ts):
| Project | Scope | Run |
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
| sphere-client-tui | Unit + smoke, FakeTerminal, adapters mocked | pnpm --filter @jocax/sphere-client-tui test |
| sphere-client-tui-runtime | tests/runtime/ — one real harness Sphere per file, the production nav app on a headless xterm, every surface asserted against ground truth | pnpm --filter @jocax/sphere-client-tui exec vitest run --project sphere-client-tui-runtime |
The runtime project needs current dists first: pnpm --filter @jocax/sphere build and pnpm --filter @jocax/sphere-cli build (the harness loads @jocax/sphere from dist).
Accepted gaps in the runtime lane — asserted only against fixtures, never a live Sphere: pid liveness and uptime, the Logs panel and its log-derived alerts (repeated-errors), the sphere-offline alert, and cross-Sphere delegation display. See concept/docs/validation/runtime-ui-coverage/tui.json for the reasons.
Architecture invariants
A few constraints a contributor must respect (full design is in the specs linked at the top):
- pi-tui is the sole render path — no React/Ink anywhere under
src/(enforced bytests/unit/forbidden-imports.test.ts). src/data/is the only module allowed to import@jocax/sphere-cli; every other module consumes its adapters. The TUI has no direct@jocax/spheredependency — the shared model factory is reached throughsrc/data/model-factory.ts, and the hermetic session helper throughsrc/data/isolated-agent.ts.- The Sphere-Monitor agent identity is defined in
src/agent/sphere-monitor.md— a reviewable markdown asset bundled with the package.src/agent/prompt.tsreads it deterministically (same resolution fromsrc/in tests anddist/in the binary) and composes the dynamic sections (registered workspaces, previous-session context) around it. Editsphere-monitor.mdto change the agent's persona without touching TypeScript. - Remote workspaces are health-probe-only in v1 (filesystem bus/log access and SSE streaming are local-only).
