[BUG] /plugin "Will install" iterates hooks path as char/index list
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
The /plugin interface's "Will install" preview, shown before installing a plugin, renders the marketplace entry's hooks field by iterating it as a generic collection and displaying the iteration keys (character indices for strings, array indices for arrays) instead of resolving the path or showing meaningful hook info.
For a marketplace entry declaring hooks as a documented string-path:
"hooks": "./hooks/hooks.json"
…the preview shows:
Will install:
· Hooks: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17
Those are the character indices of the path string ./hooks/hooks.json (18 chars, indices 0–17).
Switching to array form:
"hooks": ["./hooks/hooks.json"]
…produces:
Will install:
· Hooks: 0
…which is the index of the single array element. This is misleading: it suggests the plugin contains zero hooks, when in fact the plugin has a valid hooks/hooks.json at the default path that is correctly auto-discovered at install time. Functionality is unaffected — only the preview UI is wrong.
Related to but distinct from #41943: that issue is in the /reload-plugins code path and crashes only when the plugin has no plugin.json. The bug in this report is in the /plugin preview UI and triggers even when the plugin has a complete plugin.json.
What Should Happen?
The preview should resolve the hooks value correctly. In order of preference:
- Resolve string-paths and array-of-paths against the plugin source, read the referenced
hooks.json, and display a meaningful summary (e.g.,Hooks: SessionStart (1)). - Failing that, show a stable count (e.g.,
Hooks: 1 hook config declared). - Failing that, fall back to the existing
Component summary not available for remote pluginmessage — which, despite being terse, is more honest thanHooks: 0(which is actively wrong).
Error Messages/Logs
(No error output — pure UI rendering bug; no exception thrown.)
Steps to Reproduce
- Create a minimal plugin with a hooks file. Layout:
````
repro-plugin/
├── .claude-plugin/plugin.json
├── hooks/hooks.json
└── skills/example/SKILL.md
repro-plugin/.claude-plugin/plugin.json:
``json``
{ "name": "repro-plugin", "description": "Repro for hooks preview bug." }
repro-plugin/hooks/hooks.json:
``json``
{
"hooks": {
"SessionStart": [
{ "hooks": [{ "type": "command", "command": "echo hello" }] }
]
}
}
repro-plugin/skills/example/SKILL.md:
``markdown``
---
description: Example skill
---
Hello.
- Push the plugin to a GitHub repo (
<owner>/repro-plugin).
- Create a marketplace repo with
.claude-plugin/marketplace.json:
``json``
{
"name": "repro-marketplace",
"owner": { "name": "Example" },
"plugins": [
{
"name": "repro-plugin",
"description": "Repro for hooks preview bug.",
"source": { "source": "github", "repo": "<owner>/repro-plugin" },
"hooks": "./hooks/hooks.json"
}
]
}
- In Claude Code:
````
/plugin marketplace add <owner>/repro-marketplace
/plugin
- Navigate to Discover →
repro-plugin→ press Enter.
- Observe the Will install section.
- Expected:
Hooks: SessionStart (1)or similar meaningful summary. - Actual:
Hooks: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17.
- (Variant) Change the marketplace entry to
"hooks": ["./hooks/hooks.json"], run/plugin marketplace update repro-marketplace, repeat the preview. Now the bug showsHooks: 0.
Claude Model
Not sure / Multiple models
Is this a regression?
I don't know
Claude Code Version
2.1.123 (Claude Code)
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
VS Code integrated terminal
Additional Information
Workaround: remove the hooks field from the marketplace entry. Hooks are then auto-discovered from ${CLAUDE_PLUGIN_ROOT}/hooks/hooks.json at install time and the plugin works correctly. This means the marketplace hooks field is currently unusable for path-based declarations — it only works for inline object form (which duplicates content already in the plugin repo).
Related: #41943 — same field/declaration triggers a different downstream bug (a reduce is not a function crash in /reload-plugins) when the plugin has no plugin.json. The root cause analysis there suggests the marketplace's hooks string is being passed downstream where a resolved hook config object is expected. The bug reported here is likely the same root cause manifesting in a different code path (the /plugin preview UI).
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