Skip to content

fix(plugin): remove the duplicate hooks key from the installed manifest - #27

Merged
kherembourg merged 1 commit into
mainfrom
fix/duplicate-hooks-nested-manifest
Sep 2, 2026
Merged

kherembourg merged 1 commit into
mainfrom
fix/duplicate-hooks-nested-manifest

Conversation

@kherembourg

Copy link
Copy Markdown
Contributor

Symptom

A fresh claude plugin install purchasely@Purchasely-AI-Plugin loads the skills, the commands and the agent, but claude plugin list reports the plugin as broken:

❯ purchasely@Purchasely-AI-Plugin
    Version: 2.0.0-rc.5
    Scope: user
    Status: ✘ failed to load
    Error: Hook load failed: Duplicate hooks file detected: ./hooks/hooks.json
    resolves to already-loaded file
    /Users/…/.claude/plugins/cache/Purchasely-AI-Plugin/purchasely/2.0.0/hooks/hooks.json.
    The standard hooks/hooks.json is loaded automatically, so manifest.hooks
    should only reference additional hook files.

The consequence is the SessionStart hook: hooks/intro.md never reaches the session, so the routing text that tells the agent which skill to load is missing.

Cause

Claude Code loads hooks/hooks.json by convention. A manifest that declares it again is a duplicate.

2.0.0-rc.6 already fixed this, but in the wrong file. It removed the key from the root .claude-plugin/plugin.json, while .claude-plugin/marketplace.json installs "source": "./purchasely". The manifest the harness actually reads is purchasely/.claude-plugin/plugin.json, and that one kept "hooks": "./hooks/hooks.json" through 2.0.0, 2.0.1 and 2.1.0.

Checked the other manifests: purchasely/.cursor-plugin/plugin.json, purchasely/.codex-plugin/plugin.json, .claude-plugin/plugin.json and .cursor-plugin/plugin.json declare no hooks key. One line changes.

Verification

Installed the fixed copy from a local marketplace, uninstalled afterwards:

$ claude plugin list
❯ purchasely@Purchasely-AI-Plugin
    Version: 2.1.0
    Status: ✔ enabled

$ claude plugin details purchasely@Purchasely-AI-Plugin
  Skills (9)  …
  Hooks (1)  SessionStart  (harness-only — no model context cost)

Status goes from ✘ failed to load to ✔ enabled, and the hook is inventoried.

A 2.1.1 release follows this merge.

🤖 Generated with Claude Code

Claude Code loads hooks/hooks.json by convention, so a manifest that also
declares it fails to load:

  Hook load failed: Duplicate hooks file detected: ./hooks/hooks.json
  resolves to already-loaded file .../purchasely/2.0.0/hooks/hooks.json

The skills, the commands and the agent still loaded, the SessionStart hook
did not, and claude plugin list reported the plugin as failed.

2.0.0-rc.6 removed the same key from the root .claude-plugin/plugin.json, but
the marketplace entry installs ./purchasely, so the nested manifest is the one
that reaches the harness and it kept the key.

Verified with a real install from a local marketplace: status goes from
"failed to load" to "enabled", and claude plugin details reports
Hooks (1) SessionStart.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Sep 2, 2026

Copy link
Copy Markdown

Greptile Summary

Removes the redundant hook declaration from the nested Claude plugin manifest so marketplace installations rely on Claude Code’s conventional hooks/hooks.json discovery and no longer fail duplicate-hook validation.

  • Updates the changelog with the failure mechanism, affected installation path, and corrected behavior.
  • Leaves the packaged SessionStart hook assets in place for automatic discovery.

Confidence Score: 5/5

The PR appears safe to merge because it removes the duplicate registration while preserving the conventionally loaded SessionStart hook.

The marketplace installs the nested package, its hook assets remain present, and the removed manifest entry was the duplicate reference preventing Claude Code from loading the plugin successfully.

Important Files Changed

Filename Overview
purchasely/.claude-plugin/plugin.json Removes the duplicate explicit hook path while retaining the conventionally discovered hook file in the installed package.
CHANGELOG.md Accurately documents the duplicate-hook failure, marketplace source mapping, and scope of the fix.

Reviews (1): Last reviewed commit: "fix(plugin): remove the duplicate hooks ..." | Re-trigger Greptile

@kherembourg
kherembourg merged commit 08d98d2 into main Sep 2, 2026
3 checks passed
@kherembourg
kherembourg deleted the fix/duplicate-hooks-nested-manifest branch September 2, 2026 13:44
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.

2 participants