mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-09 00:49:41 +02:00
docs: improve CLAUDE.md structure and discoverability
- Move COM shorthand to prominent position after safety warning - Add version sync note (must match package.json) - Consolidate Key Files into 4 logical categories - Clarify next available test port (3128) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -13,11 +13,15 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|||||||
|
|
||||||
**Why this matters**: Killing your own screen terminates your session mid-work, losing context and potentially corrupting state.
|
**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
|
## 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.
|
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.1356
|
**Version**: 0.1357 (must match `package.json`)
|
||||||
|
|
||||||
**Tech Stack**: TypeScript (ES2022/NodeNext, strict mode), Node.js, Fastify, Server-Sent Events, node-pty
|
**Tech Stack**: TypeScript (ES2022/NodeNext, strict mode), Node.js, Fastify, Server-Sent Events, node-pty
|
||||||
|
|
||||||
@@ -39,8 +43,6 @@ npm install
|
|||||||
|
|
||||||
**CRITICAL**: `npm run dev` runs CLI help, NOT the web server. Use `npx tsx src/index.ts web` for development.
|
**CRITICAL**: `npm run dev` runs CLI help, NOT the web server. Use `npx tsx src/index.ts web` for development.
|
||||||
|
|
||||||
**COM Shorthand**: 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.
|
|
||||||
|
|
||||||
### Build & Clean
|
### Build & Clean
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -100,7 +102,8 @@ npx vitest run -t "should create session" # By pattern
|
|||||||
| 3120 | session-cleanup.test.ts |
|
| 3120 | session-cleanup.test.ts |
|
||||||
| 3125 | ralph-integration.test.ts |
|
| 3125 | ralph-integration.test.ts |
|
||||||
| 3127 | respawn-integration.test.ts (reserved) |
|
| 3127 | respawn-integration.test.ts (reserved) |
|
||||||
| 3128+ | Next available |
|
|
||||||
|
**Next available port**: 3128
|
||||||
|
|
||||||
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, hooks-config, ai-idle-checker, ai-plan-checker
|
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, hooks-config, ai-idle-checker, ai-plan-checker
|
||||||
|
|
||||||
@@ -196,35 +199,38 @@ claudeman reset # Reset all state
|
|||||||
|
|
||||||
### Key Files
|
### Key Files
|
||||||
|
|
||||||
|
**Core Session Management:**
|
||||||
| File | Purpose |
|
| File | Purpose |
|
||||||
|------|---------|
|
|------|---------|
|
||||||
| `src/session.ts` | Core PTY wrapper for Claude CLI. Modes: `runPrompt()`, `startInteractive()`, `startShell()` |
|
| `src/session.ts` | Core PTY wrapper for Claude CLI. Modes: `runPrompt()`, `startInteractive()`, `startShell()` |
|
||||||
| `src/respawn-controller.ts` | State machine for autonomous session cycling |
|
|
||||||
| `src/ai-idle-checker.ts` | Spawns fresh Claude session to analyze terminal output for IDLE/WORKING verdict |
|
|
||||||
| `src/ai-plan-checker.ts` | Spawns fresh Claude session to detect plan mode approval prompts for auto-accept |
|
|
||||||
| `src/screen-manager.ts` | GNU screen persistence, ghost discovery, 4-strategy kill |
|
| `src/screen-manager.ts` | GNU screen persistence, ghost discovery, 4-strategy kill |
|
||||||
| `src/ralph-tracker.ts` | Detects `<promise>PHRASE</promise>`, todos, loop status in output |
|
| `src/session-manager.ts` | Session lifecycle, task assignment, cleanup |
|
||||||
| `src/ralph-config.ts` | Parses `.claude/ralph-loop.local.md` and CLAUDE.md for Ralph config |
|
|
||||||
| `src/task-tracker.ts` | Parses background task output (agent IDs, status) from Claude CLI |
|
|
||||||
| `src/session-manager.ts` | Manages session lifecycle, task assignment, and cleanup |
|
|
||||||
| `src/state-store.ts` | JSON persistence to `~/.claudeman/` with debounced writes |
|
| `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 |
|
||||||
|
|
||||||
|
**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/server.ts` | Fastify REST API + SSE at `/api/events` |
|
||||||
| `src/web/public/app.js` | Frontend: SSE handling, xterm.js, tab management |
|
| `src/web/public/app.js` | Frontend: SSE handling, xterm.js, tab management |
|
||||||
| `src/tui/App.tsx` | TUI main component: tabs, terminal viewport, status bar (Ink/React) |
|
| `src/tui/App.tsx` | TUI main component (Ink/React) |
|
||||||
| `src/tui/components/*.tsx` | TUI components: StartScreen, TabBar, TerminalView, StatusBar, RalphPanel, HelpOverlay |
|
| `src/tui/DirectAttach.ts` | Full-screen console attach with tab switching |
|
||||||
| `src/tui/hooks/useSessionManager.ts` | TUI session state, screen polling, input handling |
|
|
||||||
| `src/hooks-config.ts` | Generates .claude/settings.local.json with Claude Code hooks for desktop notifications |
|
|
||||||
| `src/types.ts` | All TypeScript interfaces |
|
|
||||||
| `src/templates/claude-md.ts` | CLAUDE.md template generation with placeholder support |
|
|
||||||
| `src/templates/case-template.md` | Default CLAUDE.md template for new cases (with placeholders) |
|
|
||||||
| `src/spawn-types.ts` | Types, YAML parser, factory functions for spawn1337 protocol |
|
|
||||||
| `src/spawn-detector.ts` | Detects `<spawn1337>` tags in terminal output (legacy, replaced by MCP) |
|
|
||||||
| `src/spawn-orchestrator.ts` | Full agent lifecycle: spawn, monitor, budget, queue, cleanup |
|
|
||||||
| `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/subagent-watcher.ts` | Monitors Claude Code background agents in `~/.claude/projects/*/subagents/*.jsonl` |
|
|
||||||
| `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
|
### Data Flow
|
||||||
|
|
||||||
@@ -261,7 +267,9 @@ Monitors Claude Code's internal background agents (the `Task` tool) in real-time
|
|||||||
|
|
||||||
**Status lifecycle**: `active` → `idle` (30s no activity) → `completed` (process exited or file stale)
|
**Status lifecycle**: `active` → `idle` (30s no activity) → `completed` (process exited or file stale)
|
||||||
|
|
||||||
Implementation: `src/subagent-watcher.ts` - singleton `subagentWatcher` started on server boot.
|
**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
|
### Session Modes
|
||||||
|
|
||||||
@@ -532,7 +540,7 @@ All routes defined in `server.ts:buildServer()`. Key endpoint groups:
|
|||||||
| `~/.claudeman/state.json` | Full session state (all settings, tokens, respawn config, Ralph state), tasks, app config |
|
| `~/.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/state-inner.json` | Ralph loop/todo state per session (separate to reduce writes) |
|
||||||
| `~/.claudeman/screens.json` | Screen session metadata (for recovery after restart) |
|
| `~/.claudeman/screens.json` | Screen session metadata (for recovery after restart) |
|
||||||
| `~/.claudeman/settings.json` | User preferences (lastUsedCase, custom template path) |
|
| `~/.claudeman/settings.json` | User preferences (lastUsedCase, custom template path, subagentTrackingEnabled) |
|
||||||
| `~/.claudeman/certs/` | Self-signed TLS certificates for `--https` mode |
|
| `~/.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.
|
**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.
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "claudeman",
|
"name": "claudeman",
|
||||||
"version": "0.1356",
|
"version": "0.1357",
|
||||||
"description": "The missing control plane for Claude Code - run 20 autonomous agents with real-time monitoring and session persistence",
|
"description": "The missing control plane for Claude Code - run 20 autonomous agents with real-time monitoring and session persistence",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
|
|||||||
+11
-4
@@ -102,7 +102,7 @@ export class SubagentWatcher extends EventEmitter {
|
|||||||
private idleTimers = new Map<string, NodeJS.Timeout>();
|
private idleTimers = new Map<string, NodeJS.Timeout>();
|
||||||
private pollInterval: NodeJS.Timeout | null = null;
|
private pollInterval: NodeJS.Timeout | null = null;
|
||||||
private livenessInterval: NodeJS.Timeout | null = null;
|
private livenessInterval: NodeJS.Timeout | null = null;
|
||||||
private isRunning = false;
|
private _isRunning = false;
|
||||||
private knownSubagentDirs = new Set<string>();
|
private knownSubagentDirs = new Set<string>();
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -115,8 +115,8 @@ export class SubagentWatcher extends EventEmitter {
|
|||||||
* Start watching for subagent activity
|
* Start watching for subagent activity
|
||||||
*/
|
*/
|
||||||
start(): void {
|
start(): void {
|
||||||
if (this.isRunning) return;
|
if (this._isRunning) return;
|
||||||
this.isRunning = true;
|
this._isRunning = true;
|
||||||
|
|
||||||
// Initial scan
|
// Initial scan
|
||||||
this.scanForSubagents();
|
this.scanForSubagents();
|
||||||
@@ -177,11 +177,18 @@ export class SubagentWatcher extends EventEmitter {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the watcher is currently running
|
||||||
|
*/
|
||||||
|
isRunning(): boolean {
|
||||||
|
return this._isRunning;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop watching
|
* Stop watching
|
||||||
*/
|
*/
|
||||||
stop(): void {
|
stop(): void {
|
||||||
this.isRunning = false;
|
this._isRunning = false;
|
||||||
|
|
||||||
if (this.pollInterval) {
|
if (this.pollInterval) {
|
||||||
clearInterval(this.pollInterval);
|
clearInterval(this.pollInterval);
|
||||||
|
|||||||
@@ -2964,6 +2964,7 @@ class ClaudemanApp {
|
|||||||
document.getElementById('appSettingsShowSystemStats').checked = settings.showSystemStats ?? true;
|
document.getElementById('appSettingsShowSystemStats').checked = settings.showSystemStats ?? true;
|
||||||
document.getElementById('appSettingsShowTokenCount').checked = settings.showTokenCount ?? true;
|
document.getElementById('appSettingsShowTokenCount').checked = settings.showTokenCount ?? true;
|
||||||
document.getElementById('appSettingsShowMonitor').checked = settings.showMonitor ?? true;
|
document.getElementById('appSettingsShowMonitor').checked = settings.showMonitor ?? true;
|
||||||
|
document.getElementById('appSettingsSubagentTracking').checked = settings.subagentTrackingEnabled ?? true;
|
||||||
// Claude CLI settings
|
// Claude CLI settings
|
||||||
const claudeModeSelect = document.getElementById('appSettingsClaudeMode');
|
const claudeModeSelect = document.getElementById('appSettingsClaudeMode');
|
||||||
const allowedToolsRow = document.getElementById('allowedToolsRow');
|
const allowedToolsRow = document.getElementById('allowedToolsRow');
|
||||||
@@ -3023,6 +3024,7 @@ class ClaudemanApp {
|
|||||||
showSystemStats: document.getElementById('appSettingsShowSystemStats').checked,
|
showSystemStats: document.getElementById('appSettingsShowSystemStats').checked,
|
||||||
showTokenCount: document.getElementById('appSettingsShowTokenCount').checked,
|
showTokenCount: document.getElementById('appSettingsShowTokenCount').checked,
|
||||||
showMonitor: document.getElementById('appSettingsShowMonitor').checked,
|
showMonitor: document.getElementById('appSettingsShowMonitor').checked,
|
||||||
|
subagentTrackingEnabled: document.getElementById('appSettingsSubagentTracking').checked,
|
||||||
// Claude CLI settings
|
// Claude CLI settings
|
||||||
claudeMode: document.getElementById('appSettingsClaudeMode').value,
|
claudeMode: document.getElementById('appSettingsClaudeMode').value,
|
||||||
allowedTools: document.getElementById('appSettingsAllowedTools').value.trim(),
|
allowedTools: document.getElementById('appSettingsAllowedTools').value.trim(),
|
||||||
|
|||||||
@@ -536,6 +536,22 @@
|
|||||||
</label>
|
</label>
|
||||||
<span class="form-hint">Show Monitor panel at bottom right</span>
|
<span class="form-hint">Show Monitor panel at bottom right</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-row form-row-switch">
|
||||||
|
<label>Enable Subagent Tracking</label>
|
||||||
|
<label class="switch">
|
||||||
|
<input type="checkbox" id="appSettingsSubagentTracking" checked>
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
<span class="form-hint">Monitor Claude Code background agents in real-time</span>
|
||||||
|
</div>
|
||||||
|
<div class="form-row form-row-switch">
|
||||||
|
<label>Show Subagents Panel</label>
|
||||||
|
<label class="switch">
|
||||||
|
<input type="checkbox" id="appSettingsShowSubagents" checked>
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
<span class="form-hint">Show the Subagents panel (independent from Monitor)</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Claude CLI Tab -->
|
<!-- Claude CLI Tab -->
|
||||||
<div class="modal-tab-content hidden" id="settings-claude">
|
<div class="modal-tab-content hidden" id="settings-claude">
|
||||||
|
|||||||
+36
-3
@@ -1454,6 +1454,17 @@ export class WebServer extends EventEmitter {
|
|||||||
mkdirSync(dir, { recursive: true });
|
mkdirSync(dir, { recursive: true });
|
||||||
}
|
}
|
||||||
writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
||||||
|
|
||||||
|
// Handle subagent tracking toggle dynamically
|
||||||
|
const subagentEnabled = settings.subagentTrackingEnabled ?? true;
|
||||||
|
if (subagentEnabled && !subagentWatcher.isRunning()) {
|
||||||
|
subagentWatcher.start();
|
||||||
|
console.log('Subagent watcher started via settings change');
|
||||||
|
} else if (!subagentEnabled && subagentWatcher.isRunning()) {
|
||||||
|
subagentWatcher.stop();
|
||||||
|
console.log('Subagent watcher stopped via settings change');
|
||||||
|
}
|
||||||
|
|
||||||
return { success: true };
|
return { success: true };
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return createErrorResponse(ApiErrorCode.OPERATION_FAILED, getErrorMessage(err));
|
return createErrorResponse(ApiErrorCode.OPERATION_FAILED, getErrorMessage(err));
|
||||||
@@ -2627,9 +2638,31 @@ export class WebServer extends EventEmitter {
|
|||||||
// Restore screen sessions from previous run
|
// Restore screen sessions from previous run
|
||||||
await this.restoreScreenSessions();
|
await this.restoreScreenSessions();
|
||||||
|
|
||||||
// Start subagent watcher for Claude Code background agent visibility
|
// Start subagent watcher for Claude Code background agent visibility (if enabled)
|
||||||
subagentWatcher.start();
|
if (this.isSubagentTrackingEnabled()) {
|
||||||
console.log('Subagent watcher started - monitoring ~/.claude/projects for background agent activity');
|
subagentWatcher.start();
|
||||||
|
console.log('Subagent watcher started - monitoring ~/.claude/projects for background agent activity');
|
||||||
|
} else {
|
||||||
|
console.log('Subagent watcher disabled by user settings');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if subagent tracking is enabled in settings (default: true)
|
||||||
|
*/
|
||||||
|
private isSubagentTrackingEnabled(): boolean {
|
||||||
|
const settingsPath = join(homedir(), '.claudeman', 'settings.json');
|
||||||
|
try {
|
||||||
|
if (existsSync(settingsPath)) {
|
||||||
|
const content = readFileSync(settingsPath, 'utf-8');
|
||||||
|
const settings = JSON.parse(content);
|
||||||
|
// Default to true if not explicitly set
|
||||||
|
return settings.subagentTrackingEnabled ?? true;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Failed to read subagent tracking setting:', err);
|
||||||
|
}
|
||||||
|
return true; // Default enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
private async restoreScreenSessions(): Promise<void> {
|
private async restoreScreenSessions(): Promise<void> {
|
||||||
|
|||||||
Reference in New Issue
Block a user