From 944fcfb7c9a45ea0f71217a67917c30480368e21 Mon Sep 17 00:00:00 2001 From: Sam Rolfe Date: Wed, 29 Jul 2026 12:59:15 +1000 Subject: [PATCH] sam-4screen-desktop 2026-7-29:12:59:15 --- 100 inbox/Pi Dashboard.md | 259 ++++++-------------------------------- 1 file changed, 36 insertions(+), 223 deletions(-) diff --git a/100 inbox/Pi Dashboard.md b/100 inbox/Pi Dashboard.md index 9a336a2..17768b9 100644 --- a/100 inbox/Pi Dashboard.md +++ b/100 inbox/Pi Dashboard.md @@ -1,6 +1,33 @@ -# Pi Dashboard — Decisive Build Plan +# Pi Dashboard — Build Plan & Checklist -## Architecture Overview +## Task Checklist + +- [ ] **Step 1: dashboard.ts extension** — write, test, commit to Gitea + - [ ] Event hooks: agent_start, agent_end, tool_call + - [ ] Write agent state JSON files atomically + - [ ] Task tools: register_task, complete_task, list_tasks + - [ ] NTFY + Apprise notifications on completion + - [ ] Session name detection (tmux aware) + - [ ] Test with one pi session + - [ ] Commit to Gitea, pull on .13 and .51 +- [ ] **Step 2: Install companion tools** (Tuxedo, Hunk) +- [ ] **Step 3: Go TUI viewer** — build Bubble Tea binary + - [ ] Local state file reader + TUI table + - [ ] Keyboard controls: Enter (attach), d (Hunk), Tab (Tuxedo), q (quit) + - [ ] 2s polling loop + - [ ] Build to ~/bin/pi-dashboard +- [ ] **Step 4: Cross-machine SSH pull** + - [ ] YAML config file + - [ ] SSH remote state reader + - [ ] Remote attach (ssh -t → tmux attach) +- [ ] **Step 5: Try Herdr** + - [ ] `nix shell nixpkgs#herdr`, create test layout + - [ ] Run pi inside Herdr, verify dashboard picks it up + - [ ] Evaluate migration vs keeping Zellij + +--- + +## Architecture ``` ┌─────────────────────────────────────────────────────────────────┐ @@ -10,14 +37,13 @@ │ ├── agent_start → track: status, model, duration, tokens │ │ ├── agent_end → notify: NTFY/Apprise + mark complete │ │ ├── tool_call → track: last tool, tokens consumed │ -│ ├── blocked → mark: waiting, save prompt text │ │ └── register_task / complete_task → write to todo.txt │ │ │ │ │ └── Writes to: │ │ ~/.pi/agent/dashboard/.json (agent state) │ │ ~/.pi/agent/dashboard/tasks/todo.txt (task list) │ │ │ -│ On agent_end / blocked: │ +│ On agent_end / error: │ │ └── curl → NTFY server (phone notification) │ │ └── apprise → Slack/Telegram/email (configured routes) │ └─────────────────────────────────────────────────────────────────┘ @@ -30,30 +56,10 @@ │ Renders: agent status table with cost, duration, location │ │ Controls: │ │ Enter → tmux attach -t (jump to agent) │ -│ Tab → switch to Tuxedo (task list in todo.txt) │ │ d → hunk diff (review agent's worktree changes) │ +│ Tab → launch Tuxedo (task list in todo.txt) │ +│ r → force refresh │ │ q → quit │ -│ │ -│ Config: ~/.config/pi-dashboard.yaml │ -│ (local paths, SSH remotes, polling interval) │ -└─────────────────────────────────────────────────────────────────┘ - -┌─────────────────────────────────────────────────────────────────┐ -│ Companion tools (existing, not building) │ -│ │ -│ Tuxedo → TUI todo.txt manager │ -│ Reads ~/.pi/agent/dashboard/tasks/todo.txt │ -│ Vim keys, phone capture QR, project/context filters │ -│ │ -│ Hunk → TUI diff viewer │ -│ hunk diff --watch → review agent changes live │ -│ hunk show → review last commit from agent │ -│ │ -│ NTFY → Push notification server (already running) │ -│ curl → ntfy.sh/pi-alerts → phone notification │ -│ │ -│ Apprise → Multi-route notification dispatcher │ -│ One command → Slack + Telegram + Email + NTFY │ └─────────────────────────────────────────────────────────────────┘ ``` @@ -64,202 +70,9 @@ | State transfer | SSH pull Phase 1 → HTTP collector on .13 Phase 2 | Zero infra to start, resilient later | | TUI framework | Go + Bubble Tea | Single binary, fast, portable | | Web UI | Phase 2, optional | SSH from Termux works for Phase 1 | -| Task board | **Use Tuxedo** — don't build custom | Tuxedo is already a polished todo.txt TUI with phone capture, vim keys, filters | -| Diff review | **Use Hunk** — don't build custom | Hunk is purpose-built for reviewing agent changesets | -| Notifications | **Use NTFY + Apprise** — don't build custom | Both already available, extension just calls `curl` / `apprise` | +| Task board | Use Tuxedo — don't build custom | Already polished with vim keys, phone capture | +| Diff review | Use Hunk — don't build custom | Purpose-built for agent changeset review | +| Notifications | Use NTFY + Apprise — don't build custom | Both already available, extension calls curl/apprise | | Polling | 2s intervals, no file watcher | Simple, no edge cases | -| Session naming | `pi-` (pi-work, pi-explore, etc.) | Consistent jump target | +| Session naming | pi- (pi-work, pi-explore) | Consistent jump target | | Herdr | Try alongside, no special integration | Dashboard is multiplexer-agnostic | - -## What Gets Built (Phase 1) - -### 1. `~/.pi/agent/extensions/dashboard.ts` (~150 lines) - -Pi extension that collects state and writes files. - -**Event hooks:** -- `agent_start` → record: agent type, model, timestamp, status=running -- `agent_end` → record: duration, token count, cost, status=done -- `tool_call` → record: tool name, duration, input/output tokens (for cost) - -**Blocked detection:** -- Intercept `ctx.ui.confirm()`, `ctx.ui.select()`, `ctx.ui.input()` calls -- When these fire and return is pending → mark status=blocked, save the prompt text - -**Task integration:** -- Register tool `register_task(title, project, assignee)` → append line to todo.txt -- Register tool `complete_task(id)` → mark line as done in todo.txt -- Register tool `list_tasks()` → read todo.txt, return formatted list - -**Notifications (Phase 1):** -- On `agent_end`: spawn `curl` to NTFY server with completion summary -- On blocked: spawn `curl` to NTFY with blocking prompt and session name -- On error: spawn `curl` to NTFY with error details - -**State file format (`.json`):** -```json -{ - "session": "pi-work", - "machine": "nixos-desktop", - "host": "192.168.20.13", - "agent_type": "coder-basic", - "model": "opencode-go/deepseek-v4-flash", - "status": "running", - "started_at": "2026-07-27T10:23:00Z", - "current_task": "Refactor auth middleware", - "duration_seconds": 742, - "tokens_in": 28100, - "tokens_out": 20100, - "cost": 0.09, - "last_tool": "edit", - "last_tool_at": "2026-07-27T10:34:22Z", - "blocked": false, - "blocked_prompt": null, - "connection_type": "tmux", - "connection_name": "pi-work", - "worktree": "/tmp/pi/worktrees/auth-refactor/" -} -``` - -### 2. `~/bin/pi-dashboard` (Go + Bubble Tea, ~400 lines) - -Standalone TUI binary. - -**Rendering:** Agent status table with columns: - -``` -╔══════════════════════════════════════════════════════════════════╗ -║ ⬡ Pi Dashboard 3 machines · 5 agents ║ -║ Total: $0.52 · Running: 2 · Blocked: 1 · Done: 2 ║ -╠══════════════════════════════════════════════════════════════════╣ -║ MACH SESSION TYPE MODEL STATUS DUR $ ║ -║ ───────────────────────────────────────────────────────────────║ -║ .27 pi-work coder oc/dsv4-flash ● run 12:34 0.09 ║ -║ .27 pi-explore explore oc/dsv4-flash ● run 03:12 0.02 ║ -║ .13 pi-resrch rsrc gemini-flash ○ idle 00:47 0.00 ║ -║ .51 pi-bugfix coder ds/v4-pro ⚠ blk 01:23 0.11 ║ -║ └─ ⚡ Allow rm -rf src/? (y/N) ║ -╠══════════════════════════════════════════════════════════════════╣ -║ [Enter] Attach [d] Hunk diff [Tab] Tuxedo [r] Refresh [q] ║ -╚══════════════════════════════════════════════════════════════════╝ -``` - -**Keyboard controls:** - -| Key | Action | Implementation | -|-----|--------|----------------| -| `↑↓` | Select agent | Bubble Tea list model | -| `Enter` | Attach to agent | `os.Exec("tmux attach -t ")` or `ssh -t user@host tmux attach -t ` | -| `d` | Hunk diff | `os.Exec("cd && hunk diff --watch")` | -| `Tab` | Launch Tuxedo | `os.Exec("tuxedo --file ~/.pi/agent/dashboard/tasks/todo.txt")` | -| `r` | Force refresh | Clear cache, re-poll | -| `q` | Quit | Exit | - -**Config file (`~/.config/pi-dashboard.yaml`):** -```yaml -poll_interval: 2s - -local: - path: /home/sam/.pi/agent/dashboard/ - -remote: - - host: 192.168.20.13 - user: sam - path: /home/sam/.pi/agent/dashboard/ - - host: 192.168.20.51 - user: sam - path: /home/sam/.pi/agent/dashboard/ -``` - -## What You DON'T Build - -| Feature | Handled by | Why not build it | -|---------|-----------|------------------| -| Task board UI | **Tuxedo** | Already a polished todo.txt TUI with vim keys, phone capture, project/context filters. The extension just writes tasks to a standard format. | -| Diff review | **Hunk** | Already purpose-built for reviewing agent changesets with watch mode, AI annotations, split/stack layouts. | -| Push notifications | **NTFY** | Already running. Extension just POSTs to it. | -| Multi-route notifications | **Apprise** | Already available. Extension calls `apprise -b "msg"` to fan-out to Slack/Telegram/email. | -| Web UI | **Phase 2** | TUI + SSH from Termux covers Phase 1. | - -## Implementation Order - -### Step 1: dashboard.ts extension (~1.5 hours) - -- Write `~/.pi/agent/extensions/dashboard.ts` -- Add event listeners: `agent_start`, `agent_end`, `tool_call` -- Add task tool registrations: `register_task`, `complete_task`, `list_tasks` -- Add blocked detection via `ui.custom` wrappers -- Add NTFY/Apprise notification on `agent_end` and blocked -- Write state atomically to `~/.pi/agent/dashboard/.json` -- Write tasks to `~/.pi/agent/dashboard/tasks/todo.txt` -- Test with one pi session -- Commit to Gitea, pull on .13 and .51 - -### Step 2: Go TUI viewer (~3 hours) - -- Init Go module at `~/src/pi-dashboard/` -- Implement state file reader (local + SSH with `golang.org/x/crypto/ssh`) -- Implement YAML config reader -- Build Bubble Tea model with agent list (bubbletea + bubbles list) -- Add keyboard controls -- Build binary to `~/bin/pi-dashboard` -- Test with 2-3 background pi sessions on .27 - -### Step 3: Cross-machine + polish (~2 hours) - -- Test SSH pull from .51 and .13 -- Handle timeouts, unreachable machines, auth errors gracefully -- Test `Enter` jumping to remote agents (ssh -t) -- Test `d` → Hunk diff opens correctly -- Test `Tab` → Tuxedo opens with task file - -### Step 4: Try Herdr (~1 hour) - -- `nix shell nixpkgs#herdr` or download -- Create simple Herdr layout for WS 2 -- Run pi session inside Herdr -- Verify dashboard picks it up -- Evaluate whether migration from Zellij is worth it - -### Step 5: HTTP collector + web UI (~2 hours, optional Phase 2) - -- Add POST to collector endpoint in dashboard.ts -- Write collector (Go, simple HTTP server) -- Update viewer to try collector first, fall back to SSH -- If web UI wanted: Svelte frontend served by collector - -## Files to Create - -| File | Location | Purpose | -|------|----------|---------| -| `dashboard.ts` | `~/.pi/agent/extensions/` | Pi extension: collects state, writes files, tracks tasks, sends notifications | -| `pi-dashboard/main.go` | `~/src/pi-dashboard/` | Entry point | -| `pi-dashboard/config.go` | `~/src/pi-dashboard/` | YAML config reader | -| `pi-dashboard/state.go` | `~/src/pi-dashboard/` | State file reader + SSH fetcher | -| `pi-dashboard/tui.go` | `~/src/pi-dashboard/` | Bubble Tea model, view, update | -| `pi-dashboard/go.mod` | `~/src/pi-dashboard/` | Dependencies | -| `~/.config/pi-dashboard.yaml` | user config | Machine list, paths, polling interval | -| `~/bin/pi-dashboard` | binary | Built Go binary | - -## Total Effort - -| Step | Time | What you get | -|------|------|-------------| -| 1. Extension | 1.5h | State files appearing, NTFY notifications on completion | -| 2. TUI viewer | 3h | See all agents in one terminal, attach to any of them | -| 3. Cross-machine | 2h | Agents on .51 and .13 visible from .27 | -| 4. Herdr trial | 1h | Know if Herdr is worth migrating to | -| **Phase 1 total** | **~7.5h** | Full visibility across all machines | -| 5. HTTP + web | 2h | Single source of truth, browser view | - -## Prerequisites - -- ✅ Go (will install via nix) -- ✅ Bubble Tea (go get) -- ✅ NTFY server (already running) -- ✅ Apprise (already available) -- ✅ Tuxedo (will install via brew/nix) -- ✅ Hunk (will install via npm/nix) -- ✅ tmux (already available) -- ✅ SSH (already configured) -- ✅ Gitea (for syncing the extension)