@goodfoot/claude-code-hooks 1.0.1 → 1.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.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @goodfoot/claude-code-hooks
2
2
 
3
- > **Build Claude Code hooks in TypeScript.**
3
+ **Build Claude Code hooks in TypeScript.**
4
4
 
5
5
  This package is not just a library; it is a **build system** and a **runtime wrapper**. You write TypeScript, this package compiles it into self-contained executables, and _those_ are what Claude runs.
6
6
 
@@ -10,11 +10,11 @@ Load the "claude-code-hooks:sdk" skill to enable Claude to use this package.
10
10
 
11
11
  Run:
12
12
 
13
- ```bash
14
- claude plugin marketplace add goodfoot-io/marketplace && claude plugin install claude-code-hooks@goodfoot"
13
+ `claude plugin marketplace add goodfoot-io/marketplace && claude plugin install claude-code-hooks@goodfoot"`
15
14
 
16
- claude -p "Load the 'claude-code-hooks:sdk' skill then scaffold a new hook package in ./packages/hooks that outputs to '.claude/hooks/hooks.json' and contains an example SessionStart hook."
17
- ```
15
+ then:
16
+
17
+ `claude -p "Load the 'claude-code-hooks:sdk' skill then scaffold a new hook package in ./packages/hooks that outputs to '.claude/hooks/hooks.json' and contains an example SessionStart hook."`
18
18
 
19
19
  ## ⚡ Quick Start
20
20
 
@@ -157,9 +157,9 @@ Violating these rules will cause your hooks to fail silently or block Claude ent
157
157
 
158
158
  1. **NO `console.log`**: The hook communicates with Claude via `stdout`. If you print "Hello world", you corrupt the JSON protocol.
159
159
  - **Bad:** `console.log("Checking command")`
160
- - **Good:** `context.logger.info("Checking command")`
161
- 2. **Relative Paths via Environment Variable**: The generated `hooks.json` uses `node $CLAUDE_PLUGIN_ROOT/hooks/build/` paths.
162
- - Compiled hooks are placed in a `build/` subdirectory relative to `hooks.json`.
160
+ - **Good:** `logger.info("Checking command")`
161
+ 2. **Relative Paths via Environment Variable**: The generated `hooks.json` uses `node $CLAUDE_PLUGIN_ROOT/hooks/bin/` paths.
162
+ - Compiled hooks are placed in a `bin/` subdirectory relative to `hooks.json`.
163
163
  - The `$CLAUDE_PLUGIN_ROOT` environment variable is set by Claude Code at runtime.
164
164
  - Use the `--executable` CLI option to specify a custom executable (e.g., `bun`, `/usr/local/bin/node22`).
165
165
  3. **`export default` is Mandatory**: The CLI uses static analysis to find your hooks. It looks specifically for `export default factory(...)`.
@@ -252,7 +252,7 @@ plugins/my-plugin/
252
252
  │ ├── block-dangerous.ts
253
253
  │ └── inject-context.ts
254
254
  ├── hooks.json # Build output (auto-loaded by plugin)
255
- └── build/
255
+ └── bin/
256
256
  ├── block-dangerous.abc123.mjs
257
257
  └── inject-context.def456.mjs
258
258
  ```
package/dist/cli.js CHANGED
@@ -89,7 +89,7 @@ Examples:
89
89
  npx -y @goodfoot/claude-code-hooks -i "hooks/**/*.ts" -o "dist/hooks.json"
90
90
 
91
91
  2. With Runtime Logging:
92
- npx -y @goodfoot/claude-code-hooks -i "src/hooks/*.ts" -o "build/hooks.json" --log /tmp/claude-hooks.log
92
+ npx -y @goodfoot/claude-code-hooks -i "src/hooks/*.ts" -o "bin/hooks.json" --log /tmp/claude-hooks.log
93
93
 
94
94
  3. Scaffold a New Hook Project:
95
95
  npx -y @goodfoot/claude-code-hooks --scaffold ./my-hooks --hooks Stop,SubagentStop -o dist/hooks.json
