- Fix inconsistent null handling in state-store (use ?? instead of ||) - Add JSON.stringify error handling with specific messages - Add error handling for SSE init event in app.js - Fix spawn orchestrator silent failures (add logging) - Fix statSync race condition in subagent-watcher - Fix unbounded _taskNumberToContent Map in ralph-tracker - Fix YAML pattern case sensitivity in ralph-config Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
30 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
⚠️ CRITICAL: Screen Session Safety
You may be running inside a Claudeman-managed screen session. Before killing ANY screen or Claude process:
- Check environment:
echo $CLAUDEMAN_SCREEN- if it returns1, you're in a managed session - NEVER run
screen -X quit,pkill screen, orpkill claudewithout first confirming you're not killing yourself - Safe debugging: Use
screen -lsto LIST sessions, but don't kill them blindly - If you need to kill screens: Use the web UI or
./scripts/screen-manager.shinstead of direct commands
Why this matters: Killing your own screen terminates your session mid-work, losing context and potentially corrupting state.
⚡ COM Shorthand (Deployment)
When user says "COM": 1) Increment version in BOTH package.json AND CLAUDE.md, 2) git add && git commit && git push && npm run build && systemctl --user restart claudeman-web. Always bump version on every COM.
Project Overview
Claudeman is a Claude Code session manager with a web interface and autonomous Ralph Loop. It spawns Claude CLI processes via PTY, streams output in real-time via SSE, and supports scheduled/timed runs.
Version: 0.1383 (must match package.json)
Tech Stack: TypeScript (ES2022/NodeNext, strict mode), Node.js, Fastify, Server-Sent Events, node-pty
Key Dependencies: fastify (REST API), node-pty (PTY spawning), ink/react (TUI), xterm.js (web terminal), @modelcontextprotocol/sdk (MCP server for spawn protocol)
Requirements: Node.js 18+, Claude CLI (claude) installed, GNU Screen (apt install screen / brew install screen)
Note
:
claudedoes not need to be in the server process's PATH. Claudeman auto-discovers the binary from common install locations (~/.local/bin,~/.claude/local,/usr/local/bin, etc.) and augments PATH for spawned sessions.
Runtime: The web server runs as a systemd user service (
claudeman-web.service) on HTTPS port 3000 with a self-signed certificate. It auto-restarts and survives logout.
First-Time Setup
npm install
Commands
CRITICAL: npm run dev runs CLI help, NOT the web server. Use npx tsx src/index.ts web for development.
Build & Clean
npm run build # Compile TS + copy static files + templates + make bins executable
npm run clean # Remove dist/
npm run typecheck # Type check without building (or: npx tsc --noEmit)
Web Server
npx tsx src/index.ts web # Dev mode - no build needed (RECOMMENDED)
npx tsx src/index.ts web -p 8080 # Dev mode with custom port
npx tsx src/index.ts web --https # Dev mode with self-signed TLS (enables browser notifications)
npm run web # After npm run build (shorthand)
node dist/index.js web # After npm run build
claudeman web # After npm link
TUI (Terminal User Interface)
npx tsx src/index.ts tui # Dev mode - prompts to start web if not running
claudeman tui # After npm link
claudeman tui --with-web # Auto-start web server if not running (no prompt)
claudeman tui --no-web # Skip web server check entirely
claudeman tui -p 8080 # Specify web server port
Testing
npm run test # Run all tests once
npm run test:watch # Watch mode
npm run test:coverage # With coverage report
npx vitest run test/session.test.ts # Single file
npx vitest run -t "should create session" # By pattern
Test Configuration (vitest.config.ts):
globals: true- no imports needed fordescribe/it/expecttestTimeout: 30000- 30s for integration teststeardownTimeout: 60000- 60s ensures cleanup runs even on failuresfileParallelism: false- sequential file execution to respect screen session limits- Coverage excludes entry points:
src/index.ts,src/cli.ts
Test Port Allocation (integration tests spawn servers):
| Port | Test File |
|---|---|
| 3099 | quick-start.test.ts |
| 3102 | session.test.ts |
| 3105 | scheduled-runs.test.ts |
| 3107 | sse-events.test.ts |
| 3110 | edge-cases.test.ts |
| 3115 | integration-flows.test.ts |
| 3120 | session-cleanup.test.ts |
| 3125 | ralph-integration.test.ts |
| 3127 | respawn-integration.test.ts (reserved) |
| 3130 | hooks-config.test.ts (Hook Event API) |
| 3131 | hooks-config.test.ts (Hook Data Sanitization) |
| 3150 | browser-e2e.test.ts (main browser tests) |
| 3151 | browser-e2e.test.ts (SSE events tests) |
| 3152 | browser-e2e.test.ts (hook events tests) |
| 3153 | browser-e2e.test.ts (Ralph panel tests) |
| 3154 | file-link-click.test.ts |
Next available port: 3155
Unit tests (no port needed): respawn-controller, ralph-tracker, pty-interactive, task-queue, task, ralph-loop, session-manager, state-store, types, templates, ralph-config, spawn-detector, spawn-types, spawn-orchestrator, ai-idle-checker, ai-plan-checker
Test Utilities: test/respawn-test-utils.ts provides MockSession, MockAiIdleChecker, MockAiPlanChecker, time controller, state tracker, and event recorder for respawn controller testing. See test/respawn-test-plan.md for architecture and test/respawn-scenarios.md for comprehensive test scenarios.
Test Safety: test/setup.ts enforces max 10 concurrent screens, performs orphan cleanup, and protects its own process tree. You can safely run tests from within a Claudeman-managed session - the cleanup will not kill your own Claude instance. The respawn-controller tests use MockSession (not real screens).
Test Cleanup Patterns: Integration tests track resources in createdSessions and createdCases arrays, cleaned up by afterAll/afterEach hooks. However, some tests perform cleanup in the test body itself (e.g., edge-cases.test.ts:273-302 creates 5 sessions and cleans them in a loop). If assertions fail before cleanup code runs, resources leak.
Known Cleanup Issues:
pty-interactive.test.ts: Usesawait session.stop()at end of each test, not inafterEach. Test failures leave sessions running.edge-cases.test.ts: Multiple sessions created in test body with cleanup at end; failures leak sessions.- Test cases (
~/claudeman-cases/): Cases namedflow-test-*,ralph-track-loop-*,session-detail-*may persist after test failures.
Manual Cleanup:
# Remove orphaned test cases
rm -rf ~/claudeman-cases/flow-test-* ~/claudeman-cases/ralph-track-loop-* ~/claudeman-cases/session-detail-*
# Kill orphaned test screens (only detached claudeman screens)
screen -ls | grep -E 'Detached.*claudeman' | cut -d. -f1 | xargs -I{} screen -S {} -X quit
MCP Server
npx tsx src/mcp-server.ts # Dev mode (stdio transport)
Configure in Claude Code's MCP settings:
{ "command": "node", "args": ["dist/mcp-server.js"], "env": { "CLAUDEMAN_API_URL": "http://localhost:3000", "CLAUDEMAN_SESSION_ID": "<id>" } }
Debugging
screen -ls # List GNU screen sessions
screen -r <name> # Attach to screen session (Ctrl+A D to detach)
curl localhost:3000/api/sessions # Check active sessions
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
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 Screens
screen -X -S <name> quit # Graceful quit
pkill -f "SCREEN.*claudeman" # Force kill all claudeman screens
CLI Commands
claudeman session [s] # Manage Claude sessions
start # Start new session
stop <id> # Stop session
list [ls] # List all
logs <id> # View output
claudeman task [t] # Manage tasks
add <prompt> # Add task
list [ls] # List tasks
status <id> # Task details
remove [rm] <id> # Remove task
clear # Clear completed/failed
claudeman ralph [r] # Control Ralph loop
start # Start loop
stop # Stop loop
status # Show status
claudeman web # Start web interface
claudeman tui # Start TUI
claudeman status # Overall status
claudeman reset # Reset all state
Architecture
Key Files
Core Session Management:
| File | Purpose |
|---|---|
src/session.ts |
Core PTY wrapper for Claude CLI. Modes: runPrompt(), startInteractive(), startShell() |
src/screen-manager.ts |
GNU screen persistence, ghost discovery, 4-strategy kill |
src/session-manager.ts |
Session lifecycle, task assignment, cleanup |
src/state-store.ts |
JSON persistence to ~/.claudeman/ with debounced writes |
src/types.ts |
All TypeScript interfaces |
Autonomous Features:
| File | Purpose |
|---|---|
src/respawn-controller.ts |
State machine for autonomous session cycling |
src/ai-idle-checker.ts |
Spawns Claude to analyze terminal output for IDLE/WORKING verdict |
src/ai-plan-checker.ts |
Spawns Claude to detect plan mode prompts for auto-accept |
src/ralph-tracker.ts |
Detects <promise>PHRASE</promise>, todos, loop status |
src/ralph-config.ts |
Parses .claude/ralph-loop.local.md and CLAUDE.md for Ralph config |
src/run-summary.ts |
Tracks session events for "what happened while away" summaries |
Spawn Protocol (Autonomous Agents):
| File | Purpose |
|---|---|
src/spawn-orchestrator.ts |
Full agent lifecycle: spawn, monitor, budget, queue, cleanup |
src/mcp-server.ts |
MCP server binary exposing spawn tools to Claude Code |
src/subagent-watcher.ts |
Monitors Claude Code background agents in ~/.claude/projects/*/subagents/*.jsonl |
Web & TUI:
| File | Purpose |
|---|---|
src/web/server.ts |
Fastify REST API + SSE at /api/events |
src/web/public/app.js |
Frontend: SSE handling, xterm.js, tab management |
src/tui/App.tsx |
TUI main component (Ink/React) |
src/tui/DirectAttach.ts |
Full-screen console attach with tab switching |
Data Flow
- Session spawns
claude -p --dangerously-skip-permissionsvianode-pty(PATH augmented to include claude's install directory) - PTY output is buffered, ANSI stripped, and parsed for JSON messages
- WebServer broadcasts events to SSE clients at
/api/events - Full session state (settings, tokens, respawn config, Ralph state) persists to
~/.claudeman/state.jsonvia StateStore - Screen metadata persists separately to
~/.claudeman/screens.jsonfor session recovery
Respawn State Machine
State machine for autonomous session cycling: watching → confirming_idle → ai_checking → sending_update → waiting_update → sending_clear → waiting_clear → sending_init → waiting_init → monitoring_init → (optionally) sending_kickstart. Steps can be skipped via config (sendClear: false, sendInit: false). After each step, waits for completionConfirmMs (10s) of output silence before proceeding. AI idle check uses a fresh Claude session to analyze terminal output for IDLE/WORKING verdict.
See docs/respawn-state-machine.md for the full state diagram, idle detection layers, and auto-accept behavior.
Spawn1337 Protocol (Autonomous Agents)
Spawned agents are full-power Claude sessions in their own screen sessions, managed via MCP tools (spawn_agent, list_agents, get_agent_status, get_agent_result, send_agent_message, cancel_agent). Max 5 concurrent, max depth 3, default timeout 30min. Agents communicate via filesystem (spawn-comms/) and signal completion via <promise>PHRASE</promise>.
See docs/spawn-protocol.md for the full protocol flow, directory structure, resource governance, and MCP configuration.
Subagent Watcher (Claude Code Background Agents)
Monitors Claude Code's internal background agents (the Task tool) in real-time. Watches ~/.claude/projects/{project}/{session}/subagents/agent-{id}.jsonl files and emits structured events.
Events: subagent:discovered, subagent:tool_call, subagent:progress, subagent:message, subagent:completed
API:
GET /api/subagents- List all known subagents (optional?minutes=60for recent only)GET /api/subagents/:agentId- Get subagent infoGET /api/subagents/:agentId/transcript- Get transcript (?limit=N,?format=formatted)DELETE /api/subagents/:agentId- Kill subagent processGET /api/sessions/:id/subagents- Get subagents for session's working directory
Status lifecycle: active → idle (30s no activity) → completed (process exited or file stale)
Settings: Can be disabled via App Settings → Display → "Enable Subagent Tracking" (default: enabled). Setting is stored in ~/.claudeman/settings.json as subagentTrackingEnabled.
Implementation: src/subagent-watcher.ts - singleton subagentWatcher started on server boot (if enabled).
Session Modes
Sessions have a mode property (SessionMode type):
'claude': Runs Claude CLI for AI interactions (default)'shell': Runs a plain bash shell for debugging/testing
Screen-Aware Sessions
All Claude sessions spawned by Claudeman receive environment variables indicating they're running in a managed screen:
| Variable | Value | Purpose |
|---|---|---|
CLAUDEMAN_SCREEN |
1 |
Indicates session is managed by Claudeman |
CLAUDEMAN_SESSION_ID |
<uuid> |
Unique session identifier |
CLAUDEMAN_SCREEN_NAME |
claudeman-<name> |
GNU screen session name |
This prevents Claude from accidentally killing its own screen session. The default CLAUDE.md template includes guidance about this.
Implementation: Set in screen-manager.ts:createScreen() for screen-based sessions and session.ts:startInteractive()/startShell() for PTY-only sessions. Both paths also augment PATH with the claude binary's directory to ensure discovery in restricted environments (systemd, non-login shells).
Code Patterns
Pre-compiled Regex Patterns
For performance, regex patterns that are used frequently should be compiled once at module level:
// Good - compile once
const ANSI_ESCAPE_PATTERN = /\x1b\[[0-9;]*m/g;
const TOKEN_PATTERN = /(\d+(?:\.\d+)?)\s*([kKmM])?\s*tokens/;
// Bad - recompiles on each call
function parse(line: string) {
return line.replace(/\x1b\[[0-9;]*m/g, '');
}
Claude Message Parsing
Claude CLI outputs newline-delimited JSON. Strip ANSI codes before parsing:
const cleanLine = line.replace(ANSI_ESCAPE_PATTERN, '');
const msg = JSON.parse(cleanLine) as ClaudeMessage;
// msg.type: 'system' | 'assistant' | 'user' | 'result'
// msg.message?.content: Array<{ type: 'text', text: string }>
// msg.total_cost_usd: number (on result messages)
PTY Spawn Modes
All PTY spawns pass PATH: getAugmentedPath() in the env to ensure claude is discoverable even when the server runs in a restricted environment (e.g., systemd). The getAugmentedPath() function (in session.ts) resolves the claude binary's directory once at startup and prepends it to PATH. The screen-manager.ts equivalent (findClaudeDir()) does the same for screen-based spawns via export PATH="<dir>:$PATH" in the bash command.
// One-shot mode (JSON output for token tracking)
pty.spawn('claude', ['-p', '--dangerously-skip-permissions', '--output-format', 'stream-json', prompt], {
env: { ...process.env, PATH: getAugmentedPath(), ... }
})
// Interactive mode (tokens parsed from status line)
pty.spawn('claude', ['--dangerously-skip-permissions'], {
env: { ...process.env, PATH: getAugmentedPath(), ... }
})
// Shell mode (debugging/testing - no Claude CLI)
pty.spawn('bash', [], { ... })
PATH resolution search order (both session.ts and screen-manager.ts):
which claude(respects current PATH)~/.local/bin/claude~/.claude/local/claude/usr/local/bin/claude~/.npm-global/bin/claude~/bin/claude
Sending Input to Sessions
Two methods:
session.write(data)- Direct PTY write (used by/api/sessions/:id/inputendpoint)session.writeViaScreen(data)- Via GNU screen (RECOMMENDED for programmatic input). Used by RespawnController, auto-compact, auto-clear.
How writeViaScreen works internally (in screen-manager.ts:sendInput):
- Splits input into text and
\r(carriage return) - Sends text first:
screen -S name -p 0 -X stuff "text" - Sends Enter separately:
screen -S name -p 0 -X stuff "$(printf '\015')"
Why separate commands? Claude CLI uses Ink (React for terminals) which requires text and Enter as separate screen -X stuff commands. Combining them doesn't work. This is a critical implementation detail when debugging input issues.
Idle Detection
Session: emits idle/working events on prompt detection + 2s activity timeout.
RespawnController: Multi-layer detection (completion message → AI idle check → output silence → token stability → working pattern absence). See docs/respawn-state-machine.md for full details.
Token Tracking
- One-shot mode: Uses
--output-format stream-jsonfor detailed token usage from JSON - Interactive mode: Parses tokens from Claude's status line (e.g., "123.4k tokens"), estimates 60/40 input/output split
Auto-Compact & Auto-Clear
| Feature | Default Threshold | Action |
|---|---|---|
| Auto-Compact | 110k tokens | /compact with optional prompt |
| Auto-Clear | 140k tokens | /clear to reset context |
Both wait for idle. Configure via session.setAutoCompact() / session.setAutoClear().
Ralph / Todo Tracking
Detects Ralph loops and todos inside Claude sessions. Disabled by default but auto-enables when Ralph-related patterns are detected (promise tags, TodoWrite, iteration patterns, etc.). See ralph-tracker.ts:shouldAutoEnable() for the full pattern list.
Auto-Configuration from Ralph Plugin State: When a session starts, Claudeman reads .claude/ralph-loop.local.md to auto-configure:
---
enabled: true
iteration: 5
max-iterations: 50
completion-promise: "COMPLETE"
---
Priority: 1) .claude/ralph-loop.local.md (official Ralph plugin state), 2) CLAUDE.md <promise> tags (fallback). See src/ralph-config.ts.
Completion Detection (multi-strategy):
- 1st occurrence of
<promise>PHRASE</promise>: Stores as expected phrase (likely in prompt) - 2nd occurrence: Emits
completionDetectedevent (actual completion) - Bare phrase detection: Also detects phrase without tags once expected phrase is known
- All complete detection: When "All X files/tasks created/completed" detected, marks all todos complete and emits completion
- If loop is already active (via
/ralph-loop:ralph-loop): Emits immediately on first occurrence
Session Lifecycle: Each session has its own independent tracker:
- New session → Fresh tracker (no carryover)
- Close tab → Tracker state cleared, UI panel hides
tracker.reset()→ Clears todos/state, keeps enabled statustracker.fullReset()→ Complete reset to initial statetracker.configure({ enabled?, completionPhrase?, maxIterations? })→ Partial config update
API:
GET /api/sessions/:id/ralph-state- Get loop state and todosPOST /api/sessions/:id/ralph-config- Configure tracker:{ enabled: boolean }- Enable/disable{ reset: true }- Soft reset (keep enabled){ reset: "full" }- Full reset
Terminal Display Fix
Tab switch/new session fix: clear xterm → write buffer → resize PTY → Ctrl+L redraw. Uses pendingCtrlL Set, triggered on session:idle/session:working events.
SSE Events
All events broadcast to /api/events with format: { type: string, sessionId?: string, data: any }.
Event prefixes: session:, task:, respawn:, spawn:, subagent:, hook:, scheduled:, case:, screen:, init.
Key events (see app.js:handleSSEEvent()):
session:idle,session:working- Status indicatorssession:terminal,session:clearTerminal- Terminal contentsession:ralphLoopUpdate,session:ralphTodoUpdate,session:ralphCompletionDetected- Ralph trackingrespawn:detectionUpdate- Idle detection statusspawn:queued,spawn:started,spawn:completed,spawn:failed- Agent lifecyclesubagent:discovered,subagent:tool_call,subagent:progress,subagent:message,subagent:completed- Claude Code background agentshook:idle_prompt,hook:permission_prompt,hook:elicitation_dialog,hook:stop- Claude Code hooks
Run Summary
Per-session event tracking for "what happened while you were away" view. Click the chart icon (📊) on any session tab to view.
Tracked Events: session start/stop, respawn cycles, state changes, idle/working transitions, token milestones (every 50k), auto-compact/clear, Ralph completions, AI check results, hook events, errors/warnings, state stuck warnings (>10min same state).
Stats: respawn cycles, peak tokens, active time, idle time, error/warning counts.
Storage: In-memory only (not persisted). Fresh tracker created per session; cleared when session is deleted.
Implementation: RunSummaryTracker class in src/run-summary.ts, integrated via setupSessionListeners() and setupRespawnListeners() in server.ts.
Frontend (app.js)
Vanilla JS + xterm.js. 60fps rendering: server batches terminal data every 16ms, client uses requestAnimationFrame to batch xterm.js writes.
HTTPS & Browser Notifications
HTTPS: The --https flag generates/reuses self-signed certificates in ~/.claudeman/certs/. Required for the Web Notification API.
Notifications (NotificationManager in app.js): In-app drawer, tab title flashing, Web Notification API (rate limited 3s), audio alerts (critical only), tab blinking (red=action, yellow=idle).
Hook Event Data: /api/hook-event forwards data field into SSE broadcast. Hook events: permission_prompt, elicitation_dialog, idle_prompt, stop.
State Store
Writes debounced (500ms) to ~/.claudeman/state.json via persistSessionState() on every meaningful change.
Per-session fields stored (SessionState in types.ts):
id,pid,status,name,mode- Core identityworkingDir,createdAt,lastActivityAt- Location and timestampsautoClearEnabled/Threshold,autoCompactEnabled/Threshold/Prompt- Context managementralphEnabled,ralphCompletionPhrase- Ralph tracker staterespawnEnabled,respawnConfig- Respawn controller statetotalCost,inputTokens,outputTokens- Token trackingparentAgentId,childAgentIds- Spawn agent tree
CLI commands (claudeman status/session list) read from state.json to display web-managed sessions.
TypeScript Config
Module resolution: NodeNext. Target: ES2022. Strict mode enabled with all additional strictness flags (noUnusedLocals, noUnusedParameters, noImplicitReturns, noFallthroughCasesInSwitch, etc.). No ESLint/Prettier configured - rely on TypeScript strict mode.
TUI uses React JSX (jsx: react-jsx, jsxImportSource: react) for Ink components.
Adding New Features
- API endpoint: Add types in
types.ts, route inserver.ts:buildServer(), usecreateErrorResponse()for errors - SSE event: Emit via
broadcast()in server.ts, handle inapp.js:handleSSEEvent()switch - Session event: Add to
SessionEventsinterface insession.ts, emit viathis.emit(), subscribe in server.ts, handle in frontend - Session setting: Add field to
SessionStateintypes.ts, include insession.toState(), callthis.persistSessionState(session)in server.ts after the change - MCP tool: Add tool definition in
mcp-server.tsusingserver.tool(), useapiRequest()to call Claudeman REST API - New test file: Create
test/<name>.test.ts, pick unique port (next available: 3127+), add to port allocation comment above
API Error Codes
Use createErrorResponse(code, details?) from types.ts:
| Code | Use Case |
|---|---|
NOT_FOUND |
Session/resource doesn't exist |
INVALID_INPUT |
Bad request parameters |
SESSION_BUSY |
Session is currently processing |
OPERATION_FAILED |
Action couldn't complete |
ALREADY_EXISTS |
Duplicate resource |
INTERNAL_ERROR |
Unexpected server error |
Session Lifecycle & Cleanup
- Limit: Web server:
MAX_CONCURRENT_SESSIONS = 50(server.ts:56), UI tab limit: 20, CLI default: 5 (types.ts:DEFAULT_CONFIG) - Kill (
killScreen()): child PIDs → process group → screen quit → SIGKILL - Ghost discovery:
reconcileScreens()finds orphaned screens on startup - Cleanup (
cleanupSession()): stops respawn, clears buffers/timers, kills screen, removes fromstate.json - State sync: Every session create/delete/update calls
persistSessionState()which writes full state (including respawn config from controller) tostate.json - Recovery on restart: Server reads
state.jsonfirst (has all settings), falls back toscreens.jsonfor any sessions not found. Settings (auto-compact, auto-clear, respawn config, Ralph state) restored to live session objects after screen reattachment.
TUI (WIP)
Ink/React-based TUI in src/tui/. Client to the web server, uses /api/* endpoints and attaches to screens via GNU screen. Not fully implemented yet.
Buffer Limits
| Buffer | Max Size | Trim To |
|---|---|---|
| Terminal | 2MB | 1.5MB |
| Text output | 1MB | 768KB |
| Messages | 1000 | 800 |
| Line buffer | 64KB | (flushed every 100ms) |
| Respawn buffer | 1MB | 512KB |
Tab switch uses tail=256KB for fast initial load, then chunked 64KB writes via requestAnimationFrame.
API Routes
All routes defined in server.ts:buildServer(). Key endpoint groups:
/api/events- SSE stream |/api/status- Full app state/api/sessions- CRUD +/input,/resize,/interactive/api/sessions/:id/respawn/*- Start/stop/enable/config respawn controller/api/sessions/:id/ralph-*- Ralph tracker config and state/api/sessions/:id/auto-compact,/auto-clear- Token threshold settings/api/quick-start- Create case + start session ({mode?: 'claude'|'shell'})/api/cases,/api/screens- Case and screen management/api/spawn/*- Agent lifecycle (list, status, result, messages, cancel, trigger)/api/subagents- List/get/kill Claude Code background agents, get transcripts/api/sessions/:id/subagents- Get subagents for a specific session's working directory/api/sessions/:id/run-summary- Get run summary (events, stats) for "what happened while away"/api/hook-event- Claude Code hook callbacks ({event, sessionId, data?})
State Files
| File | Purpose |
|---|---|
~/.claudeman/state.json |
Full session state (all settings, tokens, respawn config, Ralph state), tasks, app config |
~/.claudeman/state-inner.json |
Ralph loop/todo state per session (separate to reduce writes) |
~/.claudeman/screens.json |
Screen session metadata (for recovery after restart) |
~/.claudeman/settings.json |
User preferences (lastUsedCase, custom template path, subagentTrackingEnabled) |
~/.claudeman/certs/ |
Self-signed TLS certificates for --https mode |
Recovery: On restart, sessions restored from state.json (primary) with screens.json as fallback. All settings re-applied to live sessions. Cases created in ~/claudeman-cases/ by default.
CLAUDE.md Templates
New cases get a CLAUDE.md generated from src/templates/case-template.md (bundled with the project). Template resolution order:
- Custom path from
~/.claudeman/settings.json(defaultClaudeMdPathfield) - Bundled
case-template.md(copied todist/templates/during build) - Minimal fallback (if bundled template is missing)
Placeholders replaced:
[PROJECT_NAME]→ Case name[PROJECT_DESCRIPTION]→ Description[DATE]→ Current date (YYYY-MM-DD)
Screen Session Manager (CLI Tool)
./scripts/screen-manager.sh - Interactive bash tool for managing screen sessions. Commands: list, attach N, kill N,M, kill-all, info N. Requires jq and screen.
Web UI Keyboard Shortcuts
| Shortcut | Action |
|---|---|
Ctrl+Enter |
Quick-start session |
Ctrl+W |
Close session |
Ctrl+Tab |
Next session |
Ctrl+K |
Kill all sessions |
Ctrl+L |
Clear terminal |
Documentation
docs/respawn-state-machine.md- Respawn controller states, idle detection, auto-acceptdocs/spawn-protocol.md- Spawn1337 agent protocol, MCP tools, resource governancedocs/ralph-wiggum-guide.md- Ralph Wiggum loop guide (plugin reference, prompt templates)docs/claude-code-hooks-reference.md- Claude Code hooks documentation
Ralph Wiggum Loops
Core Pattern: <promise>PHRASE</promise> - The completion signal that tells the loop to stop.
Skill Commands:
/ralph-loop:ralph-loop # Start Ralph Loop in current session
/ralph-loop:cancel-ralph # Cancel active Ralph Loop
/ralph-loop:help # Show help and usage
The RalphTracker class (src/ralph-tracker.ts) detects Ralph patterns in Claude output and tracks loop state, todos, and completion phrases. It auto-enables when Ralph-related patterns are detected.