mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-02 13:39:41 +02:00
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>
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
#!/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 ')}`);
|
||||
}
|
||||
Reference in New Issue
Block a user