@@ -575,19 +575,19 @@ function detectHookContext(outputPath) {
575
575
  /**
576
576
  * Generates a command path based on the hook context.
577
577
  *
578
- * Calculates the relative path from the root directory to the build directory.
578
+ * Calculates the relative path from the root directory to the bin directory.
579
579
  * Prepends the node executable.
580
580
  *
581
- * - `plugin`: Uses `node $CLAUDE_PLUGIN_ROOT/hooks/build/filename`
582
- * - `agent`: Uses `node "$CLAUDE_PROJECT_DIR"/.claude/hooks/build/filename`
581
+ * - `plugin`: Uses `node $CLAUDE_PLUGIN_ROOT/hooks/bin/filename`
582
+ * - `agent`: Uses `node "$CLAUDE_PROJECT_DIR"/.claude/hooks/bin/filename`
583
583
  * @param filename - The compiled hook filename
584
- * @param buildDir - Absolute path to the build directory
584
+ * @param buildDir - Absolute path to the bin directory
585
585
  * @param contextInfo - Hook context info including root directory
586
586
  * @param executable - Node executable path (default: "node")
587
587
  * @returns The command path string
588
588
  */
589
589
  function generateCommandPath(filename, buildDir, contextInfo, executable = 'node') {
590
- // Calculate relative path from root to build directory
590
+ // Calculate relative path from root to bin directory
591
591
  const relativeBuildPath = path.relative(contextInfo.rootDir, buildDir);
592
592
  // Normalize to forward slashes for cross-platform compatibility
593
593
  const normalizedRelativePath = relativeBuildPath.replace(/\\/g, '/');
@@ -603,7 +603,7 @@ function generateCommandPath(filename, buildDir, contextInfo, executable = 'node
603
603
  *
604
604
  * Format: { hooks: { EventType: [ { matcher?, hooks: [...] } ] } }
605
605
  * @param compiledHooks - Array of compiled hooks
606
- * @param buildDir - Absolute path to the build directory
606
+ * @param buildDir - Absolute path to the bin directory
607
607
  * @param contextInfo - Hook context info for path resolution
608
608
  * @param executable - Node executable path (default: "node")
609
609
  * @returns The hooks.json structure
@@ -802,8 +802,8 @@ async function main() {
802
802
  const cwd = process.cwd();
803
803
  const outputPath = path.resolve(cwd, args.output);
804
804
  const hooksJsonDir = path.dirname(outputPath);
805
- // Compiled hooks go in a 'build' subdirectory relative to hooks.json
806
- const buildDir = path.join(hooksJsonDir, 'build');
805
+ // Compiled hooks go in a 'bin' subdirectory relative to hooks.json
806
+ const buildDir = path.join(hooksJsonDir, 'bin');
807
807
  // Resolve log file path to absolute if provided
808
808
  const logFilePath = args.log !== undefined ? path.resolve(cwd, args.log) : undefined;
809
809
  log('info', 'Starting hook compilation', {
package/dist/scaffold.js CHANGED
@@ -181,7 +181,7 @@ function generateBiomeConfig() {
181
181
  }
182
182
  },
183
183
  "files": {
184
- "ignore": ["node_modules", "dist", "build", "*.json"]
184
+ "ignore": ["node_modules", "dist", "bin", "*.json"]
185
185
  }
186
186
  }
187
187
  `;
@@ -220,7 +220,7 @@ node_modules/
220
220
 
221
221
  # Build outputs
222
222
  dist/
223
- build/
223
+ bin/
224
224
  *.mjs
225
225
 
226
226
  # Generated files
@@ -357,8 +357,8 @@ function generateTestFile(eventName, hookFilename) {
357
357
  * Tests for the ${eventName} hook.
358
358
  */
359
359
 
360
- import { describe, expect, it } from "vitest";
361
360
  import { Logger } from "@goodfoot/claude-code-hooks";
361
+ import { describe, expect, it } from "vitest";
362
362
  import hook from "../src/${hookFilename}.js";
363
363
 
364
364
  // Logger is silent by default (no stdout/stderr output) — no mocking needed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodfoot/claude-code-hooks",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Type-safe Claude Code hooks library with camelCase types and output builders",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -27,28 +27,18 @@
27
27
  },
28
28
  "exports": {
29
29
  ".": {
30
- "import": "./src/index.ts",
31
- "types": "./src/index.ts"
30
+ "import": "./dist/index.js",
31
+ "types": "./types/index.d.ts"
32
32
  },
33
33
  "./*": {
34
- "import": "./src/*.ts",
35
- "types": "./src/*.ts"
34
+ "import": "./dist/*.js",
35
+ "types": "./types/*.d.ts"
36
36
  }
37
37
  },
38
38
  "bin": "./dist/cli.js",
39
39
  "publishConfig": {
40
40
  "bin": {
41
41
  "claude-code-hooks": "./dist/cli.js"
42
- },
43
- "exports": {
44
- ".": {
45
- "import": "./dist/index.js",
46
- "types": "./types/index.d.ts"
47
- },
48
- "./*": {
49
- "import": "./dist/*.js",
50
- "types": "./types/*.d.ts"
51
- }
52
42
  }
53
43
  },
54
44
  "dependencies": {
package/types/cli.d.ts CHANGED
@@ -197,13 +197,13 @@ declare function detectHookContext(outputPath: string): HookContextInfo;
197
197
  /**
198
198
  * Generates a command path based on the hook context.
199
199
  *
200
- * Calculates the relative path from the root directory to the build directory.
200
+ * Calculates the relative path from the root directory to the bin directory.
201
201
  * Prepends the node executable.
202
202
  *
203
- * - `plugin`: Uses `node $CLAUDE_PLUGIN_ROOT/hooks/build/filename`
204
- * - `agent`: Uses `node "$CLAUDE_PROJECT_DIR"/.claude/hooks/build/filename`
203
+ * - `plugin`: Uses `node $CLAUDE_PLUGIN_ROOT/hooks/bin/filename`
204
+ * - `agent`: Uses `node "$CLAUDE_PROJECT_DIR"/.claude/hooks/bin/filename`
205
205
  * @param filename - The compiled hook filename
206
- * @param buildDir - Absolute path to the build directory
206
+ * @param buildDir - Absolute path to the bin directory
207
207
  * @param contextInfo - Hook context info including root directory
208
208
  * @param executable - Node executable path (default: "node")
209
209
  * @returns The command path string
@@ -219,7 +219,7 @@ declare function generateCommandPath(
219
219
  *
220
220
  * Format: { hooks: { EventType: [ { matcher?, hooks: [...] } ] } }
221
221
  * @param compiledHooks - Array of compiled hooks
222
- * @param buildDir - Absolute path to the build directory
222
+ * @param buildDir - Absolute path to the bin directory
223
223
  * @param contextInfo - Hook context info for path resolution
224
224
  * @param executable - Node executable path (default: "node")
225
225
  * @returns The hooks.json structure