chore: rename Claudeman to Codeman

Full product rename across 109 files (~834 occurrences):
- Env vars: CLAUDEMAN_* → CODEMAN_*
- Data dirs: ~/.claudeman/ → ~/.codeman/, ~/claudeman-cases/ → ~/codeman-cases/
- tmux prefix: claudeman- → codeman-
- localStorage: claudeman-* → codeman-*
- Package/CLI: claudeman → codeman
- GitHub repo: Ark0N/Claudeman → Ark0N/Codeman
- systemd service: claudeman-web → codeman-web
- Class: ClaudemanApp → CodemanApp

Migration infrastructure for seamless transition:
- state-store.ts: auto-migrates data directories on startup
- tmux-manager.ts: dual-prefix detection (legacy claudeman- sessions)
- app.js: localStorage key migration (preserves old keys)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
arkon
2026-02-26 16:44:34 +01:00
co-authored by Claude Opus 4.6
parent 3ccd22161c
commit 3795c45cc1
109 changed files with 711 additions and 679 deletions
+3 -3
View File
@@ -149,7 +149,7 @@ describe('AiIdleChecker', () => {
// Verify tmux was spawned with correct args
expect(mockedSpawn).toHaveBeenCalledWith(
'tmux',
expect.arrayContaining(['new-session', '-d', '-s', expect.stringContaining('claudeman-aicheck-')]),
expect.arrayContaining(['new-session', '-d', '-s', expect.stringContaining('codeman-aicheck-')]),
expect.objectContaining({ detached: true, stdio: 'ignore' })
);
});
@@ -163,7 +163,7 @@ describe('AiIdleChecker', () => {
// First call should try to kill existing session
expect(mockedExecSync).toHaveBeenCalledWith(
expect.stringContaining('tmux kill-session -t "claudeman-aicheck-'),
expect.stringContaining('tmux kill-session -t "codeman-aicheck-'),
expect.any(Object)
);
});
@@ -176,7 +176,7 @@ describe('AiIdleChecker', () => {
await checkPromise;
expect(mockedWriteFileSync).toHaveBeenCalledWith(
expect.stringContaining('claudeman-aicheck-'),
expect.stringContaining('codeman-aicheck-'),
''
);
});
+2 -2
View File
@@ -537,7 +537,7 @@ describe('API Response Structures', () => {
it('should validate case info', () => {
const caseInfo: CaseInfo = {
name: 'my-project',
path: '/home/user/claudeman-cases/my-project',
path: '/home/user/codeman-cases/my-project',
hasClaudeMd: true,
};
@@ -549,7 +549,7 @@ describe('API Response Structures', () => {
it('should handle optional hasClaudeMd', () => {
const caseInfo: CaseInfo = {
name: 'new-project',
path: '/home/user/claudeman-cases/new-project',
path: '/home/user/codeman-cases/new-project',
};
expect(caseInfo.hasClaudeMd).toBeUndefined();
+1 -1
View File
@@ -1,7 +1,7 @@
/**
* @fileoverview Tests for buffer management and memory limits
*
* Tests the buffer management strategies used in Claudeman sessions
* Tests the buffer management strategies used in Codeman sessions
* for handling large terminal output and message storage.
*/
+6 -6
View File
@@ -318,7 +318,7 @@ describe('CLI Command Parsing', () => {
describe('Help Text Generation', () => {
const generateHelp = (command: string, description: string, options: string[]): string => {
let help = `Usage: claudeman ${command}\n\n`;
let help = `Usage: codeman ${command}\n\n`;
help += `${description}\n`;
if (options.length > 0) {
help += '\nOptions:\n';
@@ -331,7 +331,7 @@ describe('CLI Command Parsing', () => {
it('should generate basic help', () => {
const help = generateHelp('status', 'Show overall status', []);
expect(help).toContain('Usage: claudeman status');
expect(help).toContain('Usage: codeman status');
expect(help).toContain('Show overall status');
});
@@ -724,8 +724,8 @@ describe('CLI Configuration', () => {
maxConcurrentSessions: 5,
defaultPort: 3000,
defaultHost: '0.0.0.0',
casesDirectory: '~/claudeman-cases',
stateDirectory: '~/.claudeman',
casesDirectory: '~/codeman-cases',
stateDirectory: '~/.codeman',
};
const expandPath = (path: string): string => {
@@ -742,8 +742,8 @@ describe('CLI Configuration', () => {
});
it('should expand home directory paths', () => {
expect(expandPath('~/claudeman-cases')).toBe('/home/user/claudeman-cases');
expect(expandPath('~/.claudeman')).toBe('/home/user/.claudeman');
expect(expandPath('~/codeman-cases')).toBe('/home/user/codeman-cases');
expect(expandPath('~/.codeman')).toBe('/home/user/.codeman');
});
it('should not modify absolute paths', () => {
+2 -2
View File
@@ -5,7 +5,7 @@ import { join } from 'node:path';
import { homedir } from 'node:os';
const TEST_PORT = 3110;
const CASES_DIR = join(homedir(), 'claudeman-cases');
const CASES_DIR = join(homedir(), 'codeman-cases');
describe('Edge Cases and Error Handling', () => {
let server: WebServer;
@@ -349,7 +349,7 @@ describe('Concurrent Session Handling', () => {
const { join } = await import('node:path');
const { homedir } = await import('node:os');
for (const name of createdCases) {
const path = join(homedir(), 'claudeman-cases', name);
const path = join(homedir(), 'codeman-cases', name);
if (existsSync(path)) {
rmSync(path, { recursive: true, force: true });
}
+3 -3
View File
@@ -1,5 +1,5 @@
/**
* File Link Click Tests for Claudeman Web UI
* File Link Click Tests for Codeman Web UI
*
* Tests that file paths displayed in terminal output are clickable
* and open the log viewer window correctly.
@@ -88,7 +88,7 @@ describe('File Link Click Tests', () => {
closeBrowser();
// Create test directory and log file
testDir = join(tmpdir(), `claudeman-link-test-${Date.now()}`);
testDir = join(tmpdir(), `codeman-link-test-${Date.now()}`);
mkdirSync(testDir, { recursive: true });
testLogFile = join(testDir, 'test.log');
writeFileSync(testLogFile, '=== Test Log Started ===\n');
@@ -102,7 +102,7 @@ describe('File Link Click Tests', () => {
browser(`open ${baseUrl}`);
await new Promise(r => setTimeout(r, 2000));
const title = browserJson<{ title: string }>('get title');
browserAvailable = title.title === 'Claudeman';
browserAvailable = title.title === 'Codeman';
} catch (e) {
console.warn('Browser not available, skipping browser tests:', (e as Error).message);
browserAvailable = false;
+5 -5
View File
@@ -54,8 +54,8 @@ describe('generateHooksConfig', () => {
const config = generateHooksConfig();
const notifHooks = config.hooks.Notification as Array<{ hooks: Array<{ command: string }> }>;
const cmd = notifHooks[0].hooks[0].command;
expect(cmd).toContain('$CLAUDEMAN_API_URL');
expect(cmd).toContain('$CLAUDEMAN_SESSION_ID');
expect(cmd).toContain('$CODEMAN_API_URL');
expect(cmd).toContain('$CODEMAN_SESSION_ID');
expect(cmd).not.toContain('localhost');
});
@@ -99,7 +99,7 @@ describe('generateHooksConfig', () => {
});
describe('writeHooksConfig', () => {
const testDir = join(tmpdir(), 'claudeman-hooks-test-' + Date.now());
const testDir = join(tmpdir(), 'codeman-hooks-test-' + Date.now());
beforeEach(() => {
if (!existsSync(testDir)) {
@@ -648,8 +648,8 @@ describe('Hook Config Generation - Extended', () => {
const config = generateHooksConfig();
const notifHooks = config.hooks.Notification as Array<{ hooks: Array<{ command: string }> }>;
const cmd = notifHooks[0].hooks[0].command;
expect(cmd).toContain('$CLAUDEMAN_API_URL');
expect(cmd).toContain('$CLAUDEMAN_SESSION_ID');
expect(cmd).toContain('$CODEMAN_API_URL');
expect(cmd).toContain('$CODEMAN_SESSION_ID');
});
it('should generate POST curl commands', () => {
+1 -1
View File
@@ -96,7 +96,7 @@ async function main() {
page.on('console', msg => consoleLogs.push(`[${msg.type()}] ${msg.text()}`));
try {
console.log('Opening Claudeman...');
console.log('Opening Codeman...');
await page.goto(BASE);
await page.waitForSelector('.xterm-screen', { timeout: 10000 });
await page.waitForTimeout(2000);
+1 -1
View File
@@ -5,7 +5,7 @@ import { join } from 'node:path';
import { homedir } from 'node:os';
const TEST_PORT = 3115;
const CASES_DIR = join(homedir(), 'claudeman-cases');
const CASES_DIR = join(homedir(), 'codeman-cases');
/**
* Integration tests for complete user flows
+2 -2
View File
@@ -149,9 +149,9 @@ async function main() {
// Enable local echo
await page.evaluate(() => {
const s = JSON.parse(localStorage.getItem('claudeman-app-settings') || '{}');
const s = JSON.parse(localStorage.getItem('codeman-app-settings') || '{}');
s.localEchoEnabled = true;
localStorage.setItem('claudeman-app-settings', JSON.stringify(s));
localStorage.setItem('codeman-app-settings', JSON.stringify(s));
window.app?._updateLocalEchoState?.();
});
+2 -2
View File
@@ -117,9 +117,9 @@ async function main() {
// Enable local echo
await page.evaluate(() => {
const s = JSON.parse(localStorage.getItem('claudeman-app-settings') || '{}');
const s = JSON.parse(localStorage.getItem('codeman-app-settings') || '{}');
s.localEchoEnabled = true;
localStorage.setItem('claudeman-app-settings', JSON.stringify(s));
localStorage.setItem('codeman-app-settings', JSON.stringify(s));
window.app?._updateLocalEchoState?.();
});
+3 -3
View File
@@ -120,9 +120,9 @@ async function main() {
// Enable local echo
await page.evaluate(() => {
const s = JSON.parse(localStorage.getItem('claudeman-app-settings') || '{}');
const s = JSON.parse(localStorage.getItem('codeman-app-settings') || '{}');
s.localEchoEnabled = true;
localStorage.setItem('claudeman-app-settings', JSON.stringify(s));
localStorage.setItem('codeman-app-settings', JSON.stringify(s));
window.app?._updateLocalEchoState?.();
});
@@ -307,7 +307,7 @@ async function main() {
await page.keyboard.type('will-be-lost', { delay: 20 });
await page.waitForTimeout(200);
const lsBefore = await page.evaluate(() => localStorage.getItem('claudeman_local_echo_pending'));
const lsBefore = await page.evaluate(() => localStorage.getItem('codeman_local_echo_pending'));
if (!lsBefore) pass('localStorage not written (persist is no-op)');
else fail('localStorage written', `value="${lsBefore}"`);
+3 -3
View File
@@ -227,7 +227,7 @@ async function main() {
try {
// ── SETUP ──
console.log('Opening Claudeman...');
console.log('Opening Codeman...');
await page.goto(BASE, { waitUntil: 'domcontentloaded' });
await page.waitForSelector('.xterm-screen', { timeout: 10000 });
await page.waitForTimeout(2000);
@@ -235,9 +235,9 @@ async function main() {
// Enable local echo via settings
console.log('Enabling local echo...');
await page.evaluate(() => {
const settings = JSON.parse(localStorage.getItem('claudeman-app-settings') || '{}');
const settings = JSON.parse(localStorage.getItem('codeman-app-settings') || '{}');
settings.localEchoEnabled = true;
localStorage.setItem('claudeman-app-settings', JSON.stringify(settings));
localStorage.setItem('codeman-app-settings', JSON.stringify(settings));
window.app?._updateLocalEchoState?.();
});
await page.waitForTimeout(300);
+2 -2
View File
@@ -126,9 +126,9 @@ async function main() {
// Enable local echo
await page.evaluate(() => {
const s = JSON.parse(localStorage.getItem('claudeman-app-settings') || '{}');
const s = JSON.parse(localStorage.getItem('codeman-app-settings') || '{}');
s.localEchoEnabled = true;
localStorage.setItem('claudeman-app-settings', JSON.stringify(s));
localStorage.setItem('codeman-app-settings', JSON.stringify(s));
window.app?._updateLocalEchoState?.();
});
+2 -2
View File
@@ -144,7 +144,7 @@ async function main() {
try {
// ── SETUP ──
console.log('Opening Claudeman...');
console.log('Opening Codeman...');
await page.goto(BASE, { waitUntil: 'domcontentloaded' });
await page.waitForSelector('.xterm-screen', { timeout: 10000 });
await page.waitForTimeout(2500);
@@ -152,7 +152,7 @@ async function main() {
// Enable local echo
console.log('Enabling local echo...');
await page.evaluate(() => {
const key = window.app?.getSettingsStorageKey?.() || 'claudeman-app-settings';
const key = window.app?.getSettingsStorageKey?.() || 'codeman-app-settings';
const settings = JSON.parse(localStorage.getItem(key) || '{}');
settings.localEchoEnabled = true;
localStorage.setItem(key, JSON.stringify(settings));
+4 -4
View File
@@ -241,9 +241,9 @@ async function main() {
// Enable local echo
await page.evaluate(() => {
const s = JSON.parse(localStorage.getItem('claudeman-app-settings') || '{}');
const s = JSON.parse(localStorage.getItem('codeman-app-settings') || '{}');
s.localEchoEnabled = true;
localStorage.setItem('claudeman-app-settings', JSON.stringify(s));
localStorage.setItem('codeman-app-settings', JSON.stringify(s));
window.app?._updateLocalEchoState?.();
});
@@ -916,9 +916,9 @@ async function main() {
await page.evaluate((id) => document.querySelector(`.session-tab[data-id="${id}"]`)?.click(), sA);
await page.waitForTimeout(2000);
await page.evaluate(() => {
const s = JSON.parse(localStorage.getItem('claudeman-app-settings') || '{}');
const s = JSON.parse(localStorage.getItem('codeman-app-settings') || '{}');
s.localEchoEnabled = true;
localStorage.setItem('claudeman-app-settings', JSON.stringify(s));
localStorage.setItem('codeman-app-settings', JSON.stringify(s));
window.app?._updateLocalEchoState?.();
});
await page.waitForTimeout(300);
+1 -1
View File
@@ -2,7 +2,7 @@
* @fileoverview Tests for memory leak prevention patterns
*
* These tests verify the cleanup patterns used to prevent memory leaks
* in long-running Claudeman sessions (P1 improvements from P0 fixes).
* in long-running Codeman sessions (P1 improvements from P0 fixes).
*
* Port: N/A (unit tests, no server)
*/
+2 -2
View File
@@ -1,5 +1,5 @@
/**
* Performance tests: Claudeman responsiveness under subagent load
* Performance tests: Codeman responsiveness under subagent load
*
* Measures event loop lag caused by:
* 1. SubagentWatcher processing many agent files simultaneously
@@ -112,7 +112,7 @@ describe('SubagentWatcher performance', () => {
let projectsDir: string;
beforeEach(() => {
tmpDir = mkdtempSync(join(tmpdir(), 'claudeman-perf-'));
tmpDir = mkdtempSync(join(tmpdir(), 'codeman-perf-'));
projectsDir = join(tmpDir, 'projects');
mkdirSync(projectsDir, { recursive: true });
});
+1 -1
View File
@@ -5,7 +5,7 @@ import { join } from 'node:path';
import { homedir } from 'node:os';
const TEST_PORT = 3099;
const CASES_DIR = join(homedir(), 'claudeman-cases');
const CASES_DIR = join(homedir(), 'codeman-cases');
describe('Quick Start API', () => {
let server: WebServer;
+1 -1
View File
@@ -18,7 +18,7 @@ import { join } from 'node:path';
import { homedir } from 'node:os';
const TEST_PORT = 3125;
const CASES_DIR = join(homedir(), 'claudeman-cases');
const CASES_DIR = join(homedir(), 'codeman-cases');
describe('Ralph Integration Tests', () => {
let server: WebServer;
+11 -11
View File
@@ -2,10 +2,10 @@
**Date**: 2026-01-25
**Analyzed Files**:
- `/home/arkon/default/claudeman/src/respawn-controller.ts`
- `/home/arkon/default/claudeman/src/ai-idle-checker.ts`
- `/home/arkon/default/claudeman/src/ai-plan-checker.ts`
- `/home/arkon/default/claudeman/test/respawn-controller.test.ts`
- `/home/arkon/default/codeman/src/respawn-controller.ts`
- `/home/arkon/default/codeman/src/ai-idle-checker.ts`
- `/home/arkon/default/codeman/src/ai-plan-checker.ts`
- `/home/arkon/default/codeman/test/respawn-controller.test.ts`
---
@@ -55,7 +55,7 @@ The following areas lack test coverage:
### Issue 1: E2BIG Error in ai-plan-checker.ts (HIGH)
**File**: `/home/arkon/default/claudeman/src/ai-plan-checker.ts`
**File**: `/home/arkon/default/codeman/src/ai-plan-checker.ts`
**Lines**: 341-346
**Severity**: HIGH
@@ -84,7 +84,7 @@ const claudeCmd = `cat "${this.checkPromptFile}" | claude -p ${modelArg} --outpu
### Issue 2: Missing Prompt File Cleanup on Timeout (MEDIUM)
**File**: `/home/arkon/default/claudeman/src/ai-idle-checker.ts`
**File**: `/home/arkon/default/codeman/src/ai-idle-checker.ts`
**Lines**: 392-398
**Severity**: MEDIUM
@@ -98,7 +98,7 @@ const claudeCmd = `cat "${this.checkPromptFile}" | claude -p ${modelArg} --outpu
### Issue 3: Race Condition in cancel() with Promise Resolution (MEDIUM)
**File**: `/home/arkon/default/claudeman/src/ai-idle-checker.ts`
**File**: `/home/arkon/default/codeman/src/ai-idle-checker.ts`
**Lines**: 265-279
**Severity**: MEDIUM
@@ -127,7 +127,7 @@ cancel(): void {
### Issue 4: Stale Screen Name Collision (LOW)
**File**: `/home/arkon/default/claudeman/src/ai-idle-checker.ts`, `ai-plan-checker.ts`
**File**: `/home/arkon/default/codeman/src/ai-idle-checker.ts`, `ai-plan-checker.ts`
**Lines**: 326-329 (idle), 333-336 (plan)
**Severity**: LOW
@@ -135,21 +135,21 @@ cancel(): void {
**Code**:
```typescript
this.checkScreenName = `claudeman-aicheck-${shortId}`;
this.checkScreenName = `codeman-aicheck-${shortId}`;
```
**Impact**: Very unlikely in practice since checks have cooldowns, but theoretically possible.
**Suggested Fix**: Already partially mitigated by the `timestamp` in temp file names. Could add timestamp to screen name too:
```typescript
this.checkScreenName = `claudeman-aicheck-${shortId}-${timestamp}`;
this.checkScreenName = `codeman-aicheck-${shortId}-${timestamp}`;
```
---
### Issue 5: DetectionStatus Calculation During ai_checking State (LOW)
**File**: `/home/arkon/default/claudeman/src/respawn-controller.ts`
**File**: `/home/arkon/default/codeman/src/respawn-controller.ts`
**Lines**: 759-762
**Severity**: LOW
+1 -1
View File
@@ -243,7 +243,7 @@ afterEach(() => {
The global `test/setup.ts` handles:
1. **Screen Cleanup**: Kills any orphaned `claudeman-*` screens created during tests
1. **Screen Cleanup**: Kills any orphaned `codeman-*` screens created during tests
2. **Process Cleanup**: Kills any Claude processes spawned by tests
3. **Pre-existing Protection**: Never kills screens that existed before tests started
+1 -1
View File
@@ -98,7 +98,7 @@ export class MockSession extends EventEmitter {
constructor(id: string = 'mock-session-id') {
super();
this.id = id;
this._muxName = `claudeman-test-${id.slice(0, 8)}`;
this._muxName = `codeman-test-${id.slice(0, 8)}`;
}
/** Direct PTY write (used by session.write()) */
+1 -1
View File
@@ -5,7 +5,7 @@ import { join } from 'node:path';
import { homedir } from 'node:os';
const TEST_PORT = 3120;
const CASES_DIR = join(homedir(), 'claudeman-cases');
const CASES_DIR = join(homedir(), 'codeman-cases');
/**
* Session Cleanup Tests
+19 -19
View File
@@ -280,41 +280,41 @@ describe('Session State Management', () => {
describe('Mux Session Environment', () => {
interface MuxEnv {
CLAUDEMAN_MUX: string;
CLAUDEMAN_SESSION_ID: string;
CLAUDEMAN_MUX_NAME: string;
CODEMAN_MUX: string;
CODEMAN_SESSION_ID: string;
CODEMAN_MUX_NAME: string;
}
const createMuxEnv = (sessionId: string, muxName: string): MuxEnv => ({
CLAUDEMAN_MUX: '1',
CLAUDEMAN_SESSION_ID: sessionId,
CLAUDEMAN_MUX_NAME: muxName,
CODEMAN_MUX: '1',
CODEMAN_SESSION_ID: sessionId,
CODEMAN_MUX_NAME: muxName,
});
const isClaudemanSession = (env: Record<string, string | undefined>): boolean => {
return env.CLAUDEMAN_MUX === '1';
const isCodemanSession = (env: Record<string, string | undefined>): boolean => {
return env.CODEMAN_MUX === '1';
};
it('should create valid mux environment', () => {
const env = createMuxEnv('session-123', 'claudeman-test');
expect(env.CLAUDEMAN_MUX).toBe('1');
expect(env.CLAUDEMAN_SESSION_ID).toBe('session-123');
expect(env.CLAUDEMAN_MUX_NAME).toBe('claudeman-test');
const env = createMuxEnv('session-123', 'codeman-test');
expect(env.CODEMAN_MUX).toBe('1');
expect(env.CODEMAN_SESSION_ID).toBe('session-123');
expect(env.CODEMAN_MUX_NAME).toBe('codeman-test');
});
it('should detect claudeman session', () => {
const env = createMuxEnv('session-123', 'claudeman-test');
expect(isClaudemanSession(env)).toBe(true);
it('should detect codeman session', () => {
const env = createMuxEnv('session-123', 'codeman-test');
expect(isCodemanSession(env)).toBe(true);
});
it('should detect non-claudeman session', () => {
const env = { CLAUDEMAN_MUX: '0' };
expect(isClaudemanSession(env)).toBe(false);
it('should detect non-codeman session', () => {
const env = { CODEMAN_MUX: '0' };
expect(isCodemanSession(env)).toBe(false);
});
it('should handle missing environment variable', () => {
const env = {};
expect(isClaudemanSession(env)).toBe(false);
expect(isCodemanSession(env)).toBe(false);
});
});
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* @fileoverview Global test setup for Claudeman tests
* @fileoverview Global test setup for Codeman tests
*
* SAFETY: TmuxManager has built-in test mode detection
* (via process.env.VITEST) that makes ALL shell commands no-ops.
+1 -1
View File
@@ -293,7 +293,7 @@ describe('SSE Event Types', () => {
const { join } = await import('node:path');
const { homedir } = await import('node:os');
try {
rmSync(join(homedir(), 'claudeman-cases', caseName), { recursive: true });
rmSync(join(homedir(), 'codeman-cases', caseName), { recursive: true });
} catch {}
});
});
+1 -1
View File
@@ -17,7 +17,7 @@ import type { AppState, SessionState, TaskState, RalphSessionState } from '../sr
import { StateStore, getStore } from '../src/state-store.js';
describe('StateStore', () => {
const testDir = join(tmpdir(), 'claudeman-test-' + Date.now());
const testDir = join(tmpdir(), 'codeman-test-' + Date.now());
const testFilePath = join(testDir, 'state.json');
const testInnerPath = join(testDir, 'state-inner.json');
+2 -2
View File
@@ -2,7 +2,7 @@
* @fileoverview Tests for TeamWatcher - Agent Teams filesystem polling
*
* Test port: 3150 (if server needed)
* SAFETY: Never uses port 3000, never kills w1-claudeman/w2/w3-claudeman
* SAFETY: Never uses port 3000, never kills w1-codeman/w2/w3-codeman
*/
import { mkdirSync, writeFileSync, rmSync, existsSync } from 'node:fs';
@@ -13,7 +13,7 @@ import { TeamWatcher } from '../src/team-watcher.js';
import type { TeamConfig, TeamTask, InboxMessage } from '../src/types.js';
// Unique temp dir per test run
const TEST_BASE = join(tmpdir(), `claudeman-test-teams-${randomUUID().substring(0, 8)}`);
const TEST_BASE = join(tmpdir(), `codeman-test-teams-${randomUUID().substring(0, 8)}`);
const TEAMS_DIR = join(TEST_BASE, 'teams');
const TASKS_DIR = join(TEST_BASE, 'tasks');
+7 -7
View File
@@ -12,7 +12,7 @@ import { tmpdir } from 'node:os';
import { generateClaudeMd } from '../src/templates/claude-md.js';
describe('generateClaudeMd', () => {
const testDir = join(tmpdir(), 'claudeman-template-test-' + Date.now());
const testDir = join(tmpdir(), 'codeman-template-test-' + Date.now());
beforeEach(() => {
if (!existsSync(testDir)) {
@@ -54,11 +54,11 @@ describe('generateClaudeMd', () => {
expect(result).toContain(`**Last Updated**: ${today}`);
});
it('should include Claudeman environment section', () => {
it('should include Codeman environment section', () => {
const result = generateClaudeMd('my-project');
expect(result).toContain('## Claudeman Environment');
expect(result).toContain('CLAUDEMAN_MUX=1');
expect(result).toContain('## Codeman Environment');
expect(result).toContain('CODEMAN_MUX=1');
});
it('should include work principles', () => {
@@ -146,20 +146,20 @@ About [PROJECT_NAME]: [PROJECT_DESCRIPTION]
const result = generateClaudeMd('my-project', 'desc', '/nonexistent/template.md');
// Should get default template content
expect(result).toContain('## Claudeman Environment');
expect(result).toContain('## Codeman Environment');
expect(result).toContain('**Project Name**: my-project');
});
it('should fall back to default template if custom path is empty', () => {
const result = generateClaudeMd('my-project', 'desc', '');
expect(result).toContain('## Claudeman Environment');
expect(result).toContain('## Codeman Environment');
});
it('should fall back to default template if custom path is undefined', () => {
const result = generateClaudeMd('my-project', 'desc', undefined);
expect(result).toContain('## Claudeman Environment');
expect(result).toContain('## Codeman Environment');
});
});
});
+1 -1
View File
@@ -2,7 +2,7 @@
* @fileoverview Tests for terminal output parsing utilities
*
* Tests various terminal output parsing patterns used throughout
* the Claudeman application.
* the Codeman application.
*/
import { describe, it, expect } from 'vitest';
+20 -20
View File
@@ -78,8 +78,8 @@ describe('TmuxManager (unit)', () => {
describe('getAttachArgs', () => {
it('should return attach-session args', () => {
const args = manager.getAttachArgs('claudeman-abc12345');
expect(args).toEqual(['attach-session', '-t', 'claudeman-abc12345']);
const args = manager.getAttachArgs('codeman-abc12345');
expect(args).toEqual(['attach-session', '-t', 'codeman-abc12345']);
});
});
@@ -111,7 +111,7 @@ describe('TmuxManager (unit)', () => {
beforeEach(() => {
manager.registerSession({
sessionId: 'test-id',
muxName: 'claudeman-1e571234',
muxName: 'codeman-1e571234',
pid: 12345,
createdAt: Date.now(),
workingDir: '/tmp',
@@ -145,7 +145,7 @@ describe('TmuxManager (unit)', () => {
it('should return all registered sessions as alive', async () => {
manager.registerSession({
sessionId: 'alive-1',
muxName: 'claudeman-a11ce111',
muxName: 'codeman-a11ce111',
pid: 100,
createdAt: Date.now(),
workingDir: '/tmp',
@@ -181,7 +181,7 @@ describe('TmuxManager (unit)', () => {
it('should remove session from memory in test mode', async () => {
manager.registerSession({
sessionId: 'kill-test',
muxName: 'claudeman-5e1f1111',
muxName: 'codeman-5e1f1111',
pid: 999,
createdAt: Date.now(),
workingDir: '/tmp',
@@ -194,14 +194,14 @@ describe('TmuxManager (unit)', () => {
expect(manager.getSession('kill-test')).toBeUndefined();
});
it('should allow kill when session does NOT match CLAUDEMAN_MUX_NAME', async () => {
const originalEnv = process.env.CLAUDEMAN_MUX_NAME;
process.env.CLAUDEMAN_MUX_NAME = 'claudeman-0ther1111';
it('should allow kill when session does NOT match CODEMAN_MUX_NAME', async () => {
const originalEnv = process.env.CODEMAN_MUX_NAME;
process.env.CODEMAN_MUX_NAME = 'codeman-0ther1111';
try {
manager.registerSession({
sessionId: 'other-kill-test',
muxName: 'claudeman-d1ff1111',
muxName: 'codeman-d1ff1111',
pid: 888,
createdAt: Date.now(),
workingDir: '/tmp',
@@ -219,21 +219,21 @@ describe('TmuxManager (unit)', () => {
expect(manager.getSession('other-kill-test')).toBeUndefined();
} finally {
if (originalEnv === undefined) {
delete process.env.CLAUDEMAN_MUX_NAME;
delete process.env.CODEMAN_MUX_NAME;
} else {
process.env.CLAUDEMAN_MUX_NAME = originalEnv;
process.env.CODEMAN_MUX_NAME = originalEnv;
}
}
});
it('should allow kill when CLAUDEMAN_MUX_NAME is not set', async () => {
const originalEnv = process.env.CLAUDEMAN_MUX_NAME;
delete process.env.CLAUDEMAN_MUX_NAME;
it('should allow kill when CODEMAN_MUX_NAME is not set', async () => {
const originalEnv = process.env.CODEMAN_MUX_NAME;
delete process.env.CODEMAN_MUX_NAME;
try {
manager.registerSession({
sessionId: 'no-env-test',
muxName: 'claudeman-aaa11111',
muxName: 'codeman-aaa11111',
pid: 777,
createdAt: Date.now(),
workingDir: '/tmp',
@@ -247,9 +247,9 @@ describe('TmuxManager (unit)', () => {
expect(result).toBe(true);
} finally {
if (originalEnv === undefined) {
delete process.env.CLAUDEMAN_MUX_NAME;
delete process.env.CODEMAN_MUX_NAME;
} else {
process.env.CLAUDEMAN_MUX_NAME = originalEnv;
process.env.CODEMAN_MUX_NAME = originalEnv;
}
}
});
@@ -259,7 +259,7 @@ describe('TmuxManager (unit)', () => {
beforeEach(() => {
manager.registerSession({
sessionId: 'meta-test',
muxName: 'claudeman-ae1a1234',
muxName: 'codeman-ae1a1234',
pid: 300,
createdAt: Date.now(),
workingDir: '/tmp',
@@ -308,7 +308,7 @@ describe('TmuxManager (unit)', () => {
it('should return all registered sessions', () => {
manager.registerSession({
sessionId: 's1',
muxName: 'claudeman-51111111',
muxName: 'codeman-51111111',
pid: 1,
createdAt: Date.now(),
workingDir: '/tmp',
@@ -317,7 +317,7 @@ describe('TmuxManager (unit)', () => {
});
manager.registerSession({
sessionId: 's2',
muxName: 'claudeman-52222222',
muxName: 'codeman-52222222',
pid: 2,
createdAt: Date.now(),
workingDir: '/tmp',
+5 -5
View File
@@ -59,7 +59,7 @@ describe('TmuxManager restart recovery (test mode safety)', () => {
it('should report all registered sessions as alive in test mode', async () => {
manager.registerSession({
sessionId: 'test-recovery-1',
muxName: 'claudeman-de51ecaf',
muxName: 'codeman-de51ecaf',
pid: 1,
createdAt: Date.now(),
workingDir: '/tmp',
@@ -89,7 +89,7 @@ describe('TmuxManager restart recovery (test mode safety)', () => {
it('should not execute any tmux commands in test mode', async () => {
manager.registerSession({
sessionId: 'alive-session',
muxName: 'claudeman-a11eeaaa',
muxName: 'codeman-a11eeaaa',
pid: 1,
createdAt: Date.now(),
workingDir: '/tmp',
@@ -110,7 +110,7 @@ describe('TmuxManager restart recovery (test mode safety)', () => {
it('should handle multiple sessions correctly in test mode', async () => {
manager.registerSession({
sessionId: 'session-1',
muxName: 'claudeman-a11eeaaa',
muxName: 'codeman-a11eeaaa',
pid: 1,
createdAt: Date.now(),
workingDir: '/tmp',
@@ -120,7 +120,7 @@ describe('TmuxManager restart recovery (test mode safety)', () => {
});
manager.registerSession({
sessionId: 'session-2',
muxName: 'claudeman-b22ffbbb',
muxName: 'codeman-b22ffbbb',
pid: 2,
createdAt: Date.now(),
workingDir: '/tmp',
@@ -140,7 +140,7 @@ describe('TmuxManager restart recovery (test mode safety)', () => {
it('should safely remove sessions via killSession in test mode', async () => {
manager.registerSession({
sessionId: 'kill-me',
muxName: 'claudeman-deadbeef',
muxName: 'codeman-deadbeef',
pid: 99999,
createdAt: Date.now(),
workingDir: '/tmp',