chore: rename Claudeman to Codeman

Full product rename across 109 files (~834 occurrences):
- Env vars: CLAUDEMAN_* → CODEMAN_*
- Data dirs: ~/.claudeman/ → ~/.codeman/, ~/claudeman-cases/ → ~/codeman-cases/
- tmux prefix: claudeman- → codeman-
- localStorage: claudeman-* → codeman-*
- Package/CLI: claudeman → codeman
- GitHub repo: Ark0N/Claudeman → Ark0N/Codeman
- systemd service: claudeman-web → codeman-web
- Class: ClaudemanApp → CodemanApp

Migration infrastructure for seamless transition:
- state-store.ts: auto-migrates data directories on startup
- tmux-manager.ts: dual-prefix detection (legacy claudeman- sessions)
- app.js: localStorage key migration (preserves old keys)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
arkon
2026-02-26 16:44:34 +01:00
co-authored by Claude Opus 4.6
parent 3ccd22161c
commit 3795c45cc1
109 changed files with 711 additions and 679 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ Date: 2026-02-17
## Scope
Full audit of the Claudeman notification system covering:
Full audit of the Codeman notification system covering:
- Backend event pipeline (server.ts, hooks-config.ts, team-watcher.ts, subagent-watcher.ts)
- Frontend notification manager (app.js NotificationManager class, 4-layer architecture)
- Settings UI and persistence (localStorage + server backup)
+7 -7
View File
@@ -1,10 +1,10 @@
# Claudeman Notification System - Backend Research Report
# Codeman Notification System - Backend Research Report
Date: 2026-02-17
## Executive Summary
The Claudeman notification system is a **multi-layer, event-driven pipeline** that flows from backend event emitters, through SSE broadcasts, to a frontend `NotificationManager` class. The backend itself has no concept of "notifications" -- it broadcasts structured SSE events, and the frontend decides which events warrant user notification (browser notifications, audio alerts, tab title flashing, in-app notification drawer, tab alert badges).
The Codeman notification system is a **multi-layer, event-driven pipeline** that flows from backend event emitters, through SSE broadcasts, to a frontend `NotificationManager` class. The backend itself has no concept of "notifications" -- it broadcasts structured SSE events, and the frontend decides which events warrant user notification (browser notifications, audio alerts, tab title flashing, in-app notification drawer, tab alert badges).
The system handles ~25 distinct notification-triggering SSE events across 5 categories: hook events, session lifecycle, respawn state machine, Ralph Loop, and UI actions.
@@ -96,14 +96,14 @@ Terminal and output data use separate batching pipelines that bypass `broadcast(
### 2.1 Hook Configuration Generator (Lines 24-67)
The `generateHooksConfig()` function creates `.claude/settings.local.json` entries that make Claude Code POST to Claudeman when hooks fire:
The `generateHooksConfig()` function creates `.claude/settings.local.json` entries that make Claude Code POST to Codeman when hooks fire:
```typescript
const curlCmd = (event: HookEventType) =>
`HOOK_DATA=$(cat 2>/dev/null || echo '{}'); ` +
`curl -s -X POST "$CLAUDEMAN_API_URL/api/hook-event" ` +
`curl -s -X POST "$CODEMAN_API_URL/api/hook-event" ` +
`-H 'Content-Type: application/json' ` +
`-d "{\\"event\\":\\"${event}\\",\\"sessionId\\":\\"$CLAUDEMAN_SESSION_ID\\",\\"data\\":$HOOK_DATA}" ` +
`-d "{\\"event\\":\\"${event}\\",\\"sessionId\\":\\"$CODEMAN_SESSION_ID\\",\\"data\\":$HOOK_DATA}" ` +
`2>/dev/null || true`;
```
@@ -143,8 +143,8 @@ The `sanitizeHookData()` function limits what gets broadcast:
### 2.4 Environment Variables (Lines 70-101)
Two env vars are set per case directory via `updateCaseEnvVars()`:
- `CLAUDEMAN_API_URL` -- server URL (e.g., `http://localhost:3000`)
- `CLAUDEMAN_SESSION_ID` -- session identifier
- `CODEMAN_API_URL` -- server URL (e.g., `http://localhost:3000`)
- `CODEMAN_SESSION_ID` -- session identifier
These are resolved at runtime by the shell, so the hook config is static per case.
+7 -7
View File
@@ -2,7 +2,7 @@
## Overview
Claudeman implements a **4-layer notification system** managed by the `NotificationManager` class (app.js lines 860-1265). The layers are:
Codeman implements a **4-layer notification system** managed by the `NotificationManager` class (app.js lines 860-1265). The layers are:
1. **In-app notification drawer** (Layer 1) - badge + list UI
2. **Document title flashing** (Layer 2) - tab title blinks when hidden
@@ -32,19 +32,19 @@ updateTabTitle() {
this.titleFlashInterval = setInterval(() => {
this.titleFlashState = !this.titleFlashState;
document.title = this.titleFlashState
? `\u26A0\uFE0F (${this.unreadCount}) Claudeman`
? `\u26A0\uFE0F (${this.unreadCount}) Codeman`
: this.originalTitle;
}, TITLE_FLASH_INTERVAL_MS);
// Set immediately
document.title = `\u26A0\uFE0F (${this.unreadCount}) Claudeman`;
document.title = `\u26A0\uFE0F (${this.unreadCount}) Codeman`;
}
}
}
```
The title alternates between:
- Warning emoji + unread count: `"(3) Claudeman"`
- Original title: `"Claudeman"`
- Warning emoji + unread count: `"(3) Codeman"`
- Original title: `"Codeman"`
### What Triggers It
Title flashing starts when `notify()` is called **while the tab is not visible** (`!this.isTabVisible`). The check is at lines 1026-1028:
@@ -126,7 +126,7 @@ It shows a lightning bolt icon on a dark background. The favicon is **static** a
Browser notifications reference `/favicon.ico` as their icon (line 1130):
```js
const notif = new Notification(`Claudeman: ${title}`, {
const notif = new Notification(`Codeman: ${title}`, {
body,
tag,
icon: '/favicon.ico',
@@ -306,7 +306,7 @@ Key detail: Title flash always stops when tab becomes visible, but **unread coun
## 5. Focus/Blur Handling
### No window focus/blur listeners
Claudeman does **not** use `window.addEventListener('focus')` or `window.addEventListener('blur')`. It relies solely on the Page Visibility API (`visibilitychange` + `pageshow`).
Codeman does **not** use `window.addEventListener('focus')` or `window.addEventListener('blur')`. It relies solely on the Page Visibility API (`visibilitychange` + `pageshow`).
This is the correct modern approach. The `focus`/`blur` events are unreliable (fire for devtools, iframe changes, etc.) while `visibilitychange` accurately reflects whether the user can see the tab.
+13 -13
View File
@@ -1,11 +1,11 @@
# Claudeman Frontend Notification System -- Detailed Report
# Codeman Frontend Notification System -- Detailed Report
> Generated: 2026-02-17
> Source files analyzed:
> - `/home/arkon/default/claudeman/src/web/public/app.js` (main frontend, ~15k lines)
> - `/home/arkon/default/claudeman/src/web/public/index.html`
> - `/home/arkon/default/claudeman/src/web/public/styles.css`
> - `/home/arkon/default/claudeman/src/web/public/mobile.css`
> - `/home/arkon/default/codeman/src/web/public/app.js` (main frontend, ~15k lines)
> - `/home/arkon/default/codeman/src/web/public/index.html`
> - `/home/arkon/default/codeman/src/web/public/styles.css`
> - `/home/arkon/default/codeman/src/web/public/mobile.css`
---
@@ -87,8 +87,8 @@ const defaults = {
#### Storage Keys (lines 952-956)
Device-specific localStorage keys prevent mobile settings from overriding desktop settings:
- Desktop: `claudeman-notification-prefs`
- Mobile: `claudeman-notification-prefs-mobile`
- Desktop: `codeman-notification-prefs`
- Mobile: `codeman-notification-prefs-mobile`
#### Version Migrations (lines 928-940)
@@ -260,8 +260,8 @@ Mobile override: full-width with safe area padding (mobile.css lines 1049-1058).
When the tab is not visible and there are unread notifications:
1. `setInterval` at 1500ms toggles between:
- Warning emoji + unread count: `"(3) Claudeman"`
- Original title: `"Claudeman"`
- Warning emoji + unread count: `"(3) Codeman"`
- Original title: `"Codeman"`
2. Set immediately on first notification (no wait for first interval tick)
### Stopping
@@ -311,7 +311,7 @@ sendBrowserNotif() called
### Notification Object (lines 1127-1143)
```js
new Notification(`Claudeman: ${title}`, {
new Notification(`Codeman: ${title}`, {
body,
tag, // Groups same-tag notifications (replaces previous with same tag)
icon: '/favicon.ico',
@@ -341,10 +341,10 @@ In settings (index.html line 993), a `<span class="settings-status" id="notifPer
The settings UI shows a hint (index.html line 996):
```
For remote access, HTTPS is required. Start with: claudeman web --https
For remote access, HTTPS is required. Start with: codeman web --https
```
Browser Notification API requires a secure context (HTTPS or localhost). This hint warns users who access Claudeman remotely over HTTP.
Browser Notification API requires a secure context (HTTPS or localhost). This hint warns users who access Codeman remotely over HTTP.
---
@@ -579,7 +579,7 @@ On mobile devices:
### Mobile Storage Key (lines 952-956)
Mobile uses a separate localStorage key (`claudeman-notification-prefs-mobile`) so that enabling notifications on desktop does not accidentally enable them on a mobile device viewing the same Claudeman instance.
Mobile uses a separate localStorage key (`codeman-notification-prefs-mobile`) so that enabling notifications on desktop does not accidentally enable them on a mobile device viewing the same Codeman instance.
### Mobile Drawer Styling (mobile.css lines 1049-1058)
+10 -10
View File
@@ -17,7 +17,7 @@ The App Settings modal has tabs: Display, Claude CLI, Models, Paths, **Notificat
The Browser row includes an "Ask" button that calls `requestPermission()` and a status badge showing the current `Notification.permission` state.
There is also a hint: _"For remote access, HTTPS is required. Start with: `claudeman web --https`"_
There is also a hint: _"For remote access, HTTPS is required. Start with: `codeman web --https`"_
#### Alerts Section
| Setting | Element ID | Type | Default |
@@ -54,16 +54,16 @@ Notification preferences are stored in **two places simultaneously**:
#### Layer 1: localStorage (primary, device-specific)
- **Storage key**: `claudeman-notification-prefs` (desktop) or `claudeman-notification-prefs-mobile` (mobile)
- **Storage key**: `codeman-notification-prefs` (desktop) or `codeman-notification-prefs-mobile` (mobile)
- Determined by `NotificationManager.getStorageKey()` at line 953, which calls `MobileDetection.getDeviceType()`
- Device type is based on `window.innerWidth`: `<430` = mobile, `430-768` = tablet, `>=768` = desktop
- Read in `loadPreferences()` (line 896), written in `savePreferences()` (line 958)
#### Layer 2: Server-side (`~/.claudeman/settings.json`)
#### Layer 2: Server-side (`~/.codeman/settings.json`)
- On save, notification prefs are bundled with app settings: `{ ...settings, notificationPreferences: notifPrefsToSave }` (line 9475)
- Sent via `PUT /api/settings` to the Fastify server
- Server does a shallow merge: `const merged = { ...existing, ...settings }` then writes to `~/.claudeman/settings.json` (line 3098 of server.ts)
- Server does a shallow merge: `const merged = { ...existing, ...settings }` then writes to `~/.codeman/settings.json` (line 3098 of server.ts)
- The `notificationPreferences` key sits at the top level of the settings JSON alongside app settings
#### Load priority
@@ -109,8 +109,8 @@ On startup, `loadAppSettingsFromServer()` (line 9787) fetches from server and:
### App settings (separate from notification prefs)
App settings use a different device-specific localStorage key:
- Desktop: `claudeman-app-settings`
- Mobile: `claudeman-app-settings-mobile`
- Desktop: `codeman-app-settings`
- Mobile: `codeman-app-settings-mobile`
- Determined by `getSettingsStorageKey()` at line 9562
@@ -213,8 +213,8 @@ const AUTO_CLOSE_NOTIFICATION_MS = 8000; // Auto-close browser notifications
### Separate storage keys - YES
Desktop and mobile use completely separate localStorage keys:
- **Notification prefs**: `claudeman-notification-prefs` vs `claudeman-notification-prefs-mobile`
- **App settings**: `claudeman-app-settings` vs `claudeman-app-settings-mobile`
- **Notification prefs**: `codeman-notification-prefs` vs `codeman-notification-prefs-mobile`
- **App settings**: `codeman-app-settings` vs `codeman-app-settings-mobile`
### Different defaults - YES
@@ -303,7 +303,7 @@ The settings UI shows the current permission state via a status badge:
### HTTPS requirement
Browser notifications require HTTPS for remote access. The settings UI includes a hint: _"For remote access, HTTPS is required. Start with: `claudeman web --https`"_. On localhost, HTTP works fine.
Browser notifications require HTTPS for remote access. The settings UI includes a hint: _"For remote access, HTTPS is required. Start with: `codeman web --https`"_. On localhost, HTTP works fine.
## 7. Audio Setting
@@ -354,7 +354,7 @@ Yes, given the prerequisites above are met. However, due to the category key mis
Notification preferences are **strictly global**. There is no per-session notification configuration.
- The `NotificationManager` is a singleton on the `ClaudemanApp` instance (line 1404)
- The `NotificationManager` is a singleton on the `CodemanApp` instance (line 1404)
- Preferences are loaded once from localStorage (line 878)
- All sessions share the same notification rules