fix: stop emitting the "agents" key so the four subagents actually load (#494)

build.js derives plugin/.claude-plugin/plugin.json from the root manifest and
injects an `agents` array built from the generated agent files. In Claude Code
that array is exactly what stops them loading.

Verified on a throwaway local marketplace, across the plausible shapes:

  array of file paths (what build.js emits) -> 0 agents load, skills fine
  a string, e.g. "./agents"                 -> whole plugin fails to load
  array containing a directory              -> whole plugin fails to load
  key omitted                               -> all agents load, skills fine

Claude Code discovers agents/*.md on its own, and the identifier it uses is the
file name rather than the frontmatter `name`. So the key is not needed, and any
present form of it is worse than its absence.

Confirmed end to end on this repo: with the key emitted,
`claude plugin details impeccable` reports "Agents (0)"; with it omitted it
reports "Agents (4) impeccable-asset-producer, impeccable-documenter,
impeccable-finish-reviewer, impeccable-manual-edit-applier". The agent files
themselves are still copied by the existing copyDirSync a few lines below —
only the manifest key goes away.

Two things make this hard to notice: with a breaking shape
`claude plugin details` prints "Plugin not found" instead of a validation
error, and `claude plugin validate` does not catch it because it validates the
marketplace manifest, not the plugin manifest. The only reliable signal is the
"Agents (N)" line.

The same defect is reported against another project at
addyosmani/agent-skills#449, with the full reproduction.

Scope note: verified on Claude Code only. plugin/ is the Claude-Code / Grok
subtree, and the Grok manifest is written separately just below, so this does
not touch the other harnesses.
This commit is contained in:
ingnicolaboccato-lab
2026-08-03 11:55:14 -07:00
committed by GitHub
parent 71ccba9f5b
commit baa76cfd05
+7 -11
View File
@@ -627,22 +627,18 @@ async function build() {
const rootManifest = JSON.parse(fs.readFileSync(path.join(ROOT_DIR, '.claude-plugin/plugin.json'), 'utf-8'));
const claudeAgentsSrc = path.join(DIST_DIR, 'claude-code', '.claude', 'agents');
const pluginAgentEntries = fs.existsSync(claudeAgentsSrc)
? fs.readdirSync(claudeAgentsSrc)
.filter(file => file.endsWith('.md'))
.sort()
.map(file => `./agents/${file}`)
: [];
// Trailing slash on the skills path matches the documented schema in
// code.claude.com/docs/en/plugins-reference. Issue #86 has 3 reporters
// converging on "add trailing slash to fix slash commands not registering";
// the docs schema example consistently uses `"./custom/skills/"` form.
const pluginManifest = { ...rootManifest, skills: './skills/' };
if (pluginAgentEntries.length) {
pluginManifest.agents = pluginAgentEntries;
} else {
delete pluginManifest.agents;
}
// No `agents` key: Claude Code discovers agents/*.md by itself, and the
// identifier it uses is the file name. Declaring the key as an array of
// file paths makes it load ZERO agents, so the four shipped subagents were
// never reachable. The other plausible shapes are worse: a string, or an
// array containing a directory, and the whole plugin fails to load.
// Omitting the key is the only shape that works.
delete pluginManifest.agents;
fs.mkdirSync(pluginManifestDir, { recursive: true });
fs.writeFileSync(
path.join(pluginManifestDir, 'plugin.json'),