From ddb36c052443255765667d2580cc3ca5c76f783d Mon Sep 17 00:00:00 2001 From: George Lee Date: Sat, 25 Apr 2026 07:28:25 -0700 Subject: [PATCH] fix(version): sync plugin manifests with package.json on version bump The plugin manifests (.claude-plugin/plugin.json, .claude-plugin/marketplace.json) and the MCP server's hardcoded version string have all been frozen at 0.3.0 across the 0.4.0, 0.5.0, 0.5.1, and 0.5.2 releases because only package.json was bumped. Marketplace clients reading the manifest see 0.3.0, and the MCP server registers itself with the SDK as 0.3.0 regardless of the installed version. This change: - Adds scripts/sync-version.ts to make package.json the single source of truth. Reads package.json and writes plugin.json + marketplace.json to match. Supports --check for CI drift detection (non-zero exit on mismatch). - Wires it into the npm/bun "version" lifecycle in package.json so future `bun pm version ` (or `npm version `) syncs all three files into the same auto-generated version commit. No follow-up commit needed. - Replaces the hardcoded "0.3.0" in server/index.ts with an import from package.json using the standard JSON import attribute syntax. - Catches up the manifest files to the current 0.5.2. Signed-off-by: George Lee --- .claude-plugin/marketplace.json | 4 +- .claude-plugin/plugin.json | 2 +- package.json | 4 +- scripts/sync-version.ts | 85 +++++++++++++++++++++++++++++++++ server/index.ts | 3 +- 5 files changed, 93 insertions(+), 5 deletions(-) create mode 100644 scripts/sync-version.ts diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 4493691a..ac263ff9 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -5,14 +5,14 @@ }, "metadata": { "description": "Permanent coding companion for Claude Code (requires bun: https://bun.sh/install)", - "version": "0.3.0" + "version": "0.5.2" }, "plugins": [ { "name": "claude-buddy", "source": "./", "description": "Permanent coding companion for Claude Code \u2014 survives any update. MCP-based terminal pet with ASCII art, stats, reactions, and personality. Requires bun runtime (https://bun.sh/install).", - "version": "0.3.0", + "version": "0.5.2", "author": { "name": "1270011" }, diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 030ca5a9..d5efa96f 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "claude-buddy", - "version": "0.3.0", + "version": "0.5.2", "description": "Permanent coding companion for Claude Code \u2014 survives any update. MCP-based terminal pet with ASCII art, stats, reactions, and personality.", "author": { "name": "1270011" diff --git a/package.json b/package.json index c09d5018..2b00619c 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,9 @@ "tui": "bun run cli/tui.tsx", "test": "bun test", "typecheck": "tsc --noEmit", - "gen:emoji-widths": "bun run scripts/gen-emoji-widths.ts" + "gen:emoji-widths": "bun run scripts/gen-emoji-widths.ts", + "sync-version": "bun run scripts/sync-version.ts", + "version": "bun run sync-version && git add .claude-plugin" }, "files": [ "server/", diff --git a/scripts/sync-version.ts b/scripts/sync-version.ts new file mode 100644 index 00000000..a2fab23b --- /dev/null +++ b/scripts/sync-version.ts @@ -0,0 +1,85 @@ +/** + * Sync version fields across the repo so package.json is the single source of truth. + * + * Run directly: + * bun run sync-version + * + * Wired into npm lifecycle via `"version"` script in package.json so that + * `bun pm version ` (or `npm version ) updates all three files + * together and git-adds them for the auto-generated version commit. + * + * --check: exit non-zero without modifying files if anything is out of sync + * (use this in CI). + */ + +import { readFileSync, writeFileSync } from "fs"; + +const CHECK_ONLY = process.argv.includes("--check"); + +const pkg = JSON.parse(readFileSync("package.json", "utf8")); +const { version } = pkg; +if (typeof version !== "string" || !version) { + console.error("sync-version: package.json is missing a version field"); + process.exit(2); +} + +type Target = { + path: string; + read: () => unknown; + diffs: (doc: any) => { label: string; current: string }[]; + apply: (doc: any) => void; +}; + +const targets: Target[] = [ + { + path: ".claude-plugin/plugin.json", + read: () => JSON.parse(readFileSync(".claude-plugin/plugin.json", "utf8")), + diffs: (doc) => [{ label: "version", current: doc.version }], + apply: (doc) => { + doc.version = version; + }, + }, + { + path: ".claude-plugin/marketplace.json", + read: () => + JSON.parse(readFileSync(".claude-plugin/marketplace.json", "utf8")), + diffs: (doc) => { + const out: { label: string; current: string }[] = [ + { label: "metadata.version", current: doc.metadata?.version }, + ]; + for (let i = 0; i < (doc.plugins?.length ?? 0); i++) { + out.push({ + label: `plugins[${i}].version`, + current: doc.plugins[i].version, + }); + } + return out; + }, + apply: (doc) => { + if (doc.metadata) doc.metadata.version = version; + for (const p of doc.plugins ?? []) p.version = version; + }, + }, +]; + +let drifted = false; +for (const t of targets) { + const doc = t.read(); + const diffs = t.diffs(doc).filter((d) => d.current !== version); + if (diffs.length === 0) continue; + drifted = true; + for (const d of diffs) { + const prefix = CHECK_ONLY ? "DRIFT" : "sync"; + console.log(`${prefix}: ${t.path} :: ${d.label} ${d.current} -> ${version}`); + } + if (!CHECK_ONLY) { + t.apply(doc); + writeFileSync(t.path, JSON.stringify(doc, null, 4) + "\n"); + } +} + +if (CHECK_ONLY && drifted) { + console.error("sync-version: version fields are out of sync with package.json"); + process.exit(1); +} +if (!drifted) console.log(`sync-version: all version fields already at ${version}`); diff --git a/server/index.ts b/server/index.ts index 26098bf7..c5a9939d 100644 --- a/server/index.ts +++ b/server/index.ts @@ -10,6 +10,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { z } from "zod"; import { join, resolve, dirname } from "path"; +import pkg from "../package.json" with { type: "json" }; import { generateBones, @@ -122,7 +123,7 @@ function getInstructions(): string { const server = new McpServer( { name: "claude-buddy", - version: "0.3.0", + version: pkg.version, }, { instructions: getInstructions(),