mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-02 21:49:42 +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.
|
||||
|
||||
## ⚡ 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.1356
|
||||
**Version**: 0.1357 (must match `package.json`)
|
||||
|
||||
**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.
|
||||
|
||||
**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
|
||||
|
||||
```bash
|
||||
@@ -100,7 +102,8 @@ npx vitest run -t "should create session" # By pattern
|
||||
| 3120 | session-cleanup.test.ts |
|
||||
| 3125 | ralph-integration.test.ts |
|
||||
| 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
|
||||
|
||||
@@ -196,35 +199,38 @@ claudeman reset # Reset all state
|
||||
|
||||
### Key Files
|
||||
|
||||
**Core Session Management:**
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `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/ralph-tracker.ts` | Detects `<promise>PHRASE</promise>`, todos, loop status in output |
|
||||
| `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/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 |
|
||||
|
||||
**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: tabs, terminal viewport, status bar (Ink/React) |
|
||||
| `src/tui/components/*.tsx` | TUI components: StartScreen, TabBar, TerminalView, StatusBar, RalphPanel, HelpOverlay |
|
||||
| `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) |
|
||||
| `src/tui/App.tsx` | TUI main component (Ink/React) |
|
||||
| `src/tui/DirectAttach.ts` | Full-screen console attach with tab switching |
|
||||
|
||||
### 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)
|
||||
|
||||
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
|
||||
|
||||
@@ -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-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) |
|
||||
| `~/.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.
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"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",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
|
||||
+11
-4
@@ -102,7 +102,7 @@ export class SubagentWatcher extends EventEmitter {
|
||||
private idleTimers = new Map<string, NodeJS.Timeout>();
|
||||
private pollInterval: NodeJS.Timeout | null = null;
|
||||
private livenessInterval: NodeJS.Timeout | null = null;
|
||||
private isRunning = false;
|
||||
private _isRunning = false;
|
||||
private knownSubagentDirs = new Set<string>();
|
||||
|
||||
constructor() {
|
||||
@@ -115,8 +115,8 @@ export class SubagentWatcher extends EventEmitter {
|
||||
* Start watching for subagent activity
|
||||
*/
|
||||
start(): void {
|
||||
if (this.isRunning) return;
|
||||
this.isRunning = true;
|
||||
if (this._isRunning) return;
|
||||
this._isRunning = true;
|
||||
|
||||
// Initial scan
|
||||
this.scanForSubagents();
|
||||
@@ -177,11 +177,18 @@ export class SubagentWatcher extends EventEmitter {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the watcher is currently running
|
||||
*/
|
||||
isRunning(): boolean {
|
||||
return this._isRunning;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop watching
|
||||
*/
|
||||
stop(): void {
|
||||
this.isRunning = false;
|
||||
this._isRunning = false;
|
||||
|
||||
if (this.pollInterval) {
|
||||
clearInterval(this.pollInterval);
|
||||
|
||||
@@ -2964,6 +2964,7 @@ class ClaudemanApp {
|
||||
document.getElementById('appSettingsShowSystemStats').checked = settings.showSystemStats ?? true;
|
||||
document.getElementById('appSettingsShowTokenCount').checked = settings.showTokenCount ?? true;
|
||||
document.getElementById('appSettingsShowMonitor').checked = settings.showMonitor ?? true;
|
||||
document.getElementById('appSettingsSubagentTracking').checked = settings.subagentTrackingEnabled ?? true;
|
||||
// Claude CLI settings
|
||||
const claudeModeSelect = document.getElementById('appSettingsClaudeMode');
|
||||
const allowedToolsRow = document.getElementById('allowedToolsRow');
|
||||
@@ -3023,6 +3024,7 @@ class ClaudemanApp {
|
||||
showSystemStats: document.getElementById('appSettingsShowSystemStats').checked,
|
||||
showTokenCount: document.getElementById('appSettingsShowTokenCount').checked,
|
||||
showMonitor: document.getElementById('appSettingsShowMonitor').checked,
|
||||
subagentTrackingEnabled: document.getElementById('appSettingsSubagentTracking').checked,
|
||||
// Claude CLI settings
|
||||
claudeMode: document.getElementById('appSettingsClaudeMode').value,
|
||||
allowedTools: document.getElementById('appSettingsAllowedTools').value.trim(),
|
||||
|
||||
@@ -536,6 +536,22 @@
|
||||
</label>
|
||||
<span class="form-hint">Show Monitor panel at bottom right</span>
|
||||
</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>
|
||||
<!-- Claude CLI Tab -->
|
||||
<div class="modal-tab-content hidden" id="settings-claude">
|
||||
|
||||
+36
-3
@@ -1454,6 +1454,17 @@ export class WebServer extends EventEmitter {
|
||||
mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
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 };
|
||||
} catch (err) {
|
||||
return createErrorResponse(ApiErrorCode.OPERATION_FAILED, getErrorMessage(err));
|
||||
@@ -2627,9 +2638,31 @@ export class WebServer extends EventEmitter {
|
||||
// Restore screen sessions from previous run
|
||||
await this.restoreScreenSessions();
|
||||
|
||||
// Start subagent watcher for Claude Code background agent visibility
|
||||
subagentWatcher.start();
|
||||
console.log('Subagent watcher started - monitoring ~/.claude/projects for background agent activity');
|
||||
// Start subagent watcher for Claude Code background agent visibility (if enabled)
|
||||
if (this.isSubagentTrackingEnabled()) {
|
||||
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> {
|
||||
|
||||
Reference in New Issue
Block a user