UNPKG

claudekit

Version:

CLI tools for Claude Code development workflow

527 lines (445 loc) 15.9 kB
# Task Breakdown: Embedded Hooks System - POC Generated: 2025-07-30 Source: specs/feat-embedded-hooks-system-poc.md ## Overview Implementation of a minimal proof-of-concept for TypeScript-based hooks in claudekit, demonstrating the core concept of a separate binary with configuration support and Claude Code integration. The POC focuses on a single hook (auto-checkpoint) to validate the architecture before full implementation. ## Phase 1: Foundation & Project Structure ### Task 1.1: Create new TypeScript CLI file structure **Description**: Set up the new hooks-poc.ts file and binary wrapper in the existing claudekit project **Size**: Small **Priority**: High **Dependencies**: None **Can run parallel with**: Task 1.2 **Technical Requirements**: - Create `cli/hooks-poc.ts` with proper shebang - Create `bin/claudekit-hooks-poc` binary wrapper - Set executable permissions on both files - TypeScript target: es2022, module: esnext **Implementation Steps**: 1. Create `cli/hooks-poc.ts` with `#!/usr/bin/env node` shebang 2. Create `bin/claudekit-hooks-poc` wrapper that imports the compiled dist file 3. Ensure both files have executable permissions (chmod +x) **Acceptance Criteria**: - [ ] cli/hooks-poc.ts file exists with proper shebang - [ ] bin/claudekit-hooks-poc wrapper exists and imports '../dist/hooks-poc.js' - [ ] Both files have executable permissions - [ ] Files follow existing claudekit conventions ### Task 1.2: Update package.json for new binary **Description**: Modify the existing package.json to include the new hooks binary and build script **Size**: Small **Priority**: High **Dependencies**: None **Can run parallel with**: Task 1.1 **Technical Requirements**: - Add new binary entry for claudekit-hooks - Add build script for the POC - Maintain existing claudekit binary and scripts **Implementation from specification**: ```json { "bin": { "claudekit": "./bin/claudekit", "claudekit-hooks": "./bin/claudekit-hooks-poc" }, "scripts": { "build:hooks-poc": "tsc cli/hooks-poc.ts --outDir dist --module esnext --target es2022" } } ``` **Acceptance Criteria**: - [ ] package.json includes both binaries in "bin" section - [ ] build:hooks-poc script added to scripts section - [ ] TypeScript compilation configured with correct options - [ ] Existing package.json structure preserved ### Task 1.3: Create configuration directory and sample config **Description**: Set up .claudekit directory with sample configuration for the POC **Size**: Small **Priority**: Medium **Dependencies**: None **Can run parallel with**: Task 1.1, Task 1.2 **Technical Requirements**: - Create `.claudekit/` directory in project root - Create sample `config.json` with auto-checkpoint configuration - Document configuration structure **Implementation from specification**: ```json { "hooks": { "auto-checkpoint": { "prefix": "claude", "maxCheckpoints": 10 } } } ``` **Directory structure**: ``` claudekit/ ├── .claudekit/ # NEW: Hook configuration └── config.json # NEW: POC config file ``` **Acceptance Criteria**: - [ ] .claudekit directory exists in project root - [ ] config.json file contains valid JSON with auto-checkpoint settings - [ ] Configuration includes prefix and maxCheckpoints fields - [ ] File is properly formatted and valid JSON ## Phase 2: Core Implementation ### Task 2.1: Implement hooks-poc.ts with TypeScript interfaces **Description**: Create the main TypeScript file with config interface and basic structure **Size**: Medium **Priority**: High **Dependencies**: Task 1.1 **Can run parallel with**: None **Technical Requirements**: - Define Config interface for type safety - Import required Node.js modules (fs, child_process, path) - Set up main async function structure - Handle command-line arguments **Implementation from specification**: ```typescript // cli/hooks-poc.ts #!/usr/bin/env node import { readFileSync, existsSync } from 'fs'; import { spawn } from 'child_process'; import * as path from 'path'; // Simple config interface interface Config { hooks?: { 'auto-checkpoint'?: { prefix?: string; maxCheckpoints?: number; }; }; } // Main execution async function main() { const hookName = process.argv[2]; if (hookName !== 'auto-checkpoint') { console.error(`Unknown hook: ${hookName}`); process.exit(1); } // Implementation continues in next tasks... } main().catch(err => { console.error('Fatal error:', err); process.exit(1); }); ``` **Acceptance Criteria**: - [ ] TypeScript interfaces properly defined - [ ] Main function with async/await pattern - [ ] Command-line argument parsing for hook name - [ ] Error handling for unknown hooks with exit code 1 - [ ] Fatal error catching with appropriate message ### Task 2.2: Implement stdin reading functionality **Description**: Add the readStdin function to handle Claude Code JSON payload input **Size**: Small **Priority**: High **Dependencies**: Task 2.1 **Can run parallel with**: Task 2.3 **Technical Requirements**: - Asynchronous stdin reading - Timeout fallback of 1 second - Return empty string on timeout - Handle data chunks properly **Implementation from specification**: ```typescript // Read stdin payload async function readStdin(): Promise<string> { return new Promise((resolve) => { let data = ''; process.stdin.on('data', chunk => data += chunk); process.stdin.on('end', () => resolve(data)); setTimeout(() => resolve(''), 1000); // Timeout fallback }); } ``` **Acceptance Criteria**: - [ ] Function returns Promise<string> - [ ] Accumulates data chunks correctly - [ ] Resolves on stdin end event - [ ] Has 1-second timeout fallback - [ ] Returns empty string on timeout ### Task 2.3: Implement configuration loading logic **Description**: Add configuration file loading with error handling in the main function **Size**: Medium **Priority**: High **Dependencies**: Task 2.1 **Can run parallel with**: Task 2.2 **Technical Requirements**: - Load config from `.claudekit/config.json` in current directory - Handle missing config file gracefully - Parse JSON with error handling - Extract hook-specific configuration with defaults **Implementation from specification**: ```typescript // Load config if exists let config: Config = {}; const configPath = path.join(process.cwd(), '.claudekit/config.json'); if (existsSync(configPath)) { try { config = JSON.parse(readFileSync(configPath, 'utf-8')); } catch (e) { console.error('Invalid config file'); } } // Get hook config const hookConfig = config.hooks?.['auto-checkpoint'] || {}; const prefix = hookConfig.prefix || 'claude'; const maxCheckpoints = hookConfig.maxCheckpoints || 10; ``` **Acceptance Criteria**: - [ ] Checks for config file in current working directory only - [ ] Handles missing file without errors - [ ] Catches and reports JSON parse errors - [ ] Extracts auto-checkpoint configuration - [ ] Uses default values: prefix='claude', maxCheckpoints=10 - [ ] No project root traversal (POC limitation) ### Task 2.4: Implement auto-checkpoint hook logic **Description**: Build the complete auto-checkpoint functionality with git integration **Size**: Large **Priority**: High **Dependencies**: Task 2.1, Task 2.3 **Can run parallel with**: None **Technical Requirements**: - Check if current directory is git repository - Detect uncommitted changes using git status --porcelain - Create timestamped stash with configurable prefix - Apply stash to restore working directory - Handle exit codes properly **Implementation from specification**: ```typescript // Check if git repo const gitStatus = spawn('git', ['status', '--porcelain'], { stdio: ['ignore', 'pipe', 'pipe'] }); let stdout = ''; gitStatus.stdout.on('data', (data) => stdout += data); gitStatus.on('close', (code) => { if (code !== 0) { console.log('Not a git repository, skipping checkpoint'); process.exit(0); } // Check if there are changes if (!stdout.trim()) { console.log('No changes to checkpoint'); process.exit(0); } // Create checkpoint const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); const message = `${prefix}-checkpoint-${timestamp}`; const stash = spawn('git', ['stash', 'push', '-m', message], { stdio: ['ignore', 'pipe', 'pipe'] }); stash.on('close', (stashCode) => { if (stashCode !== 0) { console.error('Failed to create checkpoint'); process.exit(1); } // Apply stash to restore working directory spawn('git', ['stash', 'apply'], { stdio: 'ignore' }).on('close', () => { console.log(`✅ Checkpoint created: ${message}`); process.exit(0); }); }); }); ``` **Key implementation notes**: - Use child_process.spawn for git commands - Capture stdout to check for changes - Generate ISO timestamp and sanitize for git message - Chain git stash push and apply operations - Exit code 0 for success/skip, 1 for errors **Acceptance Criteria**: - [ ] Correctly identifies git repositories - [ ] Detects uncommitted changes using git status --porcelain - [ ] Creates checkpoint with format: ${prefix}-checkpoint-${timestamp} - [ ] Timestamp uses ISO format with colons/dots replaced by hyphens - [ ] Restores working directory after stash - [ ] Exits with code 0 on success or skip scenarios - [ ] Exits with code 1 on git command failures - [ ] Respects configured prefix from config file ## Phase 3: Build and Integration ### Task 3.1: Build the TypeScript POC **Description**: Compile the TypeScript code and verify the build output **Size**: Small **Priority**: High **Dependencies**: Task 2.1, Task 2.2, Task 2.3, Task 2.4 **Can run parallel with**: Task 3.2 **Technical Requirements**: - Run the build:hooks-poc script - Verify dist/hooks-poc.js is created - Ensure proper module format (ESNext) - Check compilation has no errors **Build command**: ```bash npm run build:hooks-poc ``` **Expected output structure**: ``` dist/ ├── cli.js # Existing compiled CLI ├── index.js # Existing exports └── hooks-poc.js # NEW: Compiled POC ``` **Acceptance Criteria**: - [ ] build:hooks-poc script runs without errors - [ ] dist/hooks-poc.js file is created - [ ] Compiled code uses ESNext module format - [ ] No TypeScript compilation errors - [ ] Binary wrapper can import the compiled file ### Task 3.2: Create Claude Code settings.json integration **Description**: Set up Claude Code hook configuration to use the new binary **Size**: Small **Priority**: High **Dependencies**: None **Can run parallel with**: Task 3.1 **Technical Requirements**: - Create valid Claude Code hooks configuration - Use Stop event with universal matcher - Reference the claudekit-hooks binary correctly **Implementation from specification**: ```json { "hooks": { "Stop": [ { "matcher": "*", "hooks": [{"type": "command", "command": "claudekit-hooks auto-checkpoint"}] } ] } } ``` **File location**: `.claude/settings.json` (in test projects) **Acceptance Criteria**: - [ ] Valid Claude Code hooks configuration format - [ ] Stop event configured with "*" matcher - [ ] Command references "claudekit-hooks auto-checkpoint" - [ ] JSON is properly formatted and valid - [ ] Follows Claude Code hooks specification ### Task 3.3: Create manual test script **Description**: Build a comprehensive test script to validate all POC functionality **Size**: Medium **Priority**: Medium **Dependencies**: Task 3.1 **Can run parallel with**: None **Technical Requirements**: - Test script should be fully automated - Cover all POC success criteria - Create test git repository - Test multiple scenarios **Implementation from specification**: ```bash #!/bin/bash # test-poc.sh # Setup: Create a git repo with changes git init test-repo cd test-repo echo "test content" > file.txt git add . git commit -m "initial" echo "changed" >> file.txt # Test 1: Auto-checkpoint with changes claudekit-hooks auto-checkpoint # Should create a checkpoint # Test 2: No changes git stash drop claudekit-hooks auto-checkpoint # Should say "No changes to checkpoint" # Test 3: With config mkdir .claudekit echo '{"hooks": {"auto-checkpoint": {"prefix": "test", "maxCheckpoints": 5}}}' > .claudekit/config.json echo "another change" >> file.txt claudekit-hooks auto-checkpoint # Should create checkpoint with "test" prefix ``` **Test scenarios**: 1. Auto-checkpoint with uncommitted changes 2. No checkpoint when no changes exist 3. Custom configuration with different prefix 4. Non-git directory handling 5. Invalid config file handling **Acceptance Criteria**: - [ ] Test script creates isolated test environment - [ ] Tests all success criteria scenarios - [ ] Verifies exit codes are correct - [ ] Checks output messages match expected - [ ] Tests configuration loading and defaults - [ ] Cleanup after test completion ## Phase 4: Documentation and Validation ### Task 4.1: Verify POC success criteria **Description**: Validate that all POC goals have been met and document results **Size**: Small **Priority**: High **Dependencies**: All previous tasks **Can run parallel with**: Task 4.2 **POC Success Criteria to verify**: 1. Can execute as separate binary 2. Can read Claude Code JSON from stdin 3. Can load and respect configuration 4. Returns proper exit codes (0, 2) 5. Works with Claude Code hooks **Validation steps**: 1. Run `claudekit-hooks auto-checkpoint` directly 2. Test with echo '{}' | claudekit-hooks auto-checkpoint 3. Verify config changes behavior 4. Check exit codes in different scenarios 5. Test integration with Claude Code **Acceptance Criteria**: - [ ] All 5 success criteria validated - [ ] Document any deviations or issues - [ ] Confirm POC demonstrates core concept - [ ] Ready for full implementation decision ### Task 4.2: Document POC limitations and next steps **Description**: Create documentation of POC limitations and roadmap for full implementation **Size**: Small **Priority**: Medium **Dependencies**: Task 4.1 **Can run parallel with**: None **Documentation requirements**: - List all POC limitations clearly - Document architectural decisions made - Outline path to full implementation - Estimate time for complete version **POC Limitations from spec**: - Single hook only (auto-checkpoint) - No proper error handling - No logging system - Minimal configuration - No tests - Hardcoded logic - Only checks current directory for config (no traversal) **Next steps if POC successful**: 1. Refactor to proper architecture (BaseHook class, HookRunner, Registry) 2. Add production features (error handling, logging, build pipeline, tests) 3. Performance optimization (command caching, incremental checking) **Acceptance Criteria**: - [ ] Clear documentation of all limitations - [ ] Architectural roadmap defined - [ ] Time estimates provided (POC: 1-2 hours, Full: 1-2 weeks) - [ ] Decision criteria for proceeding documented ## Summary **Total Tasks**: 11 **Phase Breakdown**: - Phase 1 (Foundation): 3 tasks - Phase 2 (Core Implementation): 4 tasks - Phase 3 (Build & Integration): 3 tasks - Phase 4 (Documentation): 2 tasks **Execution Strategy**: 1. Start with Phase 1 tasks in parallel (1.1, 1.2, 1.3) 2. Phase 2 tasks build on Phase 1, with some parallelization possible 3. Phase 3 requires Phase 2 completion but allows parallel build/integration 4. Phase 4 validates the entire POC **Critical Path**: Task 1.1 Task 2.1 Task 2.4 Task 3.1 Task 4.1 **Parallel Opportunities**: - Tasks 1.1, 1.2, 1.3 can run simultaneously - Tasks 2.2 and 2.3 can run in parallel after 2.1 - Tasks 3.1 and 3.2 can run in parallel **Risk Factors**: - TypeScript compilation issues with module formats - Git command behavior variations across environments - Claude Code hook integration compatibility