From f95b02311cbcdea524b51e2f8d86330cd24645c4 Mon Sep 17 00:00:00 2001 From: arkon Date: Sat, 24 Jan 2026 04:06:35 +0100 Subject: [PATCH] docs: update all docs for notifications, tab alerts, and systemd service MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CLAUDE.md: - Expanded HTTPS & Browser Notifications section with new behavior (default on, auto-permission, tab visibility rules, data forwarding) - Added Tab Alert Blinking documentation (red/yellow, timing, clear triggers) - Added Hook Event Data Forwarding section - Added systemd service commands to Commands section - Added scripts/claudeman-web.service to Key Files table - Fixed switchToSession → selectSession in Frontend docs - Added notification/tab alert timing constants - Updated hook-event API route description - Updated SSE events to mention data forwarding README.md: - Expanded notifications section with tab blinking and click-to-navigate - Added systemd service install commands to Quick Start - Updated hook-event API description Co-Authored-By: Claude Opus 4.5 --- CLAUDE.md | 50 +++++++++++++++++++++++++++++++++++++++++++------- README.md | 31 +++++++++++++++++++++++-------- 2 files changed, 66 insertions(+), 15 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index b8bf1c8f..73b00c05 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -101,6 +101,14 @@ curl localhost:3000/api/status | jq . # Full app state including respawn cat ~/.claudeman/state.json | jq . # View main state cat ~/.claudeman/state-inner.json | jq . # View Ralph loop state +# Systemd service (respawning, survives logout): +systemctl --user status claudeman-web # Check status +systemctl --user restart claudeman-web # Restart +systemctl --user stop claudeman-web # Stop +journalctl --user -u claudeman-web -f # Stream logs +# Install: ln -sf scripts/claudeman-web.service ~/.config/systemd/user/ +# Enable: systemctl --user enable claudeman-web && loginctl enable-linger $USER + # Kill stuck screen sessions screen -X -S quit # Graceful quit pkill -f "SCREEN.*claudeman" # Force kill all claudeman screens @@ -162,6 +170,7 @@ claudeman reset # Reset all state | `src/spawn-claude-md.ts` | Generates CLAUDE.md for spawned agent sessions | | `src/mcp-server.ts` | MCP server binary (`claudeman-mcp`) exposing spawn tools to Claude Code | | `src/tui/DirectAttach.ts` | Full-screen console attach with tab switching between sessions | +| `scripts/claudeman-web.service` | Systemd user service for `claudeman web --https` (Restart=always) | ### Data Flow @@ -474,14 +483,15 @@ Key events for frontend handling (see `app.js:handleSSEEvent()`): - `respawn:detectionUpdate` - Multi-layer idle detection status (confidence level, waiting state) - `spawn:queued`, `spawn:started`, `spawn:completed`, `spawn:failed`, `spawn:timeout`, `spawn:cancelled` - Agent lifecycle - `spawn:progress`, `spawn:message`, `spawn:budgetWarning`, `spawn:stateUpdate` - Agent monitoring -- `hook:idle_prompt`, `hook:permission_prompt`, `hook:elicitation_dialog`, `hook:stop` - Claude Code hooks (desktop notifications) +- `hook:idle_prompt`, `hook:permission_prompt`, `hook:elicitation_dialog`, `hook:stop` - Claude Code hooks (notifications + tab alerts, includes forwarded data fields) ### Frontend (app.js) Vanilla JS + xterm.js. Key functions: - `handleSSEEvent()` - Dispatches events to appropriate handlers -- `switchToSession()` - Tab management and terminal focus -- `createSessionTab()` - Tab creation and xterm setup +- `selectSession()` - Tab switching, terminal buffer load, and focus +- `NotificationManager` - Multi-layer notifications with click-to-navigate +- `tabAlerts` Map - Tracks blinking state per session (`'action'` | `'idle'`) **60fps Rendering Pipeline**: - Server batches terminal data every 16ms before broadcasting via SSE @@ -493,12 +503,34 @@ Vanilla JS + xterm.js. Key functions: **HTTPS**: The `--https` flag generates/reuses self-signed certificates in `~/.claudeman/certs/` (`server.key`, `server.crt`). Required for the Web Notification API in browsers. **Notification Layers** (in `app.js`, `NotificationManager` class): -1. In-app drawer with notification list +1. In-app drawer with notification list (click to navigate to session) 2. Tab title flashing with unread count (when tab unfocused) -3. Web Notification API (browser push notifications) +3. Web Notification API (browser push notifications, click navigates to session) 4. Audio alerts (critical level only) +5. Tab blinking alerts (red for action-required, yellow for idle) -Notifications triggered for: session events, respawn updates, spawn agent lifecycle. Preferences persist to server-side `state.json` per session. +**Browser Notification Behavior:** +- Enabled by default (`browserNotifications: true`, prefs version 2) +- Auto-requests permission on first notification attempt +- Critical/warning notifications fire regardless of tab visibility +- Info notifications only fire when tab is hidden +- Rate limited: max 1 browser notification per 3 seconds +- Click navigates to the affected session + +**Tab Alert Blinking:** +- `hook:permission_prompt` / `hook:elicitation_dialog` → red blink (2.5s cycle, `tab-alert-action`) +- `hook:idle_prompt` → yellow blink (3.5s cycle, `tab-alert-idle`) +- Only blinks non-active tabs (active tab is already visible) +- Clears when: user clicks the tab, or `session:working` event fires + +**Hook Event Data Forwarding:** +The `/api/hook-event` endpoint forwards the `data` field from the request body into the SSE broadcast. Notifications display actual details: +- permission_prompt: tool name + command/file (e.g., "Bash: docker push prod:latest") +- elicitation_dialog: question text (e.g., "Merge PR #42 to main?") +- idle_prompt: custom message if provided +- stop: reason if provided + +Notifications triggered for: session events, respawn updates, spawn agent lifecycle, hook events. Preferences persist to server-side `state.json` per session. ### State Store @@ -552,6 +584,10 @@ Writes debounced (500ms) to `~/.claudeman/state.json`. The web server persists f | Spawn max depth | 3 levels | `spawn-orchestrator.ts` | | Spawn budget warning | 80% | `spawn-orchestrator.ts` | | Spawn budget grace | 60s | `spawn-orchestrator.ts` | +| Browser notif rate limit | 3s | `app.js` (NotificationManager) | +| Tab blink red (action) | 2.5s cycle | `styles.css` (tab-alert-action) | +| Tab blink yellow (idle) | 3.5s cycle | `styles.css` (tab-alert-idle) | +| Systemd restart delay | 5s | `claudeman-web.service` | ### TypeScript Config @@ -678,7 +714,7 @@ Long-running sessions are supported with automatic trimming: | GET | `/api/spawn/status` | Orchestrator status (counts, config) | | PUT | `/api/spawn/config` | Update orchestrator config | | POST | `/api/spawn/trigger` | Programmatic spawn (bypass terminal detection) | -| POST | `/api/hook-event` | Receive Claude Code hook callbacks (idle_prompt, permission_prompt, elicitation_dialog, stop) | +| POST | `/api/hook-event` | Receive Claude Code hook callbacks. Body: `{event, sessionId, data?}`. Data fields forwarded to SSE broadcast | ## Keyboard Shortcuts (Web UI) diff --git a/README.md b/README.md index 3e30990b..94620742 100644 --- a/README.md +++ b/README.md @@ -163,14 +163,20 @@ curl -X POST localhost:3000/api/sessions/:id/auto-compact \ Automatic desktop notifications when sessions need attention — powered by Claude Code's hooks system: -| Hook Event | Urgency | Meaning | -|------------|---------|---------| -| `permission_prompt` | Critical | Claude needs tool approval | -| `elicitation_dialog` | Critical | Claude is asking a question | -| `idle_prompt` | Warning | Session idle, waiting for input | -| `stop` | Info | Response complete | +| Hook Event | Urgency | Tab Alert | Meaning | +|------------|---------|-----------|---------| +| `permission_prompt` | Critical | Red blink | Claude needs tool approval | +| `elicitation_dialog` | Critical | Red blink | Claude is asking a question | +| `idle_prompt` | Warning | Yellow blink | Session idle, waiting for input | +| `stop` | Info | — | Response complete | -Hooks are auto-configured per case directory (`.claude/settings.local.json`). Requires `--https` flag for browser notification API support. +**Features:** +- Browser notifications enabled by default (auto-requests permission) +- Click any notification to jump directly to the affected session +- Tab blinking alerts: red for action-required, yellow for idle +- Notifications include actual context (tool name, command, question text) +- Hooks are auto-configured per case directory (`.claude/settings.local.json`) +- Requires `--https` flag for browser notification API support --- @@ -218,6 +224,15 @@ claudeman web -p 8080 # Development mode (no build needed) npx tsx src/index.ts web + +# HTTPS (required for browser notifications) +claudeman web --https + +# Run as systemd service (auto-restarts, survives logout) +ln -sf $(pwd)/scripts/claudeman-web.service ~/.config/systemd/user/ +systemctl --user daemon-reload +systemctl --user enable --now claudeman-web +loginctl enable-linger $USER ``` **Requirements:** @@ -275,7 +290,7 @@ npx tsx src/index.ts web ### Hooks & Notifications | Method | Endpoint | Description | |--------|----------|-------------| -| `POST` | `/api/hook-event` | Claude Code hook callbacks | +| `POST` | `/api/hook-event` | Hook callbacks `{event, sessionId, data?}` → notifications + tab alerts | ### Real-Time | Method | Endpoint | Description |