@vibe-agent-toolkit/vat-development-agents 0.1.38 → 0.1.39-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.claude/plugins/marketplaces/vat-skills/.claude-plugin/marketplace.json +1 -1
- package/dist/.claude/plugins/marketplaces/vat-skills/CHANGELOG.md +20 -0
- package/dist/.claude/plugins/marketplaces/vat-skills/plugins/vibe-agent-toolkit/.claude-plugin/plugin.json +1 -1
- package/dist/.claude/plugins/marketplaces/vat-skills/plugins/vibe-agent-toolkit/skills/vat-knowledge-resources/SKILL.md +18 -0
- package/dist/.claude/plugins/marketplaces/vat-skills/plugins/vibe-agent-toolkit/skills/vat-skill-distribution/SKILL.md +3 -4
- package/dist/generated/resources/skills/CLAUDE.js +3 -3
- package/dist/generated/resources/skills/vat-knowledge-resources.d.ts +1 -0
- package/dist/generated/resources/skills/vat-knowledge-resources.js +6 -1
- package/dist/generated/resources/skills/vat-skill-distribution.js +3 -3
- package/dist/skills/vat-knowledge-resources/SKILL.md +18 -0
- package/dist/skills/vat-skill-distribution/SKILL.md +3 -4
- package/package.json +4 -4
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"name": "vibe-agent-toolkit",
|
|
10
10
|
"description": "Development agents and skills for building with vibe-agent-toolkit",
|
|
11
11
|
"source": "./plugins/vibe-agent-toolkit",
|
|
12
|
-
"version": "0.1.
|
|
12
|
+
"version": "0.1.39-rc.1",
|
|
13
13
|
"author": {
|
|
14
14
|
"name": "vibe-agent-toolkit contributors"
|
|
15
15
|
}
|
|
@@ -7,6 +7,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
### Internal
|
|
11
|
+
|
|
12
|
+
- **Empirical compatibility harness (`packages/dev-tools/src/compat-empirical/`).** Per-#100 research scaffold: a CLI (`predict`/`run`/`judge`/`report`/`all`) that runs candidate skills against claude-code, claude-cowork, and claude-chat, then joins VAT's static predictions with deterministic runtime observations and an LLM-judge semantic read into a reality-vs-prediction matrix. The output is an evidence artifact a follow-up PR will draw on to propose detector improvements, each citing specific (skill, runtime) cells. No detector code or `RUNTIME_PROFILES` changes here. Lives in the private `@vibe-agent-toolkit/dev-tools` package no adopter-facing surface.
|
|
13
|
+
- **Empirical compat harness v2 (`packages/dev-tools/src/compat-empirical/`).** Foundations PR per [the v2 design](./docs/research/2026-05-23-compat-empirical-harness-v2-design.md). Probe coverage: multi-prompt + repeat-N with adaptive N=3→N=5 extension, mandatory positive+negative prompt pairing per corpus entry, and negative-prompt agreement inversion so false-positive triggers surface as `vat-optimistic`. Evidence quality: deterministic class widened from 6 to 9 values (splitting `error` into `install-failed`/`runtime-error`, `not-invoked` into `not-invoked-engaged`/`not-invoked-empty`, adding `refused`), judge prompt rewritten to v2 with a `refused` verdict. Report fidelity: coverage stats, per-bucket headline (own/official/community × ran/agree/optimistic/pessimistic/gray-zone), gray-zone (mixed-signal) and high-variance subsections, per-attempt variance rendered inline (`runtime-error (2/3) / failed (3/3)`). Judge replay: persisted `judge-calls/<skillId>-<promptId>-<target>-<attemptIdx>.json` artifacts plus a new `re-judge` subcommand that re-executes them against an optionally different model or freshly-edited system prompt without re-spending operator hours on the runtime side. Two PR-#108 deferred bug fixes also landed: `git fetch --tags --force` before named-ref fetch (annotated tag refresh) and `setup()` teardown-first idempotency for the manual driver. Still private to `@vibe-agent-toolkit/dev-tools`; corpus authoring, first real run, and the docs deliverable are the downstream work.
|
|
14
|
+
- **Cowork driver spike.** Added [`docs/contributing/cowork-driver-spike.md`](docs/contributing/cowork-driver-spike.md) — a time-boxed investigation (per §4a of the harness v2 design) of whether `claude-cowork` can be driven programmatically by the empirical compat harness today. Verdict: **not feasible**; cowork is a Claude Desktop app product with no public API/CLI surface. The `claude-cowork` runtime stays on `scripted-assisted` until Anthropic ships a Cowork CLI mode, Sessions API, or documented filesystem-import path. Adjacent finding (not a cowork replacement): the public-beta Skills API (`POST /v1/skills` + `container.skills[]` on `/v1/messages`) supports a fully-automatable *new* runtime — captured in the spike doc as a potential follow-up, gated on a separate design decision.
|
|
15
|
+
- **Subscription-only compat harness billing.** The harness now bills a Claude Pro/Max subscription instead of the API: both token-consuming surfaces (the `claude-code` runtime driver and the LLM judge) route through one shared `claude` CLI invoker (`runtimes/shared/claude-cli.ts`) that injects the operator's `CLAUDE_CODE_OAUTH_TOKEN` and deletes every API credential from the child env, so the CLI cannot fall back to API billing. The operator's own token is sourced at preflight — env var if set, otherwise an interactive prompt — so a run only ever spends the operator's personal plan. The judge was migrated off `@anthropic-ai/sdk` (dependency removed) onto the CLI, parsing a strict JSON verdict with one retry instead of the SDK's forced-tool call (`judge-system.md` now asks for a JSON object). `RunMetadata` gains `authMode` and the report methodology discloses subscription auth + parsed-not-forced verdicts. Premise (zero API billing under the OAuth token) still pending the manual smoke test.
|
|
16
|
+
|
|
17
|
+
### Changed (breaking, pre-1.0)
|
|
18
|
+
|
|
19
|
+
- **`vat resources validate` gains per-code severity configuration, and external-URL findings no longer fail the build by default.** Resource findings now use the same configurable severity framework as `vat skills`: each is a documented code (e.g. `LINK_BROKEN_FILE`, `EXTERNAL_URL_DEAD`) with a default severity, overridable per project under `resources.validation.severity` / `resources.validation.allow`. External-URL findings now default to `warning` and no longer flip the exit code (fixing a bug where they always failed the command); set their severity to `error` to restore failing. Severity now also accepts an `info` level. The never-implemented `resources.validation.checkLinks`/`checkAnchors`/`allowExternal` keys are removed.
|
|
20
|
+
- **`validation.severity` / `validation.allow` keys are validated against real codes.** A mistyped code key (e.g. `LNIK_OUTSIDE_PROJECT`) is now a config-load error instead of a silent no-op.
|
|
21
|
+
- **Corpus seed entries now require `bucket`, `confidence`, and `maturity` metadata fields.** `PluginEntrySchema` in `vat corpus scan`'s seed loader gains three required enum fields: `bucket: 'official' | 'community'`, `confidence: 'first-party' | 'curated' | 'listed'`, and `maturity: 'production' | 'experimental' | 'example'`. The bundled `corpus/seed.yaml` is updated; downstream callers running custom seeds must add the fields to every entry. `bucket` is the load-bearing discriminator (`official` entries report named findings; `community` entries are aggregate-only in follow-up work). The other two are descriptive metadata used by triage tooling.
|
|
22
|
+
- **`vat claude marketplace publish` no longer reports the project root `package.json` version in the CLI banner, commit message, status YAML, or CHANGELOG section lookup.** The label is now derived from the staged `marketplace.json`. Single-plugin marketplaces use the plugin's version — banner reads `Publishing marketplace "X" v0.0.4`, commit subject reads `publish v0.0.4`. Multi-plugin marketplaces drop the `v<X>` entirely — banner reads `Publishing marketplace "X"`, commit subject reads `publish X` — since the per-plugin `version` fields in the published `marketplace.json` are the source of truth for which plugin moved to which version. Two visible side-effects follow: (1) the status YAML's `published[*].version` field is now absent for multi-plugin marketplaces (previously it carried the misleading project version) — automation should read per-plugin versions from the published `marketplace.json` instead; (2) the stamped `## [X.Y.Z]` CHANGELOG lookup now uses the plugin's version rather than the project's, so a previously-ignored matching section will now be picked up as the commit body for single-plugin marketplaces. The `marketplace.json` schema's optional top-level `version` field is not yet consumed — that is a separate follow-up.
|
|
23
|
+
- **`vat claude marketplace publish` no longer pushes per-plugin `<name>-v<version>` source-repo tags.** The post-publish tagging step (introduced alongside multi-plugin versioning) is removed entirely — no tags are created or pushed, and the misleading `Repository not found` / "tag already exists at a different commit" warnings it emitted on every cross-repo publish are gone ([#121](https://github.com/jdutton/vibe-agent-toolkit/issues/121)). The tags were pushed to the marketplace remote rather than a source remote, never landed anywhere useful, and there was no opt-in demand. Which plugin moved to which version is now determined solely by the per-plugin `version` fields in the published `marketplace.json`. No config key or flag is involved; if you relied on these tags, create them in your own release workflow.
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- **Transformers.js integration tests now skip on Windows CI instead of flaking.** `transformers-embedding-provider.integration.test.ts` and the Transformers.js block of `comparison.integration.test.ts` skip on Windows (in addition to skipping when the optional `@xenova/transformers` dependency is absent), matching the existing `onnx-embedding-provider` test. These tests download a model over the network and load the `onnxruntime-node` native backend — both flaky in Windows CI. Such a failure was previously mislabeled `@xenova/transformers is not installed` by an over-broad `catch` in the provider's `loadPipeline` (the package was installed; the model download/inference is what failed), which is also why an availability-only guard did not prevent it.
|
|
28
|
+
- **Config-first skill discovery now honors `..` in `skills.include` patterns.** `vat build`, `vat verify`, and `vat skills validate` all funnel through `discoverSkillsFromConfig`, which previously passed every include pattern to a single downward-only crawl rooted at `projectRoot` — so an include like `"../../docs/skills/*/SKILL.md"` (common in monorepos where SKILL.md sources live alongside, not inside, the package) silently matched zero skills. `vat audit` accepted the same config only because it has a separate filesystem-first walker. Each include pattern is now split into a literal base + glob remainder via `picomatch.scan`, patterns are grouped by their resolved absolute base, and the crawler runs once per base — making config-first discovery agree with audit. User-supplied excludes stay anchored to `projectRoot` so patterns like `docs/private/**` keep their original meaning, and a pattern resolving to a nonexistent base now silently produces zero matches.
|
|
29
|
+
|
|
10
30
|
## [0.1.38] - 2026-05-18
|
|
11
31
|
|
|
12
32
|
### Changed (breaking, pre-1.0)
|
|
@@ -93,6 +93,24 @@ Absolute URLs in URI-reference fields feed into the existing external URL health
|
|
|
93
93
|
|
|
94
94
|
Opt-out: `checkFrontmatterLinks: false` per collection, or `--no-check-frontmatter-links` on the CLI.
|
|
95
95
|
|
|
96
|
+
## Per-code severity and allow (`resources.validation`)
|
|
97
|
+
|
|
98
|
+
Every resources finding is a registry code (e.g. `LINK_BROKEN_FILE`, `FRONTMATTER_SCHEMA_ERROR`, `EXTERNAL_URL_DEAD`) with a default severity. Tune them per-code under `resources.validation`:
|
|
99
|
+
|
|
100
|
+
```yaml
|
|
101
|
+
resources:
|
|
102
|
+
validation:
|
|
103
|
+
severity:
|
|
104
|
+
EXTERNAL_URL_DEAD: ignore # silence dead external links entirely
|
|
105
|
+
LINK_UNKNOWN: error # promote unclassified links to build-failing
|
|
106
|
+
allow:
|
|
107
|
+
LINK_TO_GITIGNORED: # keyed by code; value is a list of allow entries
|
|
108
|
+
- paths: ["docs/internal/**"]
|
|
109
|
+
reason: "internal-only notes, intentionally gitignored"
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`severity` accepts `error | warning | info | ignore`. External-URL findings default to `warning` and never fail the build on their own — promote them to `error` here if you want network checks to gate CI. `allow` is keyed by code; each entry's `paths` (glob list, default `**/*`) and `reason` suppress that code for matching files rather than disabling it globally. Add `expires` (a date string) to flag the allowance for re-review.
|
|
113
|
+
|
|
96
114
|
## Annotating Frontmatter Schemas with Zod 4
|
|
97
115
|
|
|
98
116
|
If your project generates JSON Schemas from Zod (via `z.toJSONSchema()`), annotate frontmatter fields that hold links with the appropriate `format` so VAT's link validator picks them up:
|
|
@@ -307,9 +307,9 @@ Start a new Claude Code session to confirm skills load. See the [Marketplace Dis
|
|
|
307
307
|
|
|
308
308
|
VAT supports two versioning models for a marketplace:
|
|
309
309
|
|
|
310
|
-
**Single-version (default for skills-only marketplaces).** No `version` is declared on individual plugins. All plugins inherit the root `package.json:version`. This is the model used by `vibe-agent-toolkit`
|
|
310
|
+
**Single-version (default for skills-only marketplaces).** No `version` is declared on individual plugins. All plugins inherit the root `package.json:version`. This is the model used by `vibe-agent-toolkit` — the marketplace is treated as one release artifact.
|
|
311
311
|
|
|
312
|
-
**Per-plugin versioning** (multi-plugin marketplaces with independent release cadences). Each plugin declares its own `version`. Recommended when topical plugins under one marketplace evolve on independent timelines
|
|
312
|
+
**Per-plugin versioning** (multi-plugin marketplaces with independent release cadences). Each plugin declares its own `version`. Recommended when topical plugins under one marketplace evolve on independent timelines.
|
|
313
313
|
|
|
314
314
|
#### Where to declare a per-plugin version
|
|
315
315
|
|
|
@@ -337,7 +337,6 @@ If both declare a version, marketplace config wins and VAT logs a reconciliation
|
|
|
337
337
|
For each plugin with a resolved version:
|
|
338
338
|
|
|
339
339
|
- The published `.claude-plugin/marketplace.json` includes the per-plugin `version` field on each plugin entry.
|
|
340
|
-
- After the publish-branch push succeeds, VAT pushes a `<plugin>-v<version>` tag to the **source repo** (not the marketplace branch) — e.g., `ai-digest-v0.2.0`. "Source repo" means the working directory where you invoke `vat claude marketplace publish` (i.e., `process.cwd()`); if you invoke from a subdirectory of a worktree, tags land in the containing repo, not the subdirectory. Tag-push failures log a warning but do not roll back the publish.
|
|
341
340
|
- If `<plugin.source>/CHANGELOG.md` exists in source (or the marketplace plugin entry's `changelog` field points to a file), it is bundled into the published marketplace at `plugins/<name>/CHANGELOG.md`, alongside the marketplace-level CHANGELOG.
|
|
342
341
|
|
|
343
342
|
The marketplace-level CHANGELOG (under `publish.changelog` in the config) continues to work unchanged.
|
|
@@ -358,7 +357,7 @@ plugins:
|
|
|
358
357
|
|
|
359
358
|
#### Backwards compatibility
|
|
360
359
|
|
|
361
|
-
Marketplaces with no per-plugin version anywhere are unaffected. The root `package.json` version flows through to every plugin, the published `marketplace.json` either omits per-plugin `version` or includes the same value for all plugins
|
|
360
|
+
Marketplaces with no per-plugin version anywhere are unaffected. The root `package.json` version flows through to every plugin, and the published `marketplace.json` either omits per-plugin `version` or includes the same value for all plugins.
|
|
362
361
|
|
|
363
362
|
## Step 5: User Install
|
|
364
363
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
export const meta = {};
|
|
6
6
|
|
|
7
|
-
export const text = "# VAT Plugin Skills — Development Guide\n\nThis directory ships the \`vibe-agent-toolkit\` Claude Code plugin. When editing\nor creating skills here, follow the boundaries and rules below. The goal is\nthat each sub-skill has a single, sharp trigger and that they collectively\ncover VAT\'s user-facing surface without overlap.\n\n## Skill inventory and boundaries\n\n| Skill | Owns | Does NOT own | CLI |\n|---|---|---|---|\n| \`vibe-agent-toolkit\` (router, \`SKILL.md\`) | What VAT is, when to use it, routing to sub-skills | Any deep content — keep ≤150 lines, prose-only references to sub-skills | — |\n| \`vat-adoption-and-configuration\` | Project setup, \`vibe-agent-toolkit.config.yaml\` orientation, repo structure, vibe-validate integration, npm postinstall hook | Per-section config depth (each owning skill covers its own slice) | — |\n| \`vat-skill-authoring\` | \`SKILL.md\` files: frontmatter, body structure, references, packagingOptions (linkFollowDepth, excludeReferencesFromBundle), validation overrides | TypeScript agent functions, plugin packaging, RAG | — |\n| \`vat-agent-authoring\` | TypeScript portable agents: archetypes (Pure Function Tool, One-Shot LLM Analyzer, Conversational Assistant, External Event Integrator), \`agent.yaml\`, result envelopes, runtime adapters (Vercel/LangChain/OpenAI/Claude Agent SDK) | SKILL.md authoring, plugin/marketplace config | — |\n| \`vat-audit\` | \`vat audit\` on plugins/marketplaces/skills/settings; \`--compat\`, \`--exclude\`, \`--user\`, CI usage | What to fix (defer to other skills) | \`vat audit\` |\n| \`vat-knowledge-resources\` | Markdown collections, \`vibe-agent-toolkit.config.yaml\` \`resources\` section, frontmatter schemas, validation modes | RAG indexing (separate skill) | \`vat resources validate\` |\n| \`vat-skill-distribution\` | \`vat build\`, \`vat verify\`, plugin/marketplace config, npm publishing, postinstall hooks, \`vat.skills\` field | Authoring the SKILL.md itself | \`vat build\`, \`vat verify\` |\n| \`vat-rag\` | \`vat rag index\`, \`vat rag query\`, native embedding/vector store support, extension points, \"contributions welcome\" callout | Markdown collection authoring (knowledge-resources owns) | \`vat rag\` |\n| \`vat-skill-review\` | Pre-publication review rubric, validation-code reference, Anthropic best-practices integration, \`vat skill review\` command | The validators themselves (live in code) | \`vat skill review\` |\n| \`vat-enterprise-org\` | Anthropic Admin API: org users, cost/usage, workspace skills, \`ANTHROPIC_ADMIN_API_KEY\` | Per-user runtime auth | \`vat claude org\` |\n\n## Cross-cutting: \`vibe-agent-toolkit.config.yaml\`\n\nThis file is multi-skill. Each section is owned by one skill:\n\n| Config section | Owning skill |\n|---|---|\n| Top-level structure, version, multi-section orientation | \`vat-adoption-and-configuration\` |\n| \`skills:\` (include, defaults, per-skill config, packagingOptions) | \`vat-skill-authoring\` |\n| \`resources:\` (collections, schemas, validation modes) | \`vat-knowledge-resources\` |\n| \`claude:\` (marketplaces, plugins, publish, owner) | \`vat-skill-distribution\` |\n\nWhen a skill needs to mention a section it doesn\'t own, link to the owning skill rather than re-explaining the section.\n\n## Naming rules (programmatic + advisory)\n\n- **Forbidden words in \`name\`**: \`claude\`, \`anthropic\`. Claude Code rejects skills containing these words unless they are official certified skills. Enforced by validator code \`RESERVED_WORD_IN_NAME\` (warning severity).\n- **Prefer CLI-name alignment**: when a skill primarily covers a CLI command, use the same root word (\`vat-audit\` → \`vat audit\`, \`vat-skill-review\` → \`vat skill review\`). Discovery hook for users running \`--help\`.\n- **Kebab-case**, lowercase letters, digits, hyphens. Matches \`^[a-z][a-z0-9-]*$\`.\n- **No vague nouns**: \`vat-resources\` was renamed to \`vat-knowledge-resources\` because \"resources\" alone could mean anything. Each name should carry its subject.\n- **No platform names** unless certified: see forbidden words rule above. Say \"enterprise\" not \"claude\" / \"anthropic\".\n\n## Description quality\n\nA description must let Claude Code trigger correctly. Required elements:\n- **Action verb or \"Use when...\"** opener\n- **Subject** (what kind of work fires this skill)\n- **2-4 trigger keywords** (the words a user is likely to use)\n- **What it covers** (one short clause)\n- ≤250 chars total (Claude Code listing truncates at 250)\n\nExample (\`vat-audit\`):\n> Use when running \`vat audit\` to validate Claude plugins, marketplaces, or skills. Covers the audit command, \`--compat\` for surface compatibility, \`--exclude\` for noise filtering, and interpreting findings.\n\nTriggers on: \"audit my plugin\", \"validate plugin compatibility\", \"what does this audit warning mean\".\n\n## Router skill (\`SKILL.md\` / \`vibe-agent-toolkit\`) — special rules\n\nThe router exists for **discovery + routing**, not content. Strict rules:\n\n1. **≤150 lines total**\n2. **Prose references to sub-skills** — never markdown links: write \`vibe-agent-toolkit:vat-audit\`, not \`[vat-audit](./vat-audit.md)\`. Markdown links cause VAT\'s packager to transclude the sibling, bloating the bundle.\n3. **No code examples beyond a 5-line CLI overview** — depth lives in sub-skills\n4. **Description triggers entry questions** (\"what is VAT\", \"how do I get started\"), not specific tasks\n\nVerify after edits: \`vat skill review packages/vat-development-agents/resources/skills\` should report \`fileCount: 1\` (no transclusion).\n\n## Single-responsibility — when to split\n\nSplit a skill when its description must list two unrelated subjects to trigger correctly. Example: the original \`vat-authoring\` covered both SKILL.md files and TypeScript agent functions — two distinct mental models, hence the split into \`vat-skill-authoring\` and \`vat-agent-authoring\`.\n\n## Contributor vs user content\n\nThis plugin is for **users of VAT**. Contributor-facing material (debugging VAT internals, designing install architecture, working on the codebase) belongs in \`docs/contributing/\`, not in a SKILL.md here. The root CLAUDE.md routes contributors to those docs.\n\nIf a skill description says \"use when developing/contributing to VAT\", it doesn\'t belong in this directory.\n\n## This area moves fast — verify current standards\n\nSkill authoring, agent design, and Claude Code\'s own skill-loading semantics are evolving rapidly. Cached guidance under \`docs/external/\` (e.g. \`anthropic-skill-authoring-best-practices.md\`) ages quickly. Before making non-trivial changes:\n\n- Re-fetch the source URL named in the cached doc\'s preamble; diff against the cache; if material has changed, update the cache and propagate the delta into validators and \`vat-skill-review\`.\n- Web search for the latest Claude Code release notes when changing trigger semantics, frontmatter rules, or packaging behavior. Don\'t rely on training-data recall.\n- The \`vat-skill-review\` skill must carry this same instruction explicitly — it\'s the skill agents load when they\'re about to apply quality standards.\n\n## Shift left — every manual check is a future validator\n\nWhen a quality issue is caught manually (in code review, by the user noticing an error from Claude Code, or via a checklist walkthrough), treat it as a candidate for **promotion to a programmatic validator**. The bar is: if the issue has a clear pattern that can be detected from the file contents, it should not stay a manual check.\n\n**Canonical example**: the \`RESERVED_WORD_IN_NAME\` rule. The \`claude\`/\`anthropic\` naming restriction was discovered through an install-time rejection — the kind of failure a developer hits once, remembers forever, but new contributors keep re-hitting. Encoding it as a validator (warning severity, fires at \`vat audit\` / \`vat skills validate\` time) shifts the discovery left from \"Claude Code rejects my install\" to \"validator warns me before I commit.\"\n\nWhen you add a validator:\n1. Register the code in \`validation-
|
|
7
|
+
export const text = "# VAT Plugin Skills — Development Guide\n\nThis directory ships the \`vibe-agent-toolkit\` Claude Code plugin. When editing\nor creating skills here, follow the boundaries and rules below. The goal is\nthat each sub-skill has a single, sharp trigger and that they collectively\ncover VAT\'s user-facing surface without overlap.\n\n## Skill inventory and boundaries\n\n| Skill | Owns | Does NOT own | CLI |\n|---|---|---|---|\n| \`vibe-agent-toolkit\` (router, \`SKILL.md\`) | What VAT is, when to use it, routing to sub-skills | Any deep content — keep ≤150 lines, prose-only references to sub-skills | — |\n| \`vat-adoption-and-configuration\` | Project setup, \`vibe-agent-toolkit.config.yaml\` orientation, repo structure, vibe-validate integration, npm postinstall hook | Per-section config depth (each owning skill covers its own slice) | — |\n| \`vat-skill-authoring\` | \`SKILL.md\` files: frontmatter, body structure, references, packagingOptions (linkFollowDepth, excludeReferencesFromBundle), validation overrides | TypeScript agent functions, plugin packaging, RAG | — |\n| \`vat-agent-authoring\` | TypeScript portable agents: archetypes (Pure Function Tool, One-Shot LLM Analyzer, Conversational Assistant, External Event Integrator), \`agent.yaml\`, result envelopes, runtime adapters (Vercel/LangChain/OpenAI/Claude Agent SDK) | SKILL.md authoring, plugin/marketplace config | — |\n| \`vat-audit\` | \`vat audit\` on plugins/marketplaces/skills/settings; \`--compat\`, \`--exclude\`, \`--user\`, CI usage | What to fix (defer to other skills) | \`vat audit\` |\n| \`vat-knowledge-resources\` | Markdown collections, \`vibe-agent-toolkit.config.yaml\` \`resources\` section, frontmatter schemas, validation modes | RAG indexing (separate skill) | \`vat resources validate\` |\n| \`vat-skill-distribution\` | \`vat build\`, \`vat verify\`, plugin/marketplace config, npm publishing, postinstall hooks, \`vat.skills\` field | Authoring the SKILL.md itself | \`vat build\`, \`vat verify\` |\n| \`vat-rag\` | \`vat rag index\`, \`vat rag query\`, native embedding/vector store support, extension points, \"contributions welcome\" callout | Markdown collection authoring (knowledge-resources owns) | \`vat rag\` |\n| \`vat-skill-review\` | Pre-publication review rubric, validation-code reference, Anthropic best-practices integration, \`vat skill review\` command | The validators themselves (live in code) | \`vat skill review\` |\n| \`vat-enterprise-org\` | Anthropic Admin API: org users, cost/usage, workspace skills, \`ANTHROPIC_ADMIN_API_KEY\` | Per-user runtime auth | \`vat claude org\` |\n\n## Cross-cutting: \`vibe-agent-toolkit.config.yaml\`\n\nThis file is multi-skill. Each section is owned by one skill:\n\n| Config section | Owning skill |\n|---|---|\n| Top-level structure, version, multi-section orientation | \`vat-adoption-and-configuration\` |\n| \`skills:\` (include, defaults, per-skill config, packagingOptions) | \`vat-skill-authoring\` |\n| \`resources:\` (collections, schemas, validation modes) | \`vat-knowledge-resources\` |\n| \`claude:\` (marketplaces, plugins, publish, owner) | \`vat-skill-distribution\` |\n\nWhen a skill needs to mention a section it doesn\'t own, link to the owning skill rather than re-explaining the section.\n\n## Naming rules (programmatic + advisory)\n\n- **Forbidden words in \`name\`**: \`claude\`, \`anthropic\`. Claude Code rejects skills containing these words unless they are official certified skills. Enforced by validator code \`RESERVED_WORD_IN_NAME\` (warning severity).\n- **Prefer CLI-name alignment**: when a skill primarily covers a CLI command, use the same root word (\`vat-audit\` → \`vat audit\`, \`vat-skill-review\` → \`vat skill review\`). Discovery hook for users running \`--help\`.\n- **Kebab-case**, lowercase letters, digits, hyphens. Matches \`^[a-z][a-z0-9-]*$\`.\n- **No vague nouns**: \`vat-resources\` was renamed to \`vat-knowledge-resources\` because \"resources\" alone could mean anything. Each name should carry its subject.\n- **No platform names** unless certified: see forbidden words rule above. Say \"enterprise\" not \"claude\" / \"anthropic\".\n\n## Description quality\n\nA description must let Claude Code trigger correctly. Required elements:\n- **Action verb or \"Use when...\"** opener\n- **Subject** (what kind of work fires this skill)\n- **2-4 trigger keywords** (the words a user is likely to use)\n- **What it covers** (one short clause)\n- ≤250 chars total (Claude Code listing truncates at 250)\n\nExample (\`vat-audit\`):\n> Use when running \`vat audit\` to validate Claude plugins, marketplaces, or skills. Covers the audit command, \`--compat\` for surface compatibility, \`--exclude\` for noise filtering, and interpreting findings.\n\nTriggers on: \"audit my plugin\", \"validate plugin compatibility\", \"what does this audit warning mean\".\n\n## Router skill (\`SKILL.md\` / \`vibe-agent-toolkit\`) — special rules\n\nThe router exists for **discovery + routing**, not content. Strict rules:\n\n1. **≤150 lines total**\n2. **Prose references to sub-skills** — never markdown links: write \`vibe-agent-toolkit:vat-audit\`, not \`[vat-audit](./vat-audit.md)\`. Markdown links cause VAT\'s packager to transclude the sibling, bloating the bundle.\n3. **No code examples beyond a 5-line CLI overview** — depth lives in sub-skills\n4. **Description triggers entry questions** (\"what is VAT\", \"how do I get started\"), not specific tasks\n\nVerify after edits: \`vat skill review packages/vat-development-agents/resources/skills\` should report \`fileCount: 1\` (no transclusion).\n\n## Single-responsibility — when to split\n\nSplit a skill when its description must list two unrelated subjects to trigger correctly. Example: the original \`vat-authoring\` covered both SKILL.md files and TypeScript agent functions — two distinct mental models, hence the split into \`vat-skill-authoring\` and \`vat-agent-authoring\`.\n\n## Contributor vs user content\n\nThis plugin is for **users of VAT**. Contributor-facing material (debugging VAT internals, designing install architecture, working on the codebase) belongs in \`docs/contributing/\`, not in a SKILL.md here. The root CLAUDE.md routes contributors to those docs.\n\nIf a skill description says \"use when developing/contributing to VAT\", it doesn\'t belong in this directory.\n\n## This area moves fast — verify current standards\n\nSkill authoring, agent design, and Claude Code\'s own skill-loading semantics are evolving rapidly. Cached guidance under \`docs/external/\` (e.g. \`anthropic-skill-authoring-best-practices.md\`) ages quickly. Before making non-trivial changes:\n\n- Re-fetch the source URL named in the cached doc\'s preamble; diff against the cache; if material has changed, update the cache and propagate the delta into validators and \`vat-skill-review\`.\n- Web search for the latest Claude Code release notes when changing trigger semantics, frontmatter rules, or packaging behavior. Don\'t rely on training-data recall.\n- The \`vat-skill-review\` skill must carry this same instruction explicitly — it\'s the skill agents load when they\'re about to apply quality standards.\n\n## Shift left — every manual check is a future validator\n\nWhen a quality issue is caught manually (in code review, by the user noticing an error from Claude Code, or via a checklist walkthrough), treat it as a candidate for **promotion to a programmatic validator**. The bar is: if the issue has a clear pattern that can be detected from the file contents, it should not stay a manual check.\n\n**Canonical example**: the \`RESERVED_WORD_IN_NAME\` rule. The \`claude\`/\`anthropic\` naming restriction was discovered through an install-time rejection — the kind of failure a developer hits once, remembers forever, but new contributors keep re-hitting. Encoding it as a validator (warning severity, fires at \`vat audit\` / \`vat skills validate\` time) shifts the discovery left from \"Claude Code rejects my install\" to \"validator warns me before I commit.\"\n\nWhen you add a validator:\n1. Register the code in \`packages/agent-schema/src/validation-codes.ts\` (the \`CODE_REGISTRY\`) with default severity, description, fix hint, and a \`reference\` anchor into \`docs/validation-codes.md\`\n2. Wire it into the appropriate validator pipeline (frontmatter, link, packaging) so it actually fires\n3. Add a checklist entry in \`vat-skill-review\` that references the same code (so the manual rubric and the automated check stay aligned)\n4. Default severity is **warning** unless the issue genuinely blocks distribution — even then, prefer warning + clear fix hint per the [validation-rule-design policy](../../../../docs/validation-rule-design.md)\n\nWhen \`vat-skill-review\` lists a checklist item that is currently a \`[ ]\` manual judgment call, ask: *can this be detected programmatically?* If yes, file a follow-up to add the validator and convert the manual item to an automated reference.\n\n## Pre-commit checks\n\nBefore committing a skill change:\n\n\`\`\`bash\n# Review the specific skill you touched\nbun run vat skill review packages/vat-development-agents/resources/skills/<skill>.md\n\n# Audit the whole plugin\nbun run vat audit packages/vat-development-agents\n\n# Full validation\nbun run validate\n\`\`\`\n\nWatch for:\n- \`RESERVED_WORD_IN_NAME\` (warning) — naming policy violation\n- \`SKILL_DESCRIPTION_OVER_CLAUDE_CODE_LIMIT\` — trim to ≤250 chars\n- \`SKILL_DESCRIPTION_FILLER_OPENER\` — start with action verb or \"Use when\"\n- \`SKILL_NAME_MISMATCHES_DIR\` (should not fire — generic-container exemption applies here)\n- \`LINK_TO_NAVIGATION_FILE\` — link to specific files, not READMEs\n- \`LINK_TARGETS_DIRECTORY\` — link to specific files, not directories\n";
|
|
8
8
|
|
|
9
9
|
export const fragments = {
|
|
10
10
|
skillInventoryAndBoundaries: {
|
|
@@ -49,8 +49,8 @@ export const fragments = {
|
|
|
49
49
|
},
|
|
50
50
|
shiftLeft-EveryManualCheckIsAFutureValidator: {
|
|
51
51
|
header: "## Shift left — every manual check is a future validator",
|
|
52
|
-
body: "When a quality issue is caught manually (in code review, by the user noticing an error from Claude Code, or via a checklist walkthrough), treat it as a candidate for **promotion to a programmatic validator**. The bar is: if the issue has a clear pattern that can be detected from the file contents, it should not stay a manual check.\n\n**Canonical example**: the \`RESERVED_WORD_IN_NAME\` rule. The \`claude\`/\`anthropic\` naming restriction was discovered through an install-time rejection — the kind of failure a developer hits once, remembers forever, but new contributors keep re-hitting. Encoding it as a validator (warning severity, fires at \`vat audit\` / \`vat skills validate\` time) shifts the discovery left from \"Claude Code rejects my install\" to \"validator warns me before I commit.\"\n\nWhen you add a validator:\n1. Register the code in \`validation-
|
|
53
|
-
text: "## Shift left — every manual check is a future validator\n\nWhen a quality issue is caught manually (in code review, by the user noticing an error from Claude Code, or via a checklist walkthrough), treat it as a candidate for **promotion to a programmatic validator**. The bar is: if the issue has a clear pattern that can be detected from the file contents, it should not stay a manual check.\n\n**Canonical example**: the \`RESERVED_WORD_IN_NAME\` rule. The \`claude\`/\`anthropic\` naming restriction was discovered through an install-time rejection — the kind of failure a developer hits once, remembers forever, but new contributors keep re-hitting. Encoding it as a validator (warning severity, fires at \`vat audit\` / \`vat skills validate\` time) shifts the discovery left from \"Claude Code rejects my install\" to \"validator warns me before I commit.\"\n\nWhen you add a validator:\n1. Register the code in \`validation-
|
|
52
|
+
body: "When a quality issue is caught manually (in code review, by the user noticing an error from Claude Code, or via a checklist walkthrough), treat it as a candidate for **promotion to a programmatic validator**. The bar is: if the issue has a clear pattern that can be detected from the file contents, it should not stay a manual check.\n\n**Canonical example**: the \`RESERVED_WORD_IN_NAME\` rule. The \`claude\`/\`anthropic\` naming restriction was discovered through an install-time rejection — the kind of failure a developer hits once, remembers forever, but new contributors keep re-hitting. Encoding it as a validator (warning severity, fires at \`vat audit\` / \`vat skills validate\` time) shifts the discovery left from \"Claude Code rejects my install\" to \"validator warns me before I commit.\"\n\nWhen you add a validator:\n1. Register the code in \`packages/agent-schema/src/validation-codes.ts\` (the \`CODE_REGISTRY\`) with default severity, description, fix hint, and a \`reference\` anchor into \`docs/validation-codes.md\`\n2. Wire it into the appropriate validator pipeline (frontmatter, link, packaging) so it actually fires\n3. Add a checklist entry in \`vat-skill-review\` that references the same code (so the manual rubric and the automated check stay aligned)\n4. Default severity is **warning** unless the issue genuinely blocks distribution — even then, prefer warning + clear fix hint per the [validation-rule-design policy](../../../../docs/validation-rule-design.md)\n\nWhen \`vat-skill-review\` lists a checklist item that is currently a \`[ ]\` manual judgment call, ask: *can this be detected programmatically?* If yes, file a follow-up to add the validator and convert the manual item to an automated reference.",
|
|
53
|
+
text: "## Shift left — every manual check is a future validator\n\nWhen a quality issue is caught manually (in code review, by the user noticing an error from Claude Code, or via a checklist walkthrough), treat it as a candidate for **promotion to a programmatic validator**. The bar is: if the issue has a clear pattern that can be detected from the file contents, it should not stay a manual check.\n\n**Canonical example**: the \`RESERVED_WORD_IN_NAME\` rule. The \`claude\`/\`anthropic\` naming restriction was discovered through an install-time rejection — the kind of failure a developer hits once, remembers forever, but new contributors keep re-hitting. Encoding it as a validator (warning severity, fires at \`vat audit\` / \`vat skills validate\` time) shifts the discovery left from \"Claude Code rejects my install\" to \"validator warns me before I commit.\"\n\nWhen you add a validator:\n1. Register the code in \`packages/agent-schema/src/validation-codes.ts\` (the \`CODE_REGISTRY\`) with default severity, description, fix hint, and a \`reference\` anchor into \`docs/validation-codes.md\`\n2. Wire it into the appropriate validator pipeline (frontmatter, link, packaging) so it actually fires\n3. Add a checklist entry in \`vat-skill-review\` that references the same code (so the manual rubric and the automated check stay aligned)\n4. Default severity is **warning** unless the issue genuinely blocks distribution — even then, prefer warning + clear fix hint per the [validation-rule-design policy](../../../../docs/validation-rule-design.md)\n\nWhen \`vat-skill-review\` lists a checklist item that is currently a \`[ ]\` manual judgment call, ask: *can this be detected programmatically?* If yes, file a follow-up to add the validator and convert the manual item to an automated reference."
|
|
54
54
|
},
|
|
55
55
|
preCommitChecks: {
|
|
56
56
|
header: "## Pre-commit checks",
|
|
@@ -24,6 +24,7 @@ export const fragments: {
|
|
|
24
24
|
readonly schemaPathFormats: Fragment;
|
|
25
25
|
readonly addingANewDocType: Fragment;
|
|
26
26
|
readonly recommendFormatUriReferenceForPathShapedFrontmatterFields: Fragment;
|
|
27
|
+
readonly perCodeSeverityAndAllowResourcesvalidation: Fragment;
|
|
27
28
|
readonly annotatingFrontmatterSchemasWithZod4: Fragment;
|
|
28
29
|
readonly uriReferencesInFrontmatter: Fragment;
|
|
29
30
|
readonly validationOutput: Fragment;
|
|
@@ -7,7 +7,7 @@ export const meta = {
|
|
|
7
7
|
description: "Use when working with VAT resource collections, per-directory frontmatter schema validation, link validation, or the vat resources command. Covers collection configuration, schema mapping, and validation modes."
|
|
8
8
|
};
|
|
9
9
|
|
|
10
|
-
export const text = "\n# VAT Resources: Collections & Frontmatter Validation\n\n## What Resource Collections Are\n\nA **resource collection** is a named group of files that share a validation schema.\nCollections are defined in \`vibe-agent-toolkit.config.yaml\` and enable different\ndirectories to have different required frontmatter — without writing a single line of code.\n\n## Config Format\n\n\`\`\`yaml\nversion: 1\n\nresources:\n collections:\n # Name your collection to match the doc type\n systems:\n include: [\"docs/systems/**/*.md\"]\n exclude: [\"docs/systems/README.md\"] # exclude human-only ToCs\n validation:\n frontmatterSchema: \"schemas/system.schema.json\"\n mode: permissive # required fields enforced; extra fields allowed\n\n adrs:\n include: [\"docs/architecture/adr/**/*.md\"]\n validation:\n frontmatterSchema: \"schemas/adr.schema.json\"\n mode: permissive\n\n skills:\n include: [\"**/SKILL.md\"]\n validation:\n frontmatterSchema: \"@vibe-agent-toolkit/agent-skills/schemas/skill-frontmatter.json\"\n mode: strict # SKILL.md: no extra fields beyond spec\n\`\`\`\n\n## Validation Modes\n\n| Mode | Required fields | Extra fields | Use for |\n|---|---|---|---|\n| \`permissive\` | Enforced | Allowed | Docs with project-specific extras |\n| \`strict\` | Enforced | Error | SKILL.md, API specs, tightly controlled schemas |\n\n## Running Validation\n\n\`\`\`bash\n# Validate all collections (reads vibe-agent-toolkit.config.yaml)\nvat resources validate\n\n# Validate specific collection only\nvat resources validate --collection systems\n\n# Validate with extra schema (adds to collection schemas)\nvat resources validate --frontmatter-schema ./extra.json\n\`\`\`\n\n## A File Can Belong to Multiple Collections\n\nIf a file matches multiple \`include\` patterns, **all matching schemas are validated**.\nValidation fails if any schema fails.\n\n## Schema Path Formats\n\n\`\`\`yaml\nfrontmatterSchema: \"./schemas/system.schema.json\" # relative to config\nfrontmatterSchema: \"/absolute/path/schema.json\" # absolute\nfrontmatterSchema: \"@vibe-agent-toolkit/agent-skills/...\" # npm package export\n\`\`\`\n\n## Adding a New Doc Type\n\n1. Create \`schemas/<type>.schema.json\` with \`required\` fields\n2. Add a collection entry in \`vibe-agent-toolkit.config.yaml\`\n3. Run \`vat resources validate\` — any existing docs missing required fields will be flagged\n4. Fix frontmatter in existing docs, then CI is clean\n\n## Recommend \`format: \"uri-reference\"\` for path-shaped frontmatter fields\n\nWhen designing a schema for a knowledge-base collection that references other files (e.g., \`parent_prd\`, \`supersedes\`, \`adr_citations[*].adr\`, \`artifacts\`), declare \`format: \"uri-reference\"\` on the field. VAT will then validate those values against the file system using the same engine as markdown link checking — broken paths, missing anchors, gitignore violations, and unknown URI schemes all produce errors.\n\nTo require local committed files (no absolute URLs), add a \`pattern\` excluding scheme prefixes. Standard JSON Schema; stays portable.\n\nVAT walks four URI-family formats: \`uri-reference\`, \`uri\`, \`iri-reference\`, \`iri\`. \`uri-template\` (RFC 6570) is intentionally NOT walked — templated values contain placeholders.\n\nAbsolute URLs in URI-reference fields feed into the existing external URL health-check pass when \`checkUrlLinks: true\` is set on the collection.\n\nOpt-out: \`checkFrontmatterLinks: false\` per collection, or \`--no-check-frontmatter-links\` on the CLI.\n\n## Annotating Frontmatter Schemas with Zod 4\n\nIf your project generates JSON Schemas from Zod (via \`z.toJSONSchema()\`), annotate frontmatter fields that hold links with the appropriate \`format\` so VAT\'s link validator picks them up:\n\n\`\`\`typescript\nimport { z } from \'zod\';\n\nconst PrdFrontmatter = z.object({\n spec_ref: z.string().meta({ format: \'uri-reference\' }), // repo-relative or absolute\n roadmap: z.url().meta({ format: \'uri\' }), // full URL only\n doc_anchor: z.string().meta({ format: \'json-pointer\' }), // JSON Pointer\n});\n\`\`\`\n\n\`format\` values VAT walks for link validation: \`uri\`, \`uri-reference\`, \`iri\`, \`iri-reference\`. \`uri-template\` (RFC 6570) is intentionally NOT walked — templated values contain placeholders.\n\n**Zod 3 users:** \`.meta()\` does not exist in Zod 3. Either upgrade your schema-generation step to Zod 4 (runtime consumers can stay on Zod 3 via peer dependency + common-subset usage), or post-process the generated JSON Schema to inject \`format\` on the relevant field paths.\n\n**Tip:** \`format\` is advisory in JSON Schema; pair it with a \`pattern\` regex when you also need parse-time rejection of invalid inputs.\n\n## URI-references in frontmatter\n\nVAT validates frontmatter fields whose schema position has \`format: uri-reference\`\n(or \`uri\`, \`iri-reference\`, \`iri\`) against the same rules as body links:\n\n- Leading-\`/\` is RFC 3986 §4.2 absolute-path reference — resolved against\n the project root. Same semantics as body links.\n- Anchor fragments and external URLs are accepted; broken local refs error.\n- Inline comments on URI-ref fields are **preserved** when any tool rewrites\n the file via \`openFrontmatter\` (VAT packager, hand-rolled adopter scripts).\n\nExample:\n\n\`\`\`yaml\n---\nparent_spec: /docs/specs/foo.md # the spec this one supersedes\nadrs-cited:\n - /docs/adrs/0007-storage.md # primary reference\n - /docs/adrs/0011-snapshot.md # impacted by storage choice\n---\n\`\`\`\n\nSchema:\n\n\`\`\`json\n{\n \"type\": \"object\",\n \"properties\": {\n \"parent_spec\": { \"type\": \"string\", \"format\": \"uri-reference\" },\n \"adrs-cited\": {\n \"type\": \"array\",\n \"items\": { \"type\": \"string\", \"format\": \"uri-reference\" }\n }\n }\n}\n\`\`\`\n\nFor tools that **modify** frontmatter (not just validate it), see\n[[markdown-rewriting]].\n\n## Validation Output\n\n\`\`\`yaml\nstatus: success\nfilesScanned: 47\ncollections:\n systems:\n resourceCount: 7\n hasSchema: true\n validationMode: permissive\n adrs:\n resourceCount: 12\n hasSchema: true\n validationMode: permissive\nduration: 234ms\n\`\`\`\n\nErrors appear in stderr with \`file:line: message\` format for editor navigation.\n";
|
|
10
|
+
export const text = "\n# VAT Resources: Collections & Frontmatter Validation\n\n## What Resource Collections Are\n\nA **resource collection** is a named group of files that share a validation schema.\nCollections are defined in \`vibe-agent-toolkit.config.yaml\` and enable different\ndirectories to have different required frontmatter — without writing a single line of code.\n\n## Config Format\n\n\`\`\`yaml\nversion: 1\n\nresources:\n collections:\n # Name your collection to match the doc type\n systems:\n include: [\"docs/systems/**/*.md\"]\n exclude: [\"docs/systems/README.md\"] # exclude human-only ToCs\n validation:\n frontmatterSchema: \"schemas/system.schema.json\"\n mode: permissive # required fields enforced; extra fields allowed\n\n adrs:\n include: [\"docs/architecture/adr/**/*.md\"]\n validation:\n frontmatterSchema: \"schemas/adr.schema.json\"\n mode: permissive\n\n skills:\n include: [\"**/SKILL.md\"]\n validation:\n frontmatterSchema: \"@vibe-agent-toolkit/agent-skills/schemas/skill-frontmatter.json\"\n mode: strict # SKILL.md: no extra fields beyond spec\n\`\`\`\n\n## Validation Modes\n\n| Mode | Required fields | Extra fields | Use for |\n|---|---|---|---|\n| \`permissive\` | Enforced | Allowed | Docs with project-specific extras |\n| \`strict\` | Enforced | Error | SKILL.md, API specs, tightly controlled schemas |\n\n## Running Validation\n\n\`\`\`bash\n# Validate all collections (reads vibe-agent-toolkit.config.yaml)\nvat resources validate\n\n# Validate specific collection only\nvat resources validate --collection systems\n\n# Validate with extra schema (adds to collection schemas)\nvat resources validate --frontmatter-schema ./extra.json\n\`\`\`\n\n## A File Can Belong to Multiple Collections\n\nIf a file matches multiple \`include\` patterns, **all matching schemas are validated**.\nValidation fails if any schema fails.\n\n## Schema Path Formats\n\n\`\`\`yaml\nfrontmatterSchema: \"./schemas/system.schema.json\" # relative to config\nfrontmatterSchema: \"/absolute/path/schema.json\" # absolute\nfrontmatterSchema: \"@vibe-agent-toolkit/agent-skills/...\" # npm package export\n\`\`\`\n\n## Adding a New Doc Type\n\n1. Create \`schemas/<type>.schema.json\` with \`required\` fields\n2. Add a collection entry in \`vibe-agent-toolkit.config.yaml\`\n3. Run \`vat resources validate\` — any existing docs missing required fields will be flagged\n4. Fix frontmatter in existing docs, then CI is clean\n\n## Recommend \`format: \"uri-reference\"\` for path-shaped frontmatter fields\n\nWhen designing a schema for a knowledge-base collection that references other files (e.g., \`parent_prd\`, \`supersedes\`, \`adr_citations[*].adr\`, \`artifacts\`), declare \`format: \"uri-reference\"\` on the field. VAT will then validate those values against the file system using the same engine as markdown link checking — broken paths, missing anchors, gitignore violations, and unknown URI schemes all produce errors.\n\nTo require local committed files (no absolute URLs), add a \`pattern\` excluding scheme prefixes. Standard JSON Schema; stays portable.\n\nVAT walks four URI-family formats: \`uri-reference\`, \`uri\`, \`iri-reference\`, \`iri\`. \`uri-template\` (RFC 6570) is intentionally NOT walked — templated values contain placeholders.\n\nAbsolute URLs in URI-reference fields feed into the existing external URL health-check pass when \`checkUrlLinks: true\` is set on the collection.\n\nOpt-out: \`checkFrontmatterLinks: false\` per collection, or \`--no-check-frontmatter-links\` on the CLI.\n\n## Per-code severity and allow (\`resources.validation\`)\n\nEvery resources finding is a registry code (e.g. \`LINK_BROKEN_FILE\`, \`FRONTMATTER_SCHEMA_ERROR\`, \`EXTERNAL_URL_DEAD\`) with a default severity. Tune them per-code under \`resources.validation\`:\n\n\`\`\`yaml\nresources:\n validation:\n severity:\n EXTERNAL_URL_DEAD: ignore # silence dead external links entirely\n LINK_UNKNOWN: error # promote unclassified links to build-failing\n allow:\n LINK_TO_GITIGNORED: # keyed by code; value is a list of allow entries\n - paths: [\"docs/internal/**\"]\n reason: \"internal-only notes, intentionally gitignored\"\n\`\`\`\n\n\`severity\` accepts \`error | warning | info | ignore\`. External-URL findings default to \`warning\` and never fail the build on their own — promote them to \`error\` here if you want network checks to gate CI. \`allow\` is keyed by code; each entry\'s \`paths\` (glob list, default \`**/*\`) and \`reason\` suppress that code for matching files rather than disabling it globally. Add \`expires\` (a date string) to flag the allowance for re-review.\n\n## Annotating Frontmatter Schemas with Zod 4\n\nIf your project generates JSON Schemas from Zod (via \`z.toJSONSchema()\`), annotate frontmatter fields that hold links with the appropriate \`format\` so VAT\'s link validator picks them up:\n\n\`\`\`typescript\nimport { z } from \'zod\';\n\nconst PrdFrontmatter = z.object({\n spec_ref: z.string().meta({ format: \'uri-reference\' }), // repo-relative or absolute\n roadmap: z.url().meta({ format: \'uri\' }), // full URL only\n doc_anchor: z.string().meta({ format: \'json-pointer\' }), // JSON Pointer\n});\n\`\`\`\n\n\`format\` values VAT walks for link validation: \`uri\`, \`uri-reference\`, \`iri\`, \`iri-reference\`. \`uri-template\` (RFC 6570) is intentionally NOT walked — templated values contain placeholders.\n\n**Zod 3 users:** \`.meta()\` does not exist in Zod 3. Either upgrade your schema-generation step to Zod 4 (runtime consumers can stay on Zod 3 via peer dependency + common-subset usage), or post-process the generated JSON Schema to inject \`format\` on the relevant field paths.\n\n**Tip:** \`format\` is advisory in JSON Schema; pair it with a \`pattern\` regex when you also need parse-time rejection of invalid inputs.\n\n## URI-references in frontmatter\n\nVAT validates frontmatter fields whose schema position has \`format: uri-reference\`\n(or \`uri\`, \`iri-reference\`, \`iri\`) against the same rules as body links:\n\n- Leading-\`/\` is RFC 3986 §4.2 absolute-path reference — resolved against\n the project root. Same semantics as body links.\n- Anchor fragments and external URLs are accepted; broken local refs error.\n- Inline comments on URI-ref fields are **preserved** when any tool rewrites\n the file via \`openFrontmatter\` (VAT packager, hand-rolled adopter scripts).\n\nExample:\n\n\`\`\`yaml\n---\nparent_spec: /docs/specs/foo.md # the spec this one supersedes\nadrs-cited:\n - /docs/adrs/0007-storage.md # primary reference\n - /docs/adrs/0011-snapshot.md # impacted by storage choice\n---\n\`\`\`\n\nSchema:\n\n\`\`\`json\n{\n \"type\": \"object\",\n \"properties\": {\n \"parent_spec\": { \"type\": \"string\", \"format\": \"uri-reference\" },\n \"adrs-cited\": {\n \"type\": \"array\",\n \"items\": { \"type\": \"string\", \"format\": \"uri-reference\" }\n }\n }\n}\n\`\`\`\n\nFor tools that **modify** frontmatter (not just validate it), see\n[[markdown-rewriting]].\n\n## Validation Output\n\n\`\`\`yaml\nstatus: success\nfilesScanned: 47\ncollections:\n systems:\n resourceCount: 7\n hasSchema: true\n validationMode: permissive\n adrs:\n resourceCount: 12\n hasSchema: true\n validationMode: permissive\nduration: 234ms\n\`\`\`\n\nErrors appear in stderr with \`file:line: message\` format for editor navigation.\n";
|
|
11
11
|
|
|
12
12
|
export const fragments = {
|
|
13
13
|
whatResourceCollectionsAre: {
|
|
@@ -50,6 +50,11 @@ export const fragments = {
|
|
|
50
50
|
body: "When designing a schema for a knowledge-base collection that references other files (e.g., \`parent_prd\`, \`supersedes\`, \`adr_citations[*].adr\`, \`artifacts\`), declare \`format: \"uri-reference\"\` on the field. VAT will then validate those values against the file system using the same engine as markdown link checking — broken paths, missing anchors, gitignore violations, and unknown URI schemes all produce errors.\n\nTo require local committed files (no absolute URLs), add a \`pattern\` excluding scheme prefixes. Standard JSON Schema; stays portable.\n\nVAT walks four URI-family formats: \`uri-reference\`, \`uri\`, \`iri-reference\`, \`iri\`. \`uri-template\` (RFC 6570) is intentionally NOT walked — templated values contain placeholders.\n\nAbsolute URLs in URI-reference fields feed into the existing external URL health-check pass when \`checkUrlLinks: true\` is set on the collection.\n\nOpt-out: \`checkFrontmatterLinks: false\` per collection, or \`--no-check-frontmatter-links\` on the CLI.",
|
|
51
51
|
text: "## Recommend \`format: \"uri-reference\"\` for path-shaped frontmatter fields\n\nWhen designing a schema for a knowledge-base collection that references other files (e.g., \`parent_prd\`, \`supersedes\`, \`adr_citations[*].adr\`, \`artifacts\`), declare \`format: \"uri-reference\"\` on the field. VAT will then validate those values against the file system using the same engine as markdown link checking — broken paths, missing anchors, gitignore violations, and unknown URI schemes all produce errors.\n\nTo require local committed files (no absolute URLs), add a \`pattern\` excluding scheme prefixes. Standard JSON Schema; stays portable.\n\nVAT walks four URI-family formats: \`uri-reference\`, \`uri\`, \`iri-reference\`, \`iri\`. \`uri-template\` (RFC 6570) is intentionally NOT walked — templated values contain placeholders.\n\nAbsolute URLs in URI-reference fields feed into the existing external URL health-check pass when \`checkUrlLinks: true\` is set on the collection.\n\nOpt-out: \`checkFrontmatterLinks: false\` per collection, or \`--no-check-frontmatter-links\` on the CLI."
|
|
52
52
|
},
|
|
53
|
+
perCodeSeverityAndAllowResourcesvalidation: {
|
|
54
|
+
header: "## Per-code severity and allow (\`resources.validation\`)",
|
|
55
|
+
body: "Every resources finding is a registry code (e.g. \`LINK_BROKEN_FILE\`, \`FRONTMATTER_SCHEMA_ERROR\`, \`EXTERNAL_URL_DEAD\`) with a default severity. Tune them per-code under \`resources.validation\`:\n\n\`\`\`yaml\nresources:\n validation:\n severity:\n EXTERNAL_URL_DEAD: ignore # silence dead external links entirely\n LINK_UNKNOWN: error # promote unclassified links to build-failing\n allow:\n LINK_TO_GITIGNORED: # keyed by code; value is a list of allow entries\n - paths: [\"docs/internal/**\"]\n reason: \"internal-only notes, intentionally gitignored\"\n\`\`\`\n\n\`severity\` accepts \`error | warning | info | ignore\`. External-URL findings default to \`warning\` and never fail the build on their own — promote them to \`error\` here if you want network checks to gate CI. \`allow\` is keyed by code; each entry\'s \`paths\` (glob list, default \`**/*\`) and \`reason\` suppress that code for matching files rather than disabling it globally. Add \`expires\` (a date string) to flag the allowance for re-review.",
|
|
56
|
+
text: "## Per-code severity and allow (\`resources.validation\`)\n\nEvery resources finding is a registry code (e.g. \`LINK_BROKEN_FILE\`, \`FRONTMATTER_SCHEMA_ERROR\`, \`EXTERNAL_URL_DEAD\`) with a default severity. Tune them per-code under \`resources.validation\`:\n\n\`\`\`yaml\nresources:\n validation:\n severity:\n EXTERNAL_URL_DEAD: ignore # silence dead external links entirely\n LINK_UNKNOWN: error # promote unclassified links to build-failing\n allow:\n LINK_TO_GITIGNORED: # keyed by code; value is a list of allow entries\n - paths: [\"docs/internal/**\"]\n reason: \"internal-only notes, intentionally gitignored\"\n\`\`\`\n\n\`severity\` accepts \`error | warning | info | ignore\`. External-URL findings default to \`warning\` and never fail the build on their own — promote them to \`error\` here if you want network checks to gate CI. \`allow\` is keyed by code; each entry\'s \`paths\` (glob list, default \`**/*\`) and \`reason\` suppress that code for matching files rather than disabling it globally. Add \`expires\` (a date string) to flag the allowance for re-review."
|
|
57
|
+
},
|
|
53
58
|
annotatingFrontmatterSchemasWithZod4: {
|
|
54
59
|
header: "## Annotating Frontmatter Schemas with Zod 4",
|
|
55
60
|
body: "If your project generates JSON Schemas from Zod (via \`z.toJSONSchema()\`), annotate frontmatter fields that hold links with the appropriate \`format\` so VAT\'s link validator picks them up:\n\n\`\`\`typescript\nimport { z } from \'zod\';\n\nconst PrdFrontmatter = z.object({\n spec_ref: z.string().meta({ format: \'uri-reference\' }), // repo-relative or absolute\n roadmap: z.url().meta({ format: \'uri\' }), // full URL only\n doc_anchor: z.string().meta({ format: \'json-pointer\' }), // JSON Pointer\n});\n\`\`\`\n\n\`format\` values VAT walks for link validation: \`uri\`, \`uri-reference\`, \`iri\`, \`iri-reference\`. \`uri-template\` (RFC 6570) is intentionally NOT walked — templated values contain placeholders.\n\n**Zod 3 users:** \`.meta()\` does not exist in Zod 3. Either upgrade your schema-generation step to Zod 4 (runtime consumers can stay on Zod 3 via peer dependency + common-subset usage), or post-process the generated JSON Schema to inject \`format\` on the relevant field paths.\n\n**Tip:** \`format\` is advisory in JSON Schema; pair it with a \`pattern\` regex when you also need parse-time rejection of invalid inputs.",
|
|
@@ -7,7 +7,7 @@ export const meta = {
|
|
|
7
7
|
description: "Use when setting up \`vat build\`, configuring plugin distribution (marketplace, plugins, managed settings), npm publishing with postinstall hooks, or \`vat verify\` — the full pipeline from skill source to installed plugin."
|
|
8
8
|
};
|
|
9
9
|
|
|
10
|
-
export const text = "\n# VAT Distribution: Build, Publish & Install\n\n## Scope\n\nThis skill covers the **file-based install method for Claude Code CLI** (\`~/.claude/plugins/\`).\nThis is the only install method VAT currently supports.\n\nFor the full install landscape — Claude Desktop paths, enterprise CI deployment,\nAnthropic Cloud org management, MDM integration, and the \`vat plugins uninstall\`\ndesign — see the contributor reference at \`docs/contributing/vat-install-architecture.md\`\nin the \`vibe-agent-toolkit\` repo (contributor material, not bundled with this skill).\n\n## Overview\n\nVAT distributes skills as **Claude plugins** via npm packages. The pipeline:\n\n1. \`vat build\` compiles SKILL.md sources into plugin artifacts\n2. \`npm publish\` pushes the package to a registry\n3. \`npm install\` triggers a postinstall hook that registers the plugin in Claude Code\'s plugin system\n\nSkills installed this way appear in Claude Code as \`/plugin-name:skill-name\`.\n\n## Project Structure\n\n\`\`\`\nmy-project/\n├── package.json ← vat.skills + postinstall hook + publishConfig\n├── vibe-agent-toolkit.config.yaml ← skills: + claude: config\n├── resources/\n│ └── skills/\n│ └── SKILL.md\n└── dist/ ← generated by vat build\n ├── skills/my-skill/ ← packaged skill\n └── .claude/plugins/marketplaces/\n └── my-marketplace/plugins/my-plugin/\n ├── .claude-plugin/plugin.json\n └── skills/my-skill/SKILL.md\n\`\`\`\n\n## Step 1: package.json Configuration\n\n\`\`\`json\n{\n \"name\": \"@myorg/my-skills\",\n \"version\": \"1.0.0\",\n \"vat\": {\n \"version\": \"1.0\",\n \"skills\": [\"my-skill\"]\n },\n \"dependencies\": {\n \"vibe-agent-toolkit\": \"latest\"\n },\n \"scripts\": {\n \"build:vat\": \"vat build\",\n \"postinstall\": \"vat claude plugin install --npm-postinstall 2>/dev/null || exit 0\"\n },\n \"files\": [\"dist\", \"README.md\"],\n \"publishConfig\": {\n \"registry\": \"https://registry.npmjs.org\"\n }\n}\n\`\`\`\n\n**\`vibe-agent-toolkit\` must be in \`dependencies\` (not \`devDependencies\`).** npm adds all \`bin\` entries from runtime dependencies to \`./node_modules/.bin/\` and puts that on PATH when running lifecycle scripts. This is how \`vat\` is available during your postinstall without being globally installed. If it is in \`devDependencies\`, npm will not install it on the user\'s machine and the postinstall will fail with \"command not found\".\n\nThe \`vat.skills\` array contains skill name strings for npm discoverability. Skill source paths and packaging config live in \`vibe-agent-toolkit.config.yaml\` (see Step 2).\n\nFor private GitHub Packages registry:\n\`\`\`json\n\"publishConfig\": {\n \"registry\": \"https://npm.pkg.github.com\",\n \"access\": \"restricted\"\n}\n\`\`\`\n\nUsers (or IT) installing from GitHub Packages need \`.npmrc\` configured with the scope registry and a read-only token:\n\`\`\`\n@myorg:registry=https://npm.pkg.github.com\n//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}\n\`\`\`\n\nIT deploying to managed machines should pre-configure \`.npmrc\` at the system or user level before running install commands. End users do not need to understand npm or the registry — IT handles it once.\n\n## Handling Plugin Renames: vat.replaces\n\n> **Use this only when renaming a plugin, merging plugins, or cleaning up legacy flat-skill installs. Normal upgrades (same plugin name, same skills) do NOT need \`vat.replaces\` — the installer already overwrites the plugin directory on every install.**\n\n### The problem: silent stale skills\n\nWhen you rename a plugin or reorganize skills across packages, the old registration remains in Claude Code. Claude Code **does not warn you** when two plugins provide conflicting skill names — the first-registered (stale) skill silently wins. Users continue loading old content from the renamed plugin unless the old registration is explicitly removed.\n\nThis is the scenario where \`vat.replaces\` is needed:\n- Plugin renamed: \`old-plugin-name\` → \`new-plugin-name\`\n- Two old plugins merged into one new plugin\n- Skills previously installed to \`~/.claude/skills/<name>\` (legacy pre-0.1.20 flat install) now delivered via the plugin tree\n\n### How it works\n\nWhen a VAT package is installed (via postinstall hook or \`--dev\`), the installer reads \`vat.replaces\` from \`package.json\` and — **before** installing the new plugin:\n\n1. For each name in \`replaces.plugins\`: uninstalls \`<name>@<marketplace>\` — removes plugin directory, cache entry, registry entry, and \`settings.json\` entry\n2. For each name in \`replaces.flatSkills\`: deletes \`~/.claude/skills/<name>\` — removes legacy pre-0.1.20 flat installs\n\nBoth operations are idempotent — \"not found\" is handled gracefully.\n\n### Schema\n\n\`\`\`json\n\"vat\": {\n \"version\": \"1.0\",\n \"skills\": [\"authoring\", \"audit\"],\n \"replaces\": {\n \"plugins\": [\"my-old-plugin-name\"],\n \"flatSkills\": [\"my-old-skill\", \"another-old-skill\"]\n }\n}\n\`\`\`\n\nBoth \`plugins\` and \`flatSkills\` are optional arrays. The entire \`replaces\` key is optional — omit it when there is nothing to clean up.\n\n### Real example: vat-development-agents 0.1.21\n\nThis package (\`vat-development-agents\`) renamed its plugin from \`vat-development-agents\` to \`vibe-agent-toolkit\` in v0.1.21. Without \`vat.replaces\`, users who had already installed v0.1.20 would have both \`vat-development-agents@vat-skills\` and \`vibe-agent-toolkit@vat-skills\` registered — Claude Code would serve stale skill content from the old plugin.\n\nThe fix in \`package.json\`:\n\n\`\`\`json\n\"vat\": {\n \"version\": \"1.0\",\n \"skills\": [\"vibe-agent-toolkit\", \"resources\", \"distribution\", \"authoring\", \"audit\", \"debugging\", \"install\"],\n \"replaces\": {\n \"plugins\": [\"vat-development-agents\"],\n \"flatSkills\": [\"vibe-agent-toolkit\", \"resources\"]\n }\n}\n\`\`\`\n\n- \`plugins\`: removes the old plugin registration (same marketplace, old plugin name)\n- \`flatSkills\`: removes legacy \`~/.claude/skills/vibe-agent-toolkit\` and \`~/.claude/skills/resources\` entries from users who installed before 0.1.20 switched to the plugin tree\n\n### Non-obvious gotchas\n\n**1. Plugin names in \`replaces.plugins\` have NO \`@marketplace\`**\n\nThe format is just the plugin name — e.g. \`\"vat-development-agents\"\` — NOT \`\"vat-development-agents@vat-skills\"\`. The installer infers the marketplace from the current package\'s dist tree. Using \`@marketplace\` syntax here would be wrong.\n\n**2. \`replaces.plugins\` is for old plugin registrations, not for skills that moved between plugins**\n\nIf a skill moved from \`plugin-a\` to \`plugin-b\` within the same marketplace, list \`\"plugin-a\"\` in \`replaces.plugins\` to clean up the entire old plugin. You do not manage individual skills — you manage plugins.\n\n**3. \`replaces.flatSkills\` is ONLY for the legacy \`~/.claude/skills/\` location**\n\nThis is specifically for skills that were previously installed as flat files to \`~/.claude/skills/<name>\` (pre-plugin-tree, before v0.1.20). Skills within the plugin tree (under \`~/.claude/plugins/\`) are handled via \`replaces.plugins\`. Do not mix them up.\n\n**4. Normal upgrades need nothing**\n\nIf you publish a new version of the same package with the same plugin name, the installer overwrites the plugin directory automatically. \`vat.replaces\` is only for the case where the old name is different from the new name.\n\n**5. The symptom is subtle and delayed**\n\nYou will not see an error. Claude Code simply loads the first-registered skill with a given name. If the stale plugin is registered first (alphabetically or by install order), your new content is invisible until you remove the old registration.\n\n## Step 2: vibe-agent-toolkit.config.yaml\n\n\`\`\`yaml\nversion: 1\n\nskills:\n include:\n - \"resources/skills/**/SKILL.md\"\n\nclaude:\n marketplaces:\n my-marketplace: # org/publisher identity\n owner:\n name: My Organization\n plugins:\n - name: my-plugin # installable unit\n description: My plugin description\n\`\`\`\n\nThe top-level \`skills:\` section drives standalone skill builds (output: \`dist/skills/\`). The \`claude:\` section defines plugins, which are assembled from their own \`plugins/<name>/\` directories (plugin-local skills under \`plugins/<name>/skills/**/SKILL.md\`). Each marketplace has \`owner\` and \`plugins\` fields (strict schema — no extra fields).\n\n**Naming convention:** marketplace = org identity (e.g. \`acme\`), plugin = this package\n(e.g. \`acme-tools\`). Registers as \`my-plugin@my-marketplace\` in Claude\'s plugin registry.\n\n### Multiple skills in one plugin\n\nList all skills in \`vat.skills\` for npm discoverability:\n\n\`\`\`json\n\"vat\": {\n \"version\": \"1.0\",\n \"skills\": [\"my-linting\", \"my-testing\"]\n}\n\`\`\`\n\nEach skill lives as a subdirectory of the plugin under \`plugins/<name>/skills/<skill>/SKILL.md\`:\n\n\`\`\`\nplugins/my-plugin/\n skills/\n my-linting/SKILL.md\n my-testing/SKILL.md\n\`\`\`\n\nAll plugin-local skills found under \`plugins/<name>/skills/\` are packaged into the plugin automatically — no per-plugin selector is needed or supported. Skill names must be globally unique across all plugins.\n\n## Step 3: Build\n\n\`\`\`bash\nvat build # skills phase then claude phase\nvat verify # validates resources + skills + claude artifacts\n\`\`\`\n\n### What vat build does\n\nTwo phases, run in dependency order:\n\n1. **\`vat skills build\`** — reads \`vibe-agent-toolkit.config.yaml skills:\` section, discovers SKILL.md files via include/exclude globs, compiles each into \`dist/skills/<name>/\`\n2. **\`vat claude plugin build\`** — reads \`vibe-agent-toolkit.config.yaml claude:\` section, wraps built skills into \`dist/.claude/plugins/marketplaces/<mp>/plugins/<plugin>/\` structure with \`.claude-plugin/plugin.json\`. Cleans stale output before each build.\n\nIndividual commands still work:\n\`\`\`bash\nvat skills build # skills phase only\nvat claude plugin build # claude plugin phase only (requires skills already built)\n\`\`\`\n\n## Step 4: Publish\n\n\`\`\`bash\nnpm publish --tag next # RC/pre-release\nnpm publish # stable release\n\`\`\`\n\n## Marketplace Distribution\n\nMarketplace distribution publishes a dedicated branch to GitHub that Claude Code users can install directly — no npm account or registry required.\n\n### How it works\n\n1. \`vat build\` compiles skills and plugin artifacts into \`dist/\`\n2. \`vat claude marketplace publish\` pushes the \`dist/.claude/\` tree to a dedicated branch (e.g. \`claude-marketplace\`) in your GitHub repo\n3. Users install via the slash command: \`/plugin marketplace add owner/repo#claude-marketplace\`\n\n### Configuration\n\nAdd a \`publish\` section under your marketplace in \`vibe-agent-toolkit.config.yaml\`:\n\n\`\`\`yaml\nclaude:\n marketplaces:\n my-marketplace:\n owner:\n name: My Organization\n plugins:\n - name: my-plugin\n description: My plugin description\n publish:\n github:\n repo: owner/repo # GitHub repo to publish to\n branch: claude-marketplace # branch that stores the installable artifacts\n\`\`\`\n\n### Publish workflow\n\n\`\`\`bash\nvat build # build all artifacts first\nvat claude marketplace publish # push dist/.claude/ to the publish branch\nvat claude marketplace publish --dry-run # preview what would be published (no push)\n\`\`\`\n\n### Consumer install\n\nOnce published, users install with:\n\n\`\`\`\n/plugin marketplace add owner/repo#claude-marketplace\n\`\`\`\n\nNo npm, no registry, no token required. Claude Code fetches the branch directly from GitHub.\n\n### Testing locally\n\nAfter publishing, verify the marketplace works end-to-end:\n\n\`\`\`bash\nclaude plugin marketplace add owner/repo#claude-marketplace\nclaude plugin install my-plugin@my-marketplace\nclaude plugin validate ~/.claude/plugins/cache/my-marketplace/my-plugin/<version>\nclaude plugin list # verify status: enabled\n\`\`\`\n\nStart a new Claude Code session to confirm skills load. See the [Marketplace Distribution Guide](https://github.com/jdutton/vibe-agent-toolkit/blob/main/docs/guides/marketplace-distribution.md#testing-your-marketplace) for the full testing checklist and known issues.\n\n**Note (Claude Code v2.1.81):** If re-adding a marketplace with the same name as an existing one (e.g., switching from npm to GitHub source), remove the old marketplace first: \`claude plugin marketplace remove <name>\` then re-add. Otherwise the old source is silently reused.\n\n### Per-plugin versioning (multi-plugin marketplaces)\n\nVAT supports two versioning models for a marketplace:\n\n**Single-version (default for skills-only marketplaces).** No \`version\` is declared on individual plugins. All plugins inherit the root \`package.json:version\`. This is the model used by \`vibe-agent-toolkit\` and \`avonrisk-sdlc\` — the marketplace is treated as one release artifact.\n\n**Per-plugin versioning** (multi-plugin marketplaces with independent release cadences). Each plugin declares its own \`version\`. Recommended when topical plugins under one marketplace evolve on independent timelines (e.g., AvonRiskBuilders\' \`ai-digest\`, \`bank-reconciliation\`).\n\n#### Where to declare a per-plugin version\n\nTwo options, in precedence order:\n\n1. **Marketplace config** (\`vibe-agent-toolkit.config.yaml\`) — most explicit:\n \`\`\`yaml\n claude:\n marketplaces:\n my-marketplace:\n plugins:\n - name: ai-digest\n version: 0.2.0\n skills: \'*\'\n \`\`\`\n2. **Plugin source** (\`plugins/<name>/.claude-plugin/plugin.json:version\`) — most ergonomic for plugin authors:\n \`\`\`json\n { \"name\": \"ai-digest\", \"version\": \"0.2.0\", \"description\": \"...\" }\n \`\`\`\n\nIf both declare a version, marketplace config wins and VAT logs a reconciliation warning. If neither is declared, VAT falls back to the root \`package.json:version\` (single-version model).\n\n#### What \`vat claude marketplace publish\` does for multi-plugin marketplaces\n\nFor each plugin with a resolved version:\n\n- The published \`.claude-plugin/marketplace.json\` includes the per-plugin \`version\` field on each plugin entry.\n- After the publish-branch push succeeds, VAT pushes a \`<plugin>-v<version>\` tag to the **source repo** (not the marketplace branch) — e.g., \`ai-digest-v0.2.0\`. \"Source repo\" means the working directory where you invoke \`vat claude marketplace publish\` (i.e., \`process.cwd()\`); if you invoke from a subdirectory of a worktree, tags land in the containing repo, not the subdirectory. Tag-push failures log a warning but do not roll back the publish.\n- If \`<plugin.source>/CHANGELOG.md\` exists in source (or the marketplace plugin entry\'s \`changelog\` field points to a file), it is bundled into the published marketplace at \`plugins/<name>/CHANGELOG.md\`, alongside the marketplace-level CHANGELOG.\n\nThe marketplace-level CHANGELOG (under \`publish.changelog\` in the config) continues to work unchanged.\n\n#### Default CHANGELOG location\n\nThe default per-plugin CHANGELOG path is \`<plugin.source>/CHANGELOG.md\`, anchored to the entry\'s \`source\` field (default \`plugins/<name>\`). It is NOT assumed to be \`plugins/<name>/CHANGELOG.md\` — if you override \`source\`, the default CHANGELOG path follows.\n\nTo use a non-default path, set the \`changelog\` field on the marketplace plugin entry (relative to the plugin source dir):\n\n\`\`\`yaml\nplugins:\n - name: ai-digest\n source: plugins/ai-digest\n changelog: docs/RELEASES.md\n skills: \'*\'\n\`\`\`\n\n#### Backwards compatibility\n\nMarketplaces with no per-plugin version anywhere are unaffected. The root \`package.json\` version flows through to every plugin, the published \`marketplace.json\` either omits per-plugin \`version\` or includes the same value for all plugins, and tag pushes use the inherited version (e.g., both plugins tagged \`<plugin>-v1.0.0\`).\n\n## Step 5: User Install\n\n### Recommended: npm global install (postinstall runs automatically)\n\n\`\`\`bash\nnpm install -g @myorg/my-skills\n\`\`\`\n\nThe postinstall hook fires automatically and registers the plugin in Claude. This is the correct path for IT-managed deployments — no other tools required on the user\'s machine.\n\n### Developer/IT one-off install via npx\n\n\`\`\`bash\nnpx vibe-agent-toolkit claude plugin install npm:@myorg/my-skills\n\`\`\`\n\nDownloads and runs VAT via npx to install a package without a global install. Useful for CI, scripting, or testing from a developer machine. Requires the npm scope registry to be configured (\`.npmrc\`) if installing from a private registry.\n\n### How plugin installation works\n\nWhen \`npm install\` runs the postinstall hook (\`vat claude plugin install --npm-postinstall\`):\n\n- VAT detects \`dist/.claude/plugins/marketplaces/\` directory in the installed package\n- Copies the plugin tree to Claude\'s plugin directory (dumb recursive copy)\n- Writes to these locations:\n 1. \`~/.claude/plugins/marketplaces/<marketplace>/plugins/<plugin>/\` — plugin files\n 2. \`~/.claude/plugins/known_marketplaces.json\` — marketplace registry\n 3. \`~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/\` — version cache\n 4. \`~/.claude/plugins/installed_plugins.json\` — installation record\n 5. \`~/.claude/settings.json\` \`enabledPlugins\` — activates the plugin\n\nIf no \`dist/.claude/plugins/marketplaces/\` directory exists (package wasn\'t built before publish): a guidance message is emitted and the hook exits 0. The publisher must run \`vat build\` and re-publish.\n\nSkills are then available in Claude Code as \`/plugin-name:skill-name\`.\n\n## managed-settings.json Validation (Enterprise)\n\n\`\`\`yaml\nclaude:\n managedSettings: managed-settings.json\n\`\`\`\n\n\`vat verify\` validates this file against the ManagedSettings schema. Catches typos and schema errors before deployment. Does NOT deploy the file — deployment is a separate concern.\n\n## --target claude-web (ZIP Upload)\n\nFor uploading skills directly to \`claude.ai/settings/capabilities\`:\n\n\`\`\`bash\nvat skills package ./SKILL.md -o ./dist/ --target claude-web\n\`\`\`\n\nProduces a ZIP:\n\`\`\`\nmy-skill.zip\n└── my-skill/\n ├── SKILL.md # skill definition (required)\n ├── scripts/ # executable code (.mjs, .py, .sh) — optional\n ├── references/ # markdown reference material — optional\n └── assets/ # static data, templates, config — optional\n\`\`\`\n\nConfigure source path mappings in \`vibe-agent-toolkit.config.yaml\`:\n\`\`\`yaml\nskills:\n include:\n - \"skills/**/SKILL.md\"\n config:\n my-skill:\n claudeWebTarget:\n scripts: [\"./src/helpers/**/*.ts\"]\n assets: [\"./assets/**\"]\n\`\`\`\n\nTypeScript files in \`scripts\` are tree-shaken and compiled to standalone \`.mjs\`.\n\n## Quick Reference\n\n| Task | Command |\n|---|---|\n| Build everything | \`vat build\` |\n| Verify everything | \`vat verify\` |\n| Build skills only | \`vat skills build\` |\n| Build claude plugin artifacts only | \`vat claude plugin build\` |\n| Install via npm (end user) | \`npm install -g @org/pkg\` |\n| Install via npx (developer/IT) | \`npx vibe-agent-toolkit claude plugin install npm:@org/pkg\` |\n| List installed plugins | \`vat claude plugin list\` |\n| Uninstall a plugin | \`vat claude plugin uninstall --all\` |\n| Package for claude.ai upload | \`vat skills package ./SKILL.md -o ./dist/ --target claude-web\` |\n\n## Running VAT Without Global Install\n\n\`\`\`bash\nnpx vibe-agent-toolkit <command> # npm/Node.js\nbunx vibe-agent-toolkit <command> # Bun\n\`\`\`\n\nAll \`vat\` commands in this skill work with these alternatives.\n\n## Future: Zero-Dependency Postinstall (Option B)\n\nA planned improvement: \`vat build\` would bundle the plugin install logic into \`dist/postinstall.js\` — a fully self-contained script with no npm dependencies. The postinstall script would become simply \`node ./dist/postinstall.js\`. This eliminates \`vibe-agent-toolkit\` as a runtime dependency entirely, reducing install footprint for end users. Until then, Option C (runtime \`vibe-agent-toolkit\` dep) is the correct approach.\n\n## Full-plugin authoring (commands, hooks, agents, MCP)\n\nVAT supports bundling any Claude Code plugin asset — not just skills. Drop the plugin\nunder \`plugins/<name>/\` in the same native layout Claude expects. VAT tree-copies\neverything (minus \`skills/\` and \`.claude-plugin/\`), merges author \`plugin.json\` with\nVAT-owned identity fields, and applies any \`files[]\` mappings for artifacts built\noutside the plugin dir.\n\nSee [docs/guides/marketplace-distribution.md](../../../../docs/guides/marketplace-distribution.md) section \"Full-plugin authoring\".\n";
|
|
10
|
+
export const text = "\n# VAT Distribution: Build, Publish & Install\n\n## Scope\n\nThis skill covers the **file-based install method for Claude Code CLI** (\`~/.claude/plugins/\`).\nThis is the only install method VAT currently supports.\n\nFor the full install landscape — Claude Desktop paths, enterprise CI deployment,\nAnthropic Cloud org management, MDM integration, and the \`vat plugins uninstall\`\ndesign — see the contributor reference at \`docs/contributing/vat-install-architecture.md\`\nin the \`vibe-agent-toolkit\` repo (contributor material, not bundled with this skill).\n\n## Overview\n\nVAT distributes skills as **Claude plugins** via npm packages. The pipeline:\n\n1. \`vat build\` compiles SKILL.md sources into plugin artifacts\n2. \`npm publish\` pushes the package to a registry\n3. \`npm install\` triggers a postinstall hook that registers the plugin in Claude Code\'s plugin system\n\nSkills installed this way appear in Claude Code as \`/plugin-name:skill-name\`.\n\n## Project Structure\n\n\`\`\`\nmy-project/\n├── package.json ← vat.skills + postinstall hook + publishConfig\n├── vibe-agent-toolkit.config.yaml ← skills: + claude: config\n├── resources/\n│ └── skills/\n│ └── SKILL.md\n└── dist/ ← generated by vat build\n ├── skills/my-skill/ ← packaged skill\n └── .claude/plugins/marketplaces/\n └── my-marketplace/plugins/my-plugin/\n ├── .claude-plugin/plugin.json\n └── skills/my-skill/SKILL.md\n\`\`\`\n\n## Step 1: package.json Configuration\n\n\`\`\`json\n{\n \"name\": \"@myorg/my-skills\",\n \"version\": \"1.0.0\",\n \"vat\": {\n \"version\": \"1.0\",\n \"skills\": [\"my-skill\"]\n },\n \"dependencies\": {\n \"vibe-agent-toolkit\": \"latest\"\n },\n \"scripts\": {\n \"build:vat\": \"vat build\",\n \"postinstall\": \"vat claude plugin install --npm-postinstall 2>/dev/null || exit 0\"\n },\n \"files\": [\"dist\", \"README.md\"],\n \"publishConfig\": {\n \"registry\": \"https://registry.npmjs.org\"\n }\n}\n\`\`\`\n\n**\`vibe-agent-toolkit\` must be in \`dependencies\` (not \`devDependencies\`).** npm adds all \`bin\` entries from runtime dependencies to \`./node_modules/.bin/\` and puts that on PATH when running lifecycle scripts. This is how \`vat\` is available during your postinstall without being globally installed. If it is in \`devDependencies\`, npm will not install it on the user\'s machine and the postinstall will fail with \"command not found\".\n\nThe \`vat.skills\` array contains skill name strings for npm discoverability. Skill source paths and packaging config live in \`vibe-agent-toolkit.config.yaml\` (see Step 2).\n\nFor private GitHub Packages registry:\n\`\`\`json\n\"publishConfig\": {\n \"registry\": \"https://npm.pkg.github.com\",\n \"access\": \"restricted\"\n}\n\`\`\`\n\nUsers (or IT) installing from GitHub Packages need \`.npmrc\` configured with the scope registry and a read-only token:\n\`\`\`\n@myorg:registry=https://npm.pkg.github.com\n//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}\n\`\`\`\n\nIT deploying to managed machines should pre-configure \`.npmrc\` at the system or user level before running install commands. End users do not need to understand npm or the registry — IT handles it once.\n\n## Handling Plugin Renames: vat.replaces\n\n> **Use this only when renaming a plugin, merging plugins, or cleaning up legacy flat-skill installs. Normal upgrades (same plugin name, same skills) do NOT need \`vat.replaces\` — the installer already overwrites the plugin directory on every install.**\n\n### The problem: silent stale skills\n\nWhen you rename a plugin or reorganize skills across packages, the old registration remains in Claude Code. Claude Code **does not warn you** when two plugins provide conflicting skill names — the first-registered (stale) skill silently wins. Users continue loading old content from the renamed plugin unless the old registration is explicitly removed.\n\nThis is the scenario where \`vat.replaces\` is needed:\n- Plugin renamed: \`old-plugin-name\` → \`new-plugin-name\`\n- Two old plugins merged into one new plugin\n- Skills previously installed to \`~/.claude/skills/<name>\` (legacy pre-0.1.20 flat install) now delivered via the plugin tree\n\n### How it works\n\nWhen a VAT package is installed (via postinstall hook or \`--dev\`), the installer reads \`vat.replaces\` from \`package.json\` and — **before** installing the new plugin:\n\n1. For each name in \`replaces.plugins\`: uninstalls \`<name>@<marketplace>\` — removes plugin directory, cache entry, registry entry, and \`settings.json\` entry\n2. For each name in \`replaces.flatSkills\`: deletes \`~/.claude/skills/<name>\` — removes legacy pre-0.1.20 flat installs\n\nBoth operations are idempotent — \"not found\" is handled gracefully.\n\n### Schema\n\n\`\`\`json\n\"vat\": {\n \"version\": \"1.0\",\n \"skills\": [\"authoring\", \"audit\"],\n \"replaces\": {\n \"plugins\": [\"my-old-plugin-name\"],\n \"flatSkills\": [\"my-old-skill\", \"another-old-skill\"]\n }\n}\n\`\`\`\n\nBoth \`plugins\` and \`flatSkills\` are optional arrays. The entire \`replaces\` key is optional — omit it when there is nothing to clean up.\n\n### Real example: vat-development-agents 0.1.21\n\nThis package (\`vat-development-agents\`) renamed its plugin from \`vat-development-agents\` to \`vibe-agent-toolkit\` in v0.1.21. Without \`vat.replaces\`, users who had already installed v0.1.20 would have both \`vat-development-agents@vat-skills\` and \`vibe-agent-toolkit@vat-skills\` registered — Claude Code would serve stale skill content from the old plugin.\n\nThe fix in \`package.json\`:\n\n\`\`\`json\n\"vat\": {\n \"version\": \"1.0\",\n \"skills\": [\"vibe-agent-toolkit\", \"resources\", \"distribution\", \"authoring\", \"audit\", \"debugging\", \"install\"],\n \"replaces\": {\n \"plugins\": [\"vat-development-agents\"],\n \"flatSkills\": [\"vibe-agent-toolkit\", \"resources\"]\n }\n}\n\`\`\`\n\n- \`plugins\`: removes the old plugin registration (same marketplace, old plugin name)\n- \`flatSkills\`: removes legacy \`~/.claude/skills/vibe-agent-toolkit\` and \`~/.claude/skills/resources\` entries from users who installed before 0.1.20 switched to the plugin tree\n\n### Non-obvious gotchas\n\n**1. Plugin names in \`replaces.plugins\` have NO \`@marketplace\`**\n\nThe format is just the plugin name — e.g. \`\"vat-development-agents\"\` — NOT \`\"vat-development-agents@vat-skills\"\`. The installer infers the marketplace from the current package\'s dist tree. Using \`@marketplace\` syntax here would be wrong.\n\n**2. \`replaces.plugins\` is for old plugin registrations, not for skills that moved between plugins**\n\nIf a skill moved from \`plugin-a\` to \`plugin-b\` within the same marketplace, list \`\"plugin-a\"\` in \`replaces.plugins\` to clean up the entire old plugin. You do not manage individual skills — you manage plugins.\n\n**3. \`replaces.flatSkills\` is ONLY for the legacy \`~/.claude/skills/\` location**\n\nThis is specifically for skills that were previously installed as flat files to \`~/.claude/skills/<name>\` (pre-plugin-tree, before v0.1.20). Skills within the plugin tree (under \`~/.claude/plugins/\`) are handled via \`replaces.plugins\`. Do not mix them up.\n\n**4. Normal upgrades need nothing**\n\nIf you publish a new version of the same package with the same plugin name, the installer overwrites the plugin directory automatically. \`vat.replaces\` is only for the case where the old name is different from the new name.\n\n**5. The symptom is subtle and delayed**\n\nYou will not see an error. Claude Code simply loads the first-registered skill with a given name. If the stale plugin is registered first (alphabetically or by install order), your new content is invisible until you remove the old registration.\n\n## Step 2: vibe-agent-toolkit.config.yaml\n\n\`\`\`yaml\nversion: 1\n\nskills:\n include:\n - \"resources/skills/**/SKILL.md\"\n\nclaude:\n marketplaces:\n my-marketplace: # org/publisher identity\n owner:\n name: My Organization\n plugins:\n - name: my-plugin # installable unit\n description: My plugin description\n\`\`\`\n\nThe top-level \`skills:\` section drives standalone skill builds (output: \`dist/skills/\`). The \`claude:\` section defines plugins, which are assembled from their own \`plugins/<name>/\` directories (plugin-local skills under \`plugins/<name>/skills/**/SKILL.md\`). Each marketplace has \`owner\` and \`plugins\` fields (strict schema — no extra fields).\n\n**Naming convention:** marketplace = org identity (e.g. \`acme\`), plugin = this package\n(e.g. \`acme-tools\`). Registers as \`my-plugin@my-marketplace\` in Claude\'s plugin registry.\n\n### Multiple skills in one plugin\n\nList all skills in \`vat.skills\` for npm discoverability:\n\n\`\`\`json\n\"vat\": {\n \"version\": \"1.0\",\n \"skills\": [\"my-linting\", \"my-testing\"]\n}\n\`\`\`\n\nEach skill lives as a subdirectory of the plugin under \`plugins/<name>/skills/<skill>/SKILL.md\`:\n\n\`\`\`\nplugins/my-plugin/\n skills/\n my-linting/SKILL.md\n my-testing/SKILL.md\n\`\`\`\n\nAll plugin-local skills found under \`plugins/<name>/skills/\` are packaged into the plugin automatically — no per-plugin selector is needed or supported. Skill names must be globally unique across all plugins.\n\n## Step 3: Build\n\n\`\`\`bash\nvat build # skills phase then claude phase\nvat verify # validates resources + skills + claude artifacts\n\`\`\`\n\n### What vat build does\n\nTwo phases, run in dependency order:\n\n1. **\`vat skills build\`** — reads \`vibe-agent-toolkit.config.yaml skills:\` section, discovers SKILL.md files via include/exclude globs, compiles each into \`dist/skills/<name>/\`\n2. **\`vat claude plugin build\`** — reads \`vibe-agent-toolkit.config.yaml claude:\` section, wraps built skills into \`dist/.claude/plugins/marketplaces/<mp>/plugins/<plugin>/\` structure with \`.claude-plugin/plugin.json\`. Cleans stale output before each build.\n\nIndividual commands still work:\n\`\`\`bash\nvat skills build # skills phase only\nvat claude plugin build # claude plugin phase only (requires skills already built)\n\`\`\`\n\n## Step 4: Publish\n\n\`\`\`bash\nnpm publish --tag next # RC/pre-release\nnpm publish # stable release\n\`\`\`\n\n## Marketplace Distribution\n\nMarketplace distribution publishes a dedicated branch to GitHub that Claude Code users can install directly — no npm account or registry required.\n\n### How it works\n\n1. \`vat build\` compiles skills and plugin artifacts into \`dist/\`\n2. \`vat claude marketplace publish\` pushes the \`dist/.claude/\` tree to a dedicated branch (e.g. \`claude-marketplace\`) in your GitHub repo\n3. Users install via the slash command: \`/plugin marketplace add owner/repo#claude-marketplace\`\n\n### Configuration\n\nAdd a \`publish\` section under your marketplace in \`vibe-agent-toolkit.config.yaml\`:\n\n\`\`\`yaml\nclaude:\n marketplaces:\n my-marketplace:\n owner:\n name: My Organization\n plugins:\n - name: my-plugin\n description: My plugin description\n publish:\n github:\n repo: owner/repo # GitHub repo to publish to\n branch: claude-marketplace # branch that stores the installable artifacts\n\`\`\`\n\n### Publish workflow\n\n\`\`\`bash\nvat build # build all artifacts first\nvat claude marketplace publish # push dist/.claude/ to the publish branch\nvat claude marketplace publish --dry-run # preview what would be published (no push)\n\`\`\`\n\n### Consumer install\n\nOnce published, users install with:\n\n\`\`\`\n/plugin marketplace add owner/repo#claude-marketplace\n\`\`\`\n\nNo npm, no registry, no token required. Claude Code fetches the branch directly from GitHub.\n\n### Testing locally\n\nAfter publishing, verify the marketplace works end-to-end:\n\n\`\`\`bash\nclaude plugin marketplace add owner/repo#claude-marketplace\nclaude plugin install my-plugin@my-marketplace\nclaude plugin validate ~/.claude/plugins/cache/my-marketplace/my-plugin/<version>\nclaude plugin list # verify status: enabled\n\`\`\`\n\nStart a new Claude Code session to confirm skills load. See the [Marketplace Distribution Guide](https://github.com/jdutton/vibe-agent-toolkit/blob/main/docs/guides/marketplace-distribution.md#testing-your-marketplace) for the full testing checklist and known issues.\n\n**Note (Claude Code v2.1.81):** If re-adding a marketplace with the same name as an existing one (e.g., switching from npm to GitHub source), remove the old marketplace first: \`claude plugin marketplace remove <name>\` then re-add. Otherwise the old source is silently reused.\n\n### Per-plugin versioning (multi-plugin marketplaces)\n\nVAT supports two versioning models for a marketplace:\n\n**Single-version (default for skills-only marketplaces).** No \`version\` is declared on individual plugins. All plugins inherit the root \`package.json:version\`. This is the model used by \`vibe-agent-toolkit\` — the marketplace is treated as one release artifact.\n\n**Per-plugin versioning** (multi-plugin marketplaces with independent release cadences). Each plugin declares its own \`version\`. Recommended when topical plugins under one marketplace evolve on independent timelines.\n\n#### Where to declare a per-plugin version\n\nTwo options, in precedence order:\n\n1. **Marketplace config** (\`vibe-agent-toolkit.config.yaml\`) — most explicit:\n \`\`\`yaml\n claude:\n marketplaces:\n my-marketplace:\n plugins:\n - name: ai-digest\n version: 0.2.0\n skills: \'*\'\n \`\`\`\n2. **Plugin source** (\`plugins/<name>/.claude-plugin/plugin.json:version\`) — most ergonomic for plugin authors:\n \`\`\`json\n { \"name\": \"ai-digest\", \"version\": \"0.2.0\", \"description\": \"...\" }\n \`\`\`\n\nIf both declare a version, marketplace config wins and VAT logs a reconciliation warning. If neither is declared, VAT falls back to the root \`package.json:version\` (single-version model).\n\n#### What \`vat claude marketplace publish\` does for multi-plugin marketplaces\n\nFor each plugin with a resolved version:\n\n- The published \`.claude-plugin/marketplace.json\` includes the per-plugin \`version\` field on each plugin entry.\n- If \`<plugin.source>/CHANGELOG.md\` exists in source (or the marketplace plugin entry\'s \`changelog\` field points to a file), it is bundled into the published marketplace at \`plugins/<name>/CHANGELOG.md\`, alongside the marketplace-level CHANGELOG.\n\nThe marketplace-level CHANGELOG (under \`publish.changelog\` in the config) continues to work unchanged.\n\n#### Default CHANGELOG location\n\nThe default per-plugin CHANGELOG path is \`<plugin.source>/CHANGELOG.md\`, anchored to the entry\'s \`source\` field (default \`plugins/<name>\`). It is NOT assumed to be \`plugins/<name>/CHANGELOG.md\` — if you override \`source\`, the default CHANGELOG path follows.\n\nTo use a non-default path, set the \`changelog\` field on the marketplace plugin entry (relative to the plugin source dir):\n\n\`\`\`yaml\nplugins:\n - name: ai-digest\n source: plugins/ai-digest\n changelog: docs/RELEASES.md\n skills: \'*\'\n\`\`\`\n\n#### Backwards compatibility\n\nMarketplaces with no per-plugin version anywhere are unaffected. The root \`package.json\` version flows through to every plugin, and the published \`marketplace.json\` either omits per-plugin \`version\` or includes the same value for all plugins.\n\n## Step 5: User Install\n\n### Recommended: npm global install (postinstall runs automatically)\n\n\`\`\`bash\nnpm install -g @myorg/my-skills\n\`\`\`\n\nThe postinstall hook fires automatically and registers the plugin in Claude. This is the correct path for IT-managed deployments — no other tools required on the user\'s machine.\n\n### Developer/IT one-off install via npx\n\n\`\`\`bash\nnpx vibe-agent-toolkit claude plugin install npm:@myorg/my-skills\n\`\`\`\n\nDownloads and runs VAT via npx to install a package without a global install. Useful for CI, scripting, or testing from a developer machine. Requires the npm scope registry to be configured (\`.npmrc\`) if installing from a private registry.\n\n### How plugin installation works\n\nWhen \`npm install\` runs the postinstall hook (\`vat claude plugin install --npm-postinstall\`):\n\n- VAT detects \`dist/.claude/plugins/marketplaces/\` directory in the installed package\n- Copies the plugin tree to Claude\'s plugin directory (dumb recursive copy)\n- Writes to these locations:\n 1. \`~/.claude/plugins/marketplaces/<marketplace>/plugins/<plugin>/\` — plugin files\n 2. \`~/.claude/plugins/known_marketplaces.json\` — marketplace registry\n 3. \`~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/\` — version cache\n 4. \`~/.claude/plugins/installed_plugins.json\` — installation record\n 5. \`~/.claude/settings.json\` \`enabledPlugins\` — activates the plugin\n\nIf no \`dist/.claude/plugins/marketplaces/\` directory exists (package wasn\'t built before publish): a guidance message is emitted and the hook exits 0. The publisher must run \`vat build\` and re-publish.\n\nSkills are then available in Claude Code as \`/plugin-name:skill-name\`.\n\n## managed-settings.json Validation (Enterprise)\n\n\`\`\`yaml\nclaude:\n managedSettings: managed-settings.json\n\`\`\`\n\n\`vat verify\` validates this file against the ManagedSettings schema. Catches typos and schema errors before deployment. Does NOT deploy the file — deployment is a separate concern.\n\n## --target claude-web (ZIP Upload)\n\nFor uploading skills directly to \`claude.ai/settings/capabilities\`:\n\n\`\`\`bash\nvat skills package ./SKILL.md -o ./dist/ --target claude-web\n\`\`\`\n\nProduces a ZIP:\n\`\`\`\nmy-skill.zip\n└── my-skill/\n ├── SKILL.md # skill definition (required)\n ├── scripts/ # executable code (.mjs, .py, .sh) — optional\n ├── references/ # markdown reference material — optional\n └── assets/ # static data, templates, config — optional\n\`\`\`\n\nConfigure source path mappings in \`vibe-agent-toolkit.config.yaml\`:\n\`\`\`yaml\nskills:\n include:\n - \"skills/**/SKILL.md\"\n config:\n my-skill:\n claudeWebTarget:\n scripts: [\"./src/helpers/**/*.ts\"]\n assets: [\"./assets/**\"]\n\`\`\`\n\nTypeScript files in \`scripts\` are tree-shaken and compiled to standalone \`.mjs\`.\n\n## Quick Reference\n\n| Task | Command |\n|---|---|\n| Build everything | \`vat build\` |\n| Verify everything | \`vat verify\` |\n| Build skills only | \`vat skills build\` |\n| Build claude plugin artifacts only | \`vat claude plugin build\` |\n| Install via npm (end user) | \`npm install -g @org/pkg\` |\n| Install via npx (developer/IT) | \`npx vibe-agent-toolkit claude plugin install npm:@org/pkg\` |\n| List installed plugins | \`vat claude plugin list\` |\n| Uninstall a plugin | \`vat claude plugin uninstall --all\` |\n| Package for claude.ai upload | \`vat skills package ./SKILL.md -o ./dist/ --target claude-web\` |\n\n## Running VAT Without Global Install\n\n\`\`\`bash\nnpx vibe-agent-toolkit <command> # npm/Node.js\nbunx vibe-agent-toolkit <command> # Bun\n\`\`\`\n\nAll \`vat\` commands in this skill work with these alternatives.\n\n## Future: Zero-Dependency Postinstall (Option B)\n\nA planned improvement: \`vat build\` would bundle the plugin install logic into \`dist/postinstall.js\` — a fully self-contained script with no npm dependencies. The postinstall script would become simply \`node ./dist/postinstall.js\`. This eliminates \`vibe-agent-toolkit\` as a runtime dependency entirely, reducing install footprint for end users. Until then, Option C (runtime \`vibe-agent-toolkit\` dep) is the correct approach.\n\n## Full-plugin authoring (commands, hooks, agents, MCP)\n\nVAT supports bundling any Claude Code plugin asset — not just skills. Drop the plugin\nunder \`plugins/<name>/\` in the same native layout Claude expects. VAT tree-copies\neverything (minus \`skills/\` and \`.claude-plugin/\`), merges author \`plugin.json\` with\nVAT-owned identity fields, and applies any \`files[]\` mappings for artifacts built\noutside the plugin dir.\n\nSee [docs/guides/marketplace-distribution.md](../../../../docs/guides/marketplace-distribution.md) section \"Full-plugin authoring\".\n";
|
|
11
11
|
|
|
12
12
|
export const fragments = {
|
|
13
13
|
scope: {
|
|
@@ -52,8 +52,8 @@ export const fragments = {
|
|
|
52
52
|
},
|
|
53
53
|
marketplaceDistribution: {
|
|
54
54
|
header: "## Marketplace Distribution",
|
|
55
|
-
body: "Marketplace distribution publishes a dedicated branch to GitHub that Claude Code users can install directly — no npm account or registry required.\n\n### How it works\n\n1. \`vat build\` compiles skills and plugin artifacts into \`dist/\`\n2. \`vat claude marketplace publish\` pushes the \`dist/.claude/\` tree to a dedicated branch (e.g. \`claude-marketplace\`) in your GitHub repo\n3. Users install via the slash command: \`/plugin marketplace add owner/repo#claude-marketplace\`\n\n### Configuration\n\nAdd a \`publish\` section under your marketplace in \`vibe-agent-toolkit.config.yaml\`:\n\n\`\`\`yaml\nclaude:\n marketplaces:\n my-marketplace:\n owner:\n name: My Organization\n plugins:\n - name: my-plugin\n description: My plugin description\n publish:\n github:\n repo: owner/repo # GitHub repo to publish to\n branch: claude-marketplace # branch that stores the installable artifacts\n\`\`\`\n\n### Publish workflow\n\n\`\`\`bash\nvat build # build all artifacts first\nvat claude marketplace publish # push dist/.claude/ to the publish branch\nvat claude marketplace publish --dry-run # preview what would be published (no push)\n\`\`\`\n\n### Consumer install\n\nOnce published, users install with:\n\n\`\`\`\n/plugin marketplace add owner/repo#claude-marketplace\n\`\`\`\n\nNo npm, no registry, no token required. Claude Code fetches the branch directly from GitHub.\n\n### Testing locally\n\nAfter publishing, verify the marketplace works end-to-end:\n\n\`\`\`bash\nclaude plugin marketplace add owner/repo#claude-marketplace\nclaude plugin install my-plugin@my-marketplace\nclaude plugin validate ~/.claude/plugins/cache/my-marketplace/my-plugin/<version>\nclaude plugin list # verify status: enabled\n\`\`\`\n\nStart a new Claude Code session to confirm skills load. See the [Marketplace Distribution Guide](https://github.com/jdutton/vibe-agent-toolkit/blob/main/docs/guides/marketplace-distribution.md#testing-your-marketplace) for the full testing checklist and known issues.\n\n**Note (Claude Code v2.1.81):** If re-adding a marketplace with the same name as an existing one (e.g., switching from npm to GitHub source), remove the old marketplace first: \`claude plugin marketplace remove <name>\` then re-add. Otherwise the old source is silently reused.\n\n### Per-plugin versioning (multi-plugin marketplaces)\n\nVAT supports two versioning models for a marketplace:\n\n**Single-version (default for skills-only marketplaces).** No \`version\` is declared on individual plugins. All plugins inherit the root \`package.json:version\`. This is the model used by \`vibe-agent-toolkit\`
|
|
56
|
-
text: "## Marketplace Distribution\n\nMarketplace distribution publishes a dedicated branch to GitHub that Claude Code users can install directly — no npm account or registry required.\n\n### How it works\n\n1. \`vat build\` compiles skills and plugin artifacts into \`dist/\`\n2. \`vat claude marketplace publish\` pushes the \`dist/.claude/\` tree to a dedicated branch (e.g. \`claude-marketplace\`) in your GitHub repo\n3. Users install via the slash command: \`/plugin marketplace add owner/repo#claude-marketplace\`\n\n### Configuration\n\nAdd a \`publish\` section under your marketplace in \`vibe-agent-toolkit.config.yaml\`:\n\n\`\`\`yaml\nclaude:\n marketplaces:\n my-marketplace:\n owner:\n name: My Organization\n plugins:\n - name: my-plugin\n description: My plugin description\n publish:\n github:\n repo: owner/repo # GitHub repo to publish to\n branch: claude-marketplace # branch that stores the installable artifacts\n\`\`\`\n\n### Publish workflow\n\n\`\`\`bash\nvat build # build all artifacts first\nvat claude marketplace publish # push dist/.claude/ to the publish branch\nvat claude marketplace publish --dry-run # preview what would be published (no push)\n\`\`\`\n\n### Consumer install\n\nOnce published, users install with:\n\n\`\`\`\n/plugin marketplace add owner/repo#claude-marketplace\n\`\`\`\n\nNo npm, no registry, no token required. Claude Code fetches the branch directly from GitHub.\n\n### Testing locally\n\nAfter publishing, verify the marketplace works end-to-end:\n\n\`\`\`bash\nclaude plugin marketplace add owner/repo#claude-marketplace\nclaude plugin install my-plugin@my-marketplace\nclaude plugin validate ~/.claude/plugins/cache/my-marketplace/my-plugin/<version>\nclaude plugin list # verify status: enabled\n\`\`\`\n\nStart a new Claude Code session to confirm skills load. See the [Marketplace Distribution Guide](https://github.com/jdutton/vibe-agent-toolkit/blob/main/docs/guides/marketplace-distribution.md#testing-your-marketplace) for the full testing checklist and known issues.\n\n**Note (Claude Code v2.1.81):** If re-adding a marketplace with the same name as an existing one (e.g., switching from npm to GitHub source), remove the old marketplace first: \`claude plugin marketplace remove <name>\` then re-add. Otherwise the old source is silently reused.\n\n### Per-plugin versioning (multi-plugin marketplaces)\n\nVAT supports two versioning models for a marketplace:\n\n**Single-version (default for skills-only marketplaces).** No \`version\` is declared on individual plugins. All plugins inherit the root \`package.json:version\`. This is the model used by \`vibe-agent-toolkit\`
|
|
55
|
+
body: "Marketplace distribution publishes a dedicated branch to GitHub that Claude Code users can install directly — no npm account or registry required.\n\n### How it works\n\n1. \`vat build\` compiles skills and plugin artifacts into \`dist/\`\n2. \`vat claude marketplace publish\` pushes the \`dist/.claude/\` tree to a dedicated branch (e.g. \`claude-marketplace\`) in your GitHub repo\n3. Users install via the slash command: \`/plugin marketplace add owner/repo#claude-marketplace\`\n\n### Configuration\n\nAdd a \`publish\` section under your marketplace in \`vibe-agent-toolkit.config.yaml\`:\n\n\`\`\`yaml\nclaude:\n marketplaces:\n my-marketplace:\n owner:\n name: My Organization\n plugins:\n - name: my-plugin\n description: My plugin description\n publish:\n github:\n repo: owner/repo # GitHub repo to publish to\n branch: claude-marketplace # branch that stores the installable artifacts\n\`\`\`\n\n### Publish workflow\n\n\`\`\`bash\nvat build # build all artifacts first\nvat claude marketplace publish # push dist/.claude/ to the publish branch\nvat claude marketplace publish --dry-run # preview what would be published (no push)\n\`\`\`\n\n### Consumer install\n\nOnce published, users install with:\n\n\`\`\`\n/plugin marketplace add owner/repo#claude-marketplace\n\`\`\`\n\nNo npm, no registry, no token required. Claude Code fetches the branch directly from GitHub.\n\n### Testing locally\n\nAfter publishing, verify the marketplace works end-to-end:\n\n\`\`\`bash\nclaude plugin marketplace add owner/repo#claude-marketplace\nclaude plugin install my-plugin@my-marketplace\nclaude plugin validate ~/.claude/plugins/cache/my-marketplace/my-plugin/<version>\nclaude plugin list # verify status: enabled\n\`\`\`\n\nStart a new Claude Code session to confirm skills load. See the [Marketplace Distribution Guide](https://github.com/jdutton/vibe-agent-toolkit/blob/main/docs/guides/marketplace-distribution.md#testing-your-marketplace) for the full testing checklist and known issues.\n\n**Note (Claude Code v2.1.81):** If re-adding a marketplace with the same name as an existing one (e.g., switching from npm to GitHub source), remove the old marketplace first: \`claude plugin marketplace remove <name>\` then re-add. Otherwise the old source is silently reused.\n\n### Per-plugin versioning (multi-plugin marketplaces)\n\nVAT supports two versioning models for a marketplace:\n\n**Single-version (default for skills-only marketplaces).** No \`version\` is declared on individual plugins. All plugins inherit the root \`package.json:version\`. This is the model used by \`vibe-agent-toolkit\` — the marketplace is treated as one release artifact.\n\n**Per-plugin versioning** (multi-plugin marketplaces with independent release cadences). Each plugin declares its own \`version\`. Recommended when topical plugins under one marketplace evolve on independent timelines.\n\n#### Where to declare a per-plugin version\n\nTwo options, in precedence order:\n\n1. **Marketplace config** (\`vibe-agent-toolkit.config.yaml\`) — most explicit:\n \`\`\`yaml\n claude:\n marketplaces:\n my-marketplace:\n plugins:\n - name: ai-digest\n version: 0.2.0\n skills: \'*\'\n \`\`\`\n2. **Plugin source** (\`plugins/<name>/.claude-plugin/plugin.json:version\`) — most ergonomic for plugin authors:\n \`\`\`json\n { \"name\": \"ai-digest\", \"version\": \"0.2.0\", \"description\": \"...\" }\n \`\`\`\n\nIf both declare a version, marketplace config wins and VAT logs a reconciliation warning. If neither is declared, VAT falls back to the root \`package.json:version\` (single-version model).\n\n#### What \`vat claude marketplace publish\` does for multi-plugin marketplaces\n\nFor each plugin with a resolved version:\n\n- The published \`.claude-plugin/marketplace.json\` includes the per-plugin \`version\` field on each plugin entry.\n- If \`<plugin.source>/CHANGELOG.md\` exists in source (or the marketplace plugin entry\'s \`changelog\` field points to a file), it is bundled into the published marketplace at \`plugins/<name>/CHANGELOG.md\`, alongside the marketplace-level CHANGELOG.\n\nThe marketplace-level CHANGELOG (under \`publish.changelog\` in the config) continues to work unchanged.\n\n#### Default CHANGELOG location\n\nThe default per-plugin CHANGELOG path is \`<plugin.source>/CHANGELOG.md\`, anchored to the entry\'s \`source\` field (default \`plugins/<name>\`). It is NOT assumed to be \`plugins/<name>/CHANGELOG.md\` — if you override \`source\`, the default CHANGELOG path follows.\n\nTo use a non-default path, set the \`changelog\` field on the marketplace plugin entry (relative to the plugin source dir):\n\n\`\`\`yaml\nplugins:\n - name: ai-digest\n source: plugins/ai-digest\n changelog: docs/RELEASES.md\n skills: \'*\'\n\`\`\`\n\n#### Backwards compatibility\n\nMarketplaces with no per-plugin version anywhere are unaffected. The root \`package.json\` version flows through to every plugin, and the published \`marketplace.json\` either omits per-plugin \`version\` or includes the same value for all plugins.",
|
|
56
|
+
text: "## Marketplace Distribution\n\nMarketplace distribution publishes a dedicated branch to GitHub that Claude Code users can install directly — no npm account or registry required.\n\n### How it works\n\n1. \`vat build\` compiles skills and plugin artifacts into \`dist/\`\n2. \`vat claude marketplace publish\` pushes the \`dist/.claude/\` tree to a dedicated branch (e.g. \`claude-marketplace\`) in your GitHub repo\n3. Users install via the slash command: \`/plugin marketplace add owner/repo#claude-marketplace\`\n\n### Configuration\n\nAdd a \`publish\` section under your marketplace in \`vibe-agent-toolkit.config.yaml\`:\n\n\`\`\`yaml\nclaude:\n marketplaces:\n my-marketplace:\n owner:\n name: My Organization\n plugins:\n - name: my-plugin\n description: My plugin description\n publish:\n github:\n repo: owner/repo # GitHub repo to publish to\n branch: claude-marketplace # branch that stores the installable artifacts\n\`\`\`\n\n### Publish workflow\n\n\`\`\`bash\nvat build # build all artifacts first\nvat claude marketplace publish # push dist/.claude/ to the publish branch\nvat claude marketplace publish --dry-run # preview what would be published (no push)\n\`\`\`\n\n### Consumer install\n\nOnce published, users install with:\n\n\`\`\`\n/plugin marketplace add owner/repo#claude-marketplace\n\`\`\`\n\nNo npm, no registry, no token required. Claude Code fetches the branch directly from GitHub.\n\n### Testing locally\n\nAfter publishing, verify the marketplace works end-to-end:\n\n\`\`\`bash\nclaude plugin marketplace add owner/repo#claude-marketplace\nclaude plugin install my-plugin@my-marketplace\nclaude plugin validate ~/.claude/plugins/cache/my-marketplace/my-plugin/<version>\nclaude plugin list # verify status: enabled\n\`\`\`\n\nStart a new Claude Code session to confirm skills load. See the [Marketplace Distribution Guide](https://github.com/jdutton/vibe-agent-toolkit/blob/main/docs/guides/marketplace-distribution.md#testing-your-marketplace) for the full testing checklist and known issues.\n\n**Note (Claude Code v2.1.81):** If re-adding a marketplace with the same name as an existing one (e.g., switching from npm to GitHub source), remove the old marketplace first: \`claude plugin marketplace remove <name>\` then re-add. Otherwise the old source is silently reused.\n\n### Per-plugin versioning (multi-plugin marketplaces)\n\nVAT supports two versioning models for a marketplace:\n\n**Single-version (default for skills-only marketplaces).** No \`version\` is declared on individual plugins. All plugins inherit the root \`package.json:version\`. This is the model used by \`vibe-agent-toolkit\` — the marketplace is treated as one release artifact.\n\n**Per-plugin versioning** (multi-plugin marketplaces with independent release cadences). Each plugin declares its own \`version\`. Recommended when topical plugins under one marketplace evolve on independent timelines.\n\n#### Where to declare a per-plugin version\n\nTwo options, in precedence order:\n\n1. **Marketplace config** (\`vibe-agent-toolkit.config.yaml\`) — most explicit:\n \`\`\`yaml\n claude:\n marketplaces:\n my-marketplace:\n plugins:\n - name: ai-digest\n version: 0.2.0\n skills: \'*\'\n \`\`\`\n2. **Plugin source** (\`plugins/<name>/.claude-plugin/plugin.json:version\`) — most ergonomic for plugin authors:\n \`\`\`json\n { \"name\": \"ai-digest\", \"version\": \"0.2.0\", \"description\": \"...\" }\n \`\`\`\n\nIf both declare a version, marketplace config wins and VAT logs a reconciliation warning. If neither is declared, VAT falls back to the root \`package.json:version\` (single-version model).\n\n#### What \`vat claude marketplace publish\` does for multi-plugin marketplaces\n\nFor each plugin with a resolved version:\n\n- The published \`.claude-plugin/marketplace.json\` includes the per-plugin \`version\` field on each plugin entry.\n- If \`<plugin.source>/CHANGELOG.md\` exists in source (or the marketplace plugin entry\'s \`changelog\` field points to a file), it is bundled into the published marketplace at \`plugins/<name>/CHANGELOG.md\`, alongside the marketplace-level CHANGELOG.\n\nThe marketplace-level CHANGELOG (under \`publish.changelog\` in the config) continues to work unchanged.\n\n#### Default CHANGELOG location\n\nThe default per-plugin CHANGELOG path is \`<plugin.source>/CHANGELOG.md\`, anchored to the entry\'s \`source\` field (default \`plugins/<name>\`). It is NOT assumed to be \`plugins/<name>/CHANGELOG.md\` — if you override \`source\`, the default CHANGELOG path follows.\n\nTo use a non-default path, set the \`changelog\` field on the marketplace plugin entry (relative to the plugin source dir):\n\n\`\`\`yaml\nplugins:\n - name: ai-digest\n source: plugins/ai-digest\n changelog: docs/RELEASES.md\n skills: \'*\'\n\`\`\`\n\n#### Backwards compatibility\n\nMarketplaces with no per-plugin version anywhere are unaffected. The root \`package.json\` version flows through to every plugin, and the published \`marketplace.json\` either omits per-plugin \`version\` or includes the same value for all plugins."
|
|
57
57
|
},
|
|
58
58
|
step5UserInstall: {
|
|
59
59
|
header: "## Step 5: User Install",
|
|
@@ -93,6 +93,24 @@ Absolute URLs in URI-reference fields feed into the existing external URL health
|
|
|
93
93
|
|
|
94
94
|
Opt-out: `checkFrontmatterLinks: false` per collection, or `--no-check-frontmatter-links` on the CLI.
|
|
95
95
|
|
|
96
|
+
## Per-code severity and allow (`resources.validation`)
|
|
97
|
+
|
|
98
|
+
Every resources finding is a registry code (e.g. `LINK_BROKEN_FILE`, `FRONTMATTER_SCHEMA_ERROR`, `EXTERNAL_URL_DEAD`) with a default severity. Tune them per-code under `resources.validation`:
|
|
99
|
+
|
|
100
|
+
```yaml
|
|
101
|
+
resources:
|
|
102
|
+
validation:
|
|
103
|
+
severity:
|
|
104
|
+
EXTERNAL_URL_DEAD: ignore # silence dead external links entirely
|
|
105
|
+
LINK_UNKNOWN: error # promote unclassified links to build-failing
|
|
106
|
+
allow:
|
|
107
|
+
LINK_TO_GITIGNORED: # keyed by code; value is a list of allow entries
|
|
108
|
+
- paths: ["docs/internal/**"]
|
|
109
|
+
reason: "internal-only notes, intentionally gitignored"
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`severity` accepts `error | warning | info | ignore`. External-URL findings default to `warning` and never fail the build on their own — promote them to `error` here if you want network checks to gate CI. `allow` is keyed by code; each entry's `paths` (glob list, default `**/*`) and `reason` suppress that code for matching files rather than disabling it globally. Add `expires` (a date string) to flag the allowance for re-review.
|
|
113
|
+
|
|
96
114
|
## Annotating Frontmatter Schemas with Zod 4
|
|
97
115
|
|
|
98
116
|
If your project generates JSON Schemas from Zod (via `z.toJSONSchema()`), annotate frontmatter fields that hold links with the appropriate `format` so VAT's link validator picks them up:
|
|
@@ -307,9 +307,9 @@ Start a new Claude Code session to confirm skills load. See the [Marketplace Dis
|
|
|
307
307
|
|
|
308
308
|
VAT supports two versioning models for a marketplace:
|
|
309
309
|
|
|
310
|
-
**Single-version (default for skills-only marketplaces).** No `version` is declared on individual plugins. All plugins inherit the root `package.json:version`. This is the model used by `vibe-agent-toolkit`
|
|
310
|
+
**Single-version (default for skills-only marketplaces).** No `version` is declared on individual plugins. All plugins inherit the root `package.json:version`. This is the model used by `vibe-agent-toolkit` — the marketplace is treated as one release artifact.
|
|
311
311
|
|
|
312
|
-
**Per-plugin versioning** (multi-plugin marketplaces with independent release cadences). Each plugin declares its own `version`. Recommended when topical plugins under one marketplace evolve on independent timelines
|
|
312
|
+
**Per-plugin versioning** (multi-plugin marketplaces with independent release cadences). Each plugin declares its own `version`. Recommended when topical plugins under one marketplace evolve on independent timelines.
|
|
313
313
|
|
|
314
314
|
#### Where to declare a per-plugin version
|
|
315
315
|
|
|
@@ -337,7 +337,6 @@ If both declare a version, marketplace config wins and VAT logs a reconciliation
|
|
|
337
337
|
For each plugin with a resolved version:
|
|
338
338
|
|
|
339
339
|
- The published `.claude-plugin/marketplace.json` includes the per-plugin `version` field on each plugin entry.
|
|
340
|
-
- After the publish-branch push succeeds, VAT pushes a `<plugin>-v<version>` tag to the **source repo** (not the marketplace branch) — e.g., `ai-digest-v0.2.0`. "Source repo" means the working directory where you invoke `vat claude marketplace publish` (i.e., `process.cwd()`); if you invoke from a subdirectory of a worktree, tags land in the containing repo, not the subdirectory. Tag-push failures log a warning but do not roll back the publish.
|
|
341
340
|
- If `<plugin.source>/CHANGELOG.md` exists in source (or the marketplace plugin entry's `changelog` field points to a file), it is bundled into the published marketplace at `plugins/<name>/CHANGELOG.md`, alongside the marketplace-level CHANGELOG.
|
|
342
341
|
|
|
343
342
|
The marketplace-level CHANGELOG (under `publish.changelog` in the config) continues to work unchanged.
|
|
@@ -358,7 +357,7 @@ plugins:
|
|
|
358
357
|
|
|
359
358
|
#### Backwards compatibility
|
|
360
359
|
|
|
361
|
-
Marketplaces with no per-plugin version anywhere are unaffected. The root `package.json` version flows through to every plugin, the published `marketplace.json` either omits per-plugin `version` or includes the same value for all plugins
|
|
360
|
+
Marketplaces with no per-plugin version anywhere are unaffected. The root `package.json` version flows through to every plugin, and the published `marketplace.json` either omits per-plugin `version` or includes the same value for all plugins.
|
|
362
361
|
|
|
363
362
|
## Step 5: User Install
|
|
364
363
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibe-agent-toolkit/vat-development-agents",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.39-rc.1",
|
|
4
4
|
"description": "VAT development agents - dogfooding the vibe-agent-toolkit",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -67,13 +67,13 @@
|
|
|
67
67
|
"postinstall": "vat claude plugin install --npm-postinstall || exit 0"
|
|
68
68
|
},
|
|
69
69
|
"dependencies": {
|
|
70
|
-
"@vibe-agent-toolkit/agent-schema": "0.1.
|
|
71
|
-
"@vibe-agent-toolkit/cli": "0.1.
|
|
70
|
+
"@vibe-agent-toolkit/agent-schema": "0.1.39-rc.1",
|
|
71
|
+
"@vibe-agent-toolkit/cli": "0.1.39-rc.1",
|
|
72
72
|
"yaml": "^2.8.2"
|
|
73
73
|
},
|
|
74
74
|
"devDependencies": {
|
|
75
75
|
"@types/node": "^25.0.3",
|
|
76
|
-
"@vibe-agent-toolkit/resource-compiler": "0.1.
|
|
76
|
+
"@vibe-agent-toolkit/resource-compiler": "0.1.39-rc.1",
|
|
77
77
|
"ts-patch": "^3.2.1",
|
|
78
78
|
"typescript": "^5.7.3"
|
|
79
79
|
},
|