start-vibing 2.0.2 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/package.json +1 -1
  2. package/template/.claude/agents/01-orchestration/checkpoint-manager.md +1 -1
  3. package/template/.claude/agents/01-orchestration/context-manager.md +1 -1
  4. package/template/.claude/agents/01-orchestration/error-recovery.md +1 -1
  5. package/template/.claude/agents/01-orchestration/orchestrator.md +1 -1
  6. package/template/.claude/agents/01-orchestration/parallel-coordinator.md +1 -1
  7. package/template/.claude/agents/01-orchestration/task-decomposer.md +1 -1
  8. package/template/.claude/agents/01-orchestration/workflow-router.md +1 -1
  9. package/template/.claude/agents/02-typescript/bun-runtime-expert.md +1 -1
  10. package/template/.claude/agents/02-typescript/esm-resolver.md +1 -1
  11. package/template/.claude/agents/02-typescript/import-alias-enforcer.md +1 -1
  12. package/template/.claude/agents/02-typescript/ts-migration-helper.md +1 -1
  13. package/template/.claude/agents/02-typescript/ts-strict-checker.md +1 -1
  14. package/template/.claude/agents/02-typescript/ts-types-analyzer.md +1 -1
  15. package/template/.claude/agents/02-typescript/type-definition-writer.md +1 -1
  16. package/template/.claude/agents/02-typescript/zod-schema-designer.md +1 -1
  17. package/template/.claude/agents/02-typescript/zod-validator.md +1 -1
  18. package/template/.claude/hooks/SETUP.md +85 -11
  19. package/template/.claude/hooks/run-hook.cmd +46 -0
  20. package/template/.claude/hooks/run-hook.sh +43 -0
  21. package/template/.claude/hooks/run-hook.ts +158 -0
  22. package/template/.claude/hooks/stop-validator.ts +339 -0
  23. package/template/.claude/hooks/user-prompt-submit.ts +298 -0
  24. package/template/.claude/settings.json +4 -3
  25. package/template/.claude/skills/bun-runtime/SKILL.md +430 -0
  26. package/template/.claude/skills/codebase-knowledge/domains/claude-system.md +46 -4
  27. package/template/.claude/skills/mongoose-patterns/SKILL.md +512 -0
  28. package/template/.claude/skills/nextjs-app-router/SKILL.md +337 -0
  29. package/template/.claude/skills/playwright-automation/SKILL.md +438 -0
  30. package/template/.claude/skills/react-patterns/SKILL.md +376 -0
  31. package/template/.claude/skills/shadcn-ui/SKILL.md +520 -0
  32. package/template/.claude/skills/tailwind-patterns/SKILL.md +467 -0
  33. package/template/.claude/skills/trpc-api/SKILL.md +435 -0
  34. package/template/.claude/skills/typescript-strict/SKILL.md +368 -0
  35. package/template/.claude/skills/zod-validation/SKILL.md +405 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "start-vibing",
3
- "version": "2.0.2",
3
+ "version": "2.0.3",
4
4
  "description": "Setup Claude Code agents, skills, and hooks in your project. Smart copy that preserves your custom domains and configurations.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: checkpoint-manager
3
- description: "Saves and restores workflow checkpoints. Invoke before risky operations or when resuming interrupted work. Enables resume from failure."
3
+ description: "AUTOMATICALLY invoke BEFORE risky operations. Triggers: before git operations, before file deletions, before major refactors. Saves and restores workflow checkpoints. PROACTIVELY saves state before destructive operations."
4
4
  model: haiku
5
5
  tools: Read, Write, Grep, Glob
6
6
  ---
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: context-manager
3
- description: "Manages context between agents. Compresses state, saves checkpoints, prunes irrelevant data. Invoke when context is growing large or between major phases."
3
+ description: "AUTOMATICALLY invoke when context grows large or between major phases. Triggers: agent handoff, long conversation, context bloat. Compresses state, saves checkpoints, prunes irrelevant data. PROACTIVELY manages token budget."
4
4
  model: haiku
5
5
  tools: Read, Write, Grep, Glob
6
6
  ---
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: error-recovery
3
- description: "Handles agent failures and implements recovery strategies. Invoke when an agent fails or returns unexpected results. Implements retry logic and fallbacks."
3
+ description: "AUTOMATICALLY invoke when an agent fails or returns unexpected results. Triggers: tool failure, agent timeout, validation failure, unexpected error. Implements retry logic and fallbacks. PROACTIVELY handles failures in the pipeline."
4
4
  model: sonnet
