@blackbelt-technology/pi-agent-dashboard 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/AGENTS.md +342 -0
  2. package/README.md +619 -0
  3. package/docs/architecture.md +646 -0
  4. package/package.json +92 -0
  5. package/packages/extension/package.json +33 -0
  6. package/packages/extension/src/__tests__/ask-user-tool.test.ts +85 -0
  7. package/packages/extension/src/__tests__/command-handler.test.ts +712 -0
  8. package/packages/extension/src/__tests__/connection.test.ts +344 -0
  9. package/packages/extension/src/__tests__/credentials-updated.test.ts +26 -0
  10. package/packages/extension/src/__tests__/dev-build.test.ts +79 -0
  11. package/packages/extension/src/__tests__/event-forwarder.test.ts +89 -0
  12. package/packages/extension/src/__tests__/git-info.test.ts +112 -0
  13. package/packages/extension/src/__tests__/git-link-builder.test.ts +102 -0
  14. package/packages/extension/src/__tests__/openspec-activity-detector.test.ts +232 -0
  15. package/packages/extension/src/__tests__/openspec-poller.test.ts +119 -0
  16. package/packages/extension/src/__tests__/process-metrics.test.ts +47 -0
  17. package/packages/extension/src/__tests__/process-scanner.test.ts +202 -0
  18. package/packages/extension/src/__tests__/prompt-expander.test.ts +54 -0
  19. package/packages/extension/src/__tests__/server-auto-start.test.ts +167 -0
  20. package/packages/extension/src/__tests__/server-launcher.test.ts +44 -0
  21. package/packages/extension/src/__tests__/server-probe.test.ts +25 -0
  22. package/packages/extension/src/__tests__/session-switch.test.ts +139 -0
  23. package/packages/extension/src/__tests__/session-sync.test.ts +55 -0
  24. package/packages/extension/src/__tests__/source-detector.test.ts +73 -0
  25. package/packages/extension/src/__tests__/stats-extractor.test.ts +92 -0
  26. package/packages/extension/src/__tests__/ui-proxy.test.ts +583 -0
  27. package/packages/extension/src/__tests__/watchdog.test.ts +161 -0
  28. package/packages/extension/src/ask-user-tool.ts +63 -0
  29. package/packages/extension/src/bridge-context.ts +64 -0
  30. package/packages/extension/src/bridge.ts +926 -0
  31. package/packages/extension/src/command-handler.ts +538 -0
  32. package/packages/extension/src/connection.ts +204 -0
  33. package/packages/extension/src/dev-build.ts +39 -0
  34. package/packages/extension/src/event-forwarder.ts +40 -0
  35. package/packages/extension/src/flow-event-wiring.ts +102 -0
  36. package/packages/extension/src/git-info.ts +65 -0
  37. package/packages/extension/src/git-link-builder.ts +112 -0
  38. package/packages/extension/src/model-tracker.ts +56 -0
  39. package/packages/extension/src/pi-env.d.ts +23 -0
  40. package/packages/extension/src/process-metrics.ts +70 -0
  41. package/packages/extension/src/process-scanner.ts +396 -0
  42. package/packages/extension/src/prompt-expander.ts +87 -0
  43. package/packages/extension/src/provider-register.ts +276 -0
  44. package/packages/extension/src/server-auto-start.ts +87 -0
  45. package/packages/extension/src/server-launcher.ts +82 -0
  46. package/packages/extension/src/server-probe.ts +33 -0
  47. package/packages/extension/src/session-sync.ts +154 -0
  48. package/packages/extension/src/source-detector.ts +26 -0
  49. package/packages/extension/src/ui-proxy.ts +269 -0
  50. package/packages/extension/tsconfig.json +11 -0
  51. package/packages/server/package.json +37 -0
  52. package/packages/server/src/__tests__/auth-plugin.test.ts +117 -0
  53. package/packages/server/src/__tests__/auth.test.ts +224 -0
  54. package/packages/server/src/__tests__/auto-attach.test.ts +246 -0
  55. package/packages/server/src/__tests__/auto-resume.test.ts +135 -0
  56. package/packages/server/src/__tests__/auto-shutdown.test.ts +136 -0
  57. package/packages/server/src/__tests__/browse-endpoint.test.ts +104 -0
  58. package/packages/server/src/__tests__/bulk-archive-handler.test.ts +15 -0
  59. package/packages/server/src/__tests__/cli-parse.test.ts +73 -0
  60. package/packages/server/src/__tests__/client-discovery.test.ts +39 -0
  61. package/packages/server/src/__tests__/config-api.test.ts +104 -0
  62. package/packages/server/src/__tests__/cors.test.ts +48 -0
  63. package/packages/server/src/__tests__/directory-service.test.ts +240 -0
  64. package/packages/server/src/__tests__/editor-detection.test.ts +60 -0
  65. package/packages/server/src/__tests__/editor-endpoints.test.ts +26 -0
  66. package/packages/server/src/__tests__/editor-manager.test.ts +73 -0
  67. package/packages/server/src/__tests__/editor-registry.test.ts +151 -0
  68. package/packages/server/src/__tests__/event-status-extraction-flow.test.ts +55 -0
  69. package/packages/server/src/__tests__/event-status-extraction.test.ts +58 -0
  70. package/packages/server/src/__tests__/extension-register.test.ts +61 -0
  71. package/packages/server/src/__tests__/file-endpoint.test.ts +49 -0
  72. package/packages/server/src/__tests__/force-kill-handler.test.ts +109 -0
  73. package/packages/server/src/__tests__/git-operations.test.ts +251 -0
  74. package/packages/server/src/__tests__/headless-pid-registry.test.ts +233 -0
  75. package/packages/server/src/__tests__/headless-shutdown-fallback.test.ts +109 -0
  76. package/packages/server/src/__tests__/health-endpoint.test.ts +35 -0
  77. package/packages/server/src/__tests__/heartbeat-ack.test.ts +63 -0
  78. package/packages/server/src/__tests__/json-store.test.ts +70 -0
  79. package/packages/server/src/__tests__/localhost-guard.test.ts +149 -0
  80. package/packages/server/src/__tests__/memory-event-store.test.ts +260 -0
  81. package/packages/server/src/__tests__/memory-session-manager.test.ts +80 -0
  82. package/packages/server/src/__tests__/meta-persistence.test.ts +107 -0
  83. package/packages/server/src/__tests__/migrate-persistence.test.ts +180 -0
  84. package/packages/server/src/__tests__/npm-search-proxy.test.ts +153 -0
  85. package/packages/server/src/__tests__/oauth-callback-server.test.ts +165 -0
  86. package/packages/server/src/__tests__/openspec-archive.test.ts +87 -0
  87. package/packages/server/src/__tests__/package-manager-wrapper.test.ts +163 -0
  88. package/packages/server/src/__tests__/package-routes.test.ts +172 -0
  89. package/packages/server/src/__tests__/pending-fork-registry.test.ts +69 -0
  90. package/packages/server/src/__tests__/pending-load-manager.test.ts +144 -0
  91. package/packages/server/src/__tests__/pending-resume-registry.test.ts +130 -0
  92. package/packages/server/src/__tests__/pi-resource-scanner.test.ts +235 -0
  93. package/packages/server/src/__tests__/preferences-store.test.ts +108 -0
  94. package/packages/server/src/__tests__/process-manager.test.ts +184 -0
  95. package/packages/server/src/__tests__/provider-auth-handlers.test.ts +93 -0
  96. package/packages/server/src/__tests__/provider-auth-routes.test.ts +143 -0
  97. package/packages/server/src/__tests__/provider-auth-storage.test.ts +114 -0
  98. package/packages/server/src/__tests__/resolve-path.test.ts +38 -0
  99. package/packages/server/src/__tests__/ring-buffer.test.ts +45 -0
  100. package/packages/server/src/__tests__/server-pid.test.ts +89 -0
  101. package/packages/server/src/__tests__/session-api.test.ts +244 -0
  102. package/packages/server/src/__tests__/session-diff.test.ts +138 -0
  103. package/packages/server/src/__tests__/session-file-dedup.test.ts +102 -0
  104. package/packages/server/src/__tests__/session-file-reader.test.ts +85 -0
  105. package/packages/server/src/__tests__/session-lifecycle-logging.test.ts +138 -0
  106. package/packages/server/src/__tests__/session-order-manager.test.ts +135 -0
  107. package/packages/server/src/__tests__/session-ordering-integration.test.ts +102 -0
  108. package/packages/server/src/__tests__/session-scanner.test.ts +199 -0
  109. package/packages/server/src/__tests__/shutdown-endpoint.test.ts +42 -0
  110. package/packages/server/src/__tests__/skip-wipe.test.ts +123 -0
  111. package/packages/server/src/__tests__/sleep-aware-heartbeat.test.ts +126 -0
  112. package/packages/server/src/__tests__/smoke-integration.test.ts +175 -0
  113. package/packages/server/src/__tests__/spa-fallback.test.ts +68 -0
  114. package/packages/server/src/__tests__/subscription-handler.test.ts +155 -0
  115. package/packages/server/src/__tests__/terminal-gateway.test.ts +61 -0
  116. package/packages/server/src/__tests__/terminal-manager.test.ts +257 -0
  117. package/packages/server/src/__tests__/trusted-networks-config.test.ts +84 -0
  118. package/packages/server/src/__tests__/tunnel.test.ts +206 -0
  119. package/packages/server/src/__tests__/ws-ping-pong.test.ts +112 -0
  120. package/packages/server/src/auth-plugin.ts +302 -0
  121. package/packages/server/src/auth.ts +323 -0
  122. package/packages/server/src/browse.ts +55 -0
  123. package/packages/server/src/browser-gateway.ts +495 -0
  124. package/packages/server/src/browser-handlers/directory-handler.ts +137 -0
  125. package/packages/server/src/browser-handlers/handler-context.ts +45 -0
  126. package/packages/server/src/browser-handlers/session-action-handler.ts +271 -0
  127. package/packages/server/src/browser-handlers/session-meta-handler.ts +95 -0
  128. package/packages/server/src/browser-handlers/subscription-handler.ts +154 -0
  129. package/packages/server/src/browser-handlers/terminal-handler.ts +37 -0
  130. package/packages/server/src/cli.ts +347 -0
  131. package/packages/server/src/config-api.ts +130 -0
  132. package/packages/server/src/directory-service.ts +162 -0
  133. package/packages/server/src/editor-detection.ts +60 -0
  134. package/packages/server/src/editor-manager.ts +352 -0
  135. package/packages/server/src/editor-proxy.ts +134 -0
  136. package/packages/server/src/editor-registry.ts +108 -0
  137. package/packages/server/src/event-status-extraction.ts +131 -0
  138. package/packages/server/src/event-wiring.ts +589 -0
  139. package/packages/server/src/extension-register.ts +92 -0
  140. package/packages/server/src/git-operations.ts +200 -0
  141. package/packages/server/src/headless-pid-registry.ts +207 -0
  142. package/packages/server/src/idle-timer.ts +61 -0
  143. package/packages/server/src/json-store.ts +32 -0
  144. package/packages/server/src/localhost-guard.ts +117 -0
  145. package/packages/server/src/memory-event-store.ts +193 -0
  146. package/packages/server/src/memory-session-manager.ts +123 -0
  147. package/packages/server/src/meta-persistence.ts +64 -0
  148. package/packages/server/src/migrate-persistence.ts +195 -0
  149. package/packages/server/src/npm-search-proxy.ts +143 -0
  150. package/packages/server/src/oauth-callback-server.ts +177 -0
  151. package/packages/server/src/openspec-archive.ts +60 -0
  152. package/packages/server/src/package-manager-wrapper.ts +200 -0
  153. package/packages/server/src/pending-fork-registry.ts +53 -0
  154. package/packages/server/src/pending-load-manager.ts +110 -0
  155. package/packages/server/src/pending-resume-registry.ts +69 -0
  156. package/packages/server/src/pi-gateway.ts +419 -0
  157. package/packages/server/src/pi-resource-scanner.ts +369 -0
  158. package/packages/server/src/preferences-store.ts +116 -0
  159. package/packages/server/src/process-manager.ts +311 -0
  160. package/packages/server/src/provider-auth-handlers.ts +438 -0
  161. package/packages/server/src/provider-auth-storage.ts +200 -0
  162. package/packages/server/src/resolve-path.ts +12 -0
  163. package/packages/server/src/routes/editor-routes.ts +86 -0
  164. package/packages/server/src/routes/file-routes.ts +116 -0
  165. package/packages/server/src/routes/git-routes.ts +89 -0
  166. package/packages/server/src/routes/openspec-routes.ts +99 -0
  167. package/packages/server/src/routes/package-routes.ts +172 -0
  168. package/packages/server/src/routes/provider-auth-routes.ts +244 -0
  169. package/packages/server/src/routes/provider-routes.ts +101 -0
  170. package/packages/server/src/routes/route-deps.ts +23 -0
  171. package/packages/server/src/routes/session-routes.ts +91 -0
  172. package/packages/server/src/routes/system-routes.ts +271 -0
  173. package/packages/server/src/server-pid.ts +84 -0
  174. package/packages/server/src/server.ts +554 -0
  175. package/packages/server/src/session-api.ts +330 -0
  176. package/packages/server/src/session-bootstrap.ts +80 -0
  177. package/packages/server/src/session-diff.ts +178 -0
  178. package/packages/server/src/session-discovery.ts +134 -0
  179. package/packages/server/src/session-file-reader.ts +135 -0
  180. package/packages/server/src/session-order-manager.ts +73 -0
  181. package/packages/server/src/session-scanner.ts +233 -0
  182. package/packages/server/src/session-stats-reader.ts +99 -0
  183. package/packages/server/src/terminal-gateway.ts +51 -0
  184. package/packages/server/src/terminal-manager.ts +241 -0
  185. package/packages/server/src/tunnel.ts +329 -0
  186. package/packages/server/tsconfig.json +11 -0
  187. package/packages/shared/package.json +15 -0
  188. package/packages/shared/src/__tests__/config.test.ts +358 -0
  189. package/packages/shared/src/__tests__/deriveChangeState.test.ts +95 -0
  190. package/packages/shared/src/__tests__/mdns-discovery.test.ts +80 -0
  191. package/packages/shared/src/__tests__/protocol.test.ts +243 -0
  192. package/packages/shared/src/__tests__/resolve-jiti.test.ts +17 -0
  193. package/packages/shared/src/__tests__/server-identity.test.ts +73 -0
  194. package/packages/shared/src/__tests__/session-meta.test.ts +125 -0
  195. package/packages/shared/src/archive-types.ts +11 -0
  196. package/packages/shared/src/browser-protocol.ts +534 -0
  197. package/packages/shared/src/config.ts +245 -0
  198. package/packages/shared/src/diff-types.ts +41 -0
  199. package/packages/shared/src/editor-types.ts +18 -0
  200. package/packages/shared/src/mdns-discovery.ts +248 -0
  201. package/packages/shared/src/openspec-activity-detector.ts +109 -0
  202. package/packages/shared/src/openspec-poller.ts +96 -0
  203. package/packages/shared/src/protocol.ts +369 -0
  204. package/packages/shared/src/resolve-jiti.ts +43 -0
  205. package/packages/shared/src/rest-api.ts +255 -0
  206. package/packages/shared/src/server-identity.ts +51 -0
  207. package/packages/shared/src/session-meta.ts +86 -0
  208. package/packages/shared/src/state-replay.ts +174 -0
  209. package/packages/shared/src/stats-extractor.ts +54 -0
  210. package/packages/shared/src/terminal-types.ts +18 -0
  211. package/packages/shared/src/types.ts +351 -0
  212. package/packages/shared/tsconfig.json +8 -0
