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:
arkon
2026-01-25 18:09:25 +01:00
co-authored by Claude Opus 4.5
parent 8094a756c6
commit 0d22d19645
6 changed files with 102 additions and 36 deletions
+36 -28
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+2
View File
@@ -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(),
+16
View File
@@ -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
View File
@@ -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> {