feat(parsers): add Command Code CLI session support#76
Conversation
Adds command-code (npm i -g command-code) as the 17th supported tool. Discovers sessions from ~/.commandcode/projects/<cwd-slug>/<uuid>.jsonl, reads title/model from <uuid>.meta.json, extracts user/assistant messages by joining text content blocks (skipping reasoning/tool-call/tool-result), and summarizes shell_command and file tool calls via SummaryCollector. Registry: binaryName=cmdc, fallbacks=[cmd,command-code,commandcode], native resume via --resume <session-id>. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
📝 Info: New parser follows all 5 required checklist items for adding a new tool
Verified against the AGENTS.md checklist:
- ✅ Tool name added to
TOOL_NAMESinsrc/types/tool-names.ts:24 - ✅ Parser file created at
src/parsers/command-code.tswith both required exports - ✅ Registered in
src/parsers/registry.ts:944-957 - ✅ Fixture factory
createCommandCodeFixture()added insrc/__tests__/fixtures/index.ts:1293 - ✅ Conversion tests added in
src/__tests__/unit-conversions.test.ts
The implementation is consistent with existing parsers like qwen-code.ts in structure.
Was this helpful? React with 👍 or 👎 to provide feedback.
| storagePath: '~/.commandcode/projects/*/', | ||
| envVar: 'COMMAND_CODE_HOME', | ||
| binaryName: 'cmdc', | ||
| binaryFallbacks: ['cmd', 'command-code', 'commandcode'], |
There was a problem hiding this comment.
🔴 cmd in binaryFallbacks resolves to Windows Command Prompt, causing incorrect tool detection and execution
The binaryFallbacks array includes 'cmd' as a fallback binary name (src/parsers/registry.ts:951). On Windows, cmd always resolves to cmd.exe (the Windows Command Prompt), which means:
resolveToolBinaryName('command-code')atsrc/utils/resume.ts:313will findcmdviawhich/whereand return it as the resolved binary, even when Command Code is not installed.getAvailableTools()will incorrectly reportcommand-codeas available on all Windows systems.- Cross-tool handoff will invoke
cmd.exe /c cmd <handoff_prompt>(viarunCommandatsrc/utils/resume.ts:276), passing the full handoff markdown prompt through the Windows command interpreter instead of the intended tool.
This affects any Windows user who doesn't have cmdc installed — the tool appears available but executes against the wrong binary.
| binaryFallbacks: ['cmd', 'command-code', 'commandcode'], | |
| binaryFallbacks: ['command-code', 'commandcode'], |
Was this helpful? React with 👍 or 👎 to provide feedback.
| export async function parseCommandCodeSessions(): Promise<UnifiedSession[]> { | ||
| const sessions: UnifiedSession[] = []; | ||
|
|
||
| let projectDirs: string[]; | ||
| try { | ||
| projectDirs = listSubdirectories(PROJECTS_DIR); | ||
| } catch { | ||
| return sessions; | ||
| } |
There was a problem hiding this comment.
📝 Info: Parser correctly uses async streaming JSONL helpers instead of readFileSync
The command-code parser uses scanJsonlFile from src/utils/jsonl.ts for reading JSONL data (lines 91 and 137), and fsp.readFile (node:fs/promises) for the small meta.json file. This complies with the REVIEW.md rule against fs.readFileSync in parser code. The listSubdirectories call at line 62 does use synchronous fs.readdirSync internally, but this is the same shared helper used by gemini, copilot, kiro, qwen-code, and opencode parsers — it's an accepted pre-existing pattern for directory listing (the REVIEW.md rule specifically mentions readFileSync/writeFileSync, not readdirSync).
Was this helpful? React with 👍 or 👎 to provide feedback.
| } catch { | ||
| continue; | ||
| } |
There was a problem hiding this comment.
📝 Info: Catch blocks have non-empty bodies but lack logger.debug calls
The catch blocks at lines 44, 63, and 75 swallow errors silently without calling logger.debug. While the REVIEW.md convention recommends logger.debug in catch blocks, these blocks are not technically empty (they have return/continue statements) so they won't trigger Biome's noEmptyBlockStatements error. This same pattern exists in other parsers like qwen-code.ts:491 (catch { continue; }) and kimi.ts:158 (catch { return undefined; }). However, adding logger.debug would improve debuggability — especially at line 75 where directory read failures are silently skipped during session discovery.
Was this helpful? React with 👍 or 👎 to provide feedback.
| const COMMAND_CODE_HOME = | ||
| process.env.COMMAND_CODE_HOME ?? path.join(homeDir(), '.commandcode'); | ||
| const PROJECTS_DIR = path.join(COMMAND_CODE_HOME, 'projects'); |
There was a problem hiding this comment.
📝 Info: COMMAND_CODE_HOME evaluated at module load time — consistent with other parsers
The COMMAND_CODE_HOME and PROJECTS_DIR constants are computed at module-load time (lines 14-16). This means if the environment variable changes after import, the change won't be reflected. This is the same pattern used by other parsers (e.g., qwen-code, kimi) and is acceptable since the CLI is a short-lived process. The envVar: 'COMMAND_CODE_HOME' in the registry entry correctly declares this for cache invalidation purposes.
Was this helpful? React with 👍 or 👎 to provide feedback.
| } else { | ||
| const filePath = (input.path ?? input.file_path ?? input.filePath ?? '') as string; | ||
| if (filePath) { | ||
| const isWrite = /write|edit|patch|create/i.test(toolName); |
There was a problem hiding this comment.
📝 Info: Tool classification uses regex on toolName which may miss edge cases
At line 163, /write|edit|patch|create/i.test(toolName) classifies tools as write operations. This regex could match tool names containing these substrings unexpectedly (e.g., a hypothetical read_created_at tool would be classified as write). However, this is a reasonable heuristic for an unknown tool's operations and matches the defensive approach used elsewhere in the codebase. The read_file tool wouldn't match because read isn't in the regex.
Was this helpful? React with 👍 or 👎 to provide feedback.
Add command-code (npm i -g command-code) as 17th supported tool. Discovers sessions from ~/.commandcode/projects/, extracts
messages and tool activity. 984 tests pass, TypeScript builds clean.
Summary by cubic
Adds
command-codeCLI session support as the 17th tool. Sessions are discovered from ~/.commandcode/projects/, user/assistant messages are extracted cleanly, and tool activity is summarized for handoffs.New Features
shell_commandand file read/write calls via the SummaryCollector.command-codewith binarycmdc(fallbacks:cmd,command-code,commandcode), native resume--resume <id>, andCOMMAND_CODE_HOMEoverride.TOOL_NAMESto 17.Migration
command-codeglobally:npm i -g command-code. Sessions in ~/.commandcode/projects/ will be auto-detected.COMMAND_CODE_HOME. Resume withcmdc --resume <id>.Written for commit 4bb5328. Summary will update on new commits.