fix(plugin): valid Claude agents field + gate manifest in make check (0.20.2)#57
Merged
fix(plugin): valid Claude agents field + gate manifest in make check (0.20.2)#57
Conversation
…check Claude Code's plugin schema rejects an `agents` field whose value is an array containing a directory path; auto-discovery from `agents/*.md` is the canonical shape. Removing the redundant entry resolves the `/doctor` validation failure introduced in #56. Also adds the missing YAML frontmatter on flow-cleanup.md surfaced by the same validator. Wires `claude plugin validate` into `make check` via a new `validate-claude-manifest` target so future schema regressions fail CI before publish, using Claude Code's own validator as source of truth. Bumps to 0.20.2.
PR #57's validate-claude-manifest target needed `claude` on PATH but GitHub runners don't ship it, so CI failed with the very error message the script promised would offer an escape hatch — except the script never actually honored the env var. Two-part fix: - tools/validate-claude-manifest.py: honor SKIP_CLAUDE_VALIDATE=1 by exiting 0 with a notice. Reserved for local devs without Claude Code installed; CI installs it explicitly. - .github/workflows/check.yml: install @anthropic-ai/claude-code via npm before `make check` so the validator actually runs against Claude Code's official schema in CI, matching the PR's intent (catch schema regressions before publish, not just locally).
Windows runners failed with FileNotFoundError after `npm install -g
@anthropic-ai/claude-code` succeeded: `shutil.which("claude")` resolves
the .cmd shim via PATHEXT and returned non-None (passing the existence
check), but `subprocess.run(["claude", ...])` does not honor PATHEXT,
so the bare name lookup failed even with the CLI installed.
Fix: capture the full resolved path from `shutil.which` and pass that
to `subprocess.run`. Works identically on Linux/macOS and resolves the
Windows shim correctly. Comment in-place so the next person doesn't
repeat the mistake.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
"agents": ["./agents/"]from.claude-plugin/plugin.jsonintroduced by feat: improve agent config #56 — Claude Code's schema rejects an array containing a directory path, breaking/doctorfor installed users. Auto-discovery fromagents/*.mdis the canonical shape and was always active.commands/flow-cleanup.mdsurfaced by the same validator run.claude plugin validateintomake checkvia a newvalidate-claude-manifesttarget, so the next schema regression fails CI instead of shipping.Why a CLI-wrapping validator
claude plugin validateis the same loader Claude Code runs at install time. Wrapping it viatools/validate-claude-manifest.pymeans our local check tracks any future schema evolution Anthropic makes, with zero hand-rolled JSON Schema to drift. Each host's validator is the only authority on its own format — flow already does the same for Codex (validate-codex-manifest.py); this fills the Claude gap.Test plan
make checkpasses end-to-end (lint, skills, codex, claude, version sync)claude plugin validate .claude-plugin/plugin.json→ ✔ Validation passedclaude plugin validate .claude-plugin/marketplace.json→ ✔ Validation passed