claudekit
Version:
CLI tools for Claude Code development workflow
318 lines (256 loc) • 8.66 kB
Markdown
**Status**: ✅ POC Completed
**Authors**: Claude, 2025-07-29
**Type**: Proof of Concept
**Implementation Date**: 2025-07-30
Minimal implementation to validate the core concept: TypeScript hooks in a separate binary with configuration support.
1. ✅ Create `claudekit-hooks` binary with one hook (auto-checkpoint)
2. ✅ Basic configuration loading from `.claudekit/config.json`
3. ✅ Claude Code integration via stdin/stdout
4. ✅ Demonstrate exit code handling
## POC Non-Goals
1. ❌ **Multiple hooks** - Only implement auto-checkpoint, not all 6
2. ❌ **Project root discovery** - Only check current directory
3. ❌ **Error handling** - Basic errors only, no recovery strategies
4. ❌ **Logging system** - Just console.log/error, no log levels
5. ❌ **Package manager detection** - Hardcode to npx/pnpm
6. ❌ **Tests** - Manual testing only
7. ❌ **Performance** - No optimization or caching
8. ❌ **Cross-platform** - Can assume Unix-like environment
9. ❌ **Production build** - Simple tsc compilation is enough
10. ❌ **Installation process** - Manual npm link for testing
## Directory Structure
```
claudekit/ # Existing claudekit project
├── cli/
│ ├── cli.ts # Existing main CLI
│ ├── commands/ # Existing commands
│ ├── lib/ # Existing libraries
│ ├── types/ # Existing types
│ └── hooks-poc.ts # NEW: POC hooks CLI
├── bin/
│ ├── claudekit # Existing CLI wrapper
│ └── claudekit-hooks-poc # NEW: POC binary wrapper
├── dist/ # Build output
│ ├── cli.js # Existing compiled CLI
│ ├── index.js # Existing exports
│ └── hooks-poc.js # NEW: Compiled POC
├── src/ # Existing source
│ ├── commands/ # Existing slash commands
│ └── hooks/ # Existing shell hooks
├── .claudekit/ # NEW: Hook configuration
│ └── config.json # NEW: POC config file
└── package.json # MODIFIED: Add new binary
# Test directory (separate)
test-repo/
├── .claudekit/
│ └── config.json
└── file.txt # Test file with changes
```
## Minimal Implementation
### 1. Single Hook Implementation
```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;
};
};
}
// 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
});
}
// Main execution
async function main() {
const hookName = process.argv[2];
if (hookName !== 'auto-checkpoint') {
console.error(`Unknown hook: ${hookName}`);
process.exit(1);
}
// 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;
// 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);
});
});
});
}
main().catch(err => {
console.error('Fatal error:', err);
process.exit(1);
});
```
Add to the existing claudekit package.json:
```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 --moduleResolution node --skipLibCheck"
}
}
```
And create `bin/claudekit-hooks-poc`:
```bash
import('../dist/hooks-poc.js');
```
```json
{
"hooks": {
"auto-checkpoint": {
"prefix": "claude",
"maxCheckpoints": 10
}
}
}
```
```json
{
"hooks": {
"Stop": [
{
"matcher": "*",
"hooks": [{"type": "command", "command": "claudekit-hooks auto-checkpoint"}]
}
]
}
}
```
```bash
git init test-repo
cd test-repo
echo "test content" > file.txt
git add .
git commit -m "initial"
echo "changed" >> file.txt
claudekit-hooks auto-checkpoint
git stash drop
claudekit-hooks auto-checkpoint
mkdir .claudekit
echo '{"hooks": {"auto-checkpoint": {"prefix": "test", "maxCheckpoints": 5}}}' > .claudekit/config.json
echo "another change" >> file.txt
claudekit-hooks auto-checkpoint
```
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, 1)
5. ✅ Works with Claude Code hooks
## Next Steps After POC
If POC is successful:
1. **Refactor to proper architecture**
- Extract BaseHook class
- Add HookRunner and Registry
- Implement remaining hooks
2. **Add production features**
- Proper error handling
- Logging system
- Build pipeline
- Tests
3. **Performance optimization**
- Command caching
- Incremental checking
## POC Limitations
- 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)
## Implementation Time
- POC: 1-2 hours (✅ Completed in ~2 hours)
- Full implementation: 1-2 weeks
- Testing & Documentation: 3-5 days
- Total Project Time: 2-3 weeks
## POC Validation Results
Based on the implementation and testing:
1. **Architecture Validated**: TypeScript-based separate binary approach proven successful
2. **Configuration System**: Works as designed with proper defaults
3. **Claude Code Integration**: Successfully integrates via hooks system
4. **Performance**: Acceptable for POC, no noticeable delays
5. **Exit Codes**: Properly returns 0 for success/skip, 1 for errors
## Lessons Learned
1. **Build Configuration**: Required `--moduleResolution node --skipLibCheck` flags for TypeScript compilation
2. **Binary Wrapper**: Simple direct import works best: `import('../dist/hooks-poc.js');`
3. **Testing Approach**: Manual test script sufficient for POC validation
4. **Configuration Location**: Current directory only approach is limiting but acceptable for POC
✅ **Proceed with full implementation** based on validated POC architecture.
For detailed validation results and implementation report, see: [POC Validation Report](../reports/POC_VALIDATION_REPORT.md)