Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/claude-plugin-validate-manifests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"agent-bundle": patch
---

Make `agent-bundle validate --artifact` run Claude Code's validator against `.claude-plugin/plugin.json` and, when the bundle emits one, `.claude-plugin/marketplace.json`, instead of the bundle directory: Claude Code treats a directory holding both manifests as a marketplace and never opens `hooks/hooks.json`, `skills/`, `agents/`, or `commands/`, so hook, skill, and agent findings were invisible to the `claude` and `plugin` targets. On Claude Code 2.1.259 or later the runs use `claude plugin validate --json`, and every `AB6020` warning and `AB6021` error now names the validated file (`generatedPath`) and Claude Code's field path; older releases fall back to the text report with the same attribution. Duplicate `plugins[N] plugin.json →` manifest findings from the marketplace run are dropped, notes surface as info, and a run that returns no report is `AB6022` with the CLI's stderr. The native Claude eval gate validates `plugin.json` the same way. (#474)
26 changes: 26 additions & 0 deletions docs/diagnostics.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,32 @@ even when no error diagnostic was reported.
| `AB8xxx` | Development server configuration. |
| `AB9xxx` | Eval selection, harnesses, and persisted runs. |

## Claude Code host validation (`AB6019`–`AB6022`)

`agent-bundle validate --artifact <dir>` runs the installed Claude Code
validator for the `claude` and `plugin` targets when `--host-validation` is on.
Claude Code decides what to check from the manifest it is pointed at: a run
against the bundle directory picks `.claude-plugin/marketplace.json` when it is
present and never opens the plugin's skill, agent, command, or hook files
(Claude Code docs, "Create and distribute a plugin marketplace" →
"Marketplace validation errors"). Agent Bundle emits both manifests side by
side, so it runs `claude plugin validate <dir>/.claude-plugin/plugin.json --strict`
first, which covers `plugin.json`, `hooks/hooks.json`, and the `skills/`,
`agents/`, and `commands/` directories, and then
`claude plugin validate <dir>/.claude-plugin/marketplace.json --strict`, dropping
the marketplace run's `plugins[N] plugin.json →` copies of manifest findings the
plugin run already reported. On Claude Code 2.1.259 or later both runs add
`--json` and each finding is attributed to its file (`generatedPath`); older
releases fall back to the text report, attributed by its `Validating <type>:
<file>` headers.

| Code | Severity | Meaning | Recovery |
| --- | --- | --- | --- |
| `AB6019` | info | The `claude` CLI is not installed or not on `PATH`, so host validation was skipped. Local pinned-schema validation (`AB6011`/`AB6012`) still runs. | Install Claude Code and ensure `claude` is on `PATH`, then rerun artifact validation. |
| `AB6020` | warning (error in strict mode) / info | One Claude Code validation warning, or (info) one note, from the plugin or marketplace run. The message names the validated file and Claude Code's field path, for example `(hooks hooks/hooks.json): hooks: hooks.postToolUse: unknown hook event`. Claude Code tolerates these at load time; `agent-bundle validate --strict` promotes warnings to errors, mirroring `claude plugin validate --strict`. | Run `claude plugin validate <bundle-dir>/.claude-plugin/plugin.json --strict`, repair the reported Claude artifact, and rebuild. |
| `AB6021` | error | One Claude Code validation error from the plugin or marketplace run, such as invalid JSON in `hooks/hooks.json`, frontmatter that fails to parse, or a duplicate plugin name in `marketplace.json`. Claude Code loads the plugin without the failing component or refuses the marketplace. | Same as `AB6020`. |
| `AB6022` | error | The bounded `claude --version` probe or a validation run could not start, exited nonzero without a report, timed out, exceeded 1 MiB of output, or (2.1.259+) returned no JSON report; the message carries the CLI's stderr when there is one. | Verify the Claude CLI starts and responds, then rerun `claude plugin validate <bundle-dir>/.claude-plugin/plugin.json --strict`. |

## Cursor built-artifact validation (`AB6026`–`AB6029`)

| Code | Severity | Trigger | Recovery |
Expand Down
20 changes: 15 additions & 5 deletions packages/agent-bundle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,21 @@ manifests at files inside those payloads without compiling them. Payload files c

### Validate Claude bundles with Claude Code

Artifact validation runs `claude plugin validate <bundle-dir> --strict` for emitted `claude`
and unified `plugin` targets when Claude Code is on `PATH`. Host errors become Agent Bundle
errors; host warnings remain warnings unless `agent-bundle validate --strict` is set. A missing
binary is reported as an explicit informational skip, never as fabricated success. Use
`--no-host-validation` when a deterministic schema-only check is required.
When Claude Code is on `PATH`, artifact validation runs its validator for emitted `claude` and
unified `plugin` targets. Claude Code treats a directory that holds both `.claude-plugin/plugin.json`
and `.claude-plugin/marketplace.json` as a marketplace and then never opens the plugin's hook,
skill, agent, or command files, so Agent Bundle names each manifest:

```sh
claude plugin validate <bundle-dir>/.claude-plugin/plugin.json --strict
claude plugin validate <bundle-dir>/.claude-plugin/marketplace.json --strict
```

