chore: remove unused surfaces (VS Code extension, statusline, landing assets, Docker)
The repo shipped five install/publish surfaces that nothing in the project builds, tests or documents as supported any more. Each one carried its own stale docs, and the Docker/Podman path additionally described a Dockerfile whose COPY of statusline/ would have broken the build the moment that directory went away. Removed: vscode-extension/ (16 files, marketplace extension for an ID we do not own); statusline/ (3 files, standalone CLI statusline); the repo-root landing/wiki PWA assets (sw.js, manifest.json, robots.txt, sitemap.xml, og-image.svg, favicon.svg, fonts/ - 17 files for pages that no longer exist); .superpowers/ (4 files of scratch brainstorm state, already covered by .gitignore:55); and the container publish path (Dockerfile, docker-compose.yml, .dockerignore, 5 Makefile targets, 2 npm scripts). Kept deliberately - these are about the USER's containers, not ours: scripts/install-hooks.js container detection and AGENTHUB_ALLOW_CONTAINER_HOOKS (issue #193), server/lib/lane-detect.js docker-compose service detection, server/data/profile-templates/postgres-compose/, server/lib/stage-detect.js 'docker push' detection, the host.docker.internal Prometheus notes, the Config Explorer's reads of the user's own ~/.claude/statusline.py, and .devcontainer/ (its docker-in-docker feature is dropped since it existed only to build the removed Dockerfile). Docs follow the code: ARCHITECTURE.md loses the VS Code, statusline and container sections plus two dead TOC anchors, and its PWA section is rewritten from three PWAs to one; INSTALL.md, SETUP.md, docs/DEPLOYMENT.md, server/README.md, client/README.md, docs/README.md, docs/HOOKS.md and docs/DATABASE.md drop the same. The Makefile target count in ARCHITECTURE.md is corrected 25 -> 17 (it was already stale).
This commit is contained in:
+24
-213
@@ -39,8 +39,6 @@ Architectural overview and technical reference for the Agent Dashboard system, c
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
---
|
||||
@@ -63,11 +61,10 @@ Architectural overview and technical reference for the Agent Dashboard system, c
|
||||
- [Browser Notification System](#browser-notification-system)
|
||||
- [Update Notifier Subsystem](#update-notifier-subsystem)
|
||||
- [Sagi Companion Subsystem](#sagi-companion-subsystem)
|
||||
- [VS Code Extension Architecture](#vs-code-extension-architecture)
|
||||
- [Security Considerations](#security-considerations)
|
||||
- [Performance Characteristics](#performance-characteristics)
|
||||
- [Deployment Modes](#deployment-modes)
|
||||
- [Statusline Utility](#statusline-utility)
|
||||
- [Model Name Formatting](#model-name-formatting-client)
|
||||
- [Technology Choices](#technology-choices)
|
||||
- [Build & Run Targets](#build--run-targets)
|
||||
|
||||
@@ -473,57 +470,37 @@ graph TD
|
||||
|
||||
### Self-hosted assets (no external CDN)
|
||||
|
||||
Nothing the dashboard or docs render is fetched from a third-party CDN at runtime — all fonts and scripts are served locally, so every surface works fully offline and leaks nothing to external hosts.
|
||||
Nothing the dashboard renders is fetched from a third-party CDN at runtime — fonts are served locally, so the UI works fully offline and leaks nothing to external hosts.
|
||||
|
||||
- **React app fonts** — Inter + JetBrains Mono are imported from `@fontsource` (latin subset) in `client/src/main.tsx`. Vite bundles the per-weight WOFF2 into `client/dist/assets/` with content hashes at build time; there is no Google Fonts `<link>`. Importing the `latin-*` subset entry points keeps the emitted set to one WOFF2 per weight.
|
||||
- **Static pages (landing + wiki)** — load a self-hosted `@font-face` sheet at the repo-root `fonts/` directory (`fonts/fonts.css` + the `*.woff2` files). The root `index.html` references `fonts/fonts.css`; the wiki references `../fonts/fonts.css` (relative paths resolve under GitHub Pages).
|
||||
- **Wiki Mermaid** — vendored as `wiki/mermaid.min.js` (the genuine minified `mermaid@10.9.6` from npm, with a provenance banner; `.prettierignore`d) and loaded via a local `<script>` instead of `cdn.jsdelivr.net`.
|
||||
- **VS Code extension** — the inline `getErrorHtml()` error page dropped its Google Fonts loader for a system font stack (no bundler / local font path available in that webview).
|
||||
|
||||
Net effect: no `fonts.googleapis.com`, `fonts.gstatic.com`, or `cdn.jsdelivr.net` requests anywhere (verified by `git grep`).
|
||||
Net effect: no `fonts.googleapis.com` or `fonts.gstatic.com` requests anywhere (verified by `git grep`).
|
||||
|
||||
### PWA Architecture
|
||||
|
||||
The project ships three independent Progressive Web Apps. Each has its own Web App Manifest and Service Worker, so the browser treats them as separate installable applications with isolated caches.
|
||||
The dashboard ships as a Progressive Web App with its own Web App Manifest and
|
||||
Service Worker (`client/public/manifest.json` + `client/public/sw.js`), so the
|
||||
browser treats it as an installable application with its own cache.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ PWA Surface Map │
|
||||
├──────────────────┬──────────────────┬───────────────────────────┤
|
||||
│ Dashboard │ Landing Page │ Wiki │
|
||||
│ (client/) │ (root) │ (wiki/) │
|
||||
├──────────────────┼──────────────────┼───────────────────────────┤
|
||||
│ manifest.json │ manifest.json │ manifest.json │
|
||||
│ sw.js │ sw.js │ sw.js │
|
||||
│ id: dashboard │ id: landing │ id: wiki │
|
||||
├──────────────────┼──────────────────┼───────────────────────────┤
|
||||
│ Precache: │ Precache: │ Precache: │
|
||||
│ /, manifest, │ index.html, │ index.html, style.css, │
|
||||
│ favicon.svg │ favicon, og-img, │ script.js, manifest, │
|
||||
│ │ manifest │ favicon │
|
||||
│ Runtime cache: │ Runtime cache: │ Runtime cache: │
|
||||
│ JS/CSS bundles │ screenshot PNGs │ (all precached) │
|
||||
│ (cache-first) │ (cache-first) │ │
|
||||
│ │ │ │
|
||||
│ Skip: /api/*, │ N/A │ N/A │
|
||||
│ /ws, __vite │ │ │
|
||||
│ │ │ │
|
||||
│ + Push notifs │ │ │
|
||||
│ (VAPID pipeline) │ │ │
|
||||
└──────────────────┴──────────────────┴───────────────────────────┘
|
||||
```
|
||||
|
||||
**Service Worker lifecycle (all three):**
|
||||
**Service Worker lifecycle:**
|
||||
|
||||
1. **Install** → `skipWaiting()` — new SW activates immediately, no waiting for tabs to close.
|
||||
2. **Activate** → old caches deleted (keyed by `CACHE_NAME`: `dashboard-v1`, `landing-v1`, `wiki-v1`). Bump the version string to force a cache bust.
|
||||
2. **Activate** → old caches deleted (keyed by `CACHE_NAME`, e.g. `dashboard-v2`). Bump the version string to force a cache bust.
|
||||
3. **Fetch** → Navigation requests are network-first with offline fallback to cached HTML. Static assets are cache-first with runtime caching on miss.
|
||||
|
||||
**Dashboard SW specifics:** The fetch handler skips `/api/*`, `/ws`, and Vite HMR (`__vite`) URLs so live data and development tooling are never cached. Only responses with `response.type === "basic"` (same-origin) are stored. The existing push notification handlers (`push`, `notificationclick`) are preserved alongside the caching logic.
|
||||
The fetch handler skips `/api/*`, `/ws`, and Vite HMR (`__vite`) URLs so live data
|
||||
and development tooling are never cached. Only responses with
|
||||
`response.type === "basic"` (same-origin) are stored. The push notification
|
||||
handlers (`push`, `notificationclick`) live alongside the caching logic — their
|
||||
payload icon is the same-origin `/favicon.svg` (see `server/lib/push.js`).
|
||||
|
||||
**Manifest icons:** All three manifests reference `favicon.svg` with `sizes="any"` and `type="image/svg+xml"` — supported in Chrome 107+, Firefox 110+, Edge 107+. Two icon entries per manifest: one with `purpose: "any"` and one with `purpose: "maskable"`.
|
||||
**Manifest icons:** `favicon.svg` with `sizes="any"` and `type="image/svg+xml"` —
|
||||
supported in Chrome 107+, Firefox 110+, Edge 107+. Two icon entries: one with
|
||||
`purpose: "any"` and one with `purpose: "maskable"`.
|
||||
|
||||
**iOS meta tags:** All HTML files include `<meta name="apple-mobile-web-app-capable" content="yes">` and `<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">` for standalone home-screen mode on Safari.
|
||||
**iOS meta tags:** `client/index.html` includes
|
||||
`<meta name="apple-mobile-web-app-capable" content="yes">` and
|
||||
`<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">`
|
||||
for standalone home-screen mode on Safari.
|
||||
|
||||
### Client Module Graph
|
||||
|
||||
@@ -1056,7 +1033,7 @@ flowchart TD
|
||||
- Uses Node.js `http` module directly — no dependencies.
|
||||
- Resolution order is **env override → discovery file → default**:
|
||||
- `CLAUDE_DASHBOARD_PORT` forces a single target (no fan-out, no discovery).
|
||||
- Otherwise `server/lib/server-info.js` reads `~/.claude/.agenthub.json`, prunes dead-PID entries, and returns one live `port` per unique `dataDir` (lowest port wins when Docker and `npm run dev` share `~/.claude/agenthub`). The handler POSTs to each returned port in parallel.
|
||||
- Otherwise `server/lib/server-info.js` reads `~/.claude/.agenthub.json`, prunes dead-PID entries, and returns one live `port` per unique `dataDir` (lowest port wins when two instances share `~/.claude/agenthub`). The handler POSTs to each returned port in parallel.
|
||||
- If neither yields anything, the handler falls back to `4820`.
|
||||
- Per-target promises never reject — a dead listener can't starve the others, and the handler can wait on `Promise.all` for clean exit timing.
|
||||
|
||||
@@ -2116,7 +2093,7 @@ The same shape is used by `GET /status`, `POST /check`, and the `update_status`
|
||||
|
||||
The dashboard does not expose an apply/restart endpoint by design. A process cannot reliably replace itself without an external supervisor, and several real constraints make an in-process self-update path strictly worse than letting the user run two commands in a terminal:
|
||||
|
||||
- **Supervisor ambiguity.** `npm run dev` (concurrently), `npm start`, `pm2`, `systemd`, `launchd`, and Docker each need different restart logic; an in-process helper could only encode one of them and would silently mis-restart the rest.
|
||||
- **Supervisor ambiguity.** `npm run dev` (concurrently), `npm start`, `pm2`, `systemd`, and `launchd` each need different restart logic; an in-process helper could only encode one of them and would silently mis-restart the rest.
|
||||
- **Silent failures.** `npm install` / `npm run build` / port-release timing issues surface as a dead server with no user-facing feedback once the original process has exited.
|
||||
- **No rollback.** A partial pull + install leaves a broken checkout with no atomic recovery — the working tree is mutated mid-flight.
|
||||
- **Branch coverage.** Even with the situation-aware `manual_command` produced by the detection layer, an automatic apply would still need branch-aware integration (rebase vs merge vs switch) and merge-conflict handling. That belongs in the user's shell, not in a background daemon.
|
||||
@@ -2224,64 +2201,6 @@ Sagi's only contact with the rest of the app is four light, additive touchpoints
|
||||
|
||||
---
|
||||
|
||||
## VS Code Extension Architecture
|
||||
|
||||
The **AgentHub** VS Code extension provides an integrated monitoring experience directly within the editor. It communicates with the local dashboard server via standard HTTP APIs and renders the dashboard UI in a webview.
|
||||
|
||||
<p align="center">
|
||||
<img src="vscode-extension/vscode.png" alt="VS Code Extension Screenshot" width="100%">
|
||||
</p>
|
||||
|
||||
### Extension Components
|
||||
|
||||
| Component | Responsibility |
|
||||
| --- | --- |
|
||||
| **Extension Host** (`extension.js`) | Manages the extension lifecycle, registers commands, creates the status bar item, and coordinates the webview panel. |
|
||||
| **Sidebar Provider** (`sidebar.js`) | Implements the `TreeDataProvider` for the Activity Bar. It performs background polling of the dashboard APIs (`/api/stats`, `/api/analytics`, `/api/sessions`) every 5 seconds. |
|
||||
| **Status Bar Item** | Provides a persistent "Pulse" indicator in the VS Code status bar, showing active session and agent counts. |
|
||||
| **Webview Panel** | A native VS Code tab that renders the dashboard React application. It supports deep linking to specific sessions or sub-pages. |
|
||||
|
||||
### Data Flow
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
subgraph "VS Code Process"
|
||||
SB[Status Bar]
|
||||
SIDE[Sidebar TreeView]
|
||||
WV[Webview Panel]
|
||||
end
|
||||
|
||||
subgraph "Extension Host"
|
||||
EH[extension.js]
|
||||
SP[sidebar.js]
|
||||
end
|
||||
|
||||
subgraph "Dashboard Server (localhost)"
|
||||
API["/api/stats<br/>/api/analytics<br/>/api/sessions"]
|
||||
DS[Express Server]
|
||||
end
|
||||
|
||||
SIDE -->|Poll 5s| SP
|
||||
SP -->|HTTP GET| API
|
||||
EH -->|HTTP GET| API
|
||||
SB -->|Pulse| EH
|
||||
WV -->|Iframe src| DS
|
||||
```
|
||||
|
||||
### Key Implementation Details
|
||||
|
||||
1. **Auto-Detection**: The extension checks both port `5173` (Vite dev server) and `4820` (Production server) on `localhost`. It prioritizes the production port for API data but can render the UI from either.
|
||||
2. **Real-time Status**: The `SidebarProvider` uses a background loop with `onDidChangeTreeData` to automatically toggle between **Online** and **Offline** states as the local server starts or stops.
|
||||
3. **Deep Linking**: Commands like `claude-code-agent-monitor.openDashboard` accept arguments (e.g., a session ID or page path like `analytics`) to route the webview to specific views within the React SPA.
|
||||
4. **Theme Awareness**: The Activity Bar icon (`icon.svg` or `apple-touch-icon.png`) and sidebar icons use VS Code's `ThemeIcon` and `ThemeColor` to ensure they adapt to Light, Dark, and High Contrast themes.
|
||||
|
||||
For the extension source code, refer to the [vscode-extension/](./vscode-extension/) directory.
|
||||
|
||||
> [!TIP]
|
||||
> Extension on VS Code Marketplace: [AgentHub](https://marketplace.visualstudio.com/items?itemName=hoangsonw.claude-code-agent-monitor)
|
||||
|
||||
---
|
||||
|
||||
## Security Considerations
|
||||
|
||||
| Area | Approach |
|
||||
@@ -2368,59 +2287,7 @@ graph LR
|
||||
| **File watching** | `node --watch` + Vite HMR | None |
|
||||
| **Source maps** | Inline | External files |
|
||||
|
||||
### Container (Docker / Podman)
|
||||
|
||||
A multi-stage `Dockerfile` builds the client and server into a single production image. Both Docker and Podman are fully supported — the image is OCI-compliant.
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph "Multi-Stage Build"
|
||||
S1["Stage 1: server-deps\nnode:22-alpine\nnpm ci --omit=dev"]
|
||||
S2["Stage 2: client-build\nnode:22-alpine\nnpm ci + vite build"]
|
||||
S3["Stage 3: runtime\nnode:22-alpine\nCopies node_modules + client/dist"]
|
||||
S1 --> S3
|
||||
S2 --> S3
|
||||
end
|
||||
|
||||
subgraph "Container Runtime"
|
||||
VOL1["~/.claude (ro)\nlegacy session import"]
|
||||
VOL2["agent-monitor-data\nSQLite persistence"]
|
||||
S3 -->|"EXPOSE 4820"| SRV["node server/index.js\nport 4820"]
|
||||
VOL1 --> SRV
|
||||
VOL2 --> SRV
|
||||
end
|
||||
|
||||
style S3 fill:#339933,stroke:#5cb85c,color:#fff
|
||||
style SRV fill:#6366f1,stroke:#818cf8,color:#fff
|
||||
```
|
||||
|
||||
**Usage:**
|
||||
|
||||
```bash
|
||||
# Docker Compose
|
||||
docker compose up -d --build
|
||||
|
||||
# Podman Compose
|
||||
CLAUDE_HOME="$HOME/.claude" podman compose up -d --build
|
||||
|
||||
# Plain Docker / Podman (equivalent)
|
||||
docker build -t agent-monitor .
|
||||
docker run -d -p 4820:4820 \
|
||||
-v "$HOME/.claude:/root/.claude:ro" \
|
||||
-v agent-monitor-data:/app/data \
|
||||
agent-monitor
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> **Hook note:** Claude Code hooks run on the host, not inside the container. The containerized server still receives hook events via HTTP on `localhost:4820` — run `npm run install-hooks` on the host after the container is up. `scripts/install-hooks.js` detects container execution and refuses there (issue #193) so it cannot write a container-internal handler path into a bind-mounted host `~/.claude`; the containerized server's boot-time auto-install is skipped for the same reason. Override with `AGENTHUB_ALLOW_CONTAINER_HOOKS=1` only when Claude Code itself runs inside the container.
|
||||
|
||||
---
|
||||
|
||||
## Statusline Utility
|
||||
|
||||
The `statusline/` directory contains a standalone CLI statusline for Claude Code, separate from the web dashboard. It renders a color-coded bar at the bottom of the Claude Code terminal showing model, user, working directory, git branch, context window usage, per-direction token counts, and session cost in USD.
|
||||
|
||||
### Model Name Formatting (Client)
|
||||
## Model Name Formatting (Client)
|
||||
|
||||
The `client/src/lib/format.ts` module exports a `formatModelName()` utility that converts raw model identifiers stored in the database into human-readable display names throughout the UI (everywhere **except** the Settings page, which shows raw patterns for pricing rule configuration).
|
||||
|
||||
@@ -2447,60 +2314,6 @@ The function handles:
|
||||
|
||||
Components that consume this: SessionDetail, Analytics (donut chart + breakdown), Dashboard (model stats), MessageList, AgentCard, SessionDrillIn, and EventDetail.
|
||||
|
||||
### Data Flow
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant CC as Claude Code
|
||||
participant SH as statusline-command.sh
|
||||
participant PY as statusline.py
|
||||
participant GIT as git CLI
|
||||
|
||||
CC->>SH: stdin (JSON payload)
|
||||
SH->>PY: Pipes stdin through
|
||||
PY->>PY: Parse JSON (model, cwd, context_window, cost)
|
||||
PY->>GIT: git symbolic-ref --short HEAD
|
||||
GIT-->>PY: Branch name
|
||||
PY->>PY: Build ANSI-colored segments (incl. tokens by direction, cost)
|
||||
PY-->>CC: stdout (formatted statusline)
|
||||
```
|
||||
|
||||
### Segments
|
||||
|
||||
| Segment | Source | Color Logic |
|
||||
| ------------ | ------------------------------------- | ------------------------------------------------------------------------------------ |
|
||||
| Model | `data.model.display_name` | Always cyan |
|
||||
| User | `$USERNAME` / `$USER` env var | Always green |
|
||||
| Working Dir | `data.workspace.current_dir` | Always yellow, `~` prefix for home |
|
||||
| Git Branch | `git symbolic-ref --short HEAD` | Always magenta, hidden outside git repos |
|
||||
| Context Bar | `data.context_window.used_percentage` | Green < 50%, Yellow 50–79%, Red >= 80% |
|
||||
| Token Counts | `data.context_window.current_usage` | Green `↑` input, cyan `↓` output, dim `c` cache reads |
|
||||
| Session Cost | `data.cost.total_cost_usd` | Green < $5, Yellow $5–$20, Red >= $20 (shown on API and subscription plans) |
|
||||
|
||||
### Integration
|
||||
|
||||
The statusline is configured in `~/.claude/settings.json` via the `statusLine` key:
|
||||
|
||||
```json
|
||||
{
|
||||
"statusLine": {
|
||||
"type": "command",
|
||||
"command": "bash \"/path/to/.claude/statusline-command.sh\""
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Claude Code invokes this command on each update, piping a JSON payload to stdin. The script reads the JSON, extracts fields, runs `git` for branch info, and prints ANSI-formatted output to stdout.
|
||||
|
||||
**Design decisions:**
|
||||
|
||||
- **Python 3.6+** -- available on virtually all systems, handles ANSI and JSON natively
|
||||
- **No dependencies** -- uses only stdlib (`sys`, `json`, `os`, `subprocess`)
|
||||
- **Shell wrapper** -- `statusline-command.sh` sets `PYTHONUTF8=1` for Windows Unicode support and resolves the absolute path to the Python script
|
||||
- **Fail-safe** -- exits silently on empty input or JSON parse errors, never blocks Claude Code
|
||||
|
||||
---
|
||||
|
||||
## Technology Choices
|
||||
|
||||
| Technology | Why This Over Alternatives |
|
||||
@@ -2528,8 +2341,6 @@ make build Build the React client for production
|
||||
make start Start the production server
|
||||
make test Run all tests (server + client)
|
||||
make format Format all files with Prettier
|
||||
make docker-up Start via docker-compose
|
||||
make docker-down Stop docker-compose stack
|
||||
```
|
||||
|
||||
See `Makefile` for the complete set of 25 targets covering setup, dev, testing, formatting, data management, Codex extensions, and Docker/Podman workflows.
|
||||
See `Makefile` for the complete set of 17 targets covering setup, dev, testing, formatting, and data management.
|
||||
|
||||
Reference in New Issue
Block a user