Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions .claude/rules/prompt-skill-sync.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
---
paths:
- '.github/prompts/*.prompt.md'
- '.claude-plugin/marketplace.json'
- '.claude/skills/*/.claude-plugin/plugin.json'
- '.claude/skills/*/README.md'
- '.claude/skills/*/SKILL.md'
- '.claude/skills/*/references/*.md'
- '.claude/skills/*/agents/*.md'
- '.claude/skills/*/assets/*.md'
- '.claude/skills/*/.claude-plugin/plugin.json'
- '.claude-plugin/marketplace.json'
- '.claude/skills/*/references/*.md'
- '.github/prompts/*.prompt.md'
---

# Published skills and their prompt halves
Expand Down Expand Up @@ -52,7 +53,7 @@ Whichever half someone takes is the only thing they get. Four rules follow.

An illustrative link, such as `[config.py](../src/config.py)` inside an example teaching the citation format, is not a real link and is allowed. The test is whether the target exists here: if it does, the author linked to something real and it will break.

`make -f .claude/Makefile check-skills` enforces every rule in this section, plus the specification itself: `name` matching the directory, `description` within its character limit, a body under 500 lines, a licence on every skill, and every bundled path resolving. It also gives each prompt a character budget: 36,000 for [`audit-docs.prompt.md`](../../.github/prompts/audit-docs.prompt.md), whose subject is narrower, and 52,000 for the other two. A skill can move detail into `references/`; a prompt is one file a reader scrolls, so its budget is the whole of what it can say. **Growth past a budget is a signal to condense, never to raise it.** What a prompt loses first is a rule restated across sections and a worked example following the rule it illustrates, and never a rule, a checklist item, or a category.
`make -f .claude/Makefile check-skills` enforces every rule in this section, plus the specification itself: `name` matching the directory, `description` within its character limit, a body under 500 lines, a licence on every skill, and every bundled path resolving inside the skill directory. It also gives each prompt a character budget: 36,000 for [`audit-docs.prompt.md`](../../.github/prompts/audit-docs.prompt.md), whose subject is narrower, and 52,000 for the other two. A skill can move detail into `references/`; a prompt is one file a reader scrolls, so its budget is the whole of what it can say. **Growth past a budget is a signal to condense, never to raise it.** What a prompt loses first is a rule restated across sections and a worked example following the rule it illustrates, and never a rule, a checklist item, or a category.

**Characters, because a line here is a paragraph.** `MD013` is off repository-wide and Prettier leaves prose unwrapped, so a single line runs to seventeen hundred characters. A line budget charges a prompt for its blank lines and its headings and lets it pay by deleting them, which makes the document harder to read while the number improves and nothing is condensed at all. Characters do not move when a file is reformatted, so the only way down is to cut what the prompt says. It is deliberately **not** part of `npm run validate`, because the repository must build, test, and lint with no agent tooling present.

Expand All @@ -68,9 +69,10 @@ Consequences to know before editing a skill, its manifest, or the marketplace:
- **The skill's manifest and `agents/` travel with every install.** `npx skills` copies every file except `metadata.json` and the `.git`, `__pycache__`, and `__pypackages__` directories, and `gh skill` copies every file in the tree, so a recipient's copy carries `.claude-plugin/` and loads as `<name>@skills-dir` in their repository too.
- **No manifest carries a `version`.** Claude Code keys a marketplace install on it, so a fixed value freezes every recipient on the copy they first installed. Left out, the version is the commit the plugin came from, and a push to `main` reaches marketplace installs the way it reaches `npx skills`. VS Code ignores the field and pulls the repository instead.
- **A marketplace entry carries only `name`, `source`, and `description`.** VS Code reads `name`, `description`, `version`, and `source` from an entry and drops the rest, so a component declared there would exist in Claude Code alone, and `npx skills` skips any path without the leading `./`. The entry repeats the manifest's `description` because that is the copy VS Code shows. For the same reason the marketplace sets no `metadata.pluginRoot`, which VS Code applies to `./` sources and Claude Code does not.
- **Every listed skill carries a `README.md`, and it travels too.** VS Code renders `<source>/README.md` as the plugin's page, under exactly that name and with no fallback to `SKILL.md`, so a skill without one shows an empty page. It is a regular file rather than a symbolic link, because GitHub serves a link as the text of the path it points to, which `gh skill` installs in the file's place and VS Code can show before install. Every installer copies it with the skill, so it names nothing outside the skill directory and invokes the skill by name rather than by one host's command form. It also links nothing relative, naming a file beside it such as `LICENSE.txt` in a code span instead. This overrides the clickable-link rule in [`docs-authoring.md`](docs-authoring.md), because the plugin page VS Code opens from its Agent Plugins view strips a relative link's target and leaves link-coloured text that opens nothing.
- **One manifest per skill, one marketplace per repository.** VS Code reads `.plugin/plugin.json`, or a root `plugin.json` declaring the Agent Plugins `$schema`, ahead of `.claude-plugin/plugin.json`, and that format finds skills only under `skills/`, which would leave the directory's own `SKILL.md` unloaded. The Copilot CLI reads `.plugin/plugin.json`, any root `plugin.json`, and `.github/plugin/plugin.json` first. For marketplaces, VS Code and the Copilot CLI try `marketplace.json`, `.plugin/marketplace.json`, and `.github/plugin/marketplace.json` before `.claude-plugin/marketplace.json`, and the first one found is the whole catalogue.

[`plugin-manifests.mjs`](../scripts/plugin-manifests.mjs), which `make -f .claude/Makefile check-skills` runs, holds every manifest to these rules: it parses, its `name` matches the directory, it sets no `version`, no competing manifest sits beside it, and every path in an `agents` key starts with `./`, stays inside the skill directory, and resolves. It requires the marketplace to list every skill that is not internal and nothing else, each entry carrying exactly the three keys above, with a `description` equal to its manifest's. That comparison is why a listed skill needs a manifest even though the marketplace route does not. [`plugin-manifests.test.mjs`](../scripts/plugin-manifests.test.mjs) covers each of these rules, and `make -f .claude/Makefile test-scripts` runs it.
[`plugin-manifests.mjs`](../scripts/plugin-manifests.mjs), which `make -f .claude/Makefile check-skills` runs, holds every manifest to these rules: it parses, its `name` matches the directory, it sets no `version`, no competing manifest sits beside it, and every path in an `agents` key starts with `./`, stays inside the skill directory, and resolves. It requires the marketplace to list every skill that is not internal and nothing else, each entry carrying exactly the three keys above, with a `description` equal to its manifest's. That comparison is why a listed skill needs a manifest even though the marketplace route does not. It also requires each listed skill to carry a `README.md` that is a regular file. [`plugin-manifests.test.mjs`](../scripts/plugin-manifests.test.mjs) covers each of these rules, and `make -f .claude/Makefile test-scripts` runs it.

## A published skill stays reachable by name

Expand Down
Loading