Files
Codeman/scripts/sync-plugin-version.mjs
T
Codeman maintainer f6c08118dc feat(skill): ship the codeman agent skill as a Claude Code plugin from the repo's own marketplace
`.claude-plugin/marketplace.json` at the repo root makes
`/plugin marketplace add Ark0N/Codeman` work, and the one plugin it lists is
the repo itself (`source: "./"`), whose one component is `skills/codeman/`.
So `/plugin install codeman@codeman` is a third install route next to
`npx skills add` and `codeman skill install`, and the skill shows up in the
plugin directories that index Claude Code marketplaces.

Both manifests carry package.json's version: `scripts/sync-plugin-version.mjs`
rewrites them inside `version-packages`, right after `changeset version`, and
`test/plugin-manifest.test.ts` pins the equality, the skill's frontmatter name
(without it the installed skill would be named after a versioned cache dir),
and that no other plugin component (`commands/`, `agents/`, `hooks/`,
`.mcp.json`, `settings.json`) appears at the repo root, since an install would
silently ship it.

Verified with `claude plugin validate` (one expected warning: CLAUDE.md at a
plugin root is not plugin context) and a local marketplace add, install,
details, uninstall cycle against a clean checkout of this commit.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-14 14:24:35 +02:00

52 lines
2.1 KiB
JavaScript

#!/usr/bin/env node
/**
* @fileoverview Keep the Claude Code plugin manifests in step with package.json.
*
* The repo is its own plugin marketplace (`/plugin marketplace add Ark0N/Codeman`
* reads `.claude-plugin/marketplace.json` from the repo root, and the `codeman`
* plugin it lists is the repo itself, `source: "./"`, whose one skill is
* `skills/codeman/`). Claude Code's `plugin update` only sees a new release when
* the manifest version number changes, so both manifests must carry the version
* `package.json` carries. This runs inside `npm run version-packages`, right after
* `changeset version` bumps package.json, and `test/plugin-manifest.test.ts` pins
* the result so drift fails the gate.
*
* node scripts/sync-plugin-version.mjs rewrite both manifests
* node scripts/sync-plugin-version.mjs --check exit 1 on drift, change nothing
*/
import { readFileSync, writeFileSync } from 'node:fs';
const PLUGIN_NAME = 'codeman';
const MANIFESTS = ['.claude-plugin/plugin.json', '.claude-plugin/marketplace.json'];
const check = process.argv.includes('--check');
const { version } = JSON.parse(readFileSync('package.json', 'utf8'));
let drift = [];
for (const file of MANIFESTS) {
const json = JSON.parse(readFileSync(file, 'utf8'));
const targets = file.endsWith('marketplace.json')
? json.plugins.filter((p) => p.name === PLUGIN_NAME)
: [json];
if (targets.length === 0) {
console.error(`${file}: no plugin entry named "${PLUGIN_NAME}"`);
process.exit(1);
}
for (const target of targets) {
if (target.version !== version) {
drift.push(`${file}: ${target.version} -> ${version}`);
target.version = version;
}
}
if (!check) writeFileSync(file, JSON.stringify(json, null, 2) + '\n');
}
if (drift.length === 0) {
console.log(`plugin manifests already at ${version}`);
} else if (check) {
console.error(`plugin manifest version drift (run: node scripts/sync-plugin-version.mjs):\n ${drift.join('\n ')}`);
process.exit(1);
} else {
console.log(`plugin manifests synced to ${version}:\n ${drift.join('\n ')}`);
}