#!/usr/bin/env bun /** * hook - Claude Code hook scaffold generator * * Creates a complete hook template in the current directory. * Running `hook` without arguments creates the scaffold interactively. */ import { createHook } from './commands/create'; import { listEvents } from './commands/events'; import { validateHook } from './commands/validate'; function printHelp() { console.log(`hook - Claude Code hook scaffold generator USAGE: hook [name] Create a hook scaffold (interactive if no name) hook [options] COMMANDS: events List available hook events validate Validate a hook structure help Show this help message EXAMPLES: hook Interactive hook creation hook my-hook Create hook-my-hook scaffold hook --event Stop Create with Stop event hook events List hook events OPTIONS: --name Hook name (prompted if not provided) --event Hook event: PreToolUse, PostToolUse, Stop (default: PreToolUse) --matcher Tool matcher: Bash, Write, Edit, *, etc. (default: *) --output Output directory (default: current directory) --help Show help `); } async function promptForName(): Promise { process.stdout.write('Hook name (without hook- prefix): '); const reader = Bun.stdin.stream().getReader(); const { value } = await reader.read(); reader.releaseLock(); const input = new TextDecoder().decode(value).trim(); if (!input) { console.error('Error: Hook name is required'); process.exit(1); } return input; } async function main() { const args = process.argv.slice(2); // Help if (args.includes('--help') || args.includes('-h') || args[0] === 'help') { printHelp(); process.exit(0); } // Events command if (args[0] === 'events') { listEvents(); process.exit(0); } // Validate command if (args[0] === 'validate') { const path = args[1]; if (!path) { console.error('Error: Path required'); console.error('Usage: hook validate '); process.exit(1); } await validateHook(path); process.exit(0); } // Parse options const options: Record = {}; let name: string | undefined; for (let i = 0; i < args.length; i++) { const arg = args[i]; if (arg === '--name' && args[i + 1]) { name = args[++i]; } else if (arg === '--event' && args[i + 1]) { options.event = args[++i]; } else if (arg === '--matcher' && args[i + 1]) { options.matcher = args[++i]; } else if (arg === '--output' && args[i + 1]) { options.output = args[++i]; } else if (!arg.startsWith('--') && !name) { // First non-option argument is the name name = arg; } } // If no name provided, prompt for it if (!name) { name = await promptForName(); } // Create the hook await createHook(name, options); } main().catch((error) => { console.error('Fatal error:', error.message); process.exit(1); });