fix(claude): validate plugin.json and marketplace.json explicitly; read the --json report on 2.1.259+ - #474
Conversation
…ad the --json report on 2.1.259+ A bundle directory that holds both .claude-plugin manifests is a marketplace to `claude plugin validate`, and a marketplace run never opens hooks/, skills/, agents/, or commands/. Name each manifest, gate --json on the probed version, attribute every finding to its file, and de-duplicate the marketplace run's plugins[N] plugin.json copies.
🦋 Changeset detectedLatest commit: 58818c3 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
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 |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: efa9701a8b
ℹ️ 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".
| args: Object.freeze([ | ||
| 'plugin', | ||
| 'validate', | ||
| validationTarget.path, |
There was a problem hiding this comment.
Update the published README to name both manifests
Package users following packages/agent-bundle/README.md:135-139 are still told that artifact validation runs claude plugin validate <bundle-dir> --strict, although this loop now validates plugin.json and the optional marketplace.json separately. The captured Claude behavior in packages/agent-bundle/src/adapters/capabilities/claude-2.1.250.json:803 confirms that directory validation selects the marketplace and does not inspect hook, skill, agent, or command files, so the README command recreates the blind spot fixed by this commit. Because packages/agent-bundle/package.json includes README.md in the published package, update it with the two manifest invocations and version-gated --json behavior.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 58818c3: the published README now shows the two manifest invocations (.claude-plugin/plugin.json, then .claude-plugin/marketplace.json), the 2.1.259 --json floor with the text fallback, and the AB6019–AB6021 mapping, matching the website guide and docs/diagnostics.md.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
commit: |
Summary
agent-bundle validate --artifactranclaude plugin validate <bundle-dir> --strict. The emitted Claude bundle places.claude-plugin/marketplace.jsonbeside.claude-plugin/plugin.json, and Claude Code resolves a directory that holds a marketplace manifest as a marketplace. A marketplace run validatesmarketplace.jsonand re-checks each local entry'splugin.json, but — quoting the official docs — "From a marketplace directory, Claude Code doesn't open the plugins' skill, agent, command, or hook files." Every hook, skill, and agent finding was therefore invisible to theclaudeandplugintargets, while the host report saidpassed.This PR:
claude plugin validate <dir>/.claude-plugin/plugin.json --strict(coversplugin.json,hooks/hooks.json,skills/,agents/,commands/) and then, when the bundle emits one,claude plugin validate <dir>/.claude-plugin/marketplace.json --strict. Falls back to the directory only whenplugin.jsonis absent.--jsonwhen the probed CLI is ≥ 2.1.259 and parses the documented report (success/strict/target/manifest/contents[]); older releases (CI pins 2.1.250, which answerserror: unknown option '--json') keep the text report, now parsed with itsValidating <type>: <file>headers.AB6020/AB6021to its file viageneratedPathand Claude's field path, e.g.Claude plugin validation (hooks hooks/hooks.json): hooks: hooks.postToolUse: unknown hook event; entry ignored at runtime.plugins[N] plugin.json → …copies of manifest findings the plugin run already reported; surfacesnotesas info; a ≥2.1.259 run that returns no JSON (exit 2 writes only to stderr) isAB6022carrying that stderr.native-claude-contract.ts) atplugin.jsonfor the same reason.AB6019–AB6022indocs/diagnostics.md(previously listed nowhere), updates the validation guide (en + zh) with the two commands, the--jsonfloor, and theclaude --plugin-dir artifact/claude+/reload-pluginsdev loop, and records the evidence in the Claude capability JSON and schemaPROVENANCE.json.Evidence (official Claude Code docs, uploaded markdown)
plugin-marketplaces-0.md→ Troubleshooting › Marketplace validation errors (L1338–1348): a marketplace-directory run checksmarketplace.json, duplicate names, path traversal, and each local entry'splugin.json(prefixedplugins[2] plugin.json →); "From a marketplace directory, Claude Code doesn't open the plugins' skill, agent, command, or hook files."plugin-marketplaces-0.md→ Validate a plugin or a directory without a manifest › Pick the directory to name (L1375–1381): a plugin run checksplugin.json,hooks/hooks.json, and theskills,agents, andcommandsdirectories at the plugin root.plugins-reference-1.md→ CLI commands reference › plugin validate (L1212–1242): exit codes 0/1/2;--json"Requires Claude Code v2.1.259 or later"; report fieldssuccess,strict,target,manifest(ornull),contentsper-file witherrors,warnings,notes; "On exit 2, the command writes nothing to stdout; the error message goes to stderr."plugins-0.md→ Test your plugins locally (L290–309):claude --plugin-dir ./my-plugin;/reload-plugins"reloads plugins, skills, agents, hooks, plugin MCP servers, and plugin LSP servers."plugins-reference-1.md→ plugin list (L1157):--plugin-dirplugins appear inclaude plugin list"only when the same flag precedes the subcommand."Reproduction on this machine (Claude Code 2.1.259 and the CI pin 2.1.250)
Bundle with two unknown manifest fields, an agent without
description, and ahooks.jsonwith an unknown hook type and a miscasedpostToolUseevent:claude plugin validate . --strict(old behaviour)Validating marketplace manifest→ only the 2 manifest warnings; hooks and agents never mentionedclaude plugin validate .claude-plugin/plugin.json --strictagents/bad.mdwarning + 2hooks/hooks.jsonfindings (warnings on 2.1.259, errors on 2.1.250)… --strict --jsonon 2.1.250error: unknown option '--json', exit 1agent-bundle validatebefore →claude passed(2 diagnostics on the broken bundle). After → 5 diagnostics, each withgeneratedPath.Recorded
--jsonand 2.1.250 text reports live inpackages/agent-bundle/tests/fixtures/claude-plugin-validate/.Verification
pnpm typecheck,pnpm lint,pnpm test:unit(3033 tests),artifact-validator.test.ts+cli.test.tsunder the integration config,pnpm docs:site:build(parity OK).validateClaudePluginagainstexamples/host-test/artifact/claude(passed, 0 diagnostics) and the broken bundle above, with both the 2.1.259 and 2.1.250 binaries.Review status
efa9701a8(one P2 thread: published README still named the directory form) — addressed in58818c38e(README now shows both manifest invocations and the 2.1.259--jsonfloor).58818c38e(ee49efd4dchangeset PR number,58818c38eREADME). No fresh review was requested per maintainer instruction.Release gates, which fails in the release audit'snpm auditcall with503 Service Unavailablefromregistry.npmjs.org/-/npm/v1/security/audits/quick(same failure onmain; job being removed separately). Merged under the maintainer's merge-gate relaxation for that job.