CLAUDE.md
May 30, 2026 · View on GitHub
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
For End Users: See README.md for installation and usage.
This file is for contributors, maintainers, and skill developers.
What This Is
A hybrid multi-plugin marketplace for AI coding agents. Each plugin is executable documentation (a Claude Code / Agent Skills compatible skill) loaded on demand. Plugins are unrelated and versioned independently.
The manifest at .claude-plugin/marketplace.json lists every plugin. A plugin
is either:
- External — referenced via a GitHub
sourceobject. Content, tests, and releases live in that plugin's own repo. This repo only pins a ref. - Inline — content lives here under
plugins/<name>/and uses this repo's per-plugin release pipeline.
Repository Structure
agent-plugins/
├── .claude-plugin/marketplace.json # Claude Code marketplace + plugin entries
├── .agents/plugins/marketplace.json # Codex/agents mirror (external: url+ref)
├── .kiro/plugins/marketplace.json # Kiro mirror (pin-sync parity; see note)
├── plugins/ # Inline plugins only (empty until added)
│ └── .gitkeep
│ └── <inline-plugin>/ # (when added) source dir for the manifest
│ ├── skills/<plugin>/ # Autodiscovered: skills/<name>/SKILL.md
│ │ ├── SKILL.md # Core skill file — single source of truth
│ │ └── references/ # Reference files loaded on demand
│ ├── POWER.md # GENERATED Kiro Power (from SKILL.md), CI-owned
│ ├── tests/ # Baseline scenarios, rationalization table
│ └── CHANGELOG.md # Per-plugin changelog (CI-managed)
└── .github/
├── scripts/
│ ├── update_external_plugins.py # Bumps external pins in all 3 manifests
│ └── build_power.py # POWER.md generator (`--check` for CI)
└── workflows/
├── validate.yml # PR validation (hybrid source-aware)
└── automated-release.yml # Per-plugin release (inline plugins only)
Claude Code autodiscovers <source>/skills/<name>/SKILL.md and, for external
sources, auto-clones + caches the referenced repo (see
plugins reference).
Plugin Source Types
| External | Inline | |
|---|---|---|
source | { "source": "github", "repo": "owner/repo", "ref": "vX.Y.Z" } | "./plugins/<plugin>" |
| Content | Upstream repo | plugins/<plugin>/ here |
| Releases | Upstream repo's own pipeline | This repo's per-plugin pipeline |
| Update here | Bump source.ref + mirrored version | Push a scoped conventional commit |
version field | Optional, manual mirror of source.ref (NOT CI-managed) | Required, CI-managed, must equal SKILL.md metadata.version |
terraform-skill is external: antonbabenko/terraform-skill, pinned by
source.ref. Its content and tags (vX.Y.Z) live in that repo. Pins are
bumped automatically: the scheduled Update External Plugins workflow
(.github/workflows/update-external-plugins.yml) auto-discovers external
entries from .claude-plugin/marketplace.json, resolves the latest upstream
release, and opens a reviewable chore(external-plugins): ... PR updating
source.ref in all three manifests (.claude-plugin, .agents,
.kiro) plus the mirrored version in .claude-plugin. Per-plugin overrides
live in .github/external-plugin-updates.json; validate.yml cross-checks the
three manifests stay in sync. Do not hand-bump.
Kiro note. .kiro/plugins/marketplace.json mirrors .agents so external
pins never drift, but Kiro installs a Power from a GitHub repo URL ("Add power
from GitHub") — it does not consume this manifest for install today. It
exists for pattern parity and the drift guard; inline plugins are made
installable as Kiro Powers via a generated POWER.md (see below).
POWER.md is a generated, CI-owned artifact (like
.codex-plugin/plugin.json): produced from SKILL.md by
.github/scripts/build_power.py, regenerated by the release pipeline, and
checked in validate.yml (build_power.py <dir> --check fails the PR on
drift). Never hand-edit it — edit SKILL.md/references/ and run
python3 .github/scripts/build_power.py plugins/<plugin>.
Adding a Plugin
External plugin — manifest entry only:
- Add to
.claude-plugin/marketplace.jsonplugins[]:name,source: { "source": "github", "repo": "owner/repo", "ref": "vX.Y.Z" },description, optionalcategory/keywords, optionalversion(mirror of the ref, manual). - Mirror the entry into
.agents/plugins/marketplace.jsonand.kiro/plugins/marketplace.json(samesource.url/ref; noversionfield).validate.ymlfails if the three manifests drift. - No local content, CHANGELOG, or tests here. No scoped-commit release.
Inline plugin — content lives here:
- Create
plugins/<plugin>/skills/<plugin>/SKILL.mdwith valid frontmatter (name,description; optionalmetadata.version). - Add a
plugins[]entry:name,source: ./plugins/<plugin>,description,version(start at0.1.0), optionalcategory/keywords. - Add
plugins/<plugin>/CHANGELOG.md(can be empty; CI prepends to it). - The manifest
versionmust equal the SKILL.mdmetadata.version. If the plugin ships a.codex-plugin/plugin.json, itsversionmust match too. CI enforces this. - Add
plugins/<plugin>/tests/baseline-scenarios.md- required, CI enforces it: at least one## Scenario, a## Running These Testsprotocol, and a### Success Criterialist. Copy the shape ofplugins/code-intelligence/tests/baseline-scenarios.md. - To also ship it as a Kiro Power: ensure the plugin has a
.codex-plugin/plugin.json(suppliesdisplayName+keywords), then generateplugins/<plugin>/POWER.mdwithpython3 .github/scripts/build_power.py plugins/<plugin>and commit it. Never hand-edit POWER.md; the release pipeline regenerates it andvalidate.yml--checks it. Optional: addplugins/<plugin>/mcp.json(a## MCP Tools (Kiro)trailer is auto-appended naming its servers).
Development Workflow
This is documentation, not code. No build, no compiled tests.
Validation
CI runs on PRs touching plugins/** or .claude-plugin/**. It validates every
plugins/*/skills/*/SKILL.md. To check locally:
# Frontmatter + size, all skills
for f in plugins/*/skills/*/SKILL.md; do
echo "$f: $(wc -l < "$f") lines"
done
# Manifest <-> SKILL.md version sync
python3 -c "
import json, yaml, os
m = json.load(open('.claude-plugin/marketplace.json'))
for p in m['plugins']:
src = p['source'].lstrip('./')
sp = os.path.join(src, 'skills', p['name'], 'SKILL.md')
fm = yaml.safe_load(open(sp).read().split('---', 2)[1])
sv = (fm.get('metadata') or {}).get('version')
print(p['name'], p['version'], '==', sv, 'OK' if sv == p['version'] else 'MISMATCH')
"
# Broken internal links for a skill
cd plugins/<plugin>/skills/<plugin>
grep -oP '\[.*?\]\(references/.*?\.md.*?\)' SKILL.md references/*.md | \
sed 's/.*(//' | sed 's/).*//' | sed 's/#.*//' | \
while read -r link; do [ ! -f "$link" ] && echo "Broken: $link"; done
Testing Changes
No automated suite. Manual flow:
- Edit a
SKILL.mdorreferences/*.mdfile. - Run that plugin's
tests/baseline-scenarios.mdper its## Running These Tests: each prompt with the plugin OFF (baseline) then ON (target). - Every scenario must meet its
### Success Criteriawith no new rationalizations; one failure blocks the change. - Add or update a scenario whenever a PR adds or changes a behavior.
- Attach baseline + target transcripts to the PR (or
/tmp), never underplugins/. Tests are required, not optional - CI fails an inline plugin with no scenario file.
Commit Conventions & Releases
Releases are fully automated and per-plugin, for inline plugins only.
External plugins release in their own repos; you ship a newer one here by
bumping its source.ref. The release pipeline analyzes each push to master
and bumps each inline plugin independently.
A commit qualifies for a plugin if it changed release-worthy content
under plugins/<plugin>/ - anything except tests/ and the CI-managed
CHANGELOG.md - OR its subject is explicitly scoped to the plugin
(feat(<plugin>): ..., back-compat). The conventional-commit type of the
qualifying commits then sets the bump:
| Qualifying commit type | Effect |
|---|---|
feat!: / feat(<plugin>)!: / body BREAKING CHANGE: | Major bump |
feat: ... (or scoped) | Minor bump |
fix: ..., perf:, refactor: (or scoped) | Patch bump |
chore/docs/ci/test/style, or no conventional type | No bump |
Change touches only tests/, CHANGELOG.md, or no plugin content | No release |
A squash commit touching two plugins bumps both (each from that commit's
type). Bot release commits (chore(release): ...) never bump - type chore
-
so the pipeline is loop-safe. Per release the workflow:
-
bumps
plugins[].versioninmarketplace.json, -
syncs that plugin's
SKILL.mdmetadata.version, -
syncs that plugin's
.codex-plugin/plugin.jsonversion(if present), -
regenerates that plugin's
POWER.mdfromSKILL.md(if present), -
prepends an entry to
plugins/<plugin>/CHANGELOG.md, -
tags
<plugin>-vX.Y.Zand creates a GitHub Release.
The marketplace root version is the manifest schema version and is bumped
manually, not by CI.
Never manually edit plugin version numbers in the manifest, SKILL.md, or
.codex-plugin/plugin.json. CI owns them. To force a release without a code change, push a scoped commit or run
the workflow via workflow_dispatch.
Note: inline-plugin tags are
<plugin>-vX.Y.Z(scoped to this repo). External plugins liketerraform-skillkeep their ownvX.Y.Ztags in their upstream repo; this repo never tags or changelogs them.
SKILL.md Architecture
YAML Frontmatter
---
name: <plugin> # letters, numbers, hyphens only
description: Use when... # < 1024 chars, starts with "Use when"
license: Apache-2.0 # optional
metadata:
author: Anton Babenko # optional
version: X.Y.Z # optional; auto-synced by CI if present
---
Progressive Disclosure Pattern
SKILL.md is the entry point. Reference files load on demand. Cross-links use
relative paths: [Guide](references/some-guide.md). When adding content, ask:
decision framework or key pattern -> SKILL.md; detailed example or template
-> reference file.
Content Standards
- Imperative voice: "Use X" not "You should consider X"
- Scannable format: tables > bullets > prose
- DO / DON'T side-by-side for non-obvious patterns
- Version-specific features clearly marked
- Token budget: keep
SKILL.mdlean (target <500 lines; <300 ideal)
LLM Consumption Rules (enforce in every PR review)
These tune content for the primary reader: an LLM retrieving facts to answer
a query, not a human reading end to end. Mandatory for every addition to
SKILL.md and references/*.md. Reject PRs that violate them.
- Shape: decision table before playbook. When a topic has multiple viable
approaches, open with a decision table (
Goal | Use | Tradeoff) before any phase steps. Never bury branching in prose. - Cut human scaffolding. Before/after diffs and "Why this matters" paragraphs are human-only signal. If the steps already name the action, a diff is redundant; drop it.
- Compress prose to DON'T/DO rules. Any "You should...", "Note that...", "Keep in mind..." sentence becomes a terse imperative bullet. One fact per bullet.
- Every artifact earns its tokens. Each code block, table, or example must add a fact not in the prose. If it only restates, cut it.
- Anchor stability. SKILL.md routes to specific
#anchorheadings in reference files. Rewrites may restructure subsections but must preserve the top-level### Headingthe SKILL.md table points to. - Retrieval-first ordering. Within a section: (a) decision table, (b) default procedure, (c) alternatives, (d) rules as DON'T/DO. Rationale is one opening sentence, never a closing "Why this matters" block.
Token target per reference subsection: under 400 tokens (~1,600 chars).
What Belongs Where
| Content type | Location |
|---|---|
| Decision frameworks, core patterns | plugins/<plugin>/skills/<plugin>/SKILL.md |
| Detailed guides, templates, examples | .../references/*.md |
| Baseline test scenarios | plugins/<plugin>/tests/*.md |
| Per-plugin changelog | plugins/<plugin>/CHANGELOG.md (CI-managed) |
| Kiro Power (generated) | plugins/<plugin>/POWER.md (CI-owned; from SKILL.md) |
| Installation/usage docs | README.md |
| Contributor process | CONTRIBUTING.md |
| Marketplace + versions | .claude-plugin/marketplace.json (CI-managed versions) |
| External pin mirrors | .agents/plugins/ + .kiro/plugins/marketplace.json (CI-synced) |