mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-09-30 12:39:42 +02:00
feat: add RespawnController for automatic Claude Code session respawning
Implements an autonomous respawn loop that keeps Claude Code productive: - Detects idle state by monitoring PTY for prompt character + timeout - Sends configurable update prompt when idle (default: "update all the docs and CLAUDE.md") - Executes /clear and /init to reset session - Cycles automatically New features: - RespawnController class with state machine (watching → update → clear → init) - REST API endpoints for respawn control (/api/sessions/:id/respawn/*) - Web UI controls: toggle, prompt config, idle timeout settings - SSE events for real-time respawn status updates - Full CLAUDE.md template with Ralph Loop instructions Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,89 +1,122 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code when working with this repository.
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Project Overview
|
||||
|
||||
- **Project Name**: Claudeman
|
||||
- **Description**: Claude Code session manager with web interface and autonomous Ralph Loop
|
||||
- **Tech Stack**: TypeScript, Node.js, Fastify, Server-Sent Events
|
||||
- **Last Updated**: 2026-01-18
|
||||
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.
|
||||
|
||||
## Architecture
|
||||
**Tech Stack**: TypeScript, Node.js, Fastify, Server-Sent Events, node-pty
|
||||
|
||||
```
|
||||
claudeman/
|
||||
├── src/
|
||||
│ ├── index.ts # CLI entry point
|
||||
│ ├── cli.ts # Commander.js CLI commands
|
||||
│ ├── types.ts # TypeScript type definitions
|
||||
│ ├── session.ts # Claude CLI subprocess wrapper
|
||||
│ ├── session-manager.ts # Session registry and lifecycle
|
||||
│ ├── task.ts # Task definitions
|
||||
│ ├── task-queue.ts # Priority queue with dependencies
|
||||
│ ├── ralph-loop.ts # Autonomous loop controller
|
||||
│ ├── state-store.ts # JSON persistence (~/.claudeman/state.json)
|
||||
│ └── web/
|
||||
│ ├── server.ts # Fastify server with SSE
|
||||
│ └── public/ # Static frontend files
|
||||
│ ├── index.html
|
||||
│ ├── styles.css
|
||||
│ └── app.js
|
||||
├── dist/ # Compiled output
|
||||
├── package.json
|
||||
└── tsconfig.json
|
||||
```
|
||||
|
||||
## Key Commands
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
# Development
|
||||
npm run build # Compile TypeScript + copy static files
|
||||
npm run build # Compile TypeScript + copy static files to dist/web/
|
||||
npm run dev # Run with tsx (no build needed)
|
||||
|
||||
# Usage
|
||||
# Production
|
||||
npm link # Make 'claudeman' globally available
|
||||
claudeman web # Start web interface on port 3000
|
||||
claudeman web -p 8080 # Custom port
|
||||
|
||||
# CLI commands
|
||||
claudeman status # Show overall status
|
||||
claudeman task add "<prompt>" --priority N
|
||||
claudeman ralph start --min-hours 4
|
||||
# CLI examples
|
||||
claudeman status # Overall status
|
||||
claudeman session start --dir /path # Start Claude session
|
||||
claudeman task add "Fix bug" --priority 5 # Add task to queue
|
||||
claudeman ralph start --min-hours 4 # Start autonomous loop
|
||||
```
|
||||
|
||||
## How It Works
|
||||
## Architecture
|
||||
|
||||
1. **Session**: Wraps `claude -p --output-format stream-json` subprocess
|
||||
2. **Web Server**: Fastify serves static files + REST API + SSE for real-time
|
||||
3. **Timed Runs**: Loop that repeatedly runs prompts until duration expires
|
||||
4. **State**: Persisted to `~/.claudeman/state.json`
|
||||
### Core Data Flow
|
||||
|
||||
1. **Session** (`src/session.ts`) spawns Claude CLI via `node-pty` with `--dangerously-skip-permissions`
|
||||
2. PTY output is buffered and parsed for JSON messages (types: `system`, `assistant`, `result`)
|
||||
3. **WebServer** (`src/web/server.ts`) broadcasts events to connected SSE clients
|
||||
4. State persists to `~/.claudeman/state.json` via **StateStore**
|
||||
|
||||
### Key Components
|
||||
|
||||
- **Session**: Wraps `claude -p --output-format stream-json` as PTY subprocess. Emits `output`, `terminal`, `message`, `completion`, `exit` events.
|
||||
- **WebServer**: Fastify server exposing REST API + SSE endpoint at `/api/events`. Manages ScheduledRuns (timed loops that repeatedly run prompts).
|
||||
- **RespawnController**: Manages automatic respawning of interactive Claude sessions. Detects idle state → sends update prompt → `/clear` → `/init` → repeats.
|
||||
- **RalphLoop**: Autonomous controller that assigns tasks to idle sessions and detects completion via `<promise>PHRASE</promise>` markers.
|
||||
- **TaskQueue**: Priority-based queue with dependency support.
|
||||
|
||||
### REST API Endpoints
|
||||
|
||||
```
|
||||
GET /api/status # Full state (sessions + scheduled + respawn)
|
||||
GET /api/sessions # List all sessions
|
||||
POST /api/sessions # Create session { workingDir }
|
||||
POST /api/sessions/:id/run # Run prompt { prompt }
|
||||
POST /api/sessions/:id/input # Send input to interactive session
|
||||
POST /api/sessions/:id/interactive-respawn # Start interactive + respawn
|
||||
|
||||
# Respawn control
|
||||
GET /api/sessions/:id/respawn # Get respawn status
|
||||
POST /api/sessions/:id/respawn/start # Start respawn controller
|
||||
POST /api/sessions/:id/respawn/stop # Stop respawn controller
|
||||
PUT /api/sessions/:id/respawn/config # Update respawn config
|
||||
|
||||
GET /api/scheduled # List scheduled runs
|
||||
POST /api/scheduled # Create { prompt, workingDir, durationMinutes }
|
||||
POST /api/cases # Create case directory with CLAUDE.md template
|
||||
```
|
||||
|
||||
### SSE Events
|
||||
|
||||
Events broadcast to `/api/events` clients:
|
||||
- `session:output`, `session:terminal`, `session:message`
|
||||
- `session:completion`, `session:exit`, `session:working`, `session:idle`
|
||||
- `scheduled:created`, `scheduled:updated`, `scheduled:log`, `scheduled:completed`
|
||||
- `respawn:started`, `respawn:stopped`, `respawn:stateChanged`
|
||||
- `respawn:cycleStarted`, `respawn:cycleCompleted`, `respawn:stepSent`, `respawn:stepCompleted`, `respawn:log`
|
||||
|
||||
## Code Patterns
|
||||
|
||||
### Session JSON Parsing
|
||||
Claude CLI outputs newline-delimited JSON with types: `system`, `assistant`, `result`
|
||||
### Claude Message Parsing
|
||||
|
||||
Claude CLI outputs newline-delimited JSON. Strip ANSI codes before parsing:
|
||||
|
||||
```typescript
|
||||
// Parse streaming JSON lines
|
||||
const msg = JSON.parse(line) as ClaudeMessage;
|
||||
if (msg.type === 'assistant' && msg.message?.content) {
|
||||
// Extract text from content blocks
|
||||
}
|
||||
const cleanLine = line.replace(/\x1b\[[0-9;]*m/g, '');
|
||||
const msg = JSON.parse(cleanLine) as ClaudeMessage;
|
||||
// msg.type: 'system' | 'assistant' | 'result'
|
||||
// msg.message?.content: Array<{ type: 'text', text: string }>
|
||||
// msg.total_cost_usd: number (on result messages)
|
||||
```
|
||||
|
||||
### SSE Broadcasting
|
||||
```typescript
|
||||
private broadcast(event: string, data: unknown): void {
|
||||
for (const client of this.sseClients) {
|
||||
client.raw.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`);
|
||||
}
|
||||
}
|
||||
### Idle Detection
|
||||
|
||||
Session detects idle state by watching for prompt character (`❯` or `\u276f`) and waiting 2 seconds without activity.
|
||||
|
||||
### Respawn Controller State Machine
|
||||
|
||||
`RespawnController` (`src/respawn-controller.ts`) cycles through states to keep Claude productive:
|
||||
|
||||
```
|
||||
WATCHING → SENDING_UPDATE → WAITING_UPDATE → SENDING_CLEAR → WAITING_CLEAR → SENDING_INIT → WAITING_INIT → WATCHING
|
||||
```
|
||||
|
||||
## Work Principles
|
||||
**Default sequence:**
|
||||
1. Detect idle (5s timeout after prompt with no activity)
|
||||
2. Send: `update all the docs and CLAUDE.md`
|
||||
3. Wait for completion (detects prompt after work stops)
|
||||
4. Send: `/clear`
|
||||
5. Send: `/init`
|
||||
6. Return to watching
|
||||
|
||||
- Full permissions granted via `.claude/settings.json`
|
||||
- Commit after every meaningful change
|
||||
- Use conventional commits: `feat:`, `fix:`, `docs:`, `refactor:`
|
||||
**Configuration options** (`RespawnConfig`):
|
||||
- `idleTimeoutMs`: How long to wait after prompt (default: 5000)
|
||||
- `updatePrompt`: Custom prompt to send (default: "update all the docs and CLAUDE.md")
|
||||
- `interStepDelayMs`: Delay between steps (default: 1000)
|
||||
- `enabled`: Toggle respawn on/off
|
||||
|
||||
### Template Generation
|
||||
|
||||
`src/templates/claude-md.ts` generates CLAUDE.md files for new cases via the `/api/cases` endpoint.
|
||||
|
||||
## Session Log
|
||||
|
||||
@@ -91,3 +124,4 @@ private broadcast(event: string, data: unknown): void {
|
||||
|------|-----------------|---------------|-------|
|
||||
| 2026-01-18 | Initial implementation | All files | Core CLI + web interface |
|
||||
| 2026-01-18 | Add web interface | src/web/* | Fastify + SSE + responsive UI |
|
||||
| 2026-01-18 | Add RespawnController | src/respawn-controller.ts, src/web/server.ts, src/types.ts | Auto-respawn loop with state machine |
|
||||
|
||||
Reference in New Issue
Block a user