@monks1975/opencode-agent-hooks 1.0.0 → 1.0.1

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
@@ -9,7 +9,7 @@ Add the plugin to a project's `opencode.json`, or to `~/.config/opencode/opencod
9
9
  ```json
10
10
  {
11
11
  "$schema": "https://opencode.ai/config.json",
12
- "plugin": ["@monks1975/opencode-agent-hooks@1.0.0"]
12
+ "plugin": ["@monks1975/opencode-agent-hooks@1.0.1"]
13
13
  }
14
14
  ```
15
15
 
package/package.json CHANGED
@@ -1,9 +1,13 @@
1
1
  {
2
2
  "name": "@monks1975/opencode-agent-hooks",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "OpenCode plugin that runs Claude Code and Codex hook configs unmodified",
5
5
  "type": "module",
6
- "exports": "./src/index.ts",
6
+ "main": "./src/index.ts",
7
+ "exports": {
8
+ ".": "./src/index.ts",
9
+ "./server": "./src/index.ts"
10
+ },
7
11
  "files": [
8
12
  "src/index.ts"
9
13
  ],
@@ -11,7 +15,8 @@
11
15
  "test": "node --test src/index.test.ts"
12
16
  },
13
17
  "devDependencies": {
14
- "@opencode-ai/plugin": "^1.17.12"
18
+ "@opencode-ai/plugin": "^1.17.12",
19
+ "@types/node": "^24.13.2"
15
20
  },
16
21
  "keywords": [
17
22
  "opencode",
package/src/index.ts CHANGED
@@ -2,7 +2,11 @@ import type { Plugin } from "@opencode-ai/plugin"
2
2
  import { spawn } from "node:child_process"
3
3
  import { existsSync, readFileSync } from "node:fs"
4
4
  import { homedir } from "node:os"
5
- import { join } from "node:path"
5
+ import { join, parse } from "node:path"
6
+
7
+ // Keep in sync with package.json; logged at boot so stale plugin caches are
8
+ // visible in the opencode log.
9
+ const VERSION = "1.0.1"
6
10
 
7
11
  //
8
12
  // Generic OpenCode adapter for the Claude Code hook schema.
@@ -355,7 +359,10 @@ function runCommand(
355
359
  }
356
360
 
357
361
  export const server: Plugin = async ({ directory, worktree, client }) => {
358
- const projectDir = worktree ?? directory
362
+ // In a non-git directory opencode assigns the "global" project, whose
363
+ // worktree is the filesystem root — hooks config lives where the session
364
+ // was opened, so only trust worktree when it points at a real project.
365
+ const projectDir = worktree && parse(worktree).root !== worktree ? worktree : directory
359
366
  const log: Logger = (message, level = "info") =>
360
367
  client.app.log({ body: { service: "claude-hooks", level, message } }).catch(() => {})
361
368
 
@@ -363,6 +370,15 @@ export const server: Plugin = async ({ directory, worktree, client }) => {
363
370
  const config = loadHookConfig(projectDir, userConfigDir, log)
364
371
  const env = { ...process.env, CLAUDE_PROJECT_DIR: projectDir }
365
372
 
373
+ // One line on every boot so a silent skip is distinguishable from a healthy
374
+ // load (opencode itself logs nothing when a plugin registers).
375
+ const summary = EVENTS
376
+ .map((event) => [event, (config[event] ?? []).flatMap((g) => g.hooks ?? []).length] as const)
377
+ .filter(([, count]) => count > 0)
378
+ .map(([event, count]) => `${count} ${event}`)
379
+ .join(", ")
380
+ log(`opencode-agent-hooks ${VERSION}: ${summary ? `loaded ${summary}` : "no hooks configured"} (project: ${projectDir})`)
381
+
366
382
  // toolName undefined = lifecycle event; Claude ignores matchers there.
367
383
  const matchingHooks = (event: ClaudeEvent, toolName?: string): HookCommand[] =>
368
384
  (config[event] ?? [])