add-dashboard

star 29.9k

Add a monitoring dashboard to NanoClaw. Installs @nanoco/nanoclaw-dashboard and a pusher that sends periodic JSON snapshots.

nanocoai By nanocoai schedule Updated 6/6/2026

name: add-dashboard description: Add a monitoring dashboard to NanoClaw. Installs @nanoco/nanoclaw-dashboard and a pusher that sends periodic JSON snapshots.

/add-dashboard — NanoClaw Dashboard

Adds a local monitoring dashboard showing agent groups, sessions, channels, users, token usage, context windows, message activity, and real-time logs.

Architecture

NanoClaw (pusher)              Dashboard (npm package)
┌──────────┐    POST JSON      ┌──────────────┐
│ collects │ ────────────────→ │ /api/ingest  │
│ DB data  │   every 60s       │ in-memory    │
│ tails    │ ────────────────→ │ /api/logs/   │
│ log file │   every 2s        │   push       │
└──────────┘                   │ serves UI    │
                               └──────────────┘

Steps

1. Install the npm package

pnpm install @nanoco/nanoclaw-dashboard

2. Copy the pusher module and its tests

Copy all three resource files into src/. The tests ship with the skill and run against the composed project — they're how you confirm the skill works and is wired in correctly.

.claude/skills/add-dashboard/resources/dashboard-pusher.ts       → src/dashboard-pusher.ts
.claude/skills/add-dashboard/resources/dashboard-pusher.test.ts  → src/dashboard-pusher.test.ts
.claude/skills/add-dashboard/resources/dashboard-wiring.test.ts  → src/dashboard-wiring.test.ts
  • dashboard-pusher.test.ts — behavior: starts the pusher, posts a real snapshot to a fake dashboard.
  • dashboard-wiring.test.ts — the code edit in step 3: asserts (via the TS AST) that index.ts dynamically imports ./dashboard-pusher.js and awaits startDashboard() as colocated statements of main(), after DB init and before the boot-complete log. Delete or misplace the edit and this goes red.

3. Wire into src/index.ts

This is the skill's one integration point, and it's deliberately minimal and self-contained: all the startup logic lives in dashboard-pusher.ts, and the import is colocated with the call so the whole edit is a single block in one place — there's no separate top-of-file import to add (or to remember to remove).

Add this block inside main(), just before the log.info('NanoClaw running') line:

  // Dashboard (optional; no-ops without DASHBOARD_SECRET)
  const { startDashboard } = await import('./dashboard-pusher.js');
  await startDashboard();

startDashboard() reads DASHBOARD_SECRET/DASHBOARD_PORT itself and no-ops if the secret is unset, so nothing else in core needs to change.

4. Add environment variables to .env

DASHBOARD_SECRET=<generate-a-random-secret>
DASHBOARD_PORT=3100

Generate the secret: node -e "console.log('nc-' + require('crypto').randomBytes(16).toString('hex'))"

5. Build, test, and restart

Run from your NanoClaw project root:

pnpm run build
pnpm exec vitest run src/dashboard-pusher.test.ts src/dashboard-wiring.test.ts   # behavior + wiring
source setup/lib/install-slug.sh
systemctl --user restart $(systemd_unit)              # Linux
# or: launchctl kickstart -k gui/$(id -u)/$(launchd_label)  # macOS

Run build before the tests: it's what guards the @nanoco/nanoclaw-dashboard dependency. dashboard-pusher.ts reaches the package through await import('@nanoco/nanoclaw-dashboard'), so if step 4 was skipped, pnpm run build fails with TS2307: Cannot find module. The behavior test deliberately mocks that package — its startDashboard binds a real dashboard port, a side effect we don't want in a test — so the test alone would pass with the dependency missing. Build is therefore the leg that verifies the dependency is installed; keep it ahead of the tests in the validate step.

6. Verify (runtime smoke check)

Once the service is restarted, confirm the dashboard is live:

curl -s http://localhost:3100/api/status
curl -s -H "Authorization: Bearer <secret>" http://localhost:3100/api/overview

Open http://localhost:3100/dashboard in a browser.

Dashboard Pages

Page Shows
Overview Stats, token usage + cache hit rate, context windows, activity chart
Agent Groups Sessions, wirings, destinations, members, admins
Sessions Status, container state, context window usage bars
Channels Live/offline status, messaging groups, sender policies
Messages Per-session inbound/outbound messages
Users Privilege hierarchy: owner > admin > member
Logs Real-time log streaming with level filter

Troubleshooting

  • "No data yet": Wait 60s for first push, or check logs for push errors
  • 401 errors: Verify DASHBOARD_SECRET matches in .env
  • Port conflict: Change DASHBOARD_PORT in .env
  • No logs: Check logs/nanoclaw.log exists

Removal

Reverse the apply steps. Safe to re-run even if some pieces are already gone.

rm -f src/dashboard-pusher.ts src/dashboard-pusher.test.ts src/dashboard-wiring.test.ts
pnpm uninstall @nanoco/nanoclaw-dashboard 2>/dev/null || true

Then, by hand, remove the single dashboard block the skill added to main() in src/index.ts (the // Dashboard (optional…) comment, the await import('./dashboard-pusher.js') line, and the await startDashboard(); call), and remove DASHBOARD_SECRET and DASHBOARD_PORT from .env.

pnpm run build
Install via CLI
npx skills add https://github.com/nanocoai/nanoclaw --skill add-dashboard
Repository Details
star Stars 29,890
call_split Forks 12,876
navigation Branch main
article Path SKILL.md
More from Creator