sam-4screen-desktop 2026-7-29:11:14:15
This commit is contained in:
@@ -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
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 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) │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
### With tmux (recommended for background agents)
|
||||
|
||||
### 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
|
||||
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)
|
||||
- ✅ Pi extension system (all hooks available)
|
||||
- ✅ tmux (already available)
|
||||
- ✅ Shared filesystem (state files are local)
|
||||
- ✅ OmniRoute for model routing
|
||||
```
|
||||
║ ● work oc/deepseek-v4 ▓▓▓▓░░ 12:34 48.2K $0.09 ║
|
||||
║ 📍 tmux: pi-work ║
|
||||
║ └─ Refactor auth middleware ║
|
||||
║ [Enter to attach] ║
|
||||
```
|
||||
|
||||
## Open Questions
|
||||
### With Zellij (for interactive sessions)
|
||||
|
||||
1. What does the dashboard show when pi is idle (no active agent)?
|
||||
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?
|
||||
Zellij has no `zellij --focus-tab --pane` CLI. So for agents running inside Zellij panes, the dashboard shows the location manually:
|
||||
|
||||
```
|
||||
║ ● 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. |
|
||||
|
||||
Reference in New Issue
Block a user