mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-09-30 12:39:42 +02:00
`.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>
52 lines
2.1 KiB
JavaScript
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 ')}`);
|
|
}
|