Skip to content

fix(plugin): point Claude plugin.json at hooks/hooks.json so Cursor wrappers are not loaded - #450

Merged
ScriptedAlchemy merged 3 commits into
mainfrom
fix/claude-hook-event-name
Sep 3, 2026
Merged

fix(plugin): point Claude plugin.json at hooks/hooks.json so Cursor wrappers are not loaded#450
ScriptedAlchemy merged 3 commits into
mainfrom
fix/claude-hook-event-name

Conversation

@ScriptedAlchemy

Copy link
Copy Markdown
Owner

Summary

  • Unified plugin bundles emit both hooks/hooks.json (Claude/Codex, PascalCase PreToolUse/PostToolUse) and hooks/hooks-cursor.json (Cursor, camelCase preToolUse/postToolUse).
  • .claude-plugin/plugin.json omitted hooks, so Claude Code could discover the Cursor document and invoke .cursor.mjs wrappers. That produced native hook_event_name must equal postToolUse on every Claude PostToolUse.
  • The Claude manifest now names ./hooks/hooks.json. Tests pin both host spellings.

Test plan

  • rstest packages/agent-bundle/tests/plugin-claude-hook-manifest.test.ts
  • CI green on this PR
  • Confirm a rebuilt unified plugin artifact's .claude-plugin/plugin.json contains "hooks": "./hooks/hooks.json"

Claude Code was discovering hooks/hooks-cursor.json beside the shared
hooks.json and invoking Cursor wrappers that expect camelCase
hook_event_name values.
@changeset-bot

changeset-bot Bot commented Sep 3, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 27e8f4a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
agent-bundle Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 3, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-03T21:47:37.361469Z 27e8f4a Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@pkg-pr-new

pkg-pr-new Bot commented Sep 3, 2026

Copy link
Copy Markdown
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle@450
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle/create-agent-bundle@450
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@450

commit: 27e8f4a

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b69f3b7042

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

"agent-bundle": patch
---

Point the unified `plugin` bundle's `.claude-plugin/plugin.json` `hooks` field at `./hooks/hooks.json` so Claude Code loads the Claude/Codex document instead of also discovering `hooks/hooks-cursor.json` and invoking Cursor wrappers that expect camelCase `hook_event_name` values (`preToolUse` / `postToolUse`).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Append the PR reference to the changeset summary

The new changeset summary ends without the required (#PR) suffix. When this changeset is consumed into the changelog, the release note will lack the repository-mandated PR traceability; append the applicable PR reference before merging.

AGENTS.md reference: AGENTS.md:L57-L58

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in d9bc62a (chore(changeset): reference #450): the summary now ends with (#450).

…document, not on pretty-printed spacing

The on-disk .claude-plugin/plugin.json is compact JSON, so the substring
'"hooks": "./hooks/hooks.json"' never matched. Parse and toMatchObject.
@ScriptedAlchemy

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Nice work!

Reviewed commit: 27e8f4adc4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ScriptedAlchemy
ScriptedAlchemy merged commit b8949ca into main Sep 3, 2026
13 checks passed
@ScriptedAlchemy
ScriptedAlchemy deleted the fix/claude-hook-event-name branch September 3, 2026 21:59
ScriptedAlchemy added a commit that referenced this pull request Sep 3, 2026
… duplicate; pin every Claude hook_event_name (#470)

* fix(claude): drop the manifest hooks pointer and pin every Claude hook_event_name

Claude Code loads `hooks/hooks.json` on its own; `manifest.hooks` is only
for additional documents. The `claude` target has named `./hooks/hooks.json`
there since b256d44 and #450 added the same pointer to the unified
`plugin` bundle. Claude Code 2.1.259 records a `hook-load-failed` plugin
error for it: "Duplicate hooks file detected: ./hooks/hooks.json resolves
to already-loaded file ... The standard hooks/hooks.json is loaded
automatically, so manifest.hooks should only reference additional hook
files" (reproduced with an isolated CLAUDE_CONFIG_DIR against a built
Claude pack).

#450's stated root cause does not hold: Claude Code never scans `hooks/`
for other documents, so `hooks/hooks-cursor.json` is invisible to it. The
live "native hook_event_name must equal postToolUse" errors came from the
Claude wrapper path (`event-route-tool-after.mjs`, per the session
transcript) during a rebuild/reinstall window of a directory marketplace,
whose `${CLAUDE_PLUGIN_ROOT}` is the build output itself; only a
Cursor-built wrapper bakes that camelCase constant.

- claude.ts / plugin.ts: emit no `hooks` field on `.claude-plugin/plugin.json`.
- tests/claude-hook-event-name.test.ts: for every supported Claude event
  route, the planned wrapper bakes the pinned PascalCase name, the hooks
  document is keyed by it, and a real Claude envelope passes
  validateNativeEventEnvelope; the live PostToolUse:Bash envelope is
  accepted by the Claude wrapper and rejected with the exact observed
  message only under a Cursor-baked validation; the unified bundle keeps
  `.mjs`/`.cursor.mjs` spellings apart; no Claude manifest pointer.
- docs (en+zh hooks.mdx, installation.mdx) state the loader behavior.

* chore(changeset): reference #470

---------

Co-authored-by: Ubuntu <zack@ubuntu-main.local>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant