sam-4screen-desktop 2026-8-4:11:29:15
This commit is contained in:
@@ -537,57 +537,139 @@ code-review-graph build # parses codebase → .code-review-graph/graph.db
|
||||
|
||||
## Pi Dashboard
|
||||
|
||||
A multi-component system for live agent visibility across all machines. Built in this conversation (Jul 2026).
|
||||
A multi-component system for live agent visibility across all machines. Every pi session on every machine (plus sub-agents) reports its state; the TUI shows them all in one table and can attach to them, review their diffs, or open their task boards.
|
||||
|
||||
### Architecture
|
||||
|
||||
```
|
||||
pi sessions (each machine)
|
||||
└─ dashboard.ts extension ── writes ──► ~/.pi/agent/dashboard/<session>.json
|
||||
│
|
||||
pi-dashboard (Go TUI)
|
||||
reads all state files
|
||||
│
|
||||
Enter → tmux attach d → Hunk diff
|
||||
Tab → Tuxedo tasks q → quit
|
||||
pi session (any machine, any terminal: zellij / tmux / plain)
|
||||
└─ dashboard.ts extension
|
||||
├─ writes ~/.pi/agent/dashboard/<session>.json (heartbeat every 15s + on events)
|
||||
├─ tracks tasks → <project>/.pi/dashboard/tasks/todo.txt
|
||||
└─ sends NTFY / Apprise / notify-send notifications
|
||||
│ SSH pull (cat *.json)
|
||||
pi-dashboard (Go TUI on .27) ◄───────────────────────┴── .13 + .51 state dirs
|
||||
```
|
||||
|
||||
| Component | Type | Purpose |
|
||||
|-----------|------|---------|
|
||||
| **dashboard.ts** | pi extension (`~/.pi/agent/extensions/`) | Listens to `agent_start`/`agent_end`/`tool_call`, writes JSON state files, tracks tasks via todo.txt, sends NTFY/Apprise notifications |
|
||||
| **pi-dashboard** | Go binary (`~/.local/bin/pi-dashboard`) | Bubble Tea TUI. Reads state files from all machines (local + SSH pull). Renders agent table with keyboard controls |
|
||||
| **Tuxedo** | Companion TUI (Rust binary, `tuxedo`) | todo.txt task manager. The dashboard extension writes tasks to `~/.pi/agent/dashboard/tasks/todo.txt` in standard todo.txt format, Tuxedo reads it natively with vim keys, phone capture QR, project/context filters |
|
||||
| **Hunk** | Companion TUI (Node CL | npx hunk) | Review-first terminal diff viewer for agent-authored changesets. Triggered from dashboard with `d` key. Supports split/stack/responsive layouts, inline AI annotations, watch mode, Git/jj/Sapling |
|
||||
| **dashboard.ts** | pi extension (`~/.pi/agent/extensions/dashboard.ts`; source `~/.agents/extensions/dashboard.ts` → Gitea `pi-config`) | Per-session telemetry: heartbeat, cwd, started/closed times, agent status, tool count; task tools; notifications |
|
||||
| **pi-dashboard** | Go binary (`~/.local/bin/pi-dashboard`) | Bubble Tea TUI over all machines' state files |
|
||||
| **Tuxedo** | Rust binary (`tuxedo`, nix) | todo.txt task manager (vim keys, phone capture QR) — per-project boards |
|
||||
| **Hunk** | Node CLI (`hunk`, nix / npm `hunkdiff`) | Review-first terminal diff viewer for agent-authored changes |
|
||||
|
||||
### dashboard.ts extension
|
||||
### Quick start
|
||||
|
||||
- **Location:** `~/.pi/agent/extensions/dashboard.ts`
|
||||
- **Events:** `agent_start` (status→running), `agent_end` (status→completed, send notification), `tool_call` (track last tool, count)
|
||||
- **Tasks:** Registers tools `register_task`, `complete_task`, `list_tasks` — writes to todo.txt
|
||||
- **Notifications:** Calls NTFY (`$PI_NTFY_TOPIC`) and Apprise on agent completion and blocked state
|
||||
- **State files:** `~/.pi/agent/dashboard/<session>.json` (atomic writes)
|
||||
- **Session naming:** Derives from tmux session name when in tmux, otherwise working directory basename
|
||||
```bash
|
||||
pi-dashboard # full TUI
|
||||
pi-dashboard --list # plain-text snapshot of local sessions
|
||||
pi-dashboard --help # keybindings + config reference
|
||||
```
|
||||
|
||||
### pi-dashboard TUI viewer
|
||||
### Day-to-day usage (the mental model)
|
||||
|
||||
- **Location:** `~/src/pi-dashboard/` (Go module), `~/.local/bin/pi-dashboard` (binary)
|
||||
- **Built with:** Go + Bubble Tea v2
|
||||
- **Reads:** Local `~/.pi/agent/dashboard/*.json` + SSH pull from remote machines
|
||||
- **Config:** `~/.config/pi-dashboard.yaml`
|
||||
**The pi terminal is for talking; the dashboard TUI is for watching.** You never type tool names or run hunk/tuxedo inside the pi input.
|
||||
|
||||
| You want to… | What you do | What happens |
|
||||
|---|---|---|
|
||||
| Add / list / complete tasks | Tell pi: *"add a task: …"*, *"what tasks do I have?"*, *"mark … done"* | The agent calls `register_task` / `list_tasks` / `complete_task`, which write lines to `<project>/.pi/dashboard/tasks/todo.txt` |
|
||||
| See the task board | Press `Tab` in the dashboard TUI | Tuxedo opens the selected session's `todo.txt` (vim keys: `j/k`, `dd` complete, `u` undo, `s` phone QR) |
|
||||
| Review what an agent changed | Press `d` on its row in the dashboard TUI | Hunk opens in the agent's folder: `cd <cwd> && hunk diff --watch` — shows **all uncommitted changes** in that repo (not a two-file compare) |
|
||||
| Jump into a session | Press `Enter` on its row | `tmux attach` / `zellij attach` / `zellij action switch-session` |
|
||||
|
||||
Key points:
|
||||
- `register_task`/`complete_task`/`list_tasks` are **agent tools** — you ask in English, the AI calls them. They feed todo.txt, which is what Tuxedo displays.
|
||||
- **Hunk's "first/second file" mode** is `hunk diff <left> <right>` for comparing two concrete files. The dashboard `d` key uses `hunk diff --watch` (whole working tree) instead.
|
||||
- Both task systems coexist: the **dashboard tools** → todo.txt → Tuxedo (vim board), while **@tintinweb/pi-tasks** (`TaskCreate`, `TaskExecute`, `/tasks`) is a separate dependency-tracked task engine that can spawn subagents.
|
||||
|
||||
### State model
|
||||
|
||||
Each session writes `~/.pi/agent/dashboard/<session>.json` (atomic write):
|
||||
|
||||
| Field | Meaning |
|
||||
|-------|---------|
|
||||
| `session` | pi session name |
|
||||
| `cwd` | full working directory the session runs in (the **Folder** column) |
|
||||
| `session_started_at` / `closed_at` | session start / graceful-close times |
|
||||
| `last_seen_at` | heartbeat — refreshed every 15 s + on every event |
|
||||
| `agent_status` | `idle` / `running` / `blocked` / `error` (the *agent turn*) |
|
||||
| `session_state` | `open` / `closed` (the *process liveness*) |
|
||||
| `terminal_type` | `tmux` / `zellij` / `tmux+zellij` / `direct` |
|
||||
| `zellij_session` / `tmux_session` / `pid` | attach targets for Enter |
|
||||
| `is_subagent` | true for rows named `<Agent>#<8hex>` (pi-subagents) |
|
||||
|
||||
**Closed detection** — a session counts as closed when:
|
||||
- the extension wrote `session_state: "closed"` on graceful shutdown, **or**
|
||||
- `last_seen_at` is older than `stale_after` (default 45 s) — the terminal was killed (pane closed, `kill -9`) without a shutdown event.
|
||||
|
||||
Status labels: `● running` · `○ idle` · `⚠ blocked` · `✕ error` · `✗ closed` (graceful) · `✗ lost` (died without shutdown).
|
||||
|
||||
### TUI keybindings
|
||||
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `↑↓` | Select agent |
|
||||
| `Enter` | `tmux attach -t <session>` (local) or `ssh -t user@host tmux attach` (remote) |
|
||||
| `d` | Open Hunk diff in agent's worktree |
|
||||
| `Tab` | Launch Tuxedo with task todo.txt |
|
||||
| `Enter` | Attach: `tmux attach -t <name>` / `zellij attach <name>` (dashboard outside zellij) / `zellij action switch-session <name>` (dashboard inside zellij) — local, or over SSH for remote rows |
|
||||
| `d` | **Hunk** — review the selected agent's changes *in its own folder*: `cd <cwd> && hunk diff --watch` |
|
||||
| `Tab` | **Tuxedo** — open the selected agent's **project** task board: `<cwd>/.pi/dashboard/tasks/todo.txt` (created if missing; falls back to global board) |
|
||||
| `s` | Cycle sort: **smart** (live first → running first → last activity) → activity → started → folder |
|
||||
| `x` | Toggle hiding closed sessions (dead sessions sink to the bottom by default; `x` removes them from the view, press again to restore) |
|
||||
| `z` | Toggle hiding sub-agent rows (marked `◇`) |
|
||||
| `r` | Force refresh |
|
||||
| `q` | Quit |
|
||||
|
||||
Selecting a row shows a detail pane: full folder path, started / closed / last-seen times, terminal + zellij/tmux session + pid, model, tool count, current task, blocked prompt.
|
||||
|
||||
### Session naming & rename
|
||||
|
||||
Name resolution order on start: pi session name → `PI_SESSION` env → tmux session name → **zellij session name** (only when it isn't zellij's auto-generated `word-word` animal name like `chatty-echidna`) → working-directory basename.
|
||||
|
||||
**Recommended workflow — one named zellij session per pi session, same name for both:**
|
||||
|
||||
```bash
|
||||
zellij -s computer_software # create a named zellij session…
|
||||
# …pi started inside it auto-inherits "computer_software" as its pi session name
|
||||
```
|
||||
|
||||
**Rename mid-session (pi session + zellij session + dashboard row together):**
|
||||
|
||||
```text
|
||||
/dash-name <name>
|
||||
```
|
||||
|
||||
> pi's built-in `/name` only renames the pi session and cannot be hooked by extensions — `/dash-name` renames all three (pi, zellij, dashboard row). Use `/name` or `Ctrl+R` in `/tree` when you only want to rename the pi session.
|
||||
|
||||
### Long-running / background sessions (tmux survival layer)
|
||||
|
||||
To keep a pi session running after zellij (or the terminal) closes — e.g. a long agent job on a remote machine — run pi inside a tmux session **inside** the zellij pane:
|
||||
|
||||
```bash
|
||||
tmux new -s deploy-job # inside the zellij pane
|
||||
pi # start pi inside tmux
|
||||
# detach with Ctrl-b d — tmux (and pi) keep running after zellij closes
|
||||
tmux attach -t deploy-job # reattach whenever
|
||||
```
|
||||
|
||||
The extension detects the `TMUX` env var: rows show `Ⓣ`, and `Enter` does `tmux attach` — the session survives zellij closing. Rows in bare zellij panes show `Ⓩ`; `tmux+zellij` shows `ⓉⓏ`; plain terminals show `·`.
|
||||
|
||||
### Tasks & Tuxedo
|
||||
|
||||
- Agents register tasks via the `register_task` / `complete_task` / `list_tasks` tools.
|
||||
- Task files are **per project**: `<project>/.pi/dashboard/tasks/todo.txt` (standard todo.txt format).
|
||||
- In the dashboard, `Tab` opens Tuxedo on the **selected row's** project board; with nothing selected it falls back to `~/.pi/agent/dashboard/tasks/todo.txt`.
|
||||
- Tuxedo: vim keys (`j/k`, `dd`, `gg/G`), `u` undo (50 levels), `s` QR phone capture → https://github.com/webstonehq/tuxedo
|
||||
|
||||
### Hunk
|
||||
|
||||
- `d` in the dashboard runs `hunk diff --watch` in the selected agent's folder (over SSH for remote rows) — review exactly what that agent changed.
|
||||
- Standalone: `hunk diff --watch` (live review of the working tree), `hunk show` (last commit). Multi-file sidebar, inline AI annotations, split/stack/responsive layouts. → https://github.com/modem-dev/hunk
|
||||
|
||||
### Cross-machine config (`~/.config/pi-dashboard.yaml`)
|
||||
|
||||
```yaml
|
||||
poll_interval: 2s
|
||||
poll_interval: 2
|
||||
stale_after: 45 # seconds without heartbeat ⇒ session considered closed
|
||||
hide_closed: false # start with closed sessions hidden (toggle with x)
|
||||
local:
|
||||
path: /home/sam/.pi/agent/dashboard/
|
||||
remote:
|
||||
@@ -599,24 +681,14 @@ remote:
|
||||
path: /home/sam/.pi/agent/dashboard/
|
||||
```
|
||||
|
||||
Remote polling is plain `ssh … "cat <path>/*.json"` (BatchMode, 5 s connect timeout); unreachable remotes are skipped silently.
|
||||
|
||||
### Deployment
|
||||
|
||||
The extension deploys via Gitea (in `pi-config`) or manually placed in `~/.pi/agent/extensions/`. The Go binary is built from source and scp'd to remote machines.
|
||||
|
||||
### Tuxedo
|
||||
|
||||
- **Site:** https://github.com/webstonehq/tuxedo
|
||||
- **Install:** Built from source via nix
|
||||
- **Format:** Standard todo.txt — `~/.pi/agent/dashboard/tasks/todo.txt`
|
||||
- **Phone capture:** Press `s` for QR code pointing at LAN PWA — type tasks from phone
|
||||
- **Vim keys:** `j/k`, `dd`, `gg/G`, `u` (undo, 50 levels)
|
||||
|
||||
### Hunk
|
||||
|
||||
- **Site:** https://github.com/modem-dev/hunk
|
||||
- **Install:** `npm i -g hunkdiff` (also available in nixpkgs)
|
||||
- **Usage:** `hunk diff --watch` (live review), `hunk show` (review last commit)
|
||||
- **Features:** Multi-file review with sidebar, inline AI annotations, split/stack/responsive layouts, watch mode for auto-reloading
|
||||
- **Extension** — source of truth: `~/.agents/extensions/dashboard.ts` (Gitea `pi-config`). Edit there, commit + push, then copy to `~/.pi/agent/extensions/dashboard.ts` on each machine (`.27`, `.13`, `.51`).
|
||||
- **Binary** — `cd ~/src/pi-dashboard && CGO_ENABLED=0 go build -o ~/.local/bin/pi-dashboard .`, then `scp` to `.13`/`.51`.
|
||||
- After updating the extension on a machine, run `/reload` in running pi sessions (or restart) to activate it.
|
||||
- Dead state files accumulate by design (they just show as closed); the `archive/` subfolder holds pruned files.
|
||||
|
||||
---
|
||||
|
||||
@@ -793,5 +865,6 @@ compress_for_agent({ content })
|
||||
- [x] Update pi-subagents to v0.10.3 ✅ 2026-06-14
|
||||
- [x] Update pi-tasks to v0.7.0 ✅ 2026-06-13
|
||||
- [x] Install pi-langfuse tracing extension (pi → Langfuse on .13:3001) ✅ 2026-08-03
|
||||
- [x] Pi Dashboard v2: heartbeat + cwd + started/closed columns, hide/sort, /dash-name (pi+zellij), hunk in agent folder, tuxedo project boards, zellij/tmux attach ✅ 2026-08-04
|
||||
- [ ] Verify video-extract works with Gemini
|
||||
- [ ] Clean up workspace-map.json entries for any stale memory packs
|
||||
|
||||
Reference in New Issue
Block a user