sam-4screen-desktop 2026-7-29:12:59:15
This commit is contained in:
@@ -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/<session>.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 <session> (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-<role>` (pi-work, pi-explore, etc.) | Consistent jump target |
|
||||
| Session naming | pi-<role> (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 (`<session>.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 <session>")` or `ssh -t user@host tmux attach -t <session>` |
|
||||
| `d` | Hunk diff | `os.Exec("cd <worktree> && 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/<session>.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)
|
||||
|
||||
Reference in New Issue
Block a user