Contributing¶
context-kit is a Claude Code plugin marketplace and a Copilot/APM-compatible
Agent Skills pack — a catalog of plugins, not an application. The reusable value
lives in SKILL.md files, their references/, subagents, and local CLI
workflows.
Repository layout¶
| Path | Purpose |
|---|---|
.claude-plugin/marketplace.json |
The catalog (hand-authored; lists shipped plugins only). |
plugins/<name>/.claude-plugin/plugin.json |
Per-plugin manifest (Claude Code + Copilot). |
plugins/<name>/apm.yml |
Per-plugin APM manifest, mirroring plugin.json. |
plugins/<name>/skills/<name>/SKILL.md |
Skills, with references/*.md for detail. |
plugins/<name>/agents/<name>.md |
Subagents. |
docs/ |
This documentation site (MkDocs Material). |
Component directories (skills/, agents/, scripts/) live at the plugin
root, never inside .claude-plugin/ (that dir holds only plugin.json).
Validate, lint, and test¶
# Validate the marketplace + every plugin
claude plugin validate . --strict
for p in plugins/*/; do [ -f "$p/.claude-plugin/plugin.json" ] && claude plugin validate "$p" --strict; done
# Lint everything (markdownlint + shellcheck + ruff + hygiene)
pre-commit run --all-files
# Run the aggregate catalog gate and its regression/smoke tests
bash plugins/plugin-forge/scripts/check-release-readiness.sh
bash plugins/plugin-forge/scripts/test-release-readiness.sh
bash plugins/plugin-forge/scripts/check-catalog-quality.sh
bash plugins/plugin-forge/scripts/test-catalog-quality.sh
# Run the focused standard-library suites and their cross-plugin integration
python3 -m unittest discover -s plugins/runtime-evidence/tests -p 'test_*.py'
python3 -m unittest discover -s plugins/verify/tests -p 'test_*.py'
python3 -m unittest discover -s plugins/context-handoff/tests -p 'test_*.py'
python3 -m unittest discover -s plugins/memory/tests -p 'test_*.py'
python3 -m unittest discover -s tests/release -p 'test_*.py'
python3 -m unittest discover -s tests/integration -p 'test_*.py'
# Lint the ADR corpus (skips cleanly if Node is unavailable)
bash scripts/check-adr.sh
# Run the indexkit Python tests
cd plugins/indexkit && uv run --group dev pytest -q
CI (.github/workflows/validate.yml) runs claude plugin validate --strict on
every plugin, pre-commit (including release-readiness and catalog-quality
checks), and the indexkit pytest suite plus all focused standard-library
suites above.
The integration suite uses a temporary local Git repository, the real script
entry points, local memory mode, and no network or external MemPalace process.
Build the docs locally¶
The site is MkDocs Material. Serve it with live reload, or build a static copy:
# Live preview at http://127.0.0.1:8000
uv run --with-requirements docs/requirements.txt mkdocs serve
# Production build (strict: fail on broken links / nav)
uv run --with-requirements docs/requirements.txt mkdocs build --strict
The main branch deploys to GitHub Pages automatically via
.github/workflows/docs.yml. The build output (/site) is git-ignored.
Conventions¶
- Adding a plugin — create
plugins/<name>/.claude-plugin/plugin.json, addskills//agents/, add a siblingapm.yml, and aLICENSE+CHANGELOG.md. Add themarketplace.jsoncatalog entry only when the plugin is ready — stubs stay unlisted so they can't be installed half-built. Add a page here underdocs/plugins/and wire it intomkdocs.yml. Add central positive/negative discovery fixtures and keep the aggregate description budget within 4096 characters (384 per component). The catalog gate warns at 95% of the budget. - Versioning — bump
versioninplugin.jsonto ship updates (Claude Code uses it as the cache key). Bump the matchingapm.ymlversionin lockstep;plugin-forge'scheck-manifests.shenforces this. Add the same version as the top release in that plugin'sCHANGELOG.md; the release-readiness gate enforces the changelog and dependency graph invariants. On pull requests, CI also runscheck-version-bump.sh, which fails when shipped plugin content changed without a strictly-greater version. Docs-only, test-only, andCHANGELOG.mdedits are exempt; to skip deliberately, add aSkip-Version-Bump: <plugin> - <reason>trailer to a commit so the exemption is visible in review and in the CI log. - Portability — keep skill bodies host-neutral. Prefer
CONTEXT_KIT_*environment variables in examples, withCLAUDE_PLUGIN_*documented as the Claude fallback. Keep marketplace mechanics in.claude-plugin/and Claude-only docs. - Architecture decisions — decisions that are hard to reverse, contested, or
govern a path are recorded as ADRs in
docs/adr/, managed by adrkit (ADR-0001). The instruction files keep the rules; the corpus keeps the reasoning, the rejected options, and the revisit conditions. Create one withnpx @adrkit/cli@0.13.0 new "<title>", fill inaffectsso the decision is locatable by path, and check what already governs a file withnpx @adrkit/cli@0.13.0 explain <path>. Do not write an ADR for naming, formatting, or anything a contributor can flip in one commit. Code that exists because of a decision — compatibility shims especially — can declare it inline with a dedicated# @adr NNNNcomment line, whichadr explainreports asdeclared by <file>:<line>. Markers must be real comment lines (not docstrings) within the first 8192 bytes of the file, so in a large module put them in the header. This limit fails silently: a marker past the window yields an emptydeclaredlist, identical to a file with no marker at all. Themarkers.truncatedflag does not disambiguate it either — it reports only that the file is larger than the window, and istrueeven when a marker was found. Treat markers as a header convention, and never read an emptydeclaredon a large file as "no decision is declared here". adrkit is contributor-side only — no shipped plugin depends on it, andscripts/check-adr.shskips cleanly when Node is absent, so you can work without it. An agent-drafted record cannot reachacceptedwithout a named human ratifier inprovenance.ratifiedBy; that refusal is intentional. Thenpxinvocations above leave noadronPATH, which is enough for linting and authoring but not for the governance modality in/analyze-impact— that runner executes an installed binary and never fetches one, so with onlynpxit reportsunavailableforever. To make it reachable, either install the CLI (npm i -g @adrkit/cli@0.13.0, which providesadr) or pointCONTEXT_KIT_ADR_BINat an existing adrkit executable — a project-localnode_modules/.bin/adrworks. - Licensing — repo and all plugins are MIT (Mark Beacom). Content is written fresh; do not copy text from externally licensed sources. adrkit is Apache-2.0, so we invoke it as an external CLI and never vendor its code.
- Markdown —
.markdownlint-cli2.jsoncdisables MD013/MD033/MD041/MD060. Fix real lint findings rather than disabling more rules.docs/adr/extends that config with one scoped option so MD025 tolerates adrkit's frontmatter title alongside its H1.
See CLAUDE.md and
.github/copilot-instructions.md
for the full contributor guide.
See Releasing plugins for the maintainer release, tag, and recovery procedure.