sam-4screen-desktop 2026-7-29:11:14:15

This commit is contained in:
2026-07-29 11:14:15 +10:00
parent ddfb2b9e06
commit b66f7679d8

View File

@@ -1,155 +1,179 @@
# Pi Dashboard # Pi Dashboard — Architecture Decision Record
## What It Is ## Background
A **terminal-based live dashboard** that shows what all pi coding agents are doing across the system. Runs in a Zellij pane or detached tmux session. Shows sub-agent status, current tasks, token consumption, and cost — all in one place. Evaluating whether to build a custom pi dashboard or switch to Herdr for agent visibility.
## Architecture ## Jump-to-Agent Interaction
``` ### With tmux (recommended for background agents)
┌─────────────────────────────────────────────────────────────────┐
│ Background: Detached tmux sessions (nixos-desktop .13) │
│ │
│ tmux session "pi-work" │
│ ├── pi (model: opencode-go/deepseek-v4-flash) ← coder-basic │
│ ├── pi (model: deepseek/deepseek-v4-pro) ← coder-pro │
│ └── pi (model: google/gemini-2.5-flash) ← research │
│ └── Each has extension: dashboard.ts │
│ └── Writes state → ~/.pi/agent/dashboard/<id>.json │
│ │
│ tmux session "pi-explore" │
│ └── pi (model: opencode-go/deepseek-v4-flash) ← explore │
│ └── Extension: dashboard.ts │
│ └── Writes state → ~/.pi/agent/dashboard/<id>.json │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ Viewer: Zellij pane (or separate terminal) │
│ │
│ bin/pi-dashboard (standalone TUI binary) │
│ └── Reads all ~/.pi/agent/dashboard/*.json │
│ └── Renders table of all agents with live status │
│ └── Press Enter on a row → attach to that tmux session │
│ │
│ Optional: also serves HTTP on :9876 for phone (Termux) │
└─────────────────────────────────────────────────────────────────┘
```
### Key Insight: Two-Component Design The dashboard runs this when you press Enter on an agent row:
| Component | What it does | How it runs |
|-----------|-------------|-------------|
| **dashboard.ts** (pi extension) | Lives inside each pi session. Listens to events (`agent_start`, `agent_end`, `tool_call`). Writes JSON state files. Starts optional HTTP server. | Loaded by pi at startup from `~/.pi/agent/extensions/` |
| **pi-dashboard** (standalone TUI) | Separate binary. Reads all state files. Renders the unified dashboard. Lets you jump into sessions. | Run from any terminal — Zellij pane, tmux window, Termux SSH |
## Why This Design
- **dashboard.ts** has access to pi's event system (it runs inside pi)
- But it can only see its own pi session
- **pi-dashboard** is external and can aggregate all sessions
- Separates concerns: collection (inside pi) vs visualization (outside pi)
- The viewer binary can be written in any language — Go recommended
## Required Components
### 1. dashboard.ts (pi extension)
- Hooks: `agent_start`, `agent_end`, `tool_call`
- Tracks: sub-agent name, model, status, start time, duration, last tool, token count
- Persistence: writes to `~/.pi/agent/dashboard/<session-id>.json`
- Uses atomic writes (write to `.tmp` then rename) to avoid corruption
- Also: small HTTP server on localhost:9876 for real-time polling
Pi's extension API provides everything needed:
- `pi.on("agent_start", ...)` — fired when agent turn starts
- `pi.on("agent_end", ...)` — fired when agent turn ends
- `pi.on("tool_call", ...)` — fired on each tool invocation
- `ctx.sessionManager` — session state access
### 2. pi-dashboard viewer
- Standalone binary (Go recommended — see Tech Stack below)
- Directory watcher on `~/.pi/agent/dashboard/`
- Renders a live table of all agent sessions
- Features per row:
- Agent type/name
- Model/provider
- Status (idle, running, waiting, error, done)
- Current task description
- Duration
- Token count & running cost
- Last activity timestamp
- Keyboard controls:
- `Enter` → attach to that tmux session
- `r` → refresh
- `q` → quit
- `/` → filter/search agents
- Optional web mode: `--web` flag starts HTTP server on :9876
## Implementation Steps
### Phase 1: dashboard.ts extension (1 day)
1. Create `~/.pi/agent/extensions/dashboard.ts`
2. Implement event listeners for `agent_start`, `agent_end`, `tool_call`
3. Accumulate state: Map<agentId, AgentState>
4. Write snapshot to `~/.pi/agent/dashboard/<session-name>.json` on each event
5. Use atomic file writes (write to .tmp, rename)
6. Register `/dashboard` command that prints a simple in-extension status list
### Phase 2: Go TUI viewer (1-2 days)
1. Create `~/bin/pi-dashboard/` Go module
2. Use Bubble Tea for TUI rendering
3. Implement file watcher (fsnotify) on the dashboard directory
4. Build table view with agent state columns
5. Add status indicators with colors
6. Add keyboard controls (attach, filter, quit)
7. Test: launch two pi sessions in tmux, verify aggregated view
### Phase 3: Attach/jump (half day)
1. Extract tmux session name from the state file
2. `Enter` key → `tmux attach-session -t <name>`
3. Or launch a new pi session from the dashboard
### Phase 4: Polish (ongoing)
- Historical cost tracking across sessions
- Notification when an agent stalls or errors
- Web mode for phone access
- Alerts/markers when agents finish tasks
## How Sessions Tie Together
The convention for naming:
```bash
tmux new-session -d -s pi-work 'pi --model opencode-go/deepseek-v4-flash'
# dashboard.ts writes to ~/.pi/agent/dashboard/pi-work.json
# The session name "pi-work" ties the dashboard entry to the tmux session
```
When you press Enter on "pi-work" in the dashboard:
```bash ```bash
tmux attach-session -t pi-work tmux attach-session -t pi-work
# You're now in the agent's terminal, stdin/stdout intact
# Answer the prompt, agent continues
# Ctrl+B d → back to dashboard
``` ```
When running pi without tmux, dashboard.ts writes to `~/.pi/agent/dashboard/unsorted.json` — the viewer still picks it up. **This works from everywhere** — Zellij pane on .27, terminal on .13, Termux SSH from phone. tmux gives us a universal "jump to" button with no patching.
## Prerequisites Already Met The dashboard shows the session name clearly:
- ✅ Node.js (everything runs on it) ```
- ✅ Go (if chosen for TUI — installable via nix) ║ ● work oc/deepseek-v4 ▓▓▓▓░░ 12:34 48.2K $0.09 ║
- ✅ Pi extension system (all hooks available) ║ 📍 tmux: pi-work ║
- ✅ tmux (already available) ║ └─ Refactor auth middleware ║
- ✅ Shared filesystem (state files are local) ║ [Enter to attach] ║
- ✅ OmniRoute for model routing ```
## Open Questions ### With Zellij (for interactive sessions)
1. What does the dashboard show when pi is idle (no active agent)? Zellij has no `zellij --focus-tab --pane` CLI. So for agents running inside Zellij panes, the dashboard shows the location manually:
2. Should the viewer support resuming a session or only viewing?
3. How far back to keep history? Last N turns? Last 24h? ```
4. Web mode: full dashboard or just alerts / status summary? ║ ● explore oc/deepseek-v4 ▓▓░░░░ 03:12 12.1K $0.02 ║
║ 📍 Zellij: Tab 3 → Pane 2 [switch manually] ║
```
You can't automate the jump — but you can *see* where to go.
### Recommendation
Run background pi sessions in **tmux** (for jump-to capability) and keep interactive pi sessions in Zellij (readable, not remotely jumpable). The dashboard handles both.
---
## Cross-Machine Visibility
Agents running on your Thinkpad (.51) can be visible on your desktop (.27) dashboard. Three approaches:
### Option A: SSH pull (simplest, recommended)
The dashboard viewer has a config:
```yaml
# ~/.config/pi-dashboard.yaml
local:
path: ~/.pi/agent/dashboard/
remote:
- host: 192.168.20.51
user: sam
path: /home/sam/.pi/agent/dashboard/
- host: 192.168.20.13
user: sam
path: /home/sam/.pi/agent/dashboard/
```
The viewer SSHes in, reads the files, merges with local state. Shows all machines:
```
╔════════════════════════════════════════════════════════════════╗
║ ⬡ Pi Dashboard (3 machines, 5 agents) Cost: $0.52 ║
╠════════════════════════════════════════════════════════════════╣
║ MACHINE AGENT STATUS DURATION TOKENS COST ║
║ ──────────────────────────────────────────────────────────── ║
║ .27 work ● running 12:34 48.2K $0.09 ║
║ .27 explore ● running 03:12 12.1K $0.02 ║
║ .13 resrch ○ idle 00:47 8.4K $0.00 ║
║ .51 bugfix ⚠ blocked 01:23 22.1K $0.11 ║
║ └─ 📍 tmux: pi-bugfix (.51) ║
╚════════════════════════════════════════════════════════════════╝
```
Enter on a remote agent → `ssh -t sam@192.168.20.51 tmux attach-session -t pi-bugfix` → you're in the agent's terminal on the other machine. Detach → back on your desktop.
### Option B: HTTP collector (more robust)
The dashboard extension on each machine pushes state to a central collector (runs on .13 alongside OmniRoute):
```
.51 extension ──POST──→ collector (.13:9877) ──→ viewer reads from here
.27 extension ──POST──→ collector (.13:9877) ──→
.13 extension ──POST──→ collector (.13:9877) ──→
```
The viewer reads from one place. More resilient to transient SSH failures. But needs the collector process to always be running.
### Option C: Tailscale SSH (if you have it)
Simplifies auth — SSH keys are already managed. Same as Option A but with shorter hostnames.
---
## Build vs Herdr — Honest Analysis
| Criterion | Build the Dashboard | Switch to Herdr |
|-----------|-------------------|----------------|
| **What you keep** | Zellij, all keybindings, layouts, plugins, config.kdl | Nothing. Full rewrite of terminal management |
| **Migration cost** | Zero (it's additive) | High. Every Zellij layout, plugin, keybinding must be recreated in Herdr's system |
| **Agent visibility** | ✅ Unified view of all agents across all machines | ✅ Native per-pane agent state (pane border colors, status icons) |
| **Jump-to-agent** | ✅ One press → tmux attach / shows Zellij location | ✅ Native — same multiplexer |
| **Cross-machine** | ✅ Built for this from day one | ❌ Not designed for it. Would need SSH workarounds |
| **Cost tracking** | ✅ Built in (token count per session) | ❌ No cost data (Herdr doesn't see provider usage) |
| **Phone visibility** | ✅ SSH from Termux → same binary | ✅ Herdr has mobile plugins (AltanS/collie PWA) |
| **Notifications** | ✅ notify-send + any hook | ❌ Socket API exists but alerting isn't built-in |
| **Plugin ecosystem** | ✅ You control the feature set | ✅ 150+ community plugins |
| **Ongoing effort** | Maintenance of ~600 lines of code | Learning Herdr's layout system, keybinding model, plugin API |
| **Risk** | Low — additive, revert by deleting the binary | Medium — need to verify Herdr works with pi's extension system, sub-agents, OmniRoute |
| **Lock-in** | None — standard Go/Node TS | Moderate — Herdr uses its own layout YAML, plugin format |
### The real question
Herdr solves a different problem. It's a **multiplexer** that happens to have agent awareness. You're asking whether to replace Zellij with a multiplexer that has the feature you want built in, versus adding the feature to your existing setup.
If you were starting from scratch today, Herdr would be a strong choice. But you have:
- A polished Zellij config at `/etc/nixos/home/sam/config/zellij/config.kdl`
- falcode-zellij already wired in
- Years of muscle memory
- neovim running inside Zellij with custom layouts
**The dashboard gives you agent visibility without touching any of that.** Herdr would require rebuilding all of it.
### When Herdr makes sense
If you hit these limits with the dashboard approach:
- "I want to see agent state without a separate tool" → Herdr's pane indicators are more integrated
- "I want Herdr's plugin ecosystem" → The diff viewer, file tree, focus plugins are genuinely useful
- "Zellij's WASM plugin system is too limiting" → Herdr's Rust plugin system is also WASM but with more hooks
But these are "nice to have" problems, not "blocking" problems.
---
## Effort Estimate (with AI assistance)
| Component | Raw AI generation | Debugging + testing | Total |
|-----------|------------------|-------------------|-------|
| `dashboard.ts` extension | 30 minutes | 1 hour (integration testing) | 1.5h |
| Go TUI viewer | 1 hour | 2 hours (edge cases, resize, watcher races) | 3h |
| Cross-machine SSH | 30 minutes | 1 hour (error handling, timeouts, auth) | 1.5h |
| Integration + polish | 30 minutes | 1.5 hours (naming conventions, config file, escape sequences) | 2h |
| **Total** | **2.5h** | **5.5h** | **~8h** |
**No, it's not 1-2 hours.** That might get you a proof-of-concept that shows text on screen. Production-ready means:
- File watcher doesn't crash when a state file is mid-write
- Terminal resize doesn't corrupt the display
- SSH to remote machines doesn't hang if they're offline
- Pressing Enter on a remote agent actually starts the SSH session and attaches
- The extension handles edge cases (agent crash, session kill, machine sleep)
- The dashboard recovers when the extension restarts and writes fresh state
Each of these is a development loop: guess → test → fix. AI can generate the first pass fast, but debugging real-time cross-process systems is inherently iterative.
**The optimistic floor is one focused afternoon.** 3-4 hours if you've had coffee and the stars align. 8-12 hours spread over a few days is the honest expectation.
---
## Summary
| Question | Answer |
|----------|--------|
| Jump to agent terminal? | ✅ tmux: one keypress. Zellij: shows location. |
| Cross-machine visibility? | ✅ SSH pull or HTTP collector. Viewer shows all machines. |
| Build vs Herdr? | **Build.** Herdr replaces Zellij (costly migration). Dashboard is additive (no migration). If you were starting fresh, Herdr would win. |
| Realistic effort? | **~8 hours** with AI, not 1-2. Integration testing is the bottleneck, not code generation. |