Files
holocron/plugins/kyberforge/skills/plugin-author/SKILL.md
Defame1297 591b9cccb8 fix(kyberforge): resolve second round of PR #91 review findings
Two review passes on PR #91 (correctness + simplification) found the
prior fixup commit (d6fd9b6) left the deprecation notice it added
half-applied, cited a nonexistent ADR, and introduced/compounded a
few duplicate restatements of the same facts across apm-workflow's
skill files and apm-orchestrate's Hard rules.

- plugin-author/SKILL.md cited ADR-0016 (doesn't exist) instead of
  ADR-0006 for the version-parity invariant.
- The deprecation banner on plugin-author/marketplace-author wasn't
  reflected in their routing `description:` frontmatter, forge's
  routing table, either kyberforge README skill table, or CONTEXT.md
  — now propagated consistently; routing behavior is unchanged since
  issue #90 (repo-wide apm conversion) hasn't landed yet.
- apm-orchestrate's `configure` operation only covered scaffolding a
  new package, not editing an existing apm.yml (e.g. removing a
  marketplace.packages[] entry, which has no dedicated `apm` CLI verb
  and is just a manifest edit). Added `edit-config`, intentionally
  ungated — a local file edit isn't the same class of irreversible
  action as `apm publish`, and normal review already gates the commit.
- Deduplicated facts restated 3-4x across SKILL.md/references/ADR
  boundaries (audit semantics, reserved name prefixes, marketplace-add
  direction, registries precondition), and trimmed configure.md's
  ~55-line apm.yml schema dump — copied near-verbatim from the
  research doc — down to a compact key list with a pointer, matching
  install.md's existing terse cross-referencing style.

Deliberately left as-is: apm-orchestrate's parallel/sequential
fan-out logic stays inline rather than extracted to a shared
reference, since neither git-orchestrate nor gitea-orchestrate need
it yet — premature extraction for a single caller.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0186ERbyACLRuRxPRnqwpa4m
2026-08-11 15:20:46 +00:00

9.9 KiB

name, description, allowed-tools, metadata
name description allowed-tools metadata
plugin-author 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. Bash Read Write Edit
category source_keys
factory
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 scripts/new-plugin.sh <name> <repo-root>

Examples:

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:

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:

claude plugin tag --push

Report the created tag name and confirm the push completed.