feat(kyberforge): execute plugin-to-apm marketplace conversion
Why: ADR-0015 established that Microsoft APM (apm.yml + .apm/) should replace this repo's hand-authored plugin.json/marketplace.json model, with those files becoming compiled output of `apm pack` instead of files edited by hand via the (now-retired) plugin-author/marketplace-author skills. Issue #90 was the deferred execution of that decision, gated on #88 (apm tooling) and #89 (apm-native agent-author/skill-author routing). Implementation notes: - All six plugins (bin, core, git, gitea, kyberforge, lint) now carry apm.yml + .apm/{skills,agents,hooks} as their authoring source. Skills moved with a plain git mv (content-identical across targets). Agents were re-authored, not moved: per ADR-0016, .apm/agents/*.agent.md compiles verbatim to both Claude and Copilot, so plugin-scope agents now carry only name/description/model/source_keys -- no tools: field, no Claude-only knobs (isolation, maxTurns, effort, memory, permissionMode). - Root apm.yml registers all 7 marketplace packages (6 local plus mattpocock-skills as a remote entry) under versioning: per_package, matching this repo's existing independent-plugin-versioning practice. - .claude-plugin/marketplace.json and every plugin's plugin.json are now apm-pack-compiled output, verified against the prior hand-maintained content: same names/descriptions/versions/licenses/authors, only cosmetic serialization differences (JSON key order, owner email vs. url, Unicode escaping). - plugin-author and marketplace-author are retired now that apm-based authoring fully replaces their job; kyberforge bumped 1.3.1 -> 1.4.0 for that removal, and the root marketplace catalog bumped 0.3.1 -> 0.3.2 to match, per the version-bump convention now documented in apm-workflow's reference docs instead of a dedicated script (apm has no native version-bump automation). - Fixed hardcoded pre-.apm/ path assumptions across .pre-commit-config.yaml, .pre-commit-hooks.yaml, scripts/check-scope-walkup-sync.sh, scripts/sync-vale-styles.sh, scripts/check-vale-style-sync.sh, six plugins' root plugin.json (stale skills/hooks/agents pointer fields that check-manifests.sh validates), and several tests/*.bats and tests/*.sh fixtures -- including a bats REPO_ROOT relative-path depth bug (10 files, one extra .apm/ directory level to walk up) and a vale probe-path isolation regression introduced mid-fix. - Corrected empirically-wrong assumptions surfaced this session in apm-workflow/apm-install's own reference docs: `apm marketplace package add` does not accept local paths (only owner/repo remote shorthand -- local packages are registered by editing apm.yml's marketplace.packages[] directly); `apm compile` is a consumer-side AGENTS.md/CLAUDE.md generator, not the plugin.json producer, and hard-fails on skill/agent-only packages without --clean; `apm plugin init <name>` nests a stray subdirectory when run with a positional name arg from inside a same-named directory; no native Copilot marketplace output profile exists; .mcp.json is merged into the compiled plugin.json content-aware and target-scoped, with no dependencies.mcp entry needed for simple passthrough; pipx is the correct pip fallback on externally-managed Python environments. - Renamed agent-author's copilot.agent.md template asset to copilot.agent.md.template so apm compile's recursive *.agent.md glob stops misparsing the placeholder template as a real agent primitive. Impact: plugin.json and marketplace.json are compiled artifacts from here on -- editing them by hand is no longer the workflow; edit apm.yml/.apm/ and run apm pack. CONTEXT.md's Plugin/Plugin marketplace glossary entries reflect this. ADR-0001 is marked superseded, ADR-0006 moot, and ADR-0010 updated for the new .apm/agents/ path (project/user scope unaffected, per ADR-0016). Full local verification: claude plugin validate --strict on all 6 plugins, apm audit --ci, apm marketplace check, check-manifests.sh, and the full test suite (165/165 bats, 13/13 shell scripts) all pass clean. Fixes: #90 Refs: #88, #89 ADR: 0015 ADR: 0016 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ub96PyaSRD9BHPktotj1pC
This commit is contained in:
@@ -3,11 +3,8 @@ name: apm-orchestrate
|
||||
|
||||
description: Orchestrates apm package/marketplace operations for other agents. Invoke when a caller needs a multi-step apm operation (scaffold a package, register it into a marketplace, compile/pack/publish, audit) coordinated across the apm-workflow skill with safety gates, session context, and structured results — especially fanning the same operation out across multiple packages in a monorepo.
|
||||
|
||||
tools: ["execute", "read"]
|
||||
|
||||
source_keys:
|
||||
- context7-microsoft-apm
|
||||
|
||||
---
|
||||
|
||||
You are the orchestrator for apm package/marketplace operations — a composable workflow dispatcher designed for other agents to invoke multi-step `apm` operations reliably, especially the same operation repeated across several packages in a monorepo-hybrid layout. Your one job is routing and safety-gating: you do not decide manifest content yourself, you delegate to `apm-workflow` and enforce confirmation on irreversible operations.
|
||||
@@ -53,11 +50,26 @@ When invoked, you:
|
||||
2. Check the request against the Hard rules above (publish confirmation, marketplace-add direction, `type:` ordering, audit-vs-audit-ci, registries precondition) — refuse outright on violation, independent of `confirm`
|
||||
3. If `operation` is `publish`: require `confirm: true`, dispatch `--dry-run -v` first regardless, surface that output, else fail with structured "requires explicit confirmation" error
|
||||
4. Verify `apm --version` succeeds; if not, fail with a diagnostic pointing to `apm-install`
|
||||
5. Invoke `apm-workflow` with the resolved action, `package_root`, and parameters
|
||||
5. Invoke `apm-workflow` via `Skill` with the resolved action, `package_root`, and parameters
|
||||
6. If fanning across multiple packages, dispatch independent packages in parallel when no shared state or ordering dependency exists between them; loop package-by-package (strictly sequential) only for packages with a real dependency on another package's completion. Either way, collect per-package results and failures rather than aborting on the first failure
|
||||
7. Catch and handle apm errors: retry once for a dependency-not-yet-scaffolded failure after the caller confirms the dependency exists; otherwise return error structure with diagnostics
|
||||
8. Aggregate all outputs and return as structured JSON
|
||||
|
||||
## Output
|
||||
|
||||
Returns structured JSON with operation status, result (output — or a list of per-package results when fanned out — plus resolved package-root/registry context), and optional error details with recovery suggestions.
|
||||
```json
|
||||
{
|
||||
"status": "success" | "error" | "partial",
|
||||
"operation": "<operation_name>",
|
||||
"result": {
|
||||
"output": "<apm-workflow output or result, or a list of per-package results when fanned out>",
|
||||
"context": { "package_root": "...", "resolved_registry": "..." }
|
||||
},
|
||||
"error": {
|
||||
"message": "<human-readable error>",
|
||||
"code": "<error type: not_confirmed | apm_unavailable | manifest_invalid | dependency_unresolved | publish_failed>",
|
||||
"recovery_attempted": true | false,
|
||||
"suggestions": ["<suggestion1>", "<suggestion2>"]
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
setup() {
|
||||
REPO_ROOT="$(cd "$BATS_TEST_DIRNAME/../../../../../" && pwd)"
|
||||
REPO_ROOT="$(cd "$BATS_TEST_DIRNAME/../../../../../../" && pwd)"
|
||||
load "$REPO_ROOT/tests/test_helper/bats-support/load"
|
||||
load "$REPO_ROOT/tests/test_helper/bats-assert/load"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
setup() {
|
||||
REPO_ROOT="$(cd "$BATS_TEST_DIRNAME/../../../../../" && pwd)"
|
||||
REPO_ROOT="$(cd "$BATS_TEST_DIRNAME/../../../../../../" && pwd)"
|
||||
load "$REPO_ROOT/tests/test_helper/bats-support/load"
|
||||
load "$REPO_ROOT/tests/test_helper/bats-assert/load"
|
||||
|
||||
@@ -36,7 +36,7 @@ bash scripts/new-agent.sh security-reviewer ~
|
||||
| `references/scripts.md` | Conventions for new-agent.sh and any future scripts: contract, template variables, file placement, error messages |
|
||||
| `references/sources.md` | Research provenance — sources that informed this skill |
|
||||
| `assets/templates/claude-code.md` | Annotated Claude Code agent definition template (project/user scope) |
|
||||
| `assets/templates/copilot.agent.md` | Annotated Copilot CLI agent definition template (project/user scope) |
|
||||
| `assets/templates/copilot.agent.md.template` | Annotated Copilot CLI agent definition template (project/user scope) |
|
||||
| `assets/templates/apm-agent.md` | Annotated vendor-neutral APM agent definition template (plugin/APM scope) |
|
||||
| `tests/new-agent.bats` | bats tests for `scripts/new-agent.sh` |
|
||||
| `assets/README.md` | Directory meta-documentation for assets/ |
|
||||
@@ -5,5 +5,5 @@
|
||||
Annotated agent definition templates copied by `scripts/new-agent.sh` when scaffolding a new agent.
|
||||
|
||||
- **`claude-code.md`** — Claude Code agent definition template (project/user scope). Includes all supported frontmatter fields (required and optional) with inline guidance comments and `FILL IN:` placeholders.
|
||||
- **`copilot.agent.md`** — Copilot CLI agent definition template (CLI format, project/user scope). Excludes cloud/IDE-only fields (`target`, `user-invocable`, `disable-model-invocation`, `mcp-servers`) and Claude Code-only fields. Uses Copilot tool aliases (`execute`, `read`, `edit`, `search`, `agent`, `web`).
|
||||
- **`copilot.agent.md.template`** — Copilot CLI agent definition template (CLI format, project/user scope). Excludes cloud/IDE-only fields (`target`, `user-invocable`, `disable-model-invocation`, `mcp-servers`) and Claude Code-only fields. Uses Copilot tool aliases (`execute`, `read`, `edit`, `search`, `agent`, `web`).
|
||||
- **`apm-agent.md`** — Vendor-neutral APM agent definition template (plugin/APM scope). Only `name`, `description`, optional `model`, and optional `source_keys` (provenance metadata, not a runtime field) in frontmatter — no `tools` and no Claude-only fields, since `apm compile` copies frontmatter verbatim to both the Claude Code and Copilot CLI targets with no per-target integrator (ADR-0016).
|
||||
@@ -227,7 +227,7 @@ else
|
||||
if [[ -f "$CP_FILE" ]]; then
|
||||
echo "Skipping '$CP_FILE' — already exists." >&2
|
||||
else
|
||||
sed "s/AGENT_NAME/$AGENT_NAME/g" "$TEMPLATES_DIR/copilot.agent.md" > "$CP_FILE"
|
||||
sed "s/AGENT_NAME/$AGENT_NAME/g" "$TEMPLATES_DIR/copilot.agent.md.template" > "$CP_FILE"
|
||||
echo "Created: $CP_FILE" >&2
|
||||
created_any=true
|
||||
fi
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
setup() {
|
||||
REPO_ROOT="$(cd "$BATS_TEST_DIRNAME/../../../../../" && pwd)"
|
||||
REPO_ROOT="$(cd "$BATS_TEST_DIRNAME/../../../../../../" && pwd)"
|
||||
load "$REPO_ROOT/tests/test_helper/bats-support/load"
|
||||
load "$REPO_ROOT/tests/test_helper/bats-assert/load"
|
||||
|
||||
@@ -19,6 +19,7 @@ metadata:
|
||||
- apm does not execute agents itself — it only installs and manages the runtimes that do. "Install apm" and "install a runtime apm manages" are two separate steps; don't conflate them or skip the second when the user actually wants a working agent CLI, not just the package manager.
|
||||
- The air-gapped/enterprise mirror path needs `GITHUB_URL` and `VERSION` set together against a downloaded `install.sh` — it does not work through the piped one-liner form.
|
||||
- `pip install apm-cli` requires Python 3.10+; the quick-install script has no such prerequisite. Prefer the quick-install script unless the environment is pip-first.
|
||||
- On a Debian/externally-managed Python environment (PEP 668), `pip install apm-cli` fails immediately with `error: externally-managed-environment`. Fall back to `pipx install apm-cli` — same PyPI package, but pipx creates an isolated venv and correctly exposes the `apm` binary on `PATH`.
|
||||
- Installing the Copilot CLI runtime through `apm runtime setup copilot` requires Node.js v22+ and npm v10+ already present — apm does not install Node/npm for you.
|
||||
|
||||
## Install apm
|
||||
@@ -34,6 +35,7 @@ Escape hatches — combine as needed:
|
||||
- Custom install directory: set `APM_INSTALL_DIR` on the piped script's command, e.g. `curl -sSL https://aka.ms/apm-unix | APM_INSTALL_DIR=$HOME/.local/bin sh`.
|
||||
- Air-gapped / GitHub Enterprise mirror: download `install.sh` first, then run it with `GITHUB_URL` and `VERSION` set, e.g. `GITHUB_URL=https://github.corp.com VERSION=v1.2.3 sh install.sh`.
|
||||
- pip (Python 3.10+ environments): `pip install apm-cli`.
|
||||
- pipx (externally-managed/PEP 668 environments where plain `pip install` fails, e.g. Debian): `pipx install apm-cli`.
|
||||
- Manual: download the platform archive from the GitHub releases page, extract, place the binary on `PATH`.
|
||||
|
||||
Verify with `apm --version`.
|
||||
@@ -22,8 +22,8 @@ metadata:
|
||||
## Gotchas
|
||||
|
||||
- `apm.yml`'s `type:` field (`instructions`, `skill`, `hybrid`, `prompts`) constrains what `.apm/` may contain — set it before scaffolding content, not after. Changing it later doesn't retroactively validate what's already on disk.
|
||||
- `includes: auto` publishes the authoritative local layout as-is. Anything narrower needs an explicit repo-path list — don't assume `auto` means "scoped down to what's relevant."
|
||||
- `apm marketplace add` (registering a marketplace as a *consumer*, pointing at someone else's catalog) and `apm marketplace package add` (registering a local package *into* a marketplace you're building) are opposite directions of the same command family — don't conflate them.
|
||||
- `includes: auto` publishes the authoritative local layout as-is. Anything narrower needs an explicit repo-path list — don't assume `auto` means "scoped down to what's relevant." Note: `auto` still excludes generic root-level passthrough files (README.md, docs/, sources.md, config files) from the `apm pack` distribution bundle — see `references/compile.md`.
|
||||
- `apm marketplace add` (registering a marketplace as a *consumer*, pointing at someone else's catalog) and `apm marketplace package add` (registering a package by remote reference — `owner/repo`, host URL, or full URL — into a marketplace you're building) are opposite directions of the same command family — don't conflate them. `package add` does NOT accept local paths; a local package is registered by hand-editing `apm.yml`'s `marketplace.packages[]` directly — see `references/marketplace.md`.
|
||||
- MCP server secrets (headers, env vars) inside `apm.yml` must use `${VAR}` indirection, never literal values, so they're resolved at install/runtime and never committed to the manifest.
|
||||
- `apm experimental enable registries` must run before any `registry.*` config takes effect. Declaring a `registries:` block or running `apm config set registry.*` without it silently does nothing — no error, no warning.
|
||||
- Plain `apm audit` and `apm audit --ci` check different things: plain `apm audit` scans deployed files for hidden Unicode only; `--ci` additionally runs lockfile-consistency checks, install-replay drift detection, and org policy checks. A clean plain `apm audit` is not a CI-equivalent pass.
|
||||
@@ -34,7 +34,7 @@ metadata:
|
||||
|---|---|---|
|
||||
| `/apm-workflow configure` | Author/edit `apm.yml`; scaffold a new package (`apm plugin init`) | `references/configure.md` |
|
||||
| `/apm-workflow install` | Resolve/fetch dependencies declared in `apm.yml` (`apm install`, `apm install [PACKAGE_REF]`) | `references/install.md` |
|
||||
| `/apm-workflow marketplace` | Build a marketplace, register packages into it, or register a marketplace as a consumer (`apm marketplace init/check/package add/add`) | `references/marketplace.md` |
|
||||
| `/apm-workflow marketplace` | Build a marketplace, register packages into it (local: hand-edit `apm.yml`; remote: `apm marketplace package add`), or register a marketplace as a consumer (`apm marketplace init/check/package add/add`) | `references/marketplace.md` |
|
||||
| `/apm-workflow compile` | Generate per-target output, bundle, or publish (`apm compile`, `apm pack`, `apm publish`) | `references/compile.md` |
|
||||
| `/apm-workflow audit` | Validate integrity/policy or wire a CI gate (`apm audit`, `apm audit --ci`) | `references/audit.md` |
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
---
|
||||
topic: compile
|
||||
source_keys:
|
||||
- context7-microsoft-apm
|
||||
---
|
||||
|
||||
## Compile
|
||||
|
||||
```bash
|
||||
apm compile # fails on skill/agent-only packages — see Gotchas
|
||||
apm compile --clean # zero-write sanity check; use for skill/agent-only packages
|
||||
apm compile --clean --dry-run # pure preview, no writes
|
||||
```
|
||||
|
||||
Compiles `.apm/instructions/` + `.apm/agents/*.agent.md` primitives into consumer-side context files (AGENTS.md/CLAUDE.md CONTEXT files) for the deployment target, per the `compilation:` block in `apm.yml`. This is the consumer/deployment side — it is NOT the producer of `plugin.json`/`marketplace.json`; that's `apm pack`'s job (below). Run `apm compile` after any change to `.apm/instructions/`/`.apm/agents/` content or to `compilation:`/`targets:` in `apm.yml`.
|
||||
|
||||
## Pack
|
||||
|
||||
```bash
|
||||
apm pack --dry-run # resolve and print; do not write
|
||||
apm pack --offline # cached refs only
|
||||
apm pack --include-prerelease # allow pre-release tags
|
||||
apm pack -v # per-entry resolution detail
|
||||
apm pack --marketplace=claude --json # JSON output for CI pipelines
|
||||
```
|
||||
|
||||
Bundles a producer package into a distributable artifact. Default to `--dry-run -v` first when packing something for the first time or after a dependency change — resolution errors surface before anything is written.
|
||||
|
||||
### `.mcp.json` merge mechanics
|
||||
|
||||
`apm pack` reads a package's root-level `.mcp.json` directly — no `dependencies.mcp` entry in `apm.yml` is needed for simple passthrough. Behavior is content-aware:
|
||||
|
||||
- An empty `.mcp.json` (`{"mcpServers": {}}`) is NOT included in the packed output at all.
|
||||
- A populated one gets its `mcpServers` content merged directly into the compiled `plugin.json`, but only for the `claude` target.
|
||||
- The `copilot` target's compiled `plugin.json` OMITS `mcpServers` entirely — it isn't part of Copilot's plugin manifest schema.
|
||||
|
||||
`dependencies.mcp` in `apm.yml` is for a different purpose — declaring a remote MCP-server package as an APM dependency — not local `.mcp.json` passthrough.
|
||||
|
||||
### `includes: auto` and the packed bundle
|
||||
|
||||
`includes: auto` does NOT sweep generic root-level passthrough files (README.md, docs/, sources.md, config files, etc.) into the `apm pack` distribution bundle (`build/<name>-<version>`) — only `.apm/` primitives, the compiled `plugin.json`, and the content-aware `.mcp.json` handling above make it into that bundle. This does not affect Claude Code's own plugin loading, which reads a plugin's working directory directly via its `source:` path in `marketplace.json`, not the `apm pack` bundle — but it matters for anyone relying on the packed bundle for distribution via `apm install`.
|
||||
|
||||
Run `apm audit` after compile/pack, not before — audit scans deployed/compiled output, not the source `apm.yml` manifest; see `references/audit.md`.
|
||||
|
||||
## Publish
|
||||
|
||||
```bash
|
||||
apm publish --package acme/my-skill --dry-run -v
|
||||
apm publish --package acme/my-skill
|
||||
```
|
||||
|
||||
Publishes a producer package (root containing `apm.yml`, `.apm/`, and optionally a `registries:` block) to a registry. Always dry-run with `-v` first — publishing is not trivially reversible once a version tag is claimed on a registry.
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
apm run <script> [--param key=value]
|
||||
```
|
||||
|
||||
Executes a named script defined under `scripts:` in `apm.yml`, with `--param` substituting values into the script's parameters.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- Plain `apm compile` HARD-FAILS with exit 1 and `No instruction files found in .apm/ directory` on any package that has skills/agents but no `.apm/instructions/` content — the common case for a skill-only or skill+agent package. Use `apm compile --clean` as the zero-write sanity-check substitute: it sets `allow_empty=True` internally and exits 0 cleanly with zero writes; add `--dry-run` for a pure preview. `compile` ≠ `pack` — see above.
|
||||
- `claude plugin validate --strict` auto-scans every `.md` file directly under a compiled plugin's `agents/` directory and treats it as an agent definition requiring frontmatter, independent of any manifest declaration (an empirically observed Claude Code platform behavior, not an `apm` mechanic). A non-agent `.md` file (notes, provenance record, README) that ends up under `.apm/agents/` in the source tree will still fail validation once compiled to the `claude` target. Keep such files outside `.apm/agents/` (e.g. at the package root), regardless of what `apm.yml` declares.
|
||||
@@ -7,10 +7,10 @@ source_keys:
|
||||
## Scaffolding a new package
|
||||
|
||||
```bash
|
||||
apm plugin init <name> --yes
|
||||
apm plugin init --yes --target claude,copilot
|
||||
```
|
||||
|
||||
Scaffolds `apm.yml` + a `.apm/` skeleton in the current directory. Run this once per package (e.g. once per `plugins/<name>/` directory in a monorepo-hybrid layout), not once for the whole repo.
|
||||
Run from inside the target package directory, with no positional name argument (see Gotchas). Creates `apm.yml` + `plugin.json` in the current directory — it does NOT scaffold a `.apm/` skeleton. Primitive subdirectories (`.apm/skills/`, `.apm/agents/`, `.apm/hooks/`) must be created manually as content is migrated into them. Run this once per package (e.g. once per `plugins/<name>/` directory in a monorepo-hybrid layout), not once for the whole repo.
|
||||
|
||||
## `apm.yml` — required fields
|
||||
|
||||
@@ -27,7 +27,7 @@ version: 1.0.0
|
||||
- `description`, `author`, `license`, `homepage`, `repository`, `keywords` — standard package metadata
|
||||
- `type` — `instructions | skill | hybrid | prompts`; constrains `.apm/` contents
|
||||
- `targets` — which harnesses this package compiles to (plural list form preferred; legacy singular `target: copilot,claude` CSV form still accepted)
|
||||
- `includes` — `auto` publishes the authoritative local layout as-is, or list explicit repo paths
|
||||
- `includes` — `auto` publishes the authoritative local layout as-is, or list explicit repo paths. Note: `auto` does not sweep generic root-level passthrough files (README.md, docs/, sources.md, config files) into the `apm pack` distribution bundle — see `references/compile.md`
|
||||
- `dependencies`/`devDependencies` — `apm`/`mcp`/`lsp` entries; `devDependencies` share the same shape but are excluded from the shipped artifact
|
||||
- `scripts` — named commands runnable via `apm run <name>`
|
||||
- `compilation` — target/strategy/exclude/placement controls for `apm compile`/`apm pack`
|
||||
@@ -57,3 +57,7 @@ apm config set registry.corp-main.default true
|
||||
```
|
||||
|
||||
`apm config get`/`apm config unset` manage individual keys the same way.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- `apm plugin init <name>` run with a positional name argument, from inside a directory already named `<name>`, creates a wrongly-nested `<name>/<name>/` subdirectory — it treats the positional arg as "create a new project directory named X," not "confirm the current directory is X." Fix: omit the positional argument entirely when already cd'd into the target package directory — run `apm plugin init --yes --target claude,copilot` instead.
|
||||
@@ -24,11 +24,20 @@ apm pack # 4. build marketplace artifacts
|
||||
|
||||
## Registering a package into a marketplace you're building
|
||||
|
||||
```bash
|
||||
apm marketplace package add ./packages/plugin-a --name plugin-a
|
||||
`apm marketplace package add`'s `SOURCE` argument only accepts `owner/repo`, `host.tld/owner/repo`, or full URL forms (per `apm marketplace package add --help`) — it does NOT accept a local relative path. Running it against a local path (e.g. `apm marketplace package add ./packages/plugin-a`) throws a git-remote-reachability error: it tries to treat the path as a remote source and fails to reach it.
|
||||
|
||||
To register a local package — the monorepo-hybrid case, pointing at each existing `plugins/<name>/` directory once that directory has its own `apm.yml` — hand-edit `apm.yml`'s `marketplace.packages[]` list directly:
|
||||
|
||||
```yaml
|
||||
marketplace:
|
||||
packages:
|
||||
- name: plugin-a
|
||||
description: ...
|
||||
source: ./packages/plugin-a
|
||||
version: 1.0.0
|
||||
```
|
||||
|
||||
Registers an already-existing local package path into the root marketplace listing without re-scaffolding it — this is the monorepo-hybrid command: point it at each existing `plugins/<name>/` directory once that directory has its own `apm.yml`.
|
||||
This local-path `source:` form IS valid — `apm marketplace check` and `apm pack` both accept it — even though the `package add` CLI subcommand cannot create it for you. Use `apm marketplace package add` only for packages hosted at a remote git ref; for local packages, edit the YAML directly.
|
||||
|
||||
## Registering a marketplace as a consumer
|
||||
|
||||
@@ -67,5 +76,6 @@ Without this block, the default versioning strategy ties every listed package to
|
||||
|
||||
## Gotchas
|
||||
|
||||
- Only `claude` and `codex` marketplace output profiles exist in apm 0.28.0 — confirmed via source (`apm_cli/marketplace/output_profiles.py`: `MARKETPLACE_OUTPUTS = {claude: ..., codex: ...}`, nothing else). There is no native Copilot marketplace output; `apm pack` will not generate one. A repo needing a Copilot-consumable marketplace manifest must maintain it separately by other means.
|
||||
- A package/plugin `name` compiling to the `claude` target must avoid Claude Code's reserved name prefixes (see `plugin-author/SKILL.md` Gotchas for the current list) — otherwise the compiled `.claude-plugin/marketplace.json` is rejected by Claude Code's validator. This is a Claude Code platform constraint, independent of how the manifest gets authored.
|
||||
- Removing a package from `marketplace.packages[]` in `apm.yml` and re-packing changes the public/consumed catalog. Confirm with the user in conversation before removing the entry and running `apm pack` — this is a normal `apm.yml` edit (not a distinct apm-orchestrate operation with its own gate), so the confirmation is conversational, the same as any other consequential manifest edit.
|
||||
@@ -6,7 +6,7 @@ Guided entry point for building or improving something in kyberforge when the ta
|
||||
|
||||
Grills the user's intent via `bin:grill-with-docs` (inline, interactive) against this repo's `CONTEXT.md` and `docs/adr/`, classifies the target artifact type (skill, agent/subagent definition, plugin, or marketplace entry), announces the classification, then routes to the matching author skill — chaining more than one, in dependency order, if the intent spans multiple artifact types.
|
||||
|
||||
Author-skill invocation defaults to a fork subagent (inherits the grilled-intent context) and falls back to inline when forking isn't possible or the routed flow needs live user interaction (clarifying questions, a HITL gate). After a `skill-author` or `agent-author` route finishes — each already closes out with its own inline audit — forge spins up a separate clean-context subagent to independently re-run the matching audit skill (`skill-audit` / `agent-audit`) as a distinct check on the finished artifact, not a duplicate of the inline one. If that clean audit turns up any unresolved finding, forge loops — re-invoke the author skill to resolve it, re-run the clean audit — until the clean audit comes back with nothing unresolved. `plugin-author` and `marketplace-author` routes get no recheck: they have no audit counterpart, and their real terminal check (`claude plugin validate`) is already part of their own flow.
|
||||
Author-skill invocation defaults to a fork subagent (inherits the grilled-intent context) and falls back to inline when forking isn't possible or the routed flow needs live user interaction (clarifying questions, a HITL gate). After a `skill-author` or `agent-author` route finishes — each already closes out with its own inline audit — forge spins up a separate clean-context subagent to independently re-run the matching audit skill (`skill-audit` / `agent-audit`) as a distinct check on the finished artifact, not a duplicate of the inline one. If that clean audit turns up any unresolved finding, forge loops — re-invoke the author skill to resolve it, re-run the clean audit — until the clean audit comes back with nothing unresolved. `apm-workflow` routes (plugin, marketplace entry) get no recheck: they have no audit counterpart, and their real terminal check (`apm audit`) is already part of their own flow.
|
||||
|
||||
## Before you start
|
||||
|
||||
@@ -18,7 +18,7 @@ Have a rough idea of what you want to build or change. forge doesn't require you
|
||||
/forge
|
||||
```
|
||||
|
||||
Skip forge and call the target skill directly (`/skill-author`, `/agent-author`, `/plugin-author`, `/marketplace-author`) when you already know the artifact type.
|
||||
Skip forge and call the target skill directly (`/skill-author`, `/agent-author`, `/apm-workflow`) when you already know the artifact type.
|
||||
|
||||
## Files
|
||||
|
||||
@@ -33,5 +33,5 @@ Skip forge and call the target skill directly (`/skill-author`, `/agent-author`,
|
||||
|---|---|
|
||||
| Skill | `kyberforge:skill-author` |
|
||||
| Agent / subagent definition | `kyberforge:agent-author` |
|
||||
| Plugin | `kyberforge:plugin-author` |
|
||||
| Marketplace entry | `kyberforge:marketplace-author` |
|
||||
| Plugin | `kyberforge:apm-workflow` (configure) |
|
||||
| Marketplace entry | `kyberforge:apm-workflow` (marketplace) |
|
||||
@@ -21,7 +21,7 @@ metadata:
|
||||
|
||||
## Gotchas
|
||||
|
||||
- forge is an optional guided entry point, not a gate — the six existing factory skills (`skill-author`, `skill-audit`, `agent-author`, `agent-audit`, `plugin-author`, `marketplace-author`) remain directly invokable and forge does not intercept those calls. Note `plugin-author` and `marketplace-author` are deprecated per ADR-0015 — superseded by `apm-workflow`, pending issue #90 — but still function normally until that lands.
|
||||
- forge is an optional guided entry point, not a gate — the four existing factory skills (`skill-author`, `skill-audit`, `agent-author`, `agent-audit`) plus `apm-workflow` (for plugin/marketplace-entry artifacts) remain directly invokable and forge does not intercept those calls. `plugin-author` and `marketplace-author` were removed per ADR-0015 once issue #90 landed — `apm-workflow` is their sole successor.
|
||||
- Claude Code's skill-level `context: fork` frontmatter field and the `/fork` subagent command are opposites despite sharing a name — `context: fork` isolates (fresh context, no parent access), while `/fork` inherits the full conversation. Keep this straight when deciding how to invoke a subagent in Step 3.
|
||||
|
||||
## Step 1 — Grill the intent
|
||||
@@ -38,12 +38,12 @@ Match the grilled intent against exactly one row (or more than one, if the inten
|
||||
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -----------------------------| ---------------------------------|
|
||||
| A reusable capability or workflow the agent should load inline in the main conversation — triggered automatically by description-matching, not a fresh context, and free to bundle its own `references/`, `scripts/`, or `assets/` | Skill | `kyberforge:skill-author` |
|
||||
| A recurring task needs its own reusable agent/subagent definition — dedicated system prompt, tools, and description, invokable by name across sessions | Agent / subagent definition | `kyberforge:agent-author` |
|
||||
| A new distributable unit is needed — no existing plugin is the right home for the skill/agent/hook/MCP server being built, or the bundle needs its own manifest, versioning, and install lifecycle separate from what already exists | Plugin | `kyberforge:plugin-author` |
|
||||
| The plugin itself already exists (or was just created) and only its marketplace-facing metadata needs to change — listing it for the first time, or updating its version/description entry — never the plugin's contents | Marketplace entry | `kyberforge:marketplace-author` |
|
||||
| A new distributable unit is needed — no existing plugin is the right home for the skill/agent/hook/MCP server being built, or the bundle needs its own manifest, versioning, and install lifecycle separate from what already exists | Plugin | `kyberforge:apm-workflow` (configure — `apm plugin init`) |
|
||||
| The plugin itself already exists (or was just created) and only its marketplace-facing metadata needs to change — listing it for the first time, or updating its version/description entry — never the plugin's contents | Marketplace entry | `kyberforge:apm-workflow` (marketplace — `apm marketplace package add`) |
|
||||
|
||||
If the intent is genuinely ambiguous between rows even after grilling, ask the user directly rather than guessing.
|
||||
|
||||
Note: `kyberforge:plugin-author` and `kyberforge:marketplace-author` are deprecated per ADR-0015, superseded by `apm-workflow` — pending issue #90, so routing to them is unchanged for now.
|
||||
Note: plugin and marketplace-entry artifacts route through `kyberforge:apm-workflow` per ADR-0015 — the former `plugin-author` and `marketplace-author` skills were removed once issue #90 landed.
|
||||
|
||||
This table classifies what to build, not how to run it — a one-off task that merely needs an isolated vs. context-inheriting run (rather than a new, reusable definition) isn't an artifact at all; there's nothing here to route it to.
|
||||
|
||||
@@ -53,15 +53,15 @@ State the classification and which skill(s) will run before invoking anything.
|
||||
|
||||
**Invoking the author skill(s).** Default to a fork subagent — it inherits the full grilled-intent conversation, so the author skill doesn't need to be re-briefed. Fall back to an inline invocation (same conversation, no subagent) when either is true:
|
||||
- **Fork is technically unavailable** — already running inside a fork (a fork cannot spawn another fork), a nesting-depth cap is reached, or the environment doesn't support forking.
|
||||
- **The routed flow needs live user interaction mid-run** that a backgrounded fork can't surface in real time — clarifying questions, confirmation checkpoints, or a HITL gate (e.g. `plugin-author`'s release step). Judge this from context: if nothing about the routed flow signals a live checkpoint, prefer the fork subagent.
|
||||
- **The routed flow needs live user interaction mid-run** that a backgrounded fork can't surface in real time — clarifying questions, confirmation checkpoints, or a HITL gate (e.g. `apm-workflow`'s publish/release steps, or its conversational confirmation before removing a marketplace entry). Judge this from context: if nothing about the routed flow signals a live checkpoint, prefer the fork subagent.
|
||||
|
||||
`plugin-author` and `marketplace-author` routes always run inline — their flows are short, prompt-heavy, or gated, and get no follow-up audit-recheck step to justify running detached (see below).
|
||||
`apm-workflow` routes for plugin/marketplace-entry artifacts always run inline — their flows are short, prompt-heavy, or gated, and get no follow-up audit-recheck step to justify running detached (see below).
|
||||
|
||||
**After a skill or agent route finishes.** `skill-author` and `agent-author` already close out with their own inline audit (`skill-author` runs `/skill-audit`, `agent-author` invokes `kyberforge:agent-audit` directly) in the same context as the authoring work — that's unchanged. Once that author skill's run has finished, spin up a separate **clean-context subagent** (fresh, not forked, no inherited context) to independently re-run the same audit skill against the finished artifact. This is a distinct verification layer, not a duplicate: the inline audit shares context with the work it's checking and can share its blind spots, while the clean rerun has no stake in the result.
|
||||
|
||||
If the clean audit surfaces any unresolved finding — not only a disagreement with the inline pass, any actionable finding on its own — loop: re-invoke the author skill (same fork-vs-inline judgment as the initial invocation) to resolve it, then re-run the clean audit again. Repeat until the clean audit comes back with nothing unresolved. Only then is the route done — the same resolve-before-close discipline `skill-author`/`agent-author` already apply to their own inline audit.
|
||||
|
||||
When the intent spans multiple artifact types (e.g. a new skill inside a new plugin, then registering that plugin via `kyberforge:marketplace-author`), chain the routes in dependency order — an artifact that must exist on disk before another skill can target it goes first (e.g. `plugin-author` creates the plugin directory before `skill-author` scaffolds a skill inside it).
|
||||
When the intent spans multiple artifact types (e.g. a new skill inside a new plugin, then registering that plugin via `kyberforge:apm-workflow` marketplace), chain the routes in dependency order — an artifact that must exist on disk before another skill can target it goes first (e.g. `apm-workflow` scaffolds the plugin directory via `apm plugin init` before `skill-author` scaffolds a skill inside it).
|
||||
|
||||
## Step 4 — Bump plugin version (if applicable)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
setup() {
|
||||
REPO_ROOT="$(cd "$BATS_TEST_DIRNAME/../../../../../" && pwd)"
|
||||
REPO_ROOT="$(cd "$BATS_TEST_DIRNAME/../../../../../../" && pwd)"
|
||||
load "$REPO_ROOT/tests/test_helper/bats-support/load"
|
||||
load "$REPO_ROOT/tests/test_helper/bats-assert/load"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
setup() {
|
||||
REPO_ROOT="$(cd "$BATS_TEST_DIRNAME/../../../../../" && pwd)"
|
||||
REPO_ROOT="$(cd "$BATS_TEST_DIRNAME/../../../../../../" && pwd)"
|
||||
load "$REPO_ROOT/tests/test_helper/bats-support/load"
|
||||
load "$REPO_ROOT/tests/test_helper/bats-assert/load"
|
||||
|
||||
@@ -18,7 +18,7 @@ git clone https://github.com/bats-core/bats-assert tests/test_helper/bats-assert
|
||||
Run all tests for this skill (from the repo root):
|
||||
|
||||
```bash
|
||||
bats plugins/kyberforge/skills/skill-author/tests/
|
||||
bats plugins/kyberforge/.apm/skills/skill-author/tests/
|
||||
```
|
||||
|
||||
## Files
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
setup() {
|
||||
REPO_ROOT="$(cd "$BATS_TEST_DIRNAME/../../../../../" && pwd)"
|
||||
REPO_ROOT="$(cd "$BATS_TEST_DIRNAME/../../../../../../" && pwd)"
|
||||
load "$REPO_ROOT/tests/test_helper/bats-support/load"
|
||||
load "$REPO_ROOT/tests/test_helper/bats-assert/load"
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
{
|
||||
"author": {
|
||||
"email": "defame1297@rkdr.net",
|
||||
"name": "Defame1297",
|
||||
"url": "https://git.dev.rkdr.net/Defame1297/"
|
||||
},
|
||||
"description": "Skills and agents for creating, maintaining, and managing a Claude Code / Copilot CLI plugin marketplace.",
|
||||
"displayName": "Kyberforge",
|
||||
"keywords": [],
|
||||
"license": "MIT",
|
||||
"name": "kyberforge",
|
||||
"version": "1.3.1"
|
||||
"version": "1.4.0"
|
||||
}
|
||||
|
||||
11
plugins/kyberforge/.github/plugin/plugin.json
vendored
Normal file
11
plugins/kyberforge/.github/plugin/plugin.json
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"author": {
|
||||
"email": "defame1297@rkdr.net",
|
||||
"name": "Defame1297",
|
||||
"url": "https://git.dev.rkdr.net/Defame1297/"
|
||||
},
|
||||
"description": "Skills and agents for creating, maintaining, and managing a Claude Code / Copilot CLI plugin marketplace.",
|
||||
"license": "MIT",
|
||||
"name": "kyberforge",
|
||||
"version": "1.4.0"
|
||||
}
|
||||
@@ -46,8 +46,6 @@ copilot plugin install ./plugins/kyberforge
|
||||
| `agent-author` | Author an agent definition file |
|
||||
| `pc-author` | Create, add, remove, and configure `.pre-commit-config.yaml` |
|
||||
| `pc-run` | Install, run, autoupdate, and maintain the pre-commit setup |
|
||||
| `plugin-author` | (Deprecated — see apm-workflow) Create, update, and release plugin scaffolds for the holocron marketplace |
|
||||
| `marketplace-author` | (Deprecated — see apm-workflow) Add, remove, and update plugin entries in the holocron marketplace manifest |
|
||||
| `apm-install` | Install or upgrade the apm CLI and set up the agent runtimes it drives (Copilot CLI, Codex, Gemini, generic llm) |
|
||||
| `apm-workflow` | Author apm.yml, scaffold an apm package/marketplace, install dependencies, and compile/pack/publish/audit apm content |
|
||||
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
---
|
||||
name: apm-orchestrate
|
||||
|
||||
description: Orchestrates apm package/marketplace operations for other agents. Invoke when a caller needs a multi-step apm operation (scaffold a package, register it into a marketplace, compile/pack/publish, audit) coordinated across the apm-workflow skill with safety gates, session context, and structured results — especially fanning the same operation out across multiple packages in a monorepo.
|
||||
|
||||
tools: Bash, Read, Skill
|
||||
|
||||
source_keys:
|
||||
- context7-microsoft-apm
|
||||
|
||||
---
|
||||
|
||||
You are the orchestrator for apm package/marketplace operations — a composable workflow dispatcher designed for other agents to invoke multi-step `apm` operations reliably, especially the same operation repeated across several packages in a monorepo-hybrid layout. Your one job is routing and safety-gating: you do not decide manifest content yourself, you delegate to `apm-workflow` and enforce confirmation on irreversible operations.
|
||||
|
||||
You resolve the package root once per dispatched operation (the directory containing that package's `apm.yml`) and carry it forward as session context rather than making every call re-resolve it.
|
||||
|
||||
**Scope:** this orchestrator routes `apm-workflow`'s five concerns only — configure/scaffold, marketplace, install, compile/pack/publish, audit. It does not route `apm-install` (binary install, agent-runtime setup) — that's a one-time machine bootstrap, not a per-package, fan-out-able operation, and has no orchestrator counterpart. Confirm `apm --version` succeeds before dispatching any operation; if it fails, tell the caller to run `apm-install` first rather than attempting recovery here.
|
||||
|
||||
## Hard rules
|
||||
|
||||
These are non-negotiable regardless of `confirm` or any skill-local override:
|
||||
- `apm publish` claims a version on a registry — treat it as irreversible. Refuse without explicit `confirm: true`; always dispatch with `--dry-run -v` first and surface that output to the caller before the real publish, even when `confirm: true` was given.
|
||||
- Never guess the marketplace-add direction from context — resolve strictly from the operation name (`add-package` vs `add-marketplace`); see apm-workflow/SKILL.md Gotchas for why the two are easy to conflate.
|
||||
- `apm.yml`'s `type:` field constrains what `.apm/` may contain — when scaffolding (`init-package`), set `type:` before any primitive content is added; do not defer it.
|
||||
- A clean plain `apm audit` is not a CI-equivalent pass — if the caller's intent is a CI gate, dispatch `audit-ci`, not `audit`.
|
||||
- Check the `apm experimental enable registries` precondition before dispatching any operation that depends on a named registry, and fail with a clear diagnostic rather than silently no-op'ing like apm itself does — see apm-workflow/SKILL.md Gotchas for the underlying constraint.
|
||||
|
||||
When invoked, you:
|
||||
1. Parse the incoming workflow request (operation type, parameters, target package(s), context overrides)
|
||||
2. Check safety gates: if the operation is `publish` and the request lacks explicit `confirm: true`, fail immediately with "requires explicit confirmation"
|
||||
3. Route to `apm-workflow` with the resolved action (`configure`, `marketplace`, `install`, `compile`, `audit`)
|
||||
4. Manage session context: carry forward each package's root directory and any registry/marketplace config already resolved this session
|
||||
5. Handle error recovery: for recoverable failures (a stale lockfile, a marketplace ref that doesn't resolve yet because a dependency package hasn't been scaffolded), retry after the caller confirms the dependency now exists; for unrecoverable failures, fail gracefully with actionable diagnostics
|
||||
6. When fanning an operation across multiple packages (e.g. `init-package` for every `plugins/<name>/` directory in a monorepo-hybrid conversion), dispatch independent packages in parallel when no shared state or ordering dependency exists between them; keep dispatch strictly sequential only for packages with a real dependency on another package's completion (e.g. a marketplace registration that needs a dependency package scaffolded first). Either way, continue past a single package's failure rather than aborting the whole batch — collect all failures and report them together at the end
|
||||
7. Aggregate results and return structured JSON output suitable for agent chaining
|
||||
|
||||
## Inputs
|
||||
|
||||
- **operation:** string, one of:
|
||||
- configure: init-package, edit-config (→ author/edit an existing package's `apm.yml` directly — adding a dependency, script, registries block, or removing a `marketplace.packages[]` entry; not a distinct `apm` CLI verb, just a manifest edit, optionally followed by `compile: pack` if it affects a published marketplace listing)
|
||||
- marketplace: init-marketplace, check-marketplace, add-package (→ `apm marketplace package add` — register a local package into a marketplace being built), add-marketplace (→ `apm marketplace add` — register a marketplace as a consumer)
|
||||
- install: install (→ `apm install [PACKAGE_REF]` — resolve/fetch dependencies declared in `apm.yml` against `apm.lock.yaml`; no arguments re-resolves everything)
|
||||
- compile: compile, pack, publish, run-script
|
||||
- audit: audit, audit-ci
|
||||
- **package_root:** string, path to the directory containing the target `apm.yml` (required for every operation except `init-marketplace` when scaffolding the repo root)
|
||||
- **parameters:** object, operation-specific arguments (package name for `add-package`, script name for `run-script`, registry name, etc.)
|
||||
- **context:** object (optional), session state to carry forward (resolved registry config, marketplace root)
|
||||
- **confirm:** boolean (optional), explicit confirmation required for `publish`
|
||||
|
||||
## Process
|
||||
|
||||
1. Validate the request structure and check if `operation` is known
|
||||
2. Check the request against the Hard rules above (publish confirmation, marketplace-add direction, `type:` ordering, audit-vs-audit-ci, registries precondition) — refuse outright on violation, independent of `confirm`
|
||||
3. If `operation` is `publish`: require `confirm: true`, dispatch `--dry-run -v` first regardless, surface that output, else fail with structured "requires explicit confirmation" error
|
||||
4. Verify `apm --version` succeeds; if not, fail with a diagnostic pointing to `apm-install`
|
||||
5. Invoke `apm-workflow` via `Skill` with the resolved action, `package_root`, and parameters
|
||||
6. If fanning across multiple packages, dispatch independent packages in parallel when no shared state or ordering dependency exists between them; loop package-by-package (strictly sequential) only for packages with a real dependency on another package's completion. Either way, collect per-package results and failures rather than aborting on the first failure
|
||||
7. Catch and handle apm errors: retry once for a dependency-not-yet-scaffolded failure after the caller confirms the dependency exists; otherwise return error structure with diagnostics
|
||||
8. Aggregate all outputs and return as structured JSON
|
||||
|
||||
## Output
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "success" | "error" | "partial",
|
||||
"operation": "<operation_name>",
|
||||
"result": {
|
||||
"output": "<apm-workflow output or result, or a list of per-package results when fanned out>",
|
||||
"context": { "package_root": "...", "resolved_registry": "..." }
|
||||
},
|
||||
"error": {
|
||||
"message": "<human-readable error>",
|
||||
"code": "<error type: not_confirmed | apm_unavailable | manifest_invalid | dependency_unresolved | publish_failed>",
|
||||
"recovery_attempted": true | false,
|
||||
"suggestions": ["<suggestion1>", "<suggestion2>"]
|
||||
}
|
||||
}
|
||||
```
|
||||
27
plugins/kyberforge/apm.yml
Normal file
27
plugins/kyberforge/apm.yml
Normal file
@@ -0,0 +1,27 @@
|
||||
name: kyberforge
|
||||
version: 1.4.0
|
||||
description: Skills and agents for creating, maintaining, and managing a Claude Code / Copilot CLI plugin marketplace.
|
||||
author:
|
||||
name: Defame1297
|
||||
email: defame1297@rkdr.net
|
||||
url: https://git.dev.rkdr.net/Defame1297/
|
||||
license: MIT
|
||||
keywords: []
|
||||
|
||||
# Constrains what .apm/ may contain: instructions, skill, hybrid, or prompts
|
||||
type: hybrid
|
||||
|
||||
targets:
|
||||
- claude
|
||||
- copilot
|
||||
|
||||
# "auto" publishes the authoritative local source layout — the large
|
||||
# docs/research/ tree stays as root-level passthrough content, not a primitive.
|
||||
includes: auto
|
||||
|
||||
dependencies:
|
||||
apm: []
|
||||
mcp: []
|
||||
devDependencies:
|
||||
apm: []
|
||||
scripts: {}
|
||||
@@ -1,27 +0,0 @@
|
||||
# hooks/
|
||||
|
||||
**Claude Code only.** Hook definitions that run in response to Claude Code events.
|
||||
|
||||
The `hooks.json` in this directory is read by Claude Code. Structure:
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
{ "type": "command", "command": "echo 'tool used'" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Supported events: `PreToolUse`, `PostToolUse`, `Notification`, `Stop`.
|
||||
|
||||
Use `${CLAUDE_PLUGIN_ROOT}` to reference scripts inside this plugin — the plugin runs
|
||||
from a cache path after install, not its original repo location.
|
||||
|
||||
For GitHub Copilot CLI hooks, see `hooks.json` at the plugin root.
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"hooks": {}
|
||||
}
|
||||
@@ -1,17 +1,12 @@
|
||||
{
|
||||
"agents": "agents/",
|
||||
"author": {
|
||||
"email": "defame1297@rkdr.net",
|
||||
"name": "Defame1297"
|
||||
"name": "Defame1297",
|
||||
"url": "https://git.dev.rkdr.net/Defame1297/"
|
||||
},
|
||||
"description": "Skills and agents for creating, maintaining, and managing a Claude Code / Copilot CLI plugin marketplace.",
|
||||
"hooks": "hooks.json",
|
||||
"keywords": [],
|
||||
"license": "MIT",
|
||||
"mcpServers": ".mcp.json",
|
||||
"name": "kyberforge",
|
||||
"skills": [
|
||||
"skills/"
|
||||
],
|
||||
"version": "1.3.1"
|
||||
"version": "1.4.0"
|
||||
}
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
# skills/
|
||||
|
||||
Skills for this plugin. Each skill lives in its own subdirectory:
|
||||
|
||||
```
|
||||
skills/
|
||||
<skill-name>/
|
||||
SKILL.md # required — frontmatter + skill body
|
||||
META.md # required — provenance and audit fields
|
||||
references/ # optional — on-demand reference docs
|
||||
scripts/ # optional — executable helper scripts
|
||||
assets/ # optional — templates, data files, lookup tables
|
||||
```
|
||||
|
||||
**Shared** — both Claude Code and GitHub Copilot CLI read `skills/<name>/SKILL.md`.
|
||||
|
||||
To create or improve a skill, run `/skill-author` in a Claude Code session. To review a skill
|
||||
without modifying it, run `/skill-audit`. Do not write SKILL.md by hand without following the
|
||||
authoring standard — trigger descriptions and body discipline are required.
|
||||
|
||||
## Skills
|
||||
|
||||
| Skill | Description |
|
||||
|---|---|
|
||||
| `skill-author` | Create or improve a skill from scratch, audit findings, or inline feedback |
|
||||
| `skill-audit` | Audit a skill directory against the agentskills.io spec and produce a findings report |
|
||||
| `agent-author` | Author an agent definition file |
|
||||
| `pc-author` | Create, add, remove, and configure `.pre-commit-config.yaml` |
|
||||
| `pc-run` | Install, run, autoupdate, and maintain the pre-commit setup |
|
||||
| `plugin-author` | (Deprecated — see apm-workflow) Create, update, and release plugin scaffolds for the holocron marketplace |
|
||||
| `marketplace-author` | (Deprecated — see apm-workflow) Add, remove, and update plugin entries in the holocron marketplace manifest |
|
||||
| `apm-install` | Install or upgrade the apm CLI and set up the agent runtimes it drives (Copilot CLI, Codex, Gemini, generic llm) |
|
||||
| `apm-workflow` | Author apm.yml, scaffold an apm package/marketplace, install dependencies, and compile/pack/publish/audit apm content |
|
||||
@@ -1,48 +0,0 @@
|
||||
---
|
||||
topic: compile
|
||||
source_keys:
|
||||
- context7-microsoft-apm
|
||||
---
|
||||
|
||||
## Compile
|
||||
|
||||
```bash
|
||||
apm compile
|
||||
```
|
||||
|
||||
Generates per-target output (Claude, Copilot, etc.) from the vendor-neutral `.apm/` primitive source tree, per the `compilation:` block in `apm.yml`. Run this after any change to `.apm/` content or to `compilation:`/`targets:` in `apm.yml`.
|
||||
|
||||
## Pack
|
||||
|
||||
```bash
|
||||
apm pack --dry-run # resolve and print; do not write
|
||||
apm pack --offline # cached refs only
|
||||
apm pack --include-prerelease # allow pre-release tags
|
||||
apm pack -v # per-entry resolution detail
|
||||
apm pack --marketplace=claude --json # JSON output for CI pipelines
|
||||
```
|
||||
|
||||
Bundles a producer package into a distributable artifact. Default to `--dry-run -v` first when packing something for the first time or after a dependency change — resolution errors surface before anything is written.
|
||||
|
||||
Run `apm audit` after compile/pack, not before — audit scans deployed/compiled output, not the source `apm.yml` manifest; see `references/audit.md`.
|
||||
|
||||
## Publish
|
||||
|
||||
```bash
|
||||
apm publish --package acme/my-skill --dry-run -v
|
||||
apm publish --package acme/my-skill
|
||||
```
|
||||
|
||||
Publishes a producer package (root containing `apm.yml`, `.apm/`, and optionally a `registries:` block) to a registry. Always dry-run with `-v` first — publishing is not trivially reversible once a version tag is claimed on a registry.
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
apm run <script> [--param key=value]
|
||||
```
|
||||
|
||||
Executes a named script defined under `scripts:` in `apm.yml`, with `--param` substituting values into the script's parameters.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- `claude plugin validate --strict` auto-scans every `.md` file directly under a compiled plugin's `agents/` directory and treats it as an agent definition requiring frontmatter, independent of any manifest declaration (an empirically observed Claude Code platform behavior, not an `apm` mechanic). A non-agent `.md` file (notes, provenance record, README) that ends up under `.apm/agents/` in the source tree will still fail validation once compiled to the `claude` target. Keep such files outside `.apm/agents/` (e.g. at the package root), regardless of what `apm.yml` declares.
|
||||
@@ -1,35 +0,0 @@
|
||||
# marketplace-author
|
||||
|
||||
Adds, removes, and updates plugin entries in the holocron marketplace manifest.
|
||||
|
||||
## What it does
|
||||
|
||||
Manages entries in the `plugins[]` array of `marketplace.json`. Always updates both `.claude-plugin/marketplace.json` and `.github/plugin/marketplace.json` in the same edit pass — never one without the other. Routes automatically to add, remove, update, or create-from-scratch based on whether the files exist and whether the named plugin is already in the catalog. Bumps the catalog version on every mutation (minor for ADD/REMOVE, patch for UPDATE). Runs `claude plugin validate .` after every mutating operation.
|
||||
|
||||
## Before you start
|
||||
|
||||
Have ready: the plugin name (kebab-case), what you want to do (add/remove/update), and — for add — the source type and source value. If adding from an external repo, know the source type (local path, GitHub, git URL, or npm).
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
/marketplace-author
|
||||
```
|
||||
|
||||
No manual script. This skill is purely agentic — it reads, edits, and writes the marketplace files directly using the Read/Edit/Write tools.
|
||||
|
||||
## Files
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `SKILL.md` | Skill instructions for agents |
|
||||
| `references/manifest-fields.md` | Full field reference for top-level and per-entry `marketplace.json` fields, all four source type shapes with examples, and why both files must stay identical |
|
||||
| `references/sources.md` | Research provenance — sources that informed this skill |
|
||||
| `references/README.md` | Directory meta-documentation for references/ |
|
||||
|
||||
## Marketplace files managed
|
||||
|
||||
| File | Read by |
|
||||
|------|---------|
|
||||
| `.claude-plugin/marketplace.json` | Claude Code |
|
||||
| `.github/plugin/marketplace.json` | Copilot CLI |
|
||||
@@ -1,246 +0,0 @@
|
||||
---
|
||||
name: marketplace-author
|
||||
description: >
|
||||
Use when the user wants to add a plugin to the marketplace ("register my
|
||||
plugin", "add to marketplace", "list plugin X"), remove an entry ("unlist
|
||||
plugin X", "remove from marketplace"), or update an existing entry ("bump
|
||||
the marketplace version", "update the description for Y"). Always updates
|
||||
both .claude-plugin/marketplace.json and .github/plugin/marketplace.json in
|
||||
the same pass. Out of scope: plugin scaffold and configuration — use
|
||||
/plugin-author for that. Does not run `claude plugin marketplace add` or
|
||||
equivalent CLI registration commands — only manages `marketplace.json`
|
||||
entries. Deprecated per ADR-0015 — superseded by apm-workflow; kept until
|
||||
issue #90 lands.
|
||||
allowed-tools: Bash Read Write Edit
|
||||
metadata:
|
||||
category: factory
|
||||
source_keys:
|
||||
- context7-websites-code-claude
|
||||
- claude-code-plugins-docs
|
||||
- context7-github-en-copilot
|
||||
- github-cli-plugin-reference
|
||||
- github-plugins-marketplace
|
||||
- github-plugins-finding-installing
|
||||
---
|
||||
|
||||
> **Deprecated:** Superseded by `apm-workflow` per ADR-0015 — deletion pending issue #90 (not yet changed). Use `apm-workflow marketplace` (`apm marketplace init`/`package add`/`check`) for CREATE/ADD/REMOVE/UPDATE and `apm-workflow compile` (`apm pack` emits `.claude-plugin/marketplace.json`) instead.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- Both marketplace files must be identical after every operation — never update one without the other in the same edit pass.
|
||||
- Every catalog mutation (ADD, REMOVE, UPDATE) requires a catalog `version` bump in both files in the same edit pass. Clients cache the catalog and use the version to detect changes — skipping the bump means the new state is invisible until a forced refresh. Convention: ADD and REMOVE → minor bump (e.g. `0.1.1` → `0.2.0`); UPDATE → patch bump (e.g. `0.2.0` → `0.2.1`). The `version` field may be at the top level or nested inside `metadata` — bump whichever form is present.
|
||||
- `source` for local plugins is a relative path from the marketplace root, not the plugin directory name alone (e.g. `"./plugins/kyberforge"`, not `"kyberforge"`).
|
||||
- The `{ "source": "github", ... }` object form is only for GitHub. For GitLab, Gitea, or any other git host, use `{ "source": "git", "url": "https://..." }` with a full URL.
|
||||
|
||||
## Route
|
||||
|
||||
Determine which operation applies before touching any file:
|
||||
|
||||
- **Neither `.claude-plugin/marketplace.json` nor `.github/plugin/marketplace.json` exist** → follow **CREATE**
|
||||
- **Only one file exists** → stop and note the mirror is missing; ask the user whether to create the missing mirror from the existing file, or whether this is an error. Do not proceed until both files are present or the user has explicitly directed you to create the missing one.
|
||||
- **Both files exist + plugin name NOT in `plugins[]` + add/register/list intent** → follow **ADD**
|
||||
- **Both files exist + plugin name IS in `plugins[]` + remove/unlist/delete intent** → follow **REMOVE**
|
||||
- **Both files exist + plugin name IS in `plugins[]` + change/update/bump intent** → follow **UPDATE**
|
||||
- **User asks to validate without any add/remove/update intent** → follow **VALIDATE**
|
||||
- **Ambiguous** → ask: "Did you mean to add a new plugin entry, update an existing one, or remove one?"
|
||||
|
||||
---
|
||||
|
||||
## CREATE
|
||||
|
||||
Run this flow only when no marketplace.json exists anywhere in the repo.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Confirm you have:
|
||||
- [ ] Marketplace name (kebab-case, e.g. `my-marketplace`)
|
||||
- [ ] Owner name (and optionally email)
|
||||
- [ ] Marketplace description (optional but recommended)
|
||||
- [ ] At least one initial plugin entry (name, source, description)
|
||||
|
||||
If prerequisites are missing, ask before writing.
|
||||
|
||||
### Step 1 — Write `.claude-plugin/marketplace.json`
|
||||
|
||||
Create the file with the following structure (fill in the values from prerequisites):
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "<marketplace-name>",
|
||||
"owner": { "name": "<owner-name>", "email": "<owner-email>" },
|
||||
"metadata": {
|
||||
"description": "<marketplace-description>",
|
||||
"version": "0.1.0"
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"name": "<plugin-name>",
|
||||
"description": "<plugin-description>",
|
||||
"source": "<source>"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Omit `"email"` if not provided. Omit `"metadata.version"` if the user does not want a pinned catalog version. The `metadata` object is the Copilot CLI canonical location for top-level description and version — Claude Code accepts both `metadata`-nested and top-level forms; use `metadata` for dual-tool repos.
|
||||
|
||||
### Step 2 — Write `.github/plugin/marketplace.json`
|
||||
|
||||
Write identical content to `.github/plugin/marketplace.json`. These two files must always be identical.
|
||||
|
||||
### Step 3 — Validate
|
||||
|
||||
Follow the **VALIDATE** flow.
|
||||
|
||||
---
|
||||
|
||||
## ADD
|
||||
|
||||
Run this flow when a plugin name does not yet exist in `plugins[]` and the intent is to add it.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Confirm you have:
|
||||
- [ ] Plugin name (kebab-case; reserved prefixes `anthropic-*`, `claude-*`, `agent-skills`, `official-claude-plugins` are rejected by the validator)
|
||||
- [ ] Plugin description
|
||||
- [ ] Source type and source value (see source type branching below)
|
||||
- [ ] Version (optional; omit for git-sourced plugins)
|
||||
|
||||
If you need details on a specific source type shape or per-entry optional fields, read `references/manifest-fields.md`.
|
||||
|
||||
### Source type branching
|
||||
|
||||
If the user has not specified a source type, assume local path (the most common case for in-repo plugins). Only ask if the user's intent is unclear: "I'll treat this as a local path plugin — is that right, or does it live on GitHub, a git URL, or npm?"
|
||||
|
||||
Source shapes per type:
|
||||
|
||||
**Local path:**
|
||||
```json
|
||||
"source": "./plugins/<name>"
|
||||
```
|
||||
|
||||
**GitHub:**
|
||||
```json
|
||||
"source": { "source": "github", "repo": "owner/repo" }
|
||||
```
|
||||
Add `"ref": "<branch-or-tag>"` inside the object if the user specifies a branch or tag. Add `"sha": "<commit-sha>"` if pinning to an exact commit — `sha` takes precedence over `ref` when both are present.
|
||||
|
||||
**Git URL:**
|
||||
```json
|
||||
"source": { "source": "git", "url": "https://..." }
|
||||
```
|
||||
Add `"ref": "<branch-or-tag>"` inside the object if specified.
|
||||
|
||||
**npm:**
|
||||
```json
|
||||
"source": { "source": "npm", "package": "@scope/pkg", "version": "1.0.0" }
|
||||
```
|
||||
`version` is required for npm source.
|
||||
|
||||
### Entry shape
|
||||
|
||||
The full entry added to `plugins[]`:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "<name>",
|
||||
"description": "<description>",
|
||||
"source": <source per type above>
|
||||
}
|
||||
```
|
||||
|
||||
Include `"version": "<version>"` at the entry level only when the source is npm or when the user explicitly requests a pinned version in the catalog.
|
||||
|
||||
Include `"strict": false` when the plugin is a dual Claude Code / Copilot CLI plugin — this prevents Copilot from rejecting CC-specific fields in the plugin directory.
|
||||
|
||||
### Step 1 — Read both files
|
||||
|
||||
Read `.claude-plugin/marketplace.json` and `.github/plugin/marketplace.json`. Verify they are identical. If they differ, stop and report the divergence — do not proceed until the user resolves it.
|
||||
|
||||
### Step 2 — Add the entry
|
||||
|
||||
Append the new entry to the end of the `plugins[]` array in `.claude-plugin/marketplace.json`. Array order is not semantically significant, but always add at the end for consistency.
|
||||
|
||||
### Step 3 — Mirror
|
||||
|
||||
Apply the identical addition to `.github/plugin/marketplace.json` in the same edit pass.
|
||||
|
||||
### Step 4 — Bump catalog version
|
||||
|
||||
Apply a **minor bump** to the `version` field in both files in the same edit pass (e.g. `0.1.1` → `0.2.0`). Find the field at the top level or inside `metadata` — bump whichever form is present.
|
||||
|
||||
### Step 5 — Validate
|
||||
|
||||
Follow the **VALIDATE** flow.
|
||||
|
||||
---
|
||||
|
||||
## REMOVE
|
||||
|
||||
Run this flow when an entry exists in `plugins[]` and the intent is to remove it.
|
||||
|
||||
### Step 1 — Confirm the target
|
||||
|
||||
Read `.claude-plugin/marketplace.json`. Identify the entry to remove. State the full entry as it currently appears.
|
||||
|
||||
### Step 2 — HITL gate
|
||||
|
||||
State clearly before proceeding:
|
||||
|
||||
> "I will remove the `<name>` entry from both `.claude-plugin/marketplace.json` and `.github/plugin/marketplace.json`. This does not delete the plugin files. Confirm?"
|
||||
|
||||
Do not proceed until the user confirms. If the user says "yes" or equivalent, continue to Step 3.
|
||||
|
||||
### Step 3 — Remove from both files
|
||||
|
||||
Remove the entry from `plugins[]` in `.claude-plugin/marketplace.json`.
|
||||
|
||||
Apply the identical removal to `.github/plugin/marketplace.json` in the same edit pass.
|
||||
|
||||
### Step 4 — Bump catalog version
|
||||
|
||||
Apply a **minor bump** to the `version` field in both files in the same edit pass (e.g. `0.1.1` → `0.2.0`). Find the field at the top level or inside `metadata` — bump whichever form is present.
|
||||
|
||||
### Step 5 — Validate
|
||||
|
||||
Follow the **VALIDATE** flow.
|
||||
|
||||
---
|
||||
|
||||
## UPDATE
|
||||
|
||||
Run this flow when an entry exists in `plugins[]` and the intent is to change one or more fields.
|
||||
|
||||
If you need to verify a field name or source type shape, read `references/manifest-fields.md`.
|
||||
|
||||
### Step 1 — Read the current entry
|
||||
|
||||
Read `.claude-plugin/marketplace.json`. Show the current state of the target entry so the user can confirm the fields to change.
|
||||
|
||||
### Step 2 — Apply changes
|
||||
|
||||
State which fields will change and to what values, then edit `.claude-plugin/marketplace.json`.
|
||||
|
||||
Apply the identical change to `.github/plugin/marketplace.json` in the same edit pass.
|
||||
|
||||
### Step 3 — Bump catalog version
|
||||
|
||||
Apply a **patch bump** to the `version` field in both files in the same edit pass (e.g. `0.2.0` → `0.2.1`). Find the field at the top level or inside `metadata` — bump whichever form is present.
|
||||
|
||||
### Step 4 — Validate
|
||||
|
||||
Follow the **VALIDATE** flow.
|
||||
|
||||
---
|
||||
|
||||
## VALIDATE
|
||||
|
||||
Run from the repo root (not from the plugin directory or `.claude-plugin/`):
|
||||
|
||||
```bash
|
||||
claude plugin validate .
|
||||
```
|
||||
|
||||
Add `--strict` to promote warnings to errors — recommended in CI.
|
||||
|
||||
Report the output. If validation fails, describe the specific error and what needs to be fixed. Do not attempt to auto-fix validation errors unless the fix is unambiguous (e.g. a trailing comma that violates JSON syntax); otherwise, describe the fix and ask the user to confirm.
|
||||
@@ -1,9 +0,0 @@
|
||||
# references/
|
||||
|
||||
## manifest-fields.md
|
||||
|
||||
Full field reference for `marketplace.json`. Covers: top-level fields (`name`, `owner`, `description`, `version`, `plugins`), per-entry fields (`name`, `description`, `source`, `version`, `author`), all four source type shapes (local path string, `github` object, `git` object, `npm` object) with examples, where each marketplace file lives and why both must stay identical. Load this before editing any marketplace.json file.
|
||||
|
||||
## sources.md
|
||||
|
||||
Research provenance record for this skill. Lists the upstream research sources (claude-code-plugins and github-copilot-plugins research docs) that informed SKILL.md and manifest-fields.md. Used by `skill-audit` to validate the provenance chain.
|
||||
@@ -1,177 +0,0 @@
|
||||
---
|
||||
source_keys:
|
||||
- context7-websites-code-claude
|
||||
- claude-code-plugins-docs
|
||||
- context7-github-en-copilot
|
||||
- github-cli-plugin-reference
|
||||
- github-plugins-marketplace
|
||||
---
|
||||
|
||||
# Marketplace Manifest Fields
|
||||
|
||||
Reference for all fields in `marketplace.json`. Applies to both `.claude-plugin/marketplace.json` and `.github/plugin/marketplace.json`, which must always be identical.
|
||||
|
||||
## File Locations
|
||||
|
||||
| File | Read by | Notes |
|
||||
|---|---|---|
|
||||
| `.claude-plugin/marketplace.json` | Claude Code | Primary location for Claude Code marketplace manifest |
|
||||
| `.github/plugin/marketplace.json` | Copilot CLI | Canonical location for Copilot CLI marketplace manifest |
|
||||
|
||||
Both files must be kept identical at all times. Every operation that modifies one must apply the same change to the other in the same edit pass.
|
||||
|
||||
---
|
||||
|
||||
## Top-Level Fields
|
||||
|
||||
| Field | Required | Type | Description |
|
||||
|---|---|---|---|
|
||||
| `name` | Yes | string | Marketplace name. Kebab-case, max 64 chars. Becomes the marketplace identifier used in `plugin install <name>@<marketplace>`. |
|
||||
| `owner` | Yes | object | `{ "name": string, "email"?: string }` — the marketplace maintainer. |
|
||||
| `metadata` | No | object | `{ "description"?: string, "version"?: string, "pluginRoot"?: string }` — Copilot CLI canonical location for top-level description and version. Claude Code also accepts `description` and `version` directly at the top level; use `metadata` for dual-tool repos. |
|
||||
| `description` | No | string | Top-level description — Claude Code only. For dual-tool repos, prefer `metadata.description` instead. |
|
||||
| `version` | No | string | Top-level marketplace version — Claude Code only. For dual-tool repos, prefer `metadata.version` instead. |
|
||||
| `plugins` | Yes | array | Array of plugin entry objects. See Per-Entry Fields below. |
|
||||
|
||||
---
|
||||
|
||||
## Per-Entry Fields (inside `plugins[]`)
|
||||
|
||||
| Field | Required | Type | Description |
|
||||
|---|---|---|---|
|
||||
| `name` | Yes | string | Plugin name. Kebab-case, max 64 chars. Must be unique within the marketplace. Reserved prefixes (`anthropic-*`, `claude-*`, `agent-skills`, `official-claude-plugins`) are rejected by the validator. |
|
||||
| `source` | Yes | string or object | How to locate the plugin. See Source Types below. |
|
||||
| `description` | No | string | Human-readable plugin description. Max 1024 chars (Copilot CLI schema). Displayed in browse output. |
|
||||
| `version` | No | string | Pinned version for catalog display. Optional for git-sourced plugins — Claude Code derives version from git tags. Required for npm source. Include when the user wants an explicit pinned version visible in the catalog. |
|
||||
| `author` | No | object | `{ "name": string, "email"?: string, "url"?: string }` — the plugin author. |
|
||||
| `homepage` | No | string | URL for the plugin homepage or docs site. |
|
||||
| `repository` | No | string | URL for the plugin source repository. |
|
||||
| `license` | No | string | SPDX license identifier (e.g. `"MIT"`, `"Apache-2.0"`). |
|
||||
| `keywords` | No | string[] | Search terms for discovery (feeds into Discover tab search index). |
|
||||
| `category` | No | string | Single category label for grouping in the Discover tab. |
|
||||
| `tags` | No | string[] | Additional classification tags. |
|
||||
| `agents` | No | string or string[] | Override the path(s) to agent definition files inside the plugin directory. Defaults to `agents/`. |
|
||||
| `skills` | No | string or string[] | Override the path(s) to skill directories inside the plugin. Defaults to `skills/`. |
|
||||
| `commands` | No | string or string[] | Override the path(s) to command definition files. |
|
||||
| `hooks` | No | string or object | Override the path(s) to hook definitions. |
|
||||
| `mcpServers` | No | string or object | Override MCP server configuration for the plugin. |
|
||||
| `lspServers` | No | string or object | Override LSP server configuration for the plugin. |
|
||||
| `strict` | No | boolean | Default `true`. Set to `false` for relaxed schema validation — allows extra or CC-specific fields without failing Copilot CLI validation. Use this for dual Claude Code / Copilot CLI plugins. |
|
||||
|
||||
---
|
||||
|
||||
## Source Types
|
||||
|
||||
The `source` field accepts four forms.
|
||||
|
||||
### 1. Local path (string)
|
||||
|
||||
Plugin lives in the same repo as the marketplace.
|
||||
|
||||
```json
|
||||
"source": "./plugins/<plugin-name>"
|
||||
```
|
||||
|
||||
The path is relative from the marketplace root (the repo root where `marketplace.json` sits), **not** from the plugin directory. Always prefix with `./`.
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{
|
||||
"name": "kyberforge",
|
||||
"description": "Skills and agents for the Claude Code plugin factory.",
|
||||
"source": "./plugins/kyberforge"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. GitHub (object)
|
||||
|
||||
Plugin lives in a separate GitHub repository. GitHub shorthand only — do not use this form for GitLab, Gitea, or other hosts.
|
||||
|
||||
```json
|
||||
"source": { "source": "github", "repo": "owner/repo" }
|
||||
```
|
||||
|
||||
Optional fields inside the object:
|
||||
- `"ref"` — branch name, tag, or commit SHA to pin. Omit to follow the default branch.
|
||||
- `"sha"` — exact commit SHA; takes precedence over `ref` when both are present.
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{
|
||||
"name": "deploy-tools",
|
||||
"description": "Deployment automation.",
|
||||
"source": { "source": "github", "repo": "acme-corp/deploy-tools-plugin", "ref": "v2.0.0" }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. Git URL (object)
|
||||
|
||||
Plugin in any git host — GitHub, GitLab, Gitea, Bitbucket, or self-hosted — via full HTTPS or SSH URL. Use this instead of the `github` form for any non-GitHub host.
|
||||
|
||||
```json
|
||||
"source": { "source": "git", "url": "https://..." }
|
||||
```
|
||||
|
||||
Optional fields inside the object:
|
||||
- `"ref"` — branch name, tag, or commit SHA.
|
||||
|
||||
**Examples:**
|
||||
```json
|
||||
{ "source": "git", "url": "https://gitlab.com/org/plugin.git" }
|
||||
{ "source": "git", "url": "https://gitea.example.com/org/plugin.git", "ref": "v1.0.0" }
|
||||
{ "source": "git", "url": "git@github.com:org/plugin.git" }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. npm (object)
|
||||
|
||||
Plugin distributed as an npm package. `version` is required inside the object.
|
||||
|
||||
```json
|
||||
"source": { "source": "npm", "package": "@scope/pkg", "version": "1.0.0" }
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{
|
||||
"name": "formatter",
|
||||
"description": "Code formatting plugin.",
|
||||
"source": { "source": "npm", "package": "@acme/claude-formatter", "version": "3.1.0" }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Why Both Files Must Stay Identical
|
||||
|
||||
`.claude-plugin/marketplace.json` is the Claude Code-native path. `.github/plugin/marketplace.json` is the Copilot CLI canonical path per the reference docs (`github/copilot-plugins` and `github/awesome-copilot` both use this path). Both tools are used in this repo, so both files must exist and match. A divergence creates a split-catalog state where the two tools see different plugins — this is a silent inconsistency that is hard to detect and diagnose. Treat them as a single logical file that happens to exist at two paths.
|
||||
|
||||
---
|
||||
|
||||
## Complete Example
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "holocron",
|
||||
"owner": { "name": "Defame1297", "email": "defame1297@rkdr.net" },
|
||||
"description": "AI development skills for Claude Code and GitHub Copilot CLI.",
|
||||
"version": "0.1.0",
|
||||
"plugins": [
|
||||
{
|
||||
"name": "kyberforge",
|
||||
"description": "Skills and agents for creating, maintaining, and managing a Claude Code / Copilot CLI plugin marketplace.",
|
||||
"source": "./plugins/kyberforge"
|
||||
},
|
||||
{
|
||||
"name": "external-tool",
|
||||
"description": "An externally hosted plugin.",
|
||||
"source": { "source": "github", "repo": "acme/external-tool" }
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
@@ -1,147 +0,0 @@
|
||||
---
|
||||
source_keys:
|
||||
- context7-websites-code-claude
|
||||
- claude-code-plugins-docs
|
||||
- context7-github-en-copilot
|
||||
- github-cli-plugin-reference
|
||||
- github-plugins-marketplace
|
||||
- github-plugins-finding-installing
|
||||
---
|
||||
|
||||
# Sources
|
||||
|
||||
## context7-websites-code-claude
|
||||
|
||||
- **URL:** context7:/websites/code_claude
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/claude-code-plugins/sources.md
|
||||
- **Description:** Official Claude Code documentation site indexed by Context7 — marketplace.json format, source types, `claude plugin validate` command, plugin update lifecycle, private marketplace registration, source URL formats
|
||||
- **Contributing files:** SKILL.md, references/manifest-fields.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## claude-code-plugins-docs
|
||||
|
||||
- **URL:** https://code.claude.com/docs/en/plugins
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/claude-code-plugins/sources.md
|
||||
- **Description:** Official Claude Code plugin authoring guide — `marketplace.json` schema, source type shapes (local path, github object, git object, npm object), `claude plugin validate .` behavior, end-to-end publish walkthrough, marketplace catalog format
|
||||
- **Contributing files:** SKILL.md, references/manifest-fields.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## claude-code-subagents-docs
|
||||
|
||||
- **URL:** https://code.claude.com/docs/en/sub-agents
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/claude-code-plugins/sources.md
|
||||
- **Description:** Official Claude Code subagent reference — definition format, all frontmatter fields, scope priority, built-in agents, CLI flags, environment variables, known limitations
|
||||
- **Contributing files:** (none)
|
||||
- **Status:** `referenced`
|
||||
|
||||
## context7-github-en-copilot
|
||||
|
||||
- **URL:** context7:/websites/github_en_copilot
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/github-copilot-plugins/sources.md
|
||||
- **Description:** Official GitHub Copilot documentation indexed by Context7; covers CLI plugins, custom agents, SDK, and marketplace — including `metadata` object schema, per-entry optional fields, `strict` field behavior
|
||||
- **Contributing files:** SKILL.md, references/manifest-fields.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## github-cli-plugin-reference
|
||||
|
||||
- **URL:** https://docs.github.com/en/copilot/reference/copilot-cli-reference/cli-plugin-reference
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/github-copilot-plugins/sources.md
|
||||
- **Description:** Full CLI plugin reference — `marketplace.json` schema (top-level and per-entry fields), all `copilot plugin marketplace` commands, install specification formats, `.github/plugin/marketplace.json` canonical path, `strict` field behavior
|
||||
- **Contributing files:** SKILL.md, references/manifest-fields.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## github-plugins-marketplace
|
||||
|
||||
- **URL:** https://docs.github.com/en/copilot/how-tos/copilot-cli/customize-copilot/plugins-marketplace
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/github-copilot-plugins/sources.md
|
||||
- **Description:** How-to for creating and publishing a Copilot CLI plugin marketplace — `marketplace.json` structure at `.github/plugin/marketplace.json`, per-entry fields, marketplace registration commands, reference implementations (`github/copilot-plugins`, `github/awesome-copilot`)
|
||||
- **Contributing files:** SKILL.md, references/manifest-fields.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## github-plugins-finding-installing
|
||||
|
||||
- **URL:** https://docs.github.com/en/copilot/how-tos/copilot-cli/customize-copilot/plugins-finding-installing
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/github-copilot-plugins/sources.md
|
||||
- **Description:** User-facing guide to discovering and installing CLI plugins — marketplace browsing commands, install/update/uninstall workflow; informs REMOVE flow design (unlisting does not uninstall from existing users)
|
||||
- **Contributing files:** SKILL.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## github-custom-agents-configuration
|
||||
|
||||
- **URL:** https://docs.github.com/en/copilot/reference/custom-agents-configuration
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/github-copilot-plugins/sources.md
|
||||
- **Description:** Reference for cloud and IDE custom agent definition format — frontmatter fields, tool aliases, MCP server config, secrets interpolation, scoping hierarchy
|
||||
- **Contributing files:** (none)
|
||||
- **Status:** `referenced`
|
||||
|
||||
## github-plugins-creating
|
||||
|
||||
- **URL:** https://docs.github.com/en/copilot/how-tos/copilot-cli/customize-copilot/plugins-creating
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/github-copilot-plugins/sources.md
|
||||
- **Description:** How-to for creating Copilot CLI plugins — plugin structure, agent and skill authoring, hooks format, MCP config, development lifecycle
|
||||
- **Contributing files:** (none)
|
||||
- **Status:** `referenced`
|
||||
|
||||
## github-sdk-custom-agents
|
||||
|
||||
- **URL:** https://docs.github.com/en/copilot/how-tos/copilot-sdk/features/custom-agents
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/github-copilot-plugins/sources.md
|
||||
- **Description:** SDK custom agent API — CustomAgentConfig fields in all five languages, session config, sub-agent lifecycle events, tool scoping, permission handling
|
||||
- **Contributing files:** (none)
|
||||
- **Status:** `referenced`
|
||||
|
||||
## github-changelog-copilot-extensions-ga
|
||||
|
||||
- **URL:** https://github.blog/changelog/2025-02-19-announcing-the-general-availability-of-github-copilot-extensions/
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/github-copilot-plugins/sources.md
|
||||
- **Description:** Announcement of GitHub Copilot Extensions general availability (February 2025) — OIDC auth, all license tiers, VS Code/Visual Studio/JetBrains/GitHub.com support
|
||||
- **Contributing files:** (none)
|
||||
- **Status:** `referenced`
|
||||
|
||||
## github-changelog-copilot-extensions-sunset
|
||||
|
||||
- **URL:** https://github.blog/changelog/2025-09-24-deprecate-github-copilot-extensions-github-apps/
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/github-copilot-plugins/sources.md
|
||||
- **Description:** Sunset notice for GitHub App-based Copilot Extensions — creation blocked Sep 24, 2025; full shutdown Nov 10, 2025; MCP servers recommended as replacement
|
||||
- **Contributing files:** (none)
|
||||
- **Status:** `referenced`
|
||||
|
||||
## github-docs-copilot-extensions-skillsets
|
||||
|
||||
- **URL:** https://docs.github.com/en/copilot/concepts/build-copilot-extensions/skillsets-for-copilot-extensions
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/github-copilot-plugins/sources.md
|
||||
- **Description:** Concept doc for Copilot Extension skillsets — up to 5 skills per extension, Copilot handles routing/prompt crafting/response, contrast with agent extensions
|
||||
- **Contributing files:** (none)
|
||||
- **Status:** `referenced`
|
||||
|
||||
## github-docs-copilot-extensions-building
|
||||
|
||||
- **URL:** https://docs.github.com/en/copilot/building-copilot-extensions/setting-up-copilot-extensions
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/github-copilot-plugins/sources.md
|
||||
- **Description:** How-to for setting up a Copilot Extension — GitHub App registration, Copilot Chat permission, Copilot Editor Context permission, backend URL configuration
|
||||
- **Contributing files:** (none)
|
||||
- **Status:** `referenced`
|
||||
|
||||
## vscode-chat-participant-api
|
||||
|
||||
- **URL:** https://code.visualstudio.com/api/extension-guides/ai/chat
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/github-copilot-plugins/sources.md
|
||||
- **Description:** VS Code Chat Participant API — createChatParticipant(), package.json contributes.chatParticipants, Language Model API, @mention invocation in Copilot Chat
|
||||
- **Contributing files:** (none)
|
||||
- **Status:** `referenced`
|
||||
|
||||
## github-marketplace-copilot-extensions
|
||||
|
||||
- **URL:** https://github.com/marketplace?type=apps&copilot_app=true
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/github-copilot-plugins/sources.md
|
||||
- **Description:** GitHub Marketplace listing for Copilot Extensions — browsable list of available extensions (historical; page remains live but product is sunset)
|
||||
- **Contributing files:** (none)
|
||||
- **Status:** `referenced`
|
||||
|
||||
## github-docs-marketplace-listing-requirements
|
||||
|
||||
- **URL:** https://docs.github.com/en/apps/github-marketplace/creating-apps-for-github-marketplace/requirements-for-listing-an-app
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/github-copilot-plugins/sources.md
|
||||
- **Description:** Requirements for listing a GitHub App on the GitHub Marketplace — verified publisher, capability description, UX stability, submission and review process
|
||||
- **Contributing files:** (none)
|
||||
- **Status:** `referenced`
|
||||
@@ -1,39 +0,0 @@
|
||||
# plugin-author
|
||||
|
||||
Creates, updates, and releases plugin scaffolds for the holocron marketplace.
|
||||
|
||||
## What it does
|
||||
|
||||
Manages both manifests (`plugin.json` for Copilot CLI and `.claude-plugin/plugin.json` for Claude Code) in one pass. Three operations: create a new plugin scaffold with placeholder manifests and skeleton dirs; update configuration fields (shared fields updated in both manifests simultaneously); release a version with HITL gate before tagging.
|
||||
|
||||
Out of scope: plugin content (skills, agents, hooks, MCP servers inside those dirs) and `marketplace.json` entries.
|
||||
|
||||
## Before you start
|
||||
|
||||
Have ready: the plugin name (kebab-case) and the repo root path.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
/plugin-author
|
||||
```
|
||||
|
||||
**Manual scaffold (human workflow):**
|
||||
```bash
|
||||
bash scripts/new-plugin.sh <plugin-name> <repo-root>
|
||||
|
||||
# Examples:
|
||||
bash scripts/new-plugin.sh my-tools /root/ai-development
|
||||
bash scripts/new-plugin.sh data-tools .
|
||||
```
|
||||
|
||||
## Files
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `SKILL.md` | Skill instructions for agents |
|
||||
| `scripts/new-plugin.sh` | Scaffolds both manifests and skeleton dirs for a new plugin |
|
||||
| `references/manifest-fields.md` | All optional fields for both manifests beyond the scaffolded defaults |
|
||||
| `references/sources.md` | Research provenance — sources that informed this skill |
|
||||
| `scripts/README.md` | Directory meta-documentation for scripts/ |
|
||||
| `references/README.md` | Directory meta-documentation for references/ |
|
||||
@@ -1,191 +0,0 @@
|
||||
---
|
||||
name: plugin-author
|
||||
description: >
|
||||
Use when the user wants to create a new plugin scaffold ("create a plugin
|
||||
for X", "new plugin called Y"), update plugin configuration ("change the
|
||||
description", "add keyword", "bump version"), or release a plugin version
|
||||
("release", "tag", "publish"). Manages both Claude Code
|
||||
(.claude-plugin/plugin.json) and Copilot CLI (plugin.json) manifests in one
|
||||
pass. Do not use when the request is about plugin content (skills, agents,
|
||||
hooks, or MCP servers inside those directories). Do not use for
|
||||
marketplace.json entries — use /marketplace-author for that. Deprecated
|
||||
per ADR-0015 — superseded by apm-workflow; kept until issue #90 lands.
|
||||
allowed-tools: Bash Read Write Edit
|
||||
metadata:
|
||||
category: factory
|
||||
source_keys:
|
||||
- context7-websites-code-claude
|
||||
- claude-code-plugins-docs
|
||||
- claude-code-subagents-docs
|
||||
- context7-github-en-copilot
|
||||
- github-cli-plugin-reference
|
||||
- github-plugins-creating
|
||||
- github-plugins-finding-installing
|
||||
---
|
||||
|
||||
> **Deprecated:** Superseded by `apm-workflow` per ADR-0015 — deletion pending issue #90 (not yet changed). Use `apm-workflow configure` (apm.yml authoring, `apm plugin init` scaffolding) for CREATE/UPDATE and `apm-workflow compile` (`apm compile`/`apm pack`/`apm publish`) for RELEASE instead.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- Both manifests must carry identical `version` values — version parity is a hard invariant (ADR-0006). Never update version in one manifest without updating the other in the same edit pass.
|
||||
- Every UPDATE to non-version fields (description, keywords, author, etc.) requires a patch bump to `version` in both manifests in the same edit pass. Consumers cache plugin metadata and use the version to detect changes — skipping the bump makes the update invisible until a forced refresh.
|
||||
- `author.email` is placed in the Copilot manifest by convention; `author.url` is placed in the CC manifest by convention. Both fields are supported by both platforms — do not add them to the other manifest without a deliberate reason.
|
||||
- `claude plugin tag --push` is irreversible: it creates a git tag and pushes it to remote. Always present the HITL gate and wait for explicit confirmation before running it.
|
||||
- `claude plugin tag --push` requires a clean working tree and will fail if there are uncommitted changes. Commit or stash all changes before running it.
|
||||
- `name` in both manifests must be kebab-case and must not use reserved prefixes: `anthropic-*`, `claude-*`, `agent-skills`, `official-claude-plugins`.
|
||||
- Copilot manifest lookup order: `.plugin/plugin.json` → `plugin.json` → `.github/plugin/plugin.json` → `.claude-plugin/plugin.json`. The canonical location for the Copilot manifest in this repo is `plugin.json` at the plugin root.
|
||||
- `displayName` is a CC platform field — Copilot has no equivalent. Do not add it to the Copilot manifest.
|
||||
- `skills`, `agents`, `hooks`, `mcpServers` are declared in the Copilot manifest by convention — Copilot requires explicit path declarations while CC auto-discovers content from the plugin root. Both platforms support these fields; omit them from the CC manifest by convention.
|
||||
- Agent files in a plugin's `agents/` directory silently ignore `hooks`, `mcpServers`, and `permissionMode` frontmatter fields.
|
||||
- `claude plugin validate --strict` auto-discovers every `.md` file directly under `agents/` and treats it as an agent definition requiring frontmatter — this is independent of the manifest. An explicit `agents` array listing only the real agent files does not suppress the scan; unlisted `.md` files in the same directory still fail validation (tested empirically — see ADR-0010). Any non-agent file (notes, provenance records, READMEs) must live outside `agents/` — e.g. at the plugin root — regardless of what the manifest declares.
|
||||
|
||||
## Route
|
||||
|
||||
Determine which flow before touching the filesystem. Read both manifest files if the plugin directory exists.
|
||||
|
||||
- **Plugin directory does not exist** → follow **CREATE flow**
|
||||
- **Plugin directory exists + version/release intent** ("release", "tag", "bump", "publish", "version") → follow **RELEASE flow**
|
||||
- **Plugin directory exists + field change intent** ("update description", "add keyword", "change author") → follow **UPDATE flow**
|
||||
- **Ambiguous** → ask: "Did you mean to create a new plugin, update its configuration, or release a version?"
|
||||
|
||||
Validate runs automatically before tagging (in RELEASE flow) and can be invoked explicitly at any time: `claude plugin validate plugins/<name>`.
|
||||
|
||||
## CREATE flow
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Before touching the filesystem, confirm you have:
|
||||
- [ ] Plugin name (kebab-case, e.g. `my-tools`)
|
||||
- [ ] Repo root (absolute path or `.` for current directory)
|
||||
|
||||
If either is missing, stop and ask before proceeding.
|
||||
|
||||
### Step 1 — Scaffold
|
||||
|
||||
Run the scaffold script:
|
||||
|
||||
```bash
|
||||
bash scripts/new-plugin.sh <name> <repo-root>
|
||||
```
|
||||
|
||||
Examples:
|
||||
```bash
|
||||
bash scripts/new-plugin.sh my-tools /root/ai-development
|
||||
bash scripts/new-plugin.sh data-tools .
|
||||
```
|
||||
|
||||
The script creates under `<repo-root>/plugins/<name>/`:
|
||||
- `plugin.json` — Copilot manifest with `FILL_IN_*` placeholders
|
||||
- `.claude-plugin/plugin.json` — CC manifest with `FILL_IN_*` placeholders
|
||||
- Empty skeleton directories: `skills/`, `agents/`, `hooks/`, `bin/`
|
||||
|
||||
Each file/dir is a no-op if it already exists.
|
||||
|
||||
### Step 2 — Fill in placeholders
|
||||
|
||||
Open both manifest files and replace every `FILL_IN_*` placeholder.
|
||||
|
||||
**Fields shared by both manifests** (must be identical in both):
|
||||
- `name` — kebab-case plugin identifier (already set by script; verify it is correct)
|
||||
- `description` — one or two sentences; what the plugin provides
|
||||
- `version` — SemVer; defaults to `1.0.0`; must be identical in both manifests
|
||||
- `author.name` — author display name
|
||||
- `license` — SPDX identifier (default: `MIT`)
|
||||
- `keywords` — search/discovery tags (default: `[]`)
|
||||
|
||||
**CC manifest fields** (`.claude-plugin/plugin.json` only):
|
||||
- `displayName` — human-readable name shown in plugin manager; capitalised form of `name` (CC platform field — no Copilot equivalent)
|
||||
- `author.url` — author URL (e.g. Gitea profile URL) (both platforms support this; placed here by convention)
|
||||
|
||||
**Copilot manifest fields** (`plugin.json` only):
|
||||
- `author.email` — author email (both platforms support this; placed here by convention)
|
||||
- `skills`, `agents`, `hooks`, `mcpServers` — paths; defaults are already set by the script (CC auto-discovers these; Copilot requires explicit declarations)
|
||||
|
||||
### Step 3 — Validate
|
||||
|
||||
Check:
|
||||
- [ ] `name` identical in both manifests, kebab-case, no reserved prefixes
|
||||
- [ ] `description` identical in both manifests, non-empty
|
||||
- [ ] `version` identical in both manifests (version parity — ADR-0006)
|
||||
- [ ] `author.name` identical in both manifests
|
||||
- [ ] `license` identical in both manifests
|
||||
- [ ] `keywords` identical in both manifests
|
||||
- [ ] No `FILL_IN_*` placeholders remain
|
||||
- [ ] `displayName` present in CC manifest only
|
||||
- [ ] `author.url` in CC manifest, `author.email` in Copilot manifest
|
||||
|
||||
## UPDATE flow
|
||||
|
||||
### Step 1 — Read both manifests
|
||||
|
||||
Read `plugins/<name>/plugin.json` and `plugins/<name>/.claude-plugin/plugin.json`. Identify the current field values.
|
||||
|
||||
### Step 2 — Classify each change
|
||||
|
||||
For every field the user wants to change:
|
||||
|
||||
| Change type | What to update |
|
||||
|---|---|
|
||||
| Shared field (`name`, `description`, `version`, `author.name`, `license`, `keywords`) | Both manifests in the same edit pass |
|
||||
| CC platform field (`displayName`) | `.claude-plugin/plugin.json` only — Copilot has no equivalent field |
|
||||
| Copilot platform fields (`category`, `tags`, `extensions`) | `plugin.json` only — not in the CC manifest schema |
|
||||
| CC scaffold convention (`author.url`) | `.claude-plugin/plugin.json` only — both platforms support this field; it is placed here by convention |
|
||||
| Copilot scaffold convention (`author.email`, `skills`, `agents`, `hooks`, `mcpServers`) | `plugin.json` only by convention — CC also supports these fields; CC auto-discovers content from the plugin root rather than requiring explicit path declarations |
|
||||
|
||||
Never update a shared field in one manifest without updating the other in the same pass.
|
||||
|
||||
If the target field is not listed in the classification table, read `references/manifest-fields.md` for the full field list and platform support notes.
|
||||
|
||||
### Step 3 — Announce and apply
|
||||
|
||||
State which fields change and which files are affected. Then apply. For `version` changes not part of a release, bump both manifests in the same edit.
|
||||
|
||||
### Step 4 — Bump version
|
||||
|
||||
If the change did not explicitly target the `version` field, apply a **patch bump** to `version` in both manifests in the same edit pass (e.g. `1.2.3` → `1.2.4`). Skip this step only when the user has explicitly set the version themselves in Step 3.
|
||||
|
||||
### Step 5 — Validate
|
||||
|
||||
Re-run the validation checklist from CREATE flow Step 3 on both files.
|
||||
|
||||
## RELEASE flow
|
||||
|
||||
### Step 1 — Confirm version
|
||||
|
||||
If the user has not stated the new SemVer version, ask: "What version are you releasing?" Do not proceed until you have the version.
|
||||
|
||||
### Step 2 — Bump version in both manifests
|
||||
|
||||
Update `version` in both `plugin.json` and `.claude-plugin/plugin.json` in the same edit pass. Confirm they are identical after the edit.
|
||||
|
||||
### Step 3 — Validate
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
claude plugin validate plugins/<name>
|
||||
```
|
||||
|
||||
Use `--strict` to promote warnings to errors: `claude plugin validate --strict plugins/<name>`.
|
||||
|
||||
Stop and report errors if validation fails. Do not proceed to tagging until validation passes.
|
||||
|
||||
### Step 4 — HITL gate
|
||||
|
||||
State exactly:
|
||||
|
||||
> "I will run `claude plugin tag --push` for plugin `<name>`, which will create git tag `<name>--v<version>` and push it to remote. This is irreversible. Confirm?"
|
||||
|
||||
Do not call the tool until the user explicitly confirms in the conversation.
|
||||
|
||||
### Step 5 — Tag and release
|
||||
|
||||
To preview without tagging or pushing: `claude plugin tag --dry-run`.
|
||||
|
||||
After explicit confirmation, run from the repo root:
|
||||
|
||||
```bash
|
||||
claude plugin tag --push
|
||||
```
|
||||
|
||||
Report the created tag name and confirm the push completed.
|
||||
@@ -1,9 +0,0 @@
|
||||
# references/
|
||||
|
||||
## manifest-fields.md
|
||||
|
||||
Complete field reference for both plugin manifests. Covers all optional fields beyond the scaffolded defaults: field classification (shared / CC-only / Copilot-only), usage examples, and the version parity convention (ADR-0016). Loaded when a user asks to add a non-default field to either manifest.
|
||||
|
||||
## sources.md
|
||||
|
||||
Research provenance record for this skill. Lists the upstream research sources (claude-code-plugins and github-copilot-plugins research docs) that informed SKILL.md, the scaffold script, and the manifest-fields reference. Used by `skill-audit` to validate the provenance chain.
|
||||
@@ -1,146 +0,0 @@
|
||||
---
|
||||
topic: manifest-fields
|
||||
source_keys:
|
||||
- context7-websites-code-claude
|
||||
- claude-code-plugins-docs
|
||||
- context7-github-en-copilot
|
||||
- github-cli-plugin-reference
|
||||
- github-plugins-creating
|
||||
- github-plugins-finding-installing
|
||||
---
|
||||
|
||||
# Manifest Fields Reference
|
||||
|
||||
This document covers optional fields beyond the scaffolded defaults. Consult it when a user asks to add a non-default field to either manifest.
|
||||
|
||||
## Field Classification
|
||||
|
||||
Fields fall into three categories: **shared** (identical in both manifests), **platform** (one platform does not support the field at all), and **convention** (both platforms support the field, but the repo scaffold places it in one manifest only).
|
||||
|
||||
> CC auto-discovers content (skills, agents, hooks, MCP servers) from the plugin root; Copilot requires explicit path declarations. Convention fields in the CC manifest are omitted unless you have a deliberate reason to add them.
|
||||
|
||||
| Field | Copilot `plugin.json` | CC `.claude-plugin/plugin.json` | Notes |
|
||||
|---|---|---|---|
|
||||
| `name` | Yes (shared) | Yes (shared) | Identical in both; kebab-case; max 64 chars (Copilot) |
|
||||
| `description` | Yes (shared) | Yes (shared) | Identical in both; max 1024 chars (Copilot) |
|
||||
| `version` | Yes (shared) | Yes (shared) | Identical in both; SemVer; version parity required (ADR-0016) |
|
||||
| `author.name` | Yes (shared) | Yes (shared) | Identical in both |
|
||||
| `license` | Yes (shared) | Yes (shared) | Identical in both; SPDX identifier |
|
||||
| `keywords` | Yes (shared) | Yes (shared) | Identical in both; string array |
|
||||
| `displayName` | No (unsupported) | Yes | CC platform field — Copilot has no equivalent |
|
||||
| `author.url` | Omitted (convention) | Yes (convention) | Author profile URL; CC scaffold places here; Copilot also supports this field |
|
||||
| `author.email` | Yes (convention) | Omitted (convention) | Author email; Copilot scaffold places here; CC also supports this field |
|
||||
| `agents` | Yes (convention) | Omitted (convention) | Path or array; default: `agents/`; Copilot requires explicit declaration; CC auto-discovers |
|
||||
| `skills` | Yes (convention) | Omitted (convention) | Path or array; default: `skills/`; Copilot requires explicit declaration; CC auto-discovers |
|
||||
| `hooks` | Yes (convention) | Omitted (convention) | Path to hooks config; Copilot requires explicit declaration; CC auto-discovers |
|
||||
| `mcpServers` | Yes (convention) | Omitted (convention) | Path or object; Copilot requires explicit declaration; CC auto-discovers |
|
||||
| `category` | Yes | No (unsupported) | Marketplace category string; Copilot platform field — not in CC manifest schema |
|
||||
| `tags` | Yes | No (unsupported) | Additional taxonomy tags (distinct from `keywords`); Copilot platform field |
|
||||
| `extensions` | Yes | No (unsupported) | Path, array, or `{ paths, exclusive: true }` to disable built-ins; Copilot platform field |
|
||||
| `homepage` | Both (independent) | Both (independent) | Documentation URL; not required to be identical |
|
||||
| `repository` | Both (independent) | Both (independent) | Source repo URL |
|
||||
|
||||
## Non-Default Optional Fields
|
||||
|
||||
### `homepage`
|
||||
|
||||
Documentation or project page URL. Shown in the plugin manager. Independent in each manifest — the two values do not need to match.
|
||||
|
||||
```json
|
||||
// Copilot plugin.json
|
||||
{ "homepage": "https://example.com/docs" }
|
||||
|
||||
// CC .claude-plugin/plugin.json
|
||||
{ "homepage": "https://example.com/docs" }
|
||||
```
|
||||
|
||||
### `repository`
|
||||
|
||||
Source repository URL. Independent in each manifest.
|
||||
|
||||
```json
|
||||
{ "repository": "https://git.example.com/owner/repo" }
|
||||
```
|
||||
|
||||
### `category` (Copilot-only)
|
||||
|
||||
Marketplace browsing category. Single string. Copilot manifest only.
|
||||
|
||||
```json
|
||||
{ "category": "developer-tools" }
|
||||
```
|
||||
|
||||
### `tags` (Copilot-only)
|
||||
|
||||
Additional taxonomy tags for Copilot marketplace browsing. Distinct from `keywords`.
|
||||
|
||||
```json
|
||||
{ "tags": ["testing", "ci"] }
|
||||
```
|
||||
|
||||
### `extensions` (Copilot-only)
|
||||
|
||||
Path to extension files, an array of paths, or an object. Use `{ "paths": [...], "exclusive": true }` to disable built-in extensions.
|
||||
|
||||
```json
|
||||
{ "extensions": "extensions/" }
|
||||
// or
|
||||
{ "extensions": { "paths": ["extensions/"], "exclusive": true } }
|
||||
```
|
||||
|
||||
### `lspServers`
|
||||
|
||||
Language Server Protocol configuration. Supported in both Copilot and CC manifests.
|
||||
|
||||
```json
|
||||
{ "lspServers": ".lsp.json" }
|
||||
```
|
||||
|
||||
### `outputStyles` (CC-only)
|
||||
|
||||
Path to output styles directory. Claude Code manifest only.
|
||||
|
||||
```json
|
||||
{ "outputStyles": "styles/" }
|
||||
```
|
||||
|
||||
### `experimental.themes` (CC-only)
|
||||
|
||||
Path to themes directory. Claude Code manifest only. Experimental — may change.
|
||||
|
||||
```json
|
||||
{ "experimental": { "themes": "themes/" } }
|
||||
```
|
||||
|
||||
### `experimental.monitors` (CC-only)
|
||||
|
||||
Path to `monitors.json`. Claude Code manifest only. Experimental.
|
||||
|
||||
```json
|
||||
{ "experimental": { "monitors": "monitors.json" } }
|
||||
```
|
||||
|
||||
### `dependencies` (CC-only)
|
||||
|
||||
Plugin dependencies. Each entry is a string (plugin name) or `{ "name": "<name>", "version": "<semver>" }`.
|
||||
|
||||
```json
|
||||
{
|
||||
"dependencies": [
|
||||
"base-tools",
|
||||
{ "name": "data-tools", "version": "^2.0.0" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### `commands` (legacy, both)
|
||||
|
||||
Explicit list of `.md` command file paths. Deprecated in favour of `skills/`. Use `skills` instead for new plugins.
|
||||
|
||||
## Version Parity Convention (ADR-0016)
|
||||
|
||||
The `version` field must be present and identical in both manifests at all times. This is a hard invariant enforced by `/plugin-author` on every create, update, and release operation.
|
||||
|
||||
- If only the CC manifest had `version` before this convention was introduced, backfill the Copilot manifest immediately.
|
||||
- Never change `version` in one manifest without changing it in the other in the same edit pass.
|
||||
- The RELEASE flow bumps both manifests simultaneously before tagging.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user