5
5
  tools: Read, Bash, Grep, Glob
6
6
  ---
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: orchestrator
3
- description: "MAIN ORCHESTRATOR. Invoke for ANY multi-step task. Triggers: 'implement', 'build', 'create', 'fix and test'. Coordinates specialized sub-agents in parallel. Decomposes complex tasks into subtasks."
3
+ description: "AUTOMATICALLY invoke for ANY multi-step task. Triggers: 'implement feature', 'build X', 'create Y', 'fix and test', 'full workflow'. Coordinates ALL other agents in sequence. Use when task requires >2 agents or touches >3 files. PROACTIVELY takes control of complex development flows."
4
4
  model: sonnet
5
5
  tools: Read, Write, Edit, Bash, Grep, Glob, WebSearch, WebFetch
6
6
  skills: codebase-knowledge
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: parallel-coordinator
3
- description: "Coordinates parallel agent execution. Invoke when multiple independent agents should run simultaneously. Manages fan-out/gather pattern."
3
+ description: "AUTOMATICALLY invoke when multiple independent agents should run simultaneously. Triggers: parallel execution needed, fan-out/gather pattern, independent tasks identified. Coordinates parallel agent execution. PROACTIVELY optimizes multi-agent workflows."
4
4
  model: haiku
5
5
  tools: Read, Grep, Glob
6
6
  ---
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: task-decomposer
3
- description: "Breaks complex tasks into atomic subtasks. Invoke when task has >3 steps or touches >3 files. Creates structured task breakdown for parallel execution."
3
+ description: "AUTOMATICALLY invoke when task has >3 steps or touches >3 files. Triggers: complex task, multi-domain task, unclear scope, feature implementation. Breaks complex tasks into atomic subtasks for parallel execution. PROACTIVELY decomposes before implementation."
4
4
  model: haiku
5
5
  tools: Read, Grep, Glob
6
6
  skills: codebase-knowledge
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: workflow-router
3
- description: "Routes tasks to correct agent based on keywords, file types, and context. Invoke when unsure which agent handles a request."
3
+ description: "AUTOMATICALLY invoke at task start to route to correct agent. Triggers: new request, unclear which agent, multiple valid routes. Routes tasks based on keywords, file types, and context. PROACTIVELY analyzes requests for optimal routing."
4
4
  model: haiku
5
5
  tools: Read, Grep, Glob
6
6
  ---
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: bun-runtime-expert
3
- description: "Expert in Bun runtime specifics. Triggers: 'bun', runtime issues, package management. Handles Bun-specific APIs and configurations."
3
+ description: "AUTOMATICALLY invoke when using Bun runtime. Triggers: 'bun', runtime issues, package management, node compatibility. Expert in Bun-specific APIs and configurations. PROACTIVELY suggests Bun alternatives to Node.js."
4
4
  model: haiku
5
5
  tools: Read, Bash, Grep, Glob
6
6
  ---
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: esm-resolver
3
- description: "Resolves ESM module issues. Triggers: 'module error', 'import error', 'cannot find module'. Fixes ESM/CJS compatibility."
3
+ description: "AUTOMATICALLY invoke on module errors. Triggers: 'module error', 'import error', 'cannot find module', 'require is not defined'. Fixes ESM/CJS compatibility issues. PROACTIVELY resolves import problems."
4
4
  model: haiku
5
5
  tools: Read, Grep, Glob
6
6
  ---
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: import-alias-enforcer
3
- description: "Enforces path alias usage. Triggers: reviewing imports, 'import error'. Ensures $types/*, @common, @db aliases are used correctly."
3
+ description: "AUTOMATICALLY invoke AFTER editing .ts files. Triggers: new .ts file, imports added, code review. Enforces $types/*, @common, @db aliases. PROACTIVELY checks all imports use correct aliases."
4
4
  model: haiku
5
5
  tools: Read, Grep, Glob
6
6
  ---
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: ts-migration-helper
3
- description: "Helps migrate JavaScript to TypeScript. Triggers: 'migrate to ts', 'convert to typescript'. Adds types progressively with strict mode."
3
+ description: "Helps migrate JavaScript to TypeScript. Triggers: 'migrate to ts', 'convert to typescript', .js files in project. Adds types progressively with strict mode."
4
4
  model: sonnet
5
5
  tools: Read, Write, Edit, Grep, Glob, Bash