On Claude Code 2.1.259 or later both runs use `--json`; older releases are parsed from the text
report. Host errors become Agent Bundle errors (`AB6021`); host warnings remain warnings
(`AB6020`) unless `agent-bundle validate --strict` is set, and every finding names the validated
file. A missing binary is reported as an explicit informational skip (`AB6019`), never as
fabricated success. Use `--no-host-validation` when a deterministic schema-only check is required.

CI should use strict validation:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,8 @@
"Placeholder substitution for LSP servers is limited to command, args, env, and workspaceFolder.",
"Codex and Cursor publish no plugin LSP surface at their pinned revisions, so the unified bundle's .lsp.json reaches Claude Code only.",
"Plugin developer tools reference: `claude plugin validate <dir>` checks plugin.json, hooks/hooks.json, and default-directory Skill, agent, and command frontmatter; manifest-less component directories require 2.1.233 or later.",
"2026-09-03: plugins-reference (plugin validate) documents `--json` as requiring Claude Code v2.1.259 or later, with a report of `success`, `strict`, `target`, `manifest`, and per-file `contents` entries carrying `errors`, `warnings`, and `notes`; the pinned 2.1.250 revision answers `error: unknown option '--json'`, so Agent Bundle gates the flag on the probed version and parses the text report below it.",
"2026-09-03: plugin-marketplaces (Marketplace validation errors) states that from a marketplace directory Claude Code does not open the plugins' skill, agent, command, or hook files; because the emitted bundle places .claude-plugin/marketplace.json beside plugin.json, a directory run validates the marketplace only, and artifact validation names each manifest explicitly.",
"2026-09-01: https://code.claude.com/docs/en/plugins-reference documents plugin commands/ as Markdown files with optional YAML frontmatter fields description, argument-hint, allowed-tools, model, and disable-model-invocation; the filename stem is the plugin-namespaced command name.",
"2026-09-01: https://code.claude.com/docs/en/plugins-reference documents plugin-root bin/ as \"Plugin executables added to PATH\", with executables \"Invokable as bare command in Bash tool\"; its file-locations table says: \"Executables added to the Bash tool's PATH and invokable as bare commands while the plugin is enabled. You can't include this directory in a plugin you distribute through claude.ai organization settings\".",
"2026-09-01: https://code.claude.com/docs/en/plugins documents plugin-root bin/ as \"Executables added to the Bash tool's PATH while the plugin is enabled. You can't include this directory in a plugin you distribute through claude.ai organization settings\".",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"url": "https://code.claude.com/docs/en/plugins-reference"
}
},
"validation": "Pinned JSON Schema snapshots are validated locally with Ajv. Artifact validation can additionally invoke `claude plugin validate <bundle-dir> --strict`; Agent Bundle preserves host warnings unless its own strict option is enabled, and reports an explicit unavailable diagnostic when the CLI is absent.",
"validation": "Pinned JSON Schema snapshots are validated locally with Ajv. Artifact validation additionally invokes `claude plugin validate <bundle-dir>/.claude-plugin/plugin.json --strict` and, when the bundle emits one, `claude plugin validate <bundle-dir>/.claude-plugin/marketplace.json --strict`; a directory run would validate the marketplace and never open hooks/, skills/, agents/, or commands/ (plugin-marketplaces reference, Marketplace validation errors). Both runs add `--json` on Claude Code 2.1.259 or later (plugins-reference, plugin validate) and fall back to the text report before that. Agent Bundle preserves host warnings unless its own strict option is enabled, and reports an explicit unavailable diagnostic when the CLI is absent.",
"developerTools": {
"retrievedAt": "2026-09-01",
"source": "https://code.claude.com/docs/en/plugins-reference",
Expand Down
4 changes: 2 additions & 2 deletions packages/agent-bundle/src/build/artifact-diagnostics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ export const artifactDiagnosticRecoveries: Readonly<Record<ArtifactDiagnosticCod
AB6017: 'Rebuild the artifact so every target MCP manifest references its exact compiler outputs.',
AB6018: 'Rebuild the artifact so native hook commands and hook metadata agree.',
AB6019: 'Install Claude Code and ensure `claude` is on PATH, then rerun artifact validation.',
AB6020: 'Run `claude plugin validate <bundle-dir> --strict`, repair the warning, and rebuild.',
AB6021: 'Run `claude plugin validate <bundle-dir> --strict`, repair the error, and rebuild.',
AB6020: 'Run `claude plugin validate <bundle-dir>/.claude-plugin/plugin.json --strict`, repair the warning, and rebuild.',
AB6021: 'Run `claude plugin validate <bundle-dir>/.claude-plugin/plugin.json --strict`, repair the error, and rebuild.',
AB6022: 'Restore a bounded Claude validator process, then rerun artifact validation.',
AB6023: 'Rebuild the artifact so every built-in target includes its generated INSTALL.md.',
AB6024: 'Rebuild the Cursor-compatible artifact so it includes its generated install.mjs.',
Expand Down
Loading
Loading