@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.
- package/AGENTS.md +342 -0
- package/README.md +619 -0
- package/docs/architecture.md +646 -0
- package/package.json +92 -0
- package/packages/extension/package.json +33 -0
- package/packages/extension/src/__tests__/ask-user-tool.test.ts +85 -0
- package/packages/extension/src/__tests__/command-handler.test.ts +712 -0
- package/packages/extension/src/__tests__/connection.test.ts +344 -0
- package/packages/extension/src/__tests__/credentials-updated.test.ts +26 -0
- package/packages/extension/src/__tests__/dev-build.test.ts +79 -0
- package/packages/extension/src/__tests__/event-forwarder.test.ts +89 -0
- package/packages/extension/src/__tests__/git-info.test.ts +112 -0
- package/packages/extension/src/__tests__/git-link-builder.test.ts +102 -0
- package/packages/extension/src/__tests__/openspec-activity-detector.test.ts +232 -0
- package/packages/extension/src/__tests__/openspec-poller.test.ts +119 -0
- package/packages/extension/src/__tests__/process-metrics.test.ts +47 -0
- package/packages/extension/src/__tests__/process-scanner.test.ts +202 -0
- package/packages/extension/src/__tests__/prompt-expander.test.ts +54 -0
- package/packages/extension/src/__tests__/server-auto-start.test.ts +167 -0
- package/packages/extension/src/__tests__/server-launcher.test.ts +44 -0
- package/packages/extension/src/__tests__/server-probe.test.ts +25 -0
- package/packages/extension/src/__tests__/session-switch.test.ts +139 -0
- package/packages/extension/src/__tests__/session-sync.test.ts +55 -0
- package/packages/extension/src/__tests__/source-detector.test.ts +73 -0
- package/packages/extension/src/__tests__/stats-extractor.test.ts +92 -0
- package/packages/extension/src/__tests__/ui-proxy.test.ts +583 -0
- package/packages/extension/src/__tests__/watchdog.test.ts +161 -0
- package/packages/extension/src/ask-user-tool.ts +63 -0
- package/packages/extension/src/bridge-context.ts +64 -0
- package/packages/extension/src/bridge.ts +926 -0
- package/packages/extension/src/command-handler.ts +538 -0
- package/packages/extension/src/connection.ts +204 -0
- package/packages/extension/src/dev-build.ts +39 -0
- package/packages/extension/src/event-forwarder.ts +40 -0
- package/packages/extension/src/flow-event-wiring.ts +102 -0
- package/packages/extension/src/git-info.ts +65 -0
- package/packages/extension/src/git-link-builder.ts +112 -0
- package/packages/extension/src/model-tracker.ts +56 -0
- package/packages/extension/src/pi-env.d.ts +23 -0
- package/packages/extension/src/process-metrics.ts +70 -0
- package/packages/extension/src/process-scanner.ts +396 -0
- package/packages/extension/src/prompt-expander.ts +87 -0
- package/packages/extension/src/provider-register.ts +276 -0
- package/packages/extension/src/server-auto-start.ts +87 -0
- package/packages/extension/src/server-launcher.ts +82 -0
- package/packages/extension/src/server-probe.ts +33 -0
- package/packages/extension/src/session-sync.ts +154 -0
- package/packages/extension/src/source-detector.ts +26 -0
- package/packages/extension/src/ui-proxy.ts +269 -0
- package/packages/extension/tsconfig.json +11 -0
- package/packages/server/package.json +37 -0
- package/packages/server/src/__tests__/auth-plugin.test.ts +117 -0
- package/packages/server/src/__tests__/auth.test.ts +224 -0
- package/packages/server/src/__tests__/auto-attach.test.ts +246 -0
- package/packages/server/src/__tests__/auto-resume.test.ts +135 -0
- package/packages/server/src/__tests__/auto-shutdown.test.ts +136 -0
- package/packages/server/src/__tests__/browse-endpoint.test.ts +104 -0
- package/packages/server/src/__tests__/bulk-archive-handler.test.ts +15 -0
- package/packages/server/src/__tests__/cli-parse.test.ts +73 -0
- package/packages/server/src/__tests__/client-discovery.test.ts +39 -0
- package/packages/server/src/__tests__/config-api.test.ts +104 -0
- package/packages/server/src/__tests__/cors.test.ts +48 -0
- package/packages/server/src/__tests__/directory-service.test.ts +240 -0
- package/packages/server/src/__tests__/editor-detection.test.ts +60 -0
- package/packages/server/src/__tests__/editor-endpoints.test.ts +26 -0
- package/packages/server/src/__tests__/editor-manager.test.ts +73 -0
- package/packages/server/src/__tests__/editor-registry.test.ts +151 -0
- package/packages/server/src/__tests__/event-status-extraction-flow.test.ts +55 -0
- package/packages/server/src/__tests__/event-status-extraction.test.ts +58 -0
- package/packages/server/src/__tests__/extension-register.test.ts +61 -0
- package/packages/server/src/__tests__/file-endpoint.test.ts +49 -0
- package/packages/server/src/__tests__/force-kill-handler.test.ts +109 -0
- package/packages/server/src/__tests__/git-operations.test.ts +251 -0
- package/packages/server/src/__tests__/headless-pid-registry.test.ts +233 -0
- package/packages/server/src/__tests__/headless-shutdown-fallback.test.ts +109 -0
- package/packages/server/src/__tests__/health-endpoint.test.ts +35 -0
- package/packages/server/src/__tests__/heartbeat-ack.test.ts +63 -0
- package/packages/server/src/__tests__/json-store.test.ts +70 -0
- package/packages/server/src/__tests__/localhost-guard.test.ts +149 -0
- package/packages/server/src/__tests__/memory-event-store.test.ts +260 -0
- package/packages/server/src/__tests__/memory-session-manager.test.ts +80 -0
- package/packages/server/src/__tests__/meta-persistence.test.ts +107 -0
- package/packages/server/src/__tests__/migrate-persistence.test.ts +180 -0
- package/packages/server/src/__tests__/npm-search-proxy.test.ts +153 -0
- package/packages/server/src/__tests__/oauth-callback-server.test.ts +165 -0
- package/packages/server/src/__tests__/openspec-archive.test.ts +87 -0
- package/packages/server/src/__tests__/package-manager-wrapper.test.ts +163 -0
- package/packages/server/src/__tests__/package-routes.test.ts +172 -0
- package/packages/server/src/__tests__/pending-fork-registry.test.ts +69 -0
- package/packages/server/src/__tests__/pending-load-manager.test.ts +144 -0
- package/packages/server/src/__tests__/pending-resume-registry.test.ts +130 -0
- package/packages/server/src/__tests__/pi-resource-scanner.test.ts +235 -0
- package/packages/server/src/__tests__/preferences-store.test.ts +108 -0
- package/packages/server/src/__tests__/process-manager.test.ts +184 -0
- package/packages/server/src/__tests__/provider-auth-handlers.test.ts +93 -0
- package/packages/server/src/__tests__/provider-auth-routes.test.ts +143 -0
- package/packages/server/src/__tests__/provider-auth-storage.test.ts +114 -0
- package/packages/server/src/__tests__/resolve-path.test.ts +38 -0
- package/packages/server/src/__tests__/ring-buffer.test.ts +45 -0
- package/packages/server/src/__tests__/server-pid.test.ts +89 -0
- package/packages/server/src/__tests__/session-api.test.ts +244 -0
- package/packages/server/src/__tests__/session-diff.test.ts +138 -0
- package/packages/server/src/__tests__/session-file-dedup.test.ts +102 -0
- package/packages/server/src/__tests__/session-file-reader.test.ts +85 -0
- package/packages/server/src/__tests__/session-lifecycle-logging.test.ts +138 -0
- package/packages/server/src/__tests__/session-order-manager.test.ts +135 -0
- package/packages/server/src/__tests__/session-ordering-integration.test.ts +102 -0
- package/packages/server/src/__tests__/session-scanner.test.ts +199 -0
- package/packages/server/src/__tests__/shutdown-endpoint.test.ts +42 -0
- package/packages/server/src/__tests__/skip-wipe.test.ts +123 -0
- package/packages/server/src/__tests__/sleep-aware-heartbeat.test.ts +126 -0
- package/packages/server/src/__tests__/smoke-integration.test.ts +175 -0
- package/packages/server/src/__tests__/spa-fallback.test.ts +68 -0
- package/packages/server/src/__tests__/subscription-handler.test.ts +155 -0
- package/packages/server/src/__tests__/terminal-gateway.test.ts +61 -0
- package/packages/server/src/__tests__/terminal-manager.test.ts +257 -0
- package/packages/server/src/__tests__/trusted-networks-config.test.ts +84 -0
- package/packages/server/src/__tests__/tunnel.test.ts +206 -0
- package/packages/server/src/__tests__/ws-ping-pong.test.ts +112 -0
- package/packages/server/src/auth-plugin.ts +302 -0
- package/packages/server/src/auth.ts +323 -0
- package/packages/server/src/browse.ts +55 -0
- package/packages/server/src/browser-gateway.ts +495 -0
- package/packages/server/src/browser-handlers/directory-handler.ts +137 -0
- package/packages/server/src/browser-handlers/handler-context.ts +45 -0
- package/packages/server/src/browser-handlers/session-action-handler.ts +271 -0
- package/packages/server/src/browser-handlers/session-meta-handler.ts +95 -0
- package/packages/server/src/browser-handlers/subscription-handler.ts +154 -0
- package/packages/server/src/browser-handlers/terminal-handler.ts +37 -0
- package/packages/server/src/cli.ts +347 -0
- package/packages/server/src/config-api.ts +130 -0
- package/packages/server/src/directory-service.ts +162 -0
- package/packages/server/src/editor-detection.ts +60 -0
- package/packages/server/src/editor-manager.ts +352 -0
- package/packages/server/src/editor-proxy.ts +134 -0
- package/packages/server/src/editor-registry.ts +108 -0
- package/packages/server/src/event-status-extraction.ts +131 -0
- package/packages/server/src/event-wiring.ts +589 -0
- package/packages/server/src/extension-register.ts +92 -0
- package/packages/server/src/git-operations.ts +200 -0
- package/packages/server/src/headless-pid-registry.ts +207 -0
- package/packages/server/src/idle-timer.ts +61 -0
- package/packages/server/src/json-store.ts +32 -0
- package/packages/server/src/localhost-guard.ts +117 -0
- package/packages/server/src/memory-event-store.ts +193 -0
- package/packages/server/src/memory-session-manager.ts +123 -0
- package/packages/server/src/meta-persistence.ts +64 -0
- package/packages/server/src/migrate-persistence.ts +195 -0
- package/packages/server/src/npm-search-proxy.ts +143 -0
- package/packages/server/src/oauth-callback-server.ts +177 -0
- package/packages/server/src/openspec-archive.ts +60 -0
- package/packages/server/src/package-manager-wrapper.ts +200 -0
- package/packages/server/src/pending-fork-registry.ts +53 -0
- package/packages/server/src/pending-load-manager.ts +110 -0
- package/packages/server/src/pending-resume-registry.ts +69 -0
- package/packages/server/src/pi-gateway.ts +419 -0
- package/packages/server/src/pi-resource-scanner.ts +369 -0
- package/packages/server/src/preferences-store.ts +116 -0
- package/packages/server/src/process-manager.ts +311 -0
- package/packages/server/src/provider-auth-handlers.ts +438 -0
- package/packages/server/src/provider-auth-storage.ts +200 -0
- package/packages/server/src/resolve-path.ts +12 -0
- package/packages/server/src/routes/editor-routes.ts +86 -0
- package/packages/server/src/routes/file-routes.ts +116 -0
- package/packages/server/src/routes/git-routes.ts +89 -0
- package/packages/server/src/routes/openspec-routes.ts +99 -0
- package/packages/server/src/routes/package-routes.ts +172 -0
- package/packages/server/src/routes/provider-auth-routes.ts +244 -0
- package/packages/server/src/routes/provider-routes.ts +101 -0
- package/packages/server/src/routes/route-deps.ts +23 -0
- package/packages/server/src/routes/session-routes.ts +91 -0
- package/packages/server/src/routes/system-routes.ts +271 -0
- package/packages/server/src/server-pid.ts +84 -0
- package/packages/server/src/server.ts +554 -0
- package/packages/server/src/session-api.ts +330 -0
- package/packages/server/src/session-bootstrap.ts +80 -0
- package/packages/server/src/session-diff.ts +178 -0
- package/packages/server/src/session-discovery.ts +134 -0
- package/packages/server/src/session-file-reader.ts +135 -0
- package/packages/server/src/session-order-manager.ts +73 -0
- package/packages/server/src/session-scanner.ts +233 -0
- package/packages/server/src/session-stats-reader.ts +99 -0
- package/packages/server/src/terminal-gateway.ts +51 -0
- package/packages/server/src/terminal-manager.ts +241 -0
- package/packages/server/src/tunnel.ts +329 -0
- package/packages/server/tsconfig.json +11 -0
- package/packages/shared/package.json +15 -0
- package/packages/shared/src/__tests__/config.test.ts +358 -0
- package/packages/shared/src/__tests__/deriveChangeState.test.ts +95 -0
- package/packages/shared/src/__tests__/mdns-discovery.test.ts +80 -0
- package/packages/shared/src/__tests__/protocol.test.ts +243 -0
- package/packages/shared/src/__tests__/resolve-jiti.test.ts +17 -0
- package/packages/shared/src/__tests__/server-identity.test.ts +73 -0
- package/packages/shared/src/__tests__/session-meta.test.ts +125 -0
- package/packages/shared/src/archive-types.ts +11 -0
- package/packages/shared/src/browser-protocol.ts +534 -0
- package/packages/shared/src/config.ts +245 -0
- package/packages/shared/src/diff-types.ts +41 -0
- package/packages/shared/src/editor-types.ts +18 -0
- package/packages/shared/src/mdns-discovery.ts +248 -0
- package/packages/shared/src/openspec-activity-detector.ts +109 -0
- package/packages/shared/src/openspec-poller.ts +96 -0
- package/packages/shared/src/protocol.ts +369 -0
- package/packages/shared/src/resolve-jiti.ts +43 -0
- package/packages/shared/src/rest-api.ts +255 -0
- package/packages/shared/src/server-identity.ts +51 -0
- package/packages/shared/src/session-meta.ts +86 -0
- package/packages/shared/src/state-replay.ts +174 -0
- package/packages/shared/src/stats-extractor.ts +54 -0
- package/packages/shared/src/terminal-types.ts +18 -0
- package/packages/shared/src/types.ts +351 -0
- package/packages/shared/tsconfig.json +8 -0
package/README.md
ADDED
|
@@ -0,0 +1,619 @@
|
|
|
1
|
+
# PI Dashboard
|
|
2
|
+
|
|
3
|
+
[](https://github.com/BlackBeltTechnology/pi-agent-dashboard/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/@blackbelt-technology/pi-dashboard)
|
|
5
|
+
[](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
|