package/README.md ADDED
@@ -0,0 +1,619 @@
1
+ # PI Dashboard
2
+
3
+ [![CI](https://github.com/BlackBeltTechnology/pi-agent-dashboard/actions/workflows/ci.yml/badge.svg)](https://github.com/BlackBeltTechnology/pi-agent-dashboard/actions/workflows/ci.yml)
4
+ [![npm](https://img.shields.io/npm/v/@blackbelt-technology/pi-dashboard)](https://www.npmjs.com/package/@blackbelt-technology/pi-dashboard)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+
7
+ A web-based dashboard for monitoring and interacting with [pi](https://github.com/badlogic/pi-mono) agent sessions from any browser, including mobile.
8
+
9
+ ## Features
10
+
11
+ - **Real-time session mirroring** — See all active pi sessions with live streaming messages
12
+ - **Bidirectional interaction** — Send prompts and commands from the browser
13
+ - **Workspace management** — Organize sessions by project folder
14
+ - **Command autocomplete** — `/` prefix triggers command dropdown with filtering
15
+ - **Session statistics** — Token counts, costs, model info, thinking level
16
+ - **Elapsed time tracking** — Live ticking counters on running operations, final duration on completed tool calls and reasoning blocks
17
+ - **Mobile-friendly** — Responsive layout with swipe drawer and touch targets
18
+ - **Session spawning** — Launch new pi sessions from the dashboard (headless by default, or via tmux)
19
+ - **Extension UI forwarding** — Interactive dialogs (confirm/select/input) survive page refresh and server restart
20
+ - **On-demand session loading** — Browse historical sessions with lazy-loaded content from pi session files
21
+ - **Integrated terminal** — Full browser-based terminal emulator (xterm.js + node-pty) with ANSI color support, scrollback, and keep-alive
22
+ - **pi-flows integration** — Live flow execution dashboard with agent cards, detail views, summary, abort/auto controls. Launch flows and create new ones from the dashboard. Fork decisions and subagent dialogs forwarded via existing UI proxy.
23
+ - **Force kill escalation** — Two-click Stop button (in command bar and on running tool cards): first click sends soft abort, second click force-kills the process (SIGTERM → SIGKILL). Session preserved as "ended" for resume/fork. Repeated tool calls (e.g. health check loops) are auto-collapsed with a count badge.
24
+ - **Searchable select dialogs** — Keyboard-navigable picker with real-time filtering for OpenSpec changes and flow commands
25
+ - **Browser-based provider auth** — Sign in to Anthropic, OpenAI Codex, GitHub Copilot, Gemini CLI, and Antigravity directly from Settings. Enter API keys for other providers. Credentials saved to `~/.pi/agent/auth.json` and live-synced to running sessions.
26
+ - **Package management** — Browse, install, update, and remove pi packages from the dashboard. Search the npm registry for pi-package extensions/skills/themes, install from npm or git URL, manage global packages in Settings and local packages per workspace. All active sessions auto-reload after changes.
27
+
28
+ ## Architecture
29
+
30
+ ```mermaid
31
+ graph LR
32
+ subgraph "Per pi session"
33
+ B[Bridge Extension]
34
+ end
35
+
36
+ subgraph "Dashboard Server (Node.js)"
37
+ PG[Pi Gateway :9999]
38
+ BG[Browser Gateway :8000]
39
+ HTTP[HTTP / Static Files]
40
+ MEM[(In-Memory Store)]
41
+ JSON[(JSON Files)]
42
+ end
43
+
44
+ subgraph "Browser"
45
+ UI[React Web Client]
46
+ end
47
+
48
+ B <-->|WebSocket| PG
49
+ UI <-->|WebSocket| BG
50
+ UI -->|HTTP| HTTP
51
+ PG --- MEM
52
+ PG --- JSON
53
+ BG --- MEM
54
+ ```
55
+
56
+ The system has three components:
57
+
58
+ | Component | Location | Role |
59
+ |-----------|----------|------|
60
+ | **Bridge Extension** | `src/extension/` | Runs in every pi session. Forwards events, relays commands, auto-starts server. |
61
+ | **Dashboard Server** | `src/server/` | Aggregates events in-memory, persists metadata to JSON, serves the web client. |
62
+ | **Web Client** | `src/client/` | React + Tailwind UI with real-time WebSocket updates. |
63
+
64
+ See [docs/architecture.md](docs/architecture.md) for detailed data flows, reconnection logic, and persistence model.
65
+
66
+ ## Prerequisites
67
+
68
+ | Requirement | Why | Install |
69
+ |-------------|-----|---------|
70
+ | **[pi](https://github.com/badlogic/pi-mono)** or **[Oh My Pi](https://www.npmjs.com/package/@oh-my-pi/pi-coding-agent)** | The AI coding agent that the dashboard monitors | `npm i -g @mariozechner/pi-coding-agent` |
71
+ | **Node.js ≥ 20** | Runtime for the dashboard server | [nodejs.org](https://nodejs.org/) |
72
+ | **C++ build tools** | Required by `node-pty` native addon for terminal emulation | Xcode CLI Tools (macOS) / `build-essential` (Linux) |
73
+
74
+ ### Optional tools
75
+
76
+ | Tool | Purpose | When needed |
77
+ |------|---------|-------------|
78
+ | **tmux** | Spawn new pi sessions from the browser in a tmux window | When `spawnStrategy` is `"tmux"` |
79
+ | **[zrok](https://zrok.io/)** | Expose dashboard over the internet via tunnel (auto-connects on server start). Install with `brew install zrok` (macOS) and run `zrok enable <token>` to enroll — the dashboard reads zrok's own config (`~/.zrok2/environment.json`), no keys are stored in the dashboard. Uses reserved shares for persistent URLs across restarts. | When `tunnel.enabled` is `true` (default) |
80
+
81
+ ## Getting Started
82
+
83
+ ### 1. Install the dashboard package
84
+
85
+ **From npm:**
86
+ ```bash
87
+ pi install npm:@blackbelt-technology/pi-dashboard
88
+ ```
89
+
90
+ **From a local clone:**
91
+ ```bash
92
+ git clone https://github.com/nicობ/pi-agent-dashboard.git
93
+ cd pi-agent-dashboard
94
+ npm install
95
+ pi install /path/to/pi-agent-dashboard
96
+ ```
97
+
98
+ ### 2. Start pi
99
+
100
+ ```bash
101
+ pi
102
+ ```
103
+
104
+ The bridge extension auto-starts the dashboard server on first launch. You'll see:
105
+
106
+ ```
107
+ 🌐 Dashboard started at http://localhost:8000
108
+ ```
109
+
110
+ ### 3. Open the dashboard
111
+
112
+ Open **http://localhost:8000** in any browser. All active pi sessions appear automatically.
113
+
114
+ That's it — no manual server start, no configuration needed for basic use.
115
+
116
+ ### Quick test (without installing)
117
+
118
+ To try the extension in a single pi session without registering it:
119
+
120
+ ```bash
121
+ pi -e /path/to/pi-agent-dashboard/src/extension/bridge.ts
122
+ ```
123
+
124
+ ## Configuration
125
+
126
+ Config file: **`~/.pi/dashboard/config.json`** (auto-created with defaults on first run)
127
+
128
+ ```json
129
+ {
130
+ "port": 8000,
131
+ "piPort": 9999,
132
+ "autoStart": true,
133
+ "autoShutdown": false,
134
+ "shutdownIdleSeconds": 300,
135
+ "spawnStrategy": "headless",
136
+ "tunnel": { "enabled": true, "reservedToken": "auto-created-on-first-run" },
137
+ "devBuildOnReload": false
138
+ }
139
+ ```
140
+
141
+ ### Authentication (Optional)
142
+
143
+ Add an `auth` section to enable OAuth2 authentication for external (tunnel) access. Localhost is always unguarded.
144
+
145
+ ```json
146
+ {
147
+ "auth": {
148
+ "secret": "auto-generated-if-omitted",
149
+ "providers": {
150
+ "github": {
151
+ "clientId": "your-github-client-id",
152
+ "clientSecret": "your-github-client-secret"
153
+ },
154
+ "google": {
155
+ "clientId": "your-google-client-id",
156
+ "clientSecret": "your-google-client-secret"
157
+ },
158
+ "keycloak": {
159
+ "clientId": "your-keycloak-client-id",
160
+ "clientSecret": "your-keycloak-client-secret",
161
+ "issuerUrl": "https://keycloak.example.com/realms/myrealm"
162
+ }
163
+ },
164
+ "allowedUsers": ["octocat", "user@example.com", "*@company.com"]
165
+ }
166
+ }
167
+ ```
168
+
169
+ | Key | Required | Description |
170
+ |-----|----------|-------------|
171
+ | `auth.secret` | No | JWT signing secret (auto-generated if omitted) |
172
+ | `auth.providers` | Yes | Map of provider name → `{ clientId, clientSecret, issuerUrl? }` |
173
+ | `auth.allowedUsers` | No | User allowlist: usernames, emails, or `*@domain` wildcards. Empty = allow all |
174
+
175
+ **Supported providers:** `github`, `google`, `keycloak`, `oidc` (generic OIDC with `issuerUrl`).
176
+
177
+ **Callback URL:** Register `https://<tunnel-url>/auth/callback/<provider>` in your OAuth provider settings. The tunnel URL is stable across restarts (reserved shares are auto-created).
178
+
179
+ **Settings UI:** Click the ⚙ gear icon in the sidebar header to open the Settings panel, where all config fields (including auth) can be edited from the browser.
180
+
181
+ **Precedence:** CLI flags → environment variables → config file → built-in defaults.
182
+
183
+ | CLI Flag | Env Var | Config Key | Default | Description |
184
+ |----------|---------|------------|---------|-------------|
185
+ | `--port` | `PI_DASHBOARD_PORT` | `port` | `8000` | HTTP + Browser WebSocket port |
186
+ | `--pi-port` | `PI_DASHBOARD_PI_PORT` | `piPort` | `9999` | Pi extension WebSocket port |
187
+ | `--dev` | — | — | `false` | Development mode (proxy to Vite) |
188
+ | `--no-tunnel` | — | `tunnel.enabled` | `true` | Disable zrok tunnel |
189
+ | — | — | `autoStart` | `true` | Bridge auto-starts server if not running |
190
+ | — | — | `autoShutdown` | `false` | Server shuts down when idle |
191
+ | — | — | `shutdownIdleSeconds` | `300` | Seconds idle before auto-shutdown |
192
+ | — | — | `spawnStrategy` | `"headless"` | Session spawn mode: `"headless"` or `"tmux"` |
193
+ | — | — | `devBuildOnReload` | `false` | Rebuild client + restart server on `/reload` |
194
+
195
+ ### Override the server URL
196
+
197
+ By default the bridge connects to `ws://localhost:{piPort}`. To point at a remote server:
198
+
199
+ ```bash
200
+ PI_DASHBOARD_URL=ws://192.168.1.100:9999 pi
201
+ ```
202
+
203
+ ## Installation Methods
204
+
205
+ ### From npm (recommended)
206
+
207
+ ```bash
208
+ # pi
209
+ pi install npm:@blackbelt-technology/pi-dashboard
210
+
211
+ # Oh My Pi
212
+ omp install npm:@blackbelt-technology/pi-dashboard
213
+ ```
214
+
215
+ > The package is compatible with both [pi](https://github.com/badlogic/pi-mono) and [Oh My Pi](https://www.npmjs.com/package/@oh-my-pi/pi-coding-agent) — no configuration needed.
216
+
217
+ ### Local development install
218
+
219
+ ```bash
220
+ cd /path/to/pi-agent-dashboard
221
+ npm install
222
+
223
+ # Global install
224
+ pi install /path/to/pi-agent-dashboard
225
+
226
+ # Or project-local only
227
+ pi install -l /path/to/pi-agent-dashboard
228
+ ```
229
+
230
+ Pi reads the `pi.extensions` field from `package.json` and loads the bridge extension automatically.
231
+
232
+ ### Manual settings entry
233
+
234
+ Add the package path directly to your settings file:
235
+
236
+ **Global** (`~/.pi/agent/settings.json`):
237
+ ```json
238
+ {
239
+ "packages": ["/path/to/pi-agent-dashboard"]
240
+ }
241
+ ```
242
+
243
+ **Project-local** (`.pi/settings.json`):
244
+ ```json
245
+ {
246
+ "packages": ["/path/to/pi-agent-dashboard"]
247
+ }
248
+ ```
249
+
250
+ ### Removing
251
+
252
+ ```bash
253
+ pi remove /path/to/pi-agent-dashboard
254
+ ```
255
+
256
+ ## Usage
257
+
258
+ ### Auto-start (default)
259
+
260
+ The bridge extension **automatically starts the dashboard server** when pi launches if it's not already running. No separate terminal needed.
261
+
262
+ To disable: set `"autoStart": false` in `~/.pi/dashboard/config.json`.
263
+
264
+ ### Manual server start
265
+
266
+ ```bash
267
+ npx tsx src/server/cli.ts
268
+ npx tsx src/server/cli.ts --port 8000 --pi-port 9999
269
+ npx tsx src/server/cli.ts --dev # proxy to Vite dev server
270
+ ```
271
+
272
+ ### Daemon mode
273
+
274
+ ```bash
275
+ pi-dashboard start # Start as background daemon (production)
276
+ pi-dashboard start --dev # Start in dev mode (proxy to Vite, fallback to production build)
277
+ pi-dashboard stop # Stop running daemon (also kills stale port holders)
278
+ pi-dashboard restart # Restart daemon (production)
279
+ pi-dashboard restart --dev # Restart in dev mode
280
+ pi-dashboard status # Show daemon status
281
+ ```
282
+
283
+ Daemon stdout/stderr is logged to `~/.pi/dashboard/server.log` for crash diagnosis.
284
+
285
+ ### Graceful restart via API
286
+
287
+ Restart without CLI — useful from scripts, other sessions, or the dashboard skill:
288
+
289
+ ```bash
290
+ # Restart in same mode (preserves current dev/prod)
291
+ curl -X POST http://localhost:8000/api/restart
292
+
293
+ # Switch to dev mode
294
+ curl -X POST http://localhost:8000/api/restart -H 'Content-Type: application/json' -d '{"dev":true}'
295
+
296
+ # Switch to production mode
297
+ curl -X POST http://localhost:8000/api/restart -H 'Content-Type: application/json' -d '{"dev":false}'
298
+
299
+ # Check current mode
300
+ curl -s http://localhost:8000/api/health | jq .mode
301
+ ```
302
+
303
+ The restart endpoint waits for the old server to exit, starts the new one, and verifies health. If the new server fails to start, the error is logged to `server.log`.
304
+
305
+ ### Dev mode with production fallback
306
+
307
+ When started with `--dev`, the server proxies client requests to the Vite dev server for HMR. If Vite is **not running**, the server automatically falls back to serving the production build from `dist/client/`. This means:
308
+
309
+ - `pi-dashboard start --dev` **always works** — no 502 errors
310
+ - Start/stop Vite independently without restarting the dashboard
311
+ - Seamless transition: start Vite later and refresh the browser to get HMR
312
+
313
+ ### Session spawning
314
+
315
+ The dashboard can spawn new pi sessions from the browser. Two strategies are available:
316
+
317
+ **Headless** (default) — Runs pi as a background process with no terminal attached. Interaction happens entirely through the dashboard web UI.
318
+
319
+ **tmux** — Runs pi inside a tmux session named `pi-dashboard`. Each spawned session opens as a new tmux window. This lets you attach to the terminal when needed:
320
+
321
+ ```bash
322
+ # Attach to the pi-dashboard tmux session
323
+ tmux attach -t pi-dashboard
324
+
325
+ # List all windows (each is a spawned pi session)
326
+ tmux list-windows -t pi-dashboard
327
+
328
+ # Switch between windows inside tmux
329
+ Ctrl-b n # next window
330
+ Ctrl-b p # previous window
331
+ Ctrl-b w # interactive window picker
332
+ ```
333
+
334
+ To switch strategy, set `spawnStrategy` in `~/.pi/dashboard/config.json`:
335
+
336
+ ```json
337
+ {
338
+ "spawnStrategy": "tmux"
339
+ }
340
+ ```
341
+
342
+ ### Auto-start flow
343
+
344
+ ```mermaid
345
+ flowchart TD
346
+ A[pi session starts] --> B[ensureConfig]
347
+ B --> C[loadConfig]
348
+ C --> D{TCP probe :piPort}
349
+ D -->|Port open| E[Connect to server]
350
+ D -->|Port closed| F{autoStart?}
351
+ F -->|false| G[Skip]
352
+ F -->|true| H[Spawn server detached]
353
+ H --> I["Notify: 🌐 Dashboard started"]
354
+ I --> E
355
+ ```
356
+
357
+ The server is spawned detached (`child_process.spawn` with `detached: true`, `unref()`), so it outlives the pi session. Duplicate spawn attempts from concurrent pi sessions fail harmlessly with `EADDRINUSE`.
358
+
359
+ ### Dev build on reload
360
+
361
+ Set `"devBuildOnReload": true` in `config.json` for a one-command full-stack refresh:
362
+
363
+ ```
364
+ /reload → build client → stop server → reload extension → auto-start fresh server
365
+ ```
366
+
367
+ > **Note:** Blocks pi for ~2–5s during the build. The server shutdown affects all connected sessions — they auto-reconnect when one restarts the server.
368
+
369
+ ## Development
370
+
371
+ ### Commands
372
+
373
+ ```bash
374
+ npm install # Install dependencies
375
+ npm test # Run all tests (vitest)
376
+ npm run test:watch # Watch mode
377
+ npm run build # Build web client (Vite)
378
+ npm run dev # Start Vite dev server (HMR)
379
+ npm run lint # Type-check (tsc --noEmit)
380
+ npm run reload # Reload all connected pi sessions
381
+ npm run reload:check # Type-check + reload all pi sessions
382
+ ```
383
+
384
+ ### Typical local dev workflow
385
+
386
+ ```bash
387
+ # Terminal 1: Dashboard server in dev mode
388
+ npx tsx src/server/cli.ts --dev
389
+
390
+ # Terminal 2: Vite dev server (HMR for the web client)
391
+ npm run dev
392
+
393
+ # Terminal 3: pi with the bridge extension
394
+ pi -e src/extension/bridge.ts # or just `pi` if installed
395
+
396
+ # Open http://localhost:8000 (server proxies to Vite for SPA routes + assets)
397
+ # Or http://localhost:3000 (Vite directly, proxies API/WS to :8000)
398
+ ```
399
+
400
+ ### Deploy after changes
401
+
402
+ The `pi-dashboard` command is available globally when the package is installed. After making changes, restart the appropriate components:
403
+
404
+ ```bash
405
+ # After client changes (production mode)
406
+ npm run build
407
+ curl -X POST http://localhost:8000/api/restart
408
+
409
+ # After server changes (runs TypeScript directly, no build needed)
410
+ curl -X POST http://localhost:8000/api/restart
411
+
412
+ # After bridge extension changes
413
+ npm run reload # Reload all connected pi sessions
414
+
415
+ # Full rebuild (e.g., after pulling updates)
416
+ npm run build
417
+ curl -X POST http://localhost:8000/api/restart
418
+ npm run reload
419
+
420
+ # Switch between dev and production mode
421
+ curl -X POST http://localhost:8000/api/restart -H 'Content-Type: application/json' -d '{"dev":true}'
422
+ curl -X POST http://localhost:8000/api/restart -H 'Content-Type: application/json' -d '{"dev":false}'
423
+ ```
424
+
425
+ ### Project Structure
426
+
427
+ ```
428
+ src/
429
+ ├── shared/ # Shared TypeScript types
430
+ │ ├── protocol.ts # Extension ↔ Server messages
431
+ │ ├── browser-protocol.ts # Server ↔ Browser messages
432
+ │ ├── types.ts # Data models
433
+ │ ├── config.ts # Shared config loader
434
+ │ └── rest-api.ts # REST API types
435
+ ├── extension/ # Bridge extension (runs in pi)
436
+ │ ├── bridge.ts # Main extension entry
437
+ │ ├── connection.ts # WebSocket with reconnection
438
+ │ ├── event-forwarder.ts # Event mapping
439
+ │ ├── source-detector.ts # Session source detection (via .meta.json sidecar)
440
+ │ ├── command-handler.ts # Command relay
441
+ │ ├── server-probe.ts # TCP probe for server detection
442
+ │ ├── server-launcher.ts # Auto-start server as detached process
443
+ │ ├── git-info.ts # Git branch/remote/PR detection
444
+ │ ├── openspec-poller.ts # OpenSpec change data polling
445
+ │ ├── session-history.ts # Session history sync
446
+ │ ├── state-replay.ts # Event synthesis on reconnect
447
+ │ ├── stats-extractor.ts # Token/cost stats extraction
448
+ │ └── dev-build.ts # Dev build-on-reload helper
449
+ ├── server/ # Dashboard server
450
+ │ ├── cli.ts # CLI entry (start/stop/restart/status)
451
+ │ ├── server.ts # HTTP + WebSocket server
452
+ │ ├── pi-gateway.ts # Extension WebSocket gateway
453
+ │ ├── browser-gateway.ts # Browser WebSocket gateway
454
+ │ ├── memory-event-store.ts # In-memory event buffer (LRU, per-session cap, truncation)
455
+ │ ├── memory-session-manager.ts # In-memory session registry
456
+ │ ├── state-store.ts # User prefs: hidden sessions, pinned dirs, session order
457
+ │ ├── state-store.ts # JSON-backed user preferences
458
+ │ ├── session-persistence.ts # Session metadata persistence
459
+ │ ├── session-order-manager.ts # Per-cwd session ordering
460
+ │ ├── process-manager.ts # tmux/headless session spawning
461
+ │ ├── editor-registry.ts # Available editor detection
462
+ │ ├── tunnel.ts # Zrok tunnel with reserved shares for persistent URLs, binary detection, PID tracking
463
+ │ ├── server-pid.ts # PID file for daemon management
464
+ │ └── json-store.ts # Atomic JSON file helpers
465
+ ├── shared/session-meta.ts # Session metadata sidecar (.meta.json) read/write
466
+ └── client/ # React web client
467
+ ├── App.tsx
468
+ ├── hooks/ # WebSocket hook
469
+ ├── lib/ # Event reducer, command filter
470
+ └── components/ # UI components
471
+ ```
472
+
473
+ ## Monitoring
474
+
475
+ The health endpoint provides server and agent process metrics:
476
+
477
+ ```bash
478
+ curl -s http://localhost:8000/api/health | jq
479
+ ```
480
+
481
+ Returns:
482
+ - `mode` — `"dev"` or `"production"`
483
+ - `server.rss`, `server.heapUsed`, `server.heapTotal` — server memory
484
+ - `server.activeSessions`, `server.totalSessions` — session counts
485
+ - `agents[]` — per-agent metrics (CPU%, RSS, heap, event loop max delay, system load)
486
+
487
+ Agent metrics are collected every 15s via heartbeats and include `eventLoopMaxMs` — useful for diagnosing connection drops during long-running operations.
488
+
489
+ ## Extension UI Events
490
+
491
+ Your own extensions can broadcast UI events to the dashboard:
492
+
493
+ ```typescript
494
+ pi.events.emit("dashboard:ui", {
495
+ method: "notify",
496
+ message: "Deployment complete!",
497
+ level: "success",
498
+ });
499
+ ```
500
+
501
+ Supported methods: `confirm`, `select`, `input`, `notify`.
502
+
503
+ ## Electron Desktop App
504
+
505
+ The project includes an Electron wrapper at `packages/electron/` that bundles the dashboard as a native desktop app.
506
+
507
+ ### Prerequisites
508
+
509
+ - **Node.js 22.12+** (required for building — the Vite plugin and native dependencies need it)
510
+ - Platform-specific tools are handled by Electron Forge automatically
511
+
512
+ ### Building for Your Platform
513
+
514
+ The easiest way — one command that handles everything (client build, Node.js bundling, installer creation):
515
+
516
+ ```bash
517
+ npm run electron:build # Build for current platform & arch
518
+ npm run electron:build -- --arch x64 # Override architecture
519
+ npm run electron:build -- --skip-client # Skip client rebuild
520
+ ```
521
+
522
+ Or step by step:
523
+
524
+ ```bash
525
+ npm run build # Build web client
526
+ cd packages/electron
527
+ bash scripts/download-node.sh # Download Node.js for bundling
528
+ npm run make # Build installer
529
+ ```
530
+
531
+ Output by platform:
532
+
533
+ | Platform | Output | Location |
534
+ |----------|--------|----------|
535
+ | macOS | `.dmg` | `packages/electron/out/make/` |
536
+ | Linux | `.deb` + `.AppImage` | `packages/electron/out/make/` |
537
+ | Windows | `.exe` (NSIS installer) | `packages/electron/out/make/` |
538
+
539
+ ### Cross-Platform Builds (via Docker)
540
+
541
+ From macOS or Linux, you can build installers for **all platforms** using Docker:
542
+
543
+ ```bash
544
+ npm run electron:build -- --all # macOS (native) + Linux + Windows (Docker)
545
+ npm run electron:build -- --linux # Linux .deb + .AppImage only
546
+ npm run electron:build -- --windows # Windows .exe (NSIS) only
547
+ npm run electron:build -- --linux --windows # Both, skip native
548
+ ```
549
+
550
+ Docker builds use a Node 22 Debian container with NSIS installed for Windows cross-compilation.
551
+ All output goes to `packages/electron/out/make/`.
552
+
553
+ > **Note:** Native builds (no flags) build for the current platform only. Docker is required for `--linux`, `--windows`, and `--all`.
554
+
555
+ ### Development Mode
556
+
557
+ ```bash
558
+ # Start the dashboard server and Vite dev server first
559
+ pi-dashboard start --dev
560
+ npm run dev
561
+
562
+ # Then launch Electron pointing at the dev server
563
+ cd packages/electron
564
+ npm run start:dev
565
+ ```
566
+
567
+ ### Regenerating Icons
568
+
569
+ All platform icon variants are generated from the master icon at `packages/electron/resources/icon.png`:
570
+
571
+ ```bash
572
+ cd packages/electron
573
+ npm run icons # Generates .icns (macOS), .ico (Windows), and resized PNGs
574
+ ```
575
+
576
+ ### CI Builds
577
+
578
+ The Electron build workflow (`.github/workflows/electron-build.yml`) builds installers for all platforms using GitHub-hosted runners:
579
+
580
+ - **macOS arm64** — `macos-14` runner → `.dmg`
581
+ - **macOS x64** — `macos-13` runner → `.dmg`
582
+ - **Linux x64** — `ubuntu-latest` runner → `.deb` + `.AppImage`
583
+ - **Windows x64** — `windows-latest` runner → `.exe` (NSIS)
584
+
585
+ Triggered by version tags (`v*`) or manually via GitHub Actions → "Run workflow".
586
+
587
+ ## CI/CD
588
+
589
+ ### Continuous Integration
590
+
591
+ Every push to `main` and every pull request triggers the CI workflow (`.github/workflows/ci.yml`):
592
+
593
+ 1. `npm ci` — install dependencies
594
+ 2. `npm run lint` — type check
595
+ 3. `npm test` — run tests
596
+ 4. `npm run build` — build web client
597
+
598
+ ### Releasing to npm
599
+
600
+ The publish workflow (`.github/workflows/publish.yml`) triggers on `v*` tags:
601
+
602
+ ```bash
603
+ npm version patch # or minor / major
604
+ git push --follow-tags
605
+ ```
606
+
607
+ This runs CI checks, then publishes to npm with `--provenance` for supply chain transparency.
608
+
609
+ ### npm Token Setup
610
+
611
+ The publish workflow requires an `NPM_TOKEN` secret in the GitHub repository:
612
+
613
+ 1. Generate a token at [npmjs.com](https://www.npmjs.com/) → Access Tokens → Generate New Token (Granular Access Token)
614
+ 2. Grant publish access to `@blackbelt-technology` packages
615
+ 3. Add it as a repository secret: GitHub repo → Settings → Secrets and variables → Actions → New repository secret → Name: `NPM_TOKEN`
616
+
617
+ ## License
618
+
619
+ MIT