Merge pull request #1490 from gaurav0107/fix/1459-remove-agents-manifest-field

fix: remove unsupported `agents` field from plugin.json
This commit is contained in:
Affaan Mustafa
2026-04-21 18:14:12 -04:00
committed by GitHub
5 changed files with 24 additions and 121 deletions

View File

@@ -45,60 +45,37 @@ Example:
The following fields **must always be arrays**: The following fields **must always be arrays**:
* `agents`
* `commands` * `commands`
* `skills` * `skills`
* `hooks` (if present) * `hooks` (if present)
Even if there is only one entry, **strings are not accepted**. Even if there is only one entry, **strings are not accepted**.
### Invalid
```json
{
"agents": "./agents"
}
```
### Valid
```json
{
"agents": ["./agents/planner.md"]
}
```
This applies consistently across all component path fields. This applies consistently across all component path fields.
--- ---
## Path Resolution Rules (Critical) ## The `agents` Field: DO NOT ADD
### Agents MUST use explicit file paths > WARNING: **CRITICAL:** Do NOT add an `"agents"` field to `plugin.json`. The Claude Code plugin validator rejects it entirely.
The validator **does not accept directory paths for `agents`**. ### Why This Matters
Even the following will fail: The `agents` field is not part of the Claude Code plugin manifest schema. Any form of it -- string path, array of paths, or array of directories -- causes a validation error:
```json ```
{ agents: Invalid input
"agents": ["./agents/"]
}
``` ```
Instead, you must enumerate agent files explicitly: Agent `.md` files under `agents/` are discovered automatically by convention (similar to hooks). They do not need to be declared in the manifest.
```json ### History
{
"agents": [
"./agents/planner.md",
"./agents/architect.md",
"./agents/code-reviewer.md"
]
}
```
This is the most common source of validation errors. Previously this repo listed agents explicitly in `plugin.json` as an array of file paths. This passed the repo's own schema but failed Claude Code's actual validator, which does not recognize the field. Removed in #1459.
---
## Path Resolution Rules
### Commands and Skills ### Commands and Skills
@@ -160,7 +137,7 @@ The test `plugin.json does NOT have explicit hooks declaration` in `tests/hooks/
These look correct but are rejected: These look correct but are rejected:
* String values instead of arrays * String values instead of arrays
* Arrays of directories for `agents` * **Adding `"agents"` in any form** - not a recognized manifest field, causes `Invalid input`
* Missing `version` * Missing `version`
* Relying on inferred paths * Relying on inferred paths
* Assuming marketplace behavior matches local validation * Assuming marketplace behavior matches local validation
@@ -175,10 +152,6 @@ Avoid cleverness. Be explicit.
```json ```json
{ {
"version": "1.1.0", "version": "1.1.0",
"agents": [
"./agents/planner.md",
"./agents/code-reviewer.md"
],
"commands": ["./commands/"], "commands": ["./commands/"],
"skills": ["./skills/"] "skills": ["./skills/"]
} }
@@ -186,7 +159,7 @@ Avoid cleverness. Be explicit.
This structure has been validated against the Claude plugin validator. This structure has been validated against the Claude plugin validator.
**Important:** Notice there is NO `"hooks"` field. The `hooks/hooks.json` file is loaded automatically by convention. Adding it explicitly causes a duplicate error. **Important:** Notice there is NO `"hooks"` field and NO `"agents"` field. Both are loaded automatically by convention. Adding either explicitly causes errors.
--- ---
@@ -194,9 +167,9 @@ This structure has been validated against the Claude plugin validator.
Before submitting changes that touch `plugin.json`: Before submitting changes that touch `plugin.json`:
1. Use explicit file paths for agents 1. Ensure all component fields are arrays
2. Ensure all component fields are arrays 2. Include a `version`
3. Include a `version` 3. Do NOT add `agents` or `hooks` fields (both are auto-loaded by convention)
4. Run: 4. Run:
```bash ```bash

View File

@@ -1,6 +1,6 @@
### Plugin Manifest Gotchas ### Plugin Manifest Gotchas
If you plan to edit `.claude-plugin/plugin.json`, be aware that the Claude plugin validator enforces several **undocumented but strict constraints** that can cause installs to fail with vague errors (for example, `agents: Invalid input`). In particular, component fields must be arrays, `agents` must use explicit file paths rather than directories, and a `version` field is required for reliable validation and installation. If you plan to edit `.claude-plugin/plugin.json`, be aware that the Claude plugin validator enforces several **undocumented but strict constraints** that can cause installs to fail with vague errors (for example, `agents: Invalid input`). In particular, component fields must be arrays, `agents` is not a supported manifest field and must not be included in plugin.json, and a `version` field is required for reliable validation and installation.
These constraints are not obvious from public examples and have caused repeated installation failures in the past. They are documented in detail in `.claude-plugin/PLUGIN_SCHEMA_NOTES.md`, which should be reviewed before making any changes to the plugin manifest. These constraints are not obvious from public examples and have caused repeated installation failures in the past. They are documented in detail in `.claude-plugin/PLUGIN_SCHEMA_NOTES.md`, which should be reviewed before making any changes to the plugin manifest.

View File

@@ -22,46 +22,6 @@
"automation", "automation",
"best-practices" "best-practices"
], ],
"agents": [
"./agents/architect.md",
"./agents/build-error-resolver.md",
"./agents/chief-of-staff.md",
"./agents/code-reviewer.md",
"./agents/cpp-build-resolver.md",
"./agents/cpp-reviewer.md",
"./agents/csharp-reviewer.md",
"./agents/dart-build-resolver.md",
"./agents/database-reviewer.md",
"./agents/doc-updater.md",
"./agents/docs-lookup.md",
"./agents/e2e-runner.md",
"./agents/flutter-reviewer.md",
"./agents/gan-evaluator.md",
"./agents/gan-generator.md",
"./agents/gan-planner.md",
"./agents/go-build-resolver.md",
"./agents/go-reviewer.md",
"./agents/harness-optimizer.md",
"./agents/healthcare-reviewer.md",
"./agents/java-build-resolver.md",
"./agents/java-reviewer.md",
"./agents/kotlin-build-resolver.md",
"./agents/kotlin-reviewer.md",
"./agents/loop-operator.md",
"./agents/opensource-forker.md",
"./agents/opensource-packager.md",
"./agents/opensource-sanitizer.md",
"./agents/performance-optimizer.md",
"./agents/planner.md",
"./agents/python-reviewer.md",
"./agents/pytorch-build-resolver.md",
"./agents/refactor-cleaner.md",
"./agents/rust-build-resolver.md",
"./agents/rust-reviewer.md",
"./agents/security-reviewer.md",
"./agents/tdd-guide.md",
"./agents/typescript-reviewer.md"
],
"skills": ["./skills/"], "skills": ["./skills/"],
"commands": ["./commands/"] "commands": ["./commands/"]
} }

View File

@@ -31,10 +31,6 @@
"type": "array", "type": "array",
"items": { "type": "string" } "items": { "type": "string" }
}, },
"agents": {
"type": "array",
"items": { "type": "string" }
},
"features": { "features": {
"type": "object", "type": "object",
"properties": { "properties": {

View File

@@ -212,37 +212,11 @@ test('claude plugin.json uses published plugin name', () => {
assert.strictEqual(claudePlugin.name, 'everything-claude-code'); assert.strictEqual(claudePlugin.name, 'everything-claude-code');
}); });
test('claude plugin.json agents is an array', () => { test('claude plugin.json does NOT have agents field (unsupported by Claude Code validator)', () => {
assert.ok(Array.isArray(claudePlugin.agents), 'Expected agents to be an array (not a string/directory)');
});
test('claude plugin.json agents uses explicit file paths (not directories)', () => {
for (const agentPath of claudePlugin.agents) {
assertSafeRepoRelativePath(agentPath, 'Agent path');
assert.ok( assert.ok(
agentPath.endsWith('.md'), !('agents' in claudePlugin),
`Expected explicit .md file path, got: ${agentPath}`, 'agents field must NOT be declared — Claude Code plugin validator rejects it',
); );
assert.ok(
!agentPath.endsWith('/'),
`Expected explicit file path, not directory, got: ${agentPath}`,
);
}
});
test('claude plugin.json all agent files exist', () => {
for (const agentRelPath of claudePlugin.agents) {
assertSafeRepoRelativePath(agentRelPath, 'Agent path');
const absolute = path.resolve(repoRoot, agentRelPath);
assert.ok(
absolute === repoRoot || absolute.startsWith(repoRootWithSep),
`Agent path resolves outside repo root: ${agentRelPath}`,
);
assert.ok(
fs.existsSync(absolute),
`Agent file missing: ${agentRelPath}`,
);
}
}); });
test('claude plugin.json skills is an array', () => { test('claude plugin.json skills is an array', () => {