6
6
  ---
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: ts-strict-checker
3
- description: "Enforces TypeScript strict mode rules. Triggers: editing .ts files, 'strict mode', 'type error'. Validates index access, literal types, null checks."
3
+ description: "AUTOMATICALLY invoke AFTER editing any .ts file. Triggers: editing .ts files, new .ts file, process.env access. Validates index access, literal types, null checks. PROACTIVELY enforces TypeScript strict mode rules."
4
4
  model: haiku
5
5
  tools: Read, Grep, Glob, Bash
6
6
  ---
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: ts-types-analyzer
3
- description: "Analyzes complex TypeScript types. Triggers: 'type error', 'inference issue', 'generic problem'. Debugs type inference and provides fixes."
3
+ description: "AUTOMATICALLY invoke on type errors. Triggers: 'type error', 'inference issue', 'generic problem', typecheck fails. Analyzes complex TypeScript types and debugs inference. PROACTIVELY fixes type issues."
4
4
  model: sonnet
5
5
  tools: Read, Grep, Glob, Bash
6
6
  ---
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: type-definition-writer
3
- description: "Writes type definitions for types/ folder. Triggers: new model, new API, 'add types'. Creates interfaces and types following project conventions."
3
+ description: "AUTOMATICALLY invoke BEFORE implementing new entities. Triggers: new model, new API, new entity, interface needed. Writes type definitions for types/ folder. PROACTIVELY creates interfaces following project conventions."
4
4
  model: haiku
5
5
  tools: Read, Write, Edit, Grep, Glob
6
6
  ---
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: zod-schema-designer
3
- description: "Designs Zod validation schemas. Triggers: 'zod', 'validation', 'schema', new API endpoint. Creates comprehensive input validation."
3
+ description: "AUTOMATICALLY invoke BEFORE implementing any API endpoint. Triggers: new API endpoint, new route, form input, user input. Designs Zod validation schemas. PROACTIVELY creates comprehensive input validation."
4
4
  model: sonnet
5
5
  tools: Read, Write, Edit, Grep, Glob
6
6
  skills: codebase-knowledge
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: zod-validator
3
- description: "Validates existing Zod schemas for completeness. Triggers: 'validate schema', reviewing API. Checks all routes have proper validation."
3
+ description: "AUTOMATICALLY invoke BEFORE commit when API routes exist. Triggers: API route modified, security audit, validation audit. Validates all routes have proper Zod validation. PROACTIVELY checks schema completeness."
4
4
  model: haiku
5
5
  tools: Read, Grep, Glob
6
6
  ---
@@ -2,21 +2,37 @@
2
2
 
3
3
  ## Overview
4
4
 
5
- This system provides agent selection guidance by analyzing prompts and suggesting the best agent for the task.
5
+ This system provides agent selection guidance by analyzing prompts and suggesting the best agent for the task. It includes a **universal hook runner** that supports multiple runtimes with automatic fallback.
6
6
 
7
- ## Requirements
7
+ ## Runtime Support
8
8
 
9
- - Python 3.8+
9
+ The hooks use a universal runner (`run-hook.ts`) that automatically detects and uses the first available runtime:
10
+
11
+ | Priority | Runtime | Extension | Notes |
12
+ | -------- | ---------- | --------- | -------------------------- |
13
+ | 1 | python3 | .py | Primary (user's preferred) |
14
+ | 2 | python | .py | Fallback |
15
+ | 3 | bun | .ts | TypeScript fallback |
16
+ | 4 | npx tsx | .ts | Final fallback |
17
+
18
+ **If no runtime is available**, the hooks return a safe default (approve/continue) to avoid blocking the user.
10
19
 
11
20
  ## Files
12
21
 
13
- | File | Purpose |
14
- | ------------------------ | ----------------------------------------------------- |
15
- | `user-prompt-submit.py` | Analyzes prompts and suggests appropriate agents |
22
+ | File | Purpose |
23
+ | ------------------------- | ------------------------------------------------------- |
24
+ | `run-hook.ts` | Universal runner with runtime detection |
25
+ | `run-hook.sh` | Shell wrapper for Unix/Linux/Mac |
26
+ | `run-hook.cmd` | Batch wrapper for Windows |
27
+ | `user-prompt-submit.py` | Analyzes prompts and suggests agents (Python) |
28
+ | `user-prompt-submit.ts` | Same as above (TypeScript fallback) |
29
+ | `stop-validator.py` | Validates before task completion (Python) |
30
+ | `stop-validator.ts` | Same as above (TypeScript fallback) |
31
+ | `check-documentation.py` | Verifies file documentation (Python) |
16
32
 
17
33
  ## Claude Code Configuration
18
34
 
19
- The hooks are configured in `.claude/settings.local.json`:
35
+ The hooks are configured in `.claude/settings.json`:
20
36
 
21
37
  ```json
22
38
  {
@@ -27,16 +43,34 @@ The hooks are configured in `.claude/settings.local.json`:
27
43
  "hooks": [
28
44
  {
29
45
  "type": "command",
30
- "command": "python .claude/hooks/user-prompt-submit.py",
46
+ "command": "bun .claude/hooks/run-hook.ts user-prompt-submit",
31
47
  "timeout": 10
32
48
  }
33
49
  ]
34
50
  }
51
+ ],
52
+ "Stop": [
53
+ {
54
+ "hooks": [
55
+ {
56
+ "type": "command",
57
+ "command": "bun .claude/hooks/run-hook.ts stop-validator",
58
+ "timeout": 30
59
+ }
60
+ ]
61
+ }
35
62
  ]
36
63
  }
37
64
  }
38
65
  ```
39
66
 
67
+ ## How It Works
68
+
69
+ 1. Claude Code calls `bun .claude/hooks/run-hook.ts <hook-name>`
70
+ 2. `run-hook.ts` checks for available runtimes in priority order
71
+ 3. First available runtime executes the corresponding hook file (.py or .ts)
72
+ 4. If no runtime is available, returns safe default to avoid blocking
73
+
40
74
  ## Environment Variables
41
75
 
42
76
  | Variable | Default | Description |
@@ -47,6 +81,46 @@ The hooks are configured in `.claude/settings.local.json`:
47
81
 
48
82
  ### Hooks not executing
49
83
 
50
- 1. Verify Python is in PATH
51
- 2. Check `.claude/settings.local.json` hooks configuration
52
- 3. Ensure hook files have execute permissions
84
+ 1. Verify Bun is in PATH: `bun --version`
85
+ 2. If Python is preferred, verify: `python3 --version` or `python --version`
86
+ 3. Check `.claude/settings.json` hooks configuration
87
+ 4. Ensure hook files exist in `.claude/hooks/`
88
+
89
+ ### "python: not found" error
90
+
91
+ This error occurs when Python is not installed or not in PATH. The universal runner will automatically fallback to TypeScript hooks run by Bun.
92
+
93
+ **Solutions:**
94
+
95
+ 1. **Install Python** (recommended for full functionality):
96
+ - Windows: `winget install Python.Python.3.12` or download from python.org
97
+ - Linux: `apt install python3` or `dnf install python3`
98
+ - Mac: `brew install python3`
99
+
100
+ 2. **Use Bun only** (already configured):
101
+ - TypeScript fallback hooks are automatically used when Python is unavailable
102
+ - No additional setup required
103
+
104
+ ### Runtime detection failed
105
+
106
+ If you see `[run-hook] No runtime available`:
107
+
108
+ 1. Ensure at least one runtime is installed: python3, python, bun, or Node.js
109
+ 2. Verify the runtime is in your system PATH
110
+ 3. For Bun: `curl -fsSL https://bun.sh/install | bash`
111
+ 4. For Node.js (npx tsx): Install from nodejs.org
112
+
113
+ ## Testing Hooks
114
+
115
+ Test the hook runner manually:
116
+
117
+ ```bash
118
+ # Test with Bun
119
+ echo '{}' | bun .claude/hooks/run-hook.ts user-prompt-submit
120
+
121
+ # Test with Python (if available)
122
+ echo '{}' | python3 .claude/hooks/user-prompt-submit.py
123
+
124
+ # Test stop-validator
125
+ echo '{}' | bun .claude/hooks/run-hook.ts stop-validator
126
+ ```
@@ -0,0 +1,46 @@
1
+ @echo off
2
+ REM Universal Hook Runner for Windows
3
+ REM Tries: python -> python3 -> bun -> npx tsx
4
+
5
+ set HOOK_NAME=%1
6
+ set HOOKS_DIR=%~dp0
7
+
8
+ REM Try Python first
9
+ where python >nul 2>&1
10
+ if %ERRORLEVEL% EQU 0 (
11
+ if exist "%HOOKS_DIR%%HOOK_NAME%.py" (
12
+ python "%HOOKS_DIR%%HOOK_NAME%.py"
13
+ exit /b %ERRORLEVEL%
14
+ )
15
+ )
16
+
17
+ REM Try Python3
18
+ where python3 >nul 2>&1
19
+ if %ERRORLEVEL% EQU 0 (
20
+ if exist "%HOOKS_DIR%%HOOK_NAME%.py" (
21
+ python3 "%HOOKS_DIR%%HOOK_NAME%.py"
22
+ exit /b %ERRORLEVEL%
23
+ )
24
+ )
25
+
26
+ REM Try Bun with TypeScript
27
+ where bun >nul 2>&1
28
+ if %ERRORLEVEL% EQU 0 (
29
+ if exist "%HOOKS_DIR%%HOOK_NAME%.ts" (
30
+ bun "%HOOKS_DIR%%HOOK_NAME%.ts"
31
+ exit /b %ERRORLEVEL%
32
+ )
33
+ )
34
+
35
+ REM Try npx tsx as final fallback
36
+ where npx >nul 2>&1
37
+ if %ERRORLEVEL% EQU 0 (
38
+ if exist "%HOOKS_DIR%%HOOK_NAME%.ts" (
39
+ npx tsx "%HOOKS_DIR%%HOOK_NAME%.ts"
40
+ exit /b %ERRORLEVEL%
41
+ )
42
+ )
43
+
44
+ REM No runtime available - return safe default
45
+ echo {"decision":"approve","reason":"No runtime available for hook, allowing by default"}
46
+ exit /b 0
@@ -0,0 +1,43 @@
1
+ #!/bin/bash
2
+ # Universal Hook Runner for Unix/Linux/Mac
3
+ # Tries: python3 -> python -> bun -> npx tsx
4
+
5
+ HOOK_NAME="$1"
6
+ HOOKS_DIR="$(dirname "$0")"
7
+
8
+ # Check if a command exists
9
+ command_exists() {
10
+ command -v "$1" >/dev/null 2>&1
11
+ }
12
+
13
+ # Try Python3 first
14
+ if command_exists python3; then
15
+ if [ -f "$HOOKS_DIR/$HOOK_NAME.py" ]; then
16
+ exec python3 "$HOOKS_DIR/$HOOK_NAME.py"
17
+ fi
18
+ fi
19
+
20
+ # Try Python
21
+ if command_exists python; then
22
+ if [ -f "$HOOKS_DIR/$HOOK_NAME.py" ]; then
23
+ exec python "$HOOKS_DIR/$HOOK_NAME.py"
24
+ fi
25
+ fi
26
+
27
+ # Try Bun with TypeScript
28
+ if command_exists bun; then
29
+ if [ -f "$HOOKS_DIR/$HOOK_NAME.ts" ]; then
30
+ exec bun "$HOOKS_DIR/$HOOK_NAME.ts"
31
+ fi
32
+ fi
33
+
34
+ # Try npx tsx as final fallback
35
+ if command_exists npx; then
36
+ if [ -f "$HOOKS_DIR/$HOOK_NAME.ts" ]; then
37
+ exec npx tsx "$HOOKS_DIR/$HOOK_NAME.ts"
38
+ fi
39
+ fi
40
+
41
+ # No runtime available - return safe default
42
+ echo '{"decision":"approve","reason":"No runtime available for hook, allowing by default"}'
43
+ exit 0
@@ -0,0 +1,158 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Universal Hook Runner
4
+ *
5
+ * Runs hooks with multiple runtime fallbacks:
6
+ * 1. python3 (primary - user's preferred)
7
+ * 2. python (fallback)
8
+ * 3. Bun TypeScript (fallback if Python not available)
9
+ * 4. npx tsx (final fallback)
10
+ *
11
+ * Usage: bun run-hook.ts <hook-name>
12
+ * The hook-name should be without extension (e.g., "stop-validator")
13
+ */
14
+
15
+ import { spawnSync } from 'child_process';
16
+ import { existsSync } from 'fs';
17
+ import { join, dirname } from 'path';
18
+ import { fileURLToPath } from 'url';
19
+
20
+ // Get hooks directory - handle both ESM and CJS contexts
21
+ const getHooksDir = (): string => {
22
+ try {
23
+ if (typeof import.meta.url !== 'undefined') {
24
+ return dirname(fileURLToPath(import.meta.url));
25
+ }
26
+ } catch {
27
+ // Fallback for environments where import.meta is not available
28
+ }
29
+ return process.cwd();
30
+ };
31
+
32
+ const HOOKS_DIR = getHooksDir();
33
+
34
+ function checkRuntime(cmd: string): boolean {
35
+ try {
36
+ const result = spawnSync(cmd, ['--version'], {
37
+ stdio: 'pipe',
38
+ shell: true,
39
+ timeout: 5000,
40
+ windowsHide: true
41
+ });
42
+ return result.status === 0;
43
+ } catch {
44
+ return false;
45
+ }
46
+ }
47
+
48
+ function runWithRuntime(cmd: string, args: string[], input: string): { success: boolean; output: string; error?: string } {
49
+ try {
50
+ const result = spawnSync(cmd, args, {
51
+ input,
52
+ shell: true,
53
+ stdio: ['pipe', 'pipe', 'pipe'],
54
+ timeout: 30000,
55
+ windowsHide: true,
56
+ encoding: 'utf8'
57
+ });
58
+
59
+ return {
60
+ success: result.status === 0,
61
+ output: result.stdout?.toString() || '',
62
+ error: result.stderr?.toString() || undefined
63
+ };
64
+ } catch (err) {
65
+ return {
66
+ success: false,
67
+ output: '',
68
+ error: err instanceof Error ? err.message : 'Unknown error'
69
+ };
70
+ }
71
+ }
72
+
73
+ async function runHook(hookName: string, stdinData: string): Promise<void> {
74
+ const tsPath = join(HOOKS_DIR, `${hookName}.ts`);
75
+ const pyPath = join(HOOKS_DIR, `${hookName}.py`);
76
+
77
+ // Runtime detection order - Python FIRST, then fallbacks
78
+ const runtimes: Array<{ name: string; cmd: string; ext: string }> = [
79
+ { name: 'python3', cmd: 'python3', ext: '.py' },
80
+ { name: 'python', cmd: 'python', ext: '.py' },
81
+ { name: 'bun-ts', cmd: 'bun', ext: '.ts' },
82
+ { name: 'npx-tsx', cmd: 'npx tsx', ext: '.ts' }
83
+ ];
84
+
85
+ for (const runtime of runtimes) {
86
+ const hookPath = runtime.ext === '.ts' ? tsPath : pyPath;
87
+
88
+ if (!existsSync(hookPath)) {
89
+ continue;
90
+ }
91
+
92
+ if (!checkRuntime(runtime.cmd.split(' ')[0])) {
93
+ continue;
94
+ }
95
+
96
+ const result = runWithRuntime(runtime.cmd, [hookPath], stdinData);
97
+
98
+ if (result.success || !result.error?.includes('not found')) {
99
+ // Runtime worked (success or runtime-specific failure)
100
+ process.stdout.write(result.output);
101
+ if (result.error && !result.success) {
102
+ process.stderr.write(result.error);
103
+ }
104
+ process.exit(result.success ? 0 : 1);
105
+ }
106
+ // Runtime not available, try next
107
+ }
108
+
109
+ // No runtime available - return safe default
110
+ console.error(`[run-hook] No runtime available to run hook: ${hookName}`);
111
+ console.error('[run-hook] Please install one of: python3, python, bun, or Node.js');
112
+ const safeDefault = JSON.stringify({
113
+ decision: 'approve',
114
+ continue: true,
115
+ reason: 'Hook runtime not available, allowing by default'
116
+ });
117
+ process.stdout.write(safeDefault);
118
+ process.exit(0);
119
+ }
120
+
121
+ async function readStdinWithTimeout(timeoutMs: number): Promise<string> {
122
+ return new Promise((resolve) => {
123
+ const timeout = setTimeout(() => resolve('{}'), timeoutMs);
124
+
125
+ Bun.stdin.text().then((text) => {
126
+ clearTimeout(timeout);
127
+ resolve(text || '{}');
128
+ }).catch(() => {
129
+ clearTimeout(timeout);
130
+ resolve('{}');
131
+ });
132
+ });
133
+ }
134
+
135
+ // Main
136
+ async function main(): Promise<void> {
137
+ const hookName = process.argv[2];
138
+ if (!hookName) {
139
+ console.error('Usage: bun run-hook.ts <hook-name>');
140
+ process.exit(1);
141
+ }
142
+
143
+ // Read stdin with timeout to avoid hanging
144
+ const stdinData = await readStdinWithTimeout(2000);
145
+ await runHook(hookName, stdinData);
146
+ }
147
+
148
+ main().catch((err) => {
149
+ console.error('[run-hook] Fatal error:', err);
150
+ // Return safe default on error
151
+ const safeDefault = JSON.stringify({
152
+ decision: 'approve',
153
+ continue: true,
154
+ reason: 'Hook runner error, allowing by default'
155
+ });
156
+ process.stdout.write(safeDefault);
157
+ process.exit(0);
158
+ });