From 41a047e3282691518ae32d5d08283f615baca050 Mon Sep 17 00:00:00 2001 From: Theo Ephraim Date: Fri, 19 Jun 2026 15:08:08 -0700 Subject: [PATCH 1/3] Refactor skill distribution; remove bumpy ai command Move the canonical add-change agent skill to the repo root (skills/) as a single source of truth, synced into the package on build/prepack (gitignored copy) so it ships version-pinned in the npm tarball and via the Claude Code plugin. Mirrors dmno-dev/varlock#808. Remove the bumpy ai command: its file-copying targets (opencode/cursor/codex) forked the skill into tool-specific dirs that drifted from canonical and were silently broken in the published package, while the claude target just wrapped claude plugin install. Skill is now installed via the plugin or referenced directly from node_modules. --- .bumpy/skill-distribution.md | 9 ++ README.md | 11 +- docs/cli.md | 17 --- packages/bumpy/.gitignore | 2 + packages/bumpy/package.json | 5 +- packages/bumpy/scripts/sync-skill.ts | 27 ++++ packages/bumpy/src/cli.ts | 21 --- packages/bumpy/src/commands/ai.ts | 138 ------------------ .../skills => skills}/add-change/SKILL.md | 0 9 files changed, 47 insertions(+), 183 deletions(-) create mode 100644 .bumpy/skill-distribution.md create mode 100644 packages/bumpy/.gitignore create mode 100644 packages/bumpy/scripts/sync-skill.ts delete mode 100644 packages/bumpy/src/commands/ai.ts rename {packages/bumpy/skills => skills}/add-change/SKILL.md (100%) diff --git a/.bumpy/skill-distribution.md b/.bumpy/skill-distribution.md new file mode 100644 index 0000000..ed3c5c4 --- /dev/null +++ b/.bumpy/skill-distribution.md @@ -0,0 +1,9 @@ +--- +'@varlock/bumpy': patch +--- + +Streamline agent skill distribution and remove the `bumpy ai` command. + +The canonical `add-change` skill now lives at the repo root (`skills/`) as a single source of truth and is synced into the package on `build`/`prepack` (gitignored copy), so it ships version-pinned in the npm tarball and via the Claude Code plugin (`claude plugin install @varlock/bumpy`). + +The `bumpy ai setup` command has been removed. Its file-copying targets (`opencode`, `cursor`, `codex`) duplicated the skill into tool-specific directories that drifted from the canonical copy — and had silently been broken in the published package — while the `claude` target was a thin wrapper around `claude plugin install`. Install the skill via the Claude Code plugin, or reference the bundled `SKILL.md` directly from `node_modules/@varlock/bumpy/skills/add-change/SKILL.md`. diff --git a/README.md b/README.md index 7ea08b1..383a2b0 100644 --- a/README.md +++ b/README.md @@ -102,15 +102,16 @@ bumpy publish # pack and publish, create git tags, push tags, and create GitHu ## AI Integration -Bumpy ships with an AI skill that teaches LLMs how to create bump files. +Bumpy ships with an [agent skill](https://github.com/dmno-dev/bumpy/blob/main/skills/add-change/SKILL.md) that teaches LLMs how to create bump files. + +For Claude Code, install it as a plugin: ```bash -bumpy ai setup --target claude # installs Claude Code plugin -bumpy ai setup --target opencode # creates OpenCode command file -bumpy ai setup --target cursor # creates Cursor rule file -bumpy ai setup --target codex # creates Codex instruction file +claude plugin install @varlock/bumpy ``` +The skill is also bundled in the published npm package, so once bumpy is installed it lives at `node_modules/@varlock/bumpy/skills/add-change/SKILL.md` — version-pinned to your installed bumpy. Agents and tools that support the [SKILL.md](https://github.com/dmno-dev/bumpy/blob/main/skills/add-change/SKILL.md) format can reference it directly. + The skill teaches the AI to examine git changes, identify affected packages, choose bump levels, and create bump files with `bumpy add`. It also instructs the AI to keep existing bump files up to date as work continues on a branch - updating packages, bump levels, and summaries to reflect the final state of changes. ## Documentation diff --git a/docs/cli.md b/docs/cli.md index 7a6045d..7b79741 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -263,20 +263,3 @@ Interactive guide to set up `BUMPY_GH_TOKEN` for CI. Walks through creating a fi ```bash bumpy ci setup ``` - -## `bumpy ai setup` - -Install an AI skill for creating bump files in supported coding tools. - -```bash -bumpy ai setup --target claude -bumpy ai setup --target opencode -bumpy ai setup --target cursor -bumpy ai setup --target codex -``` - -| Flag | Description | -| ----------------- | ------------------------------------------ | -| `--target ` | `claude`, `opencode`, `cursor`, or `codex` | - -For Claude Code, this runs `claude plugin install @varlock/bumpy` under the hood. For other targets, it copies a command/rule file into your project. diff --git a/packages/bumpy/.gitignore b/packages/bumpy/.gitignore new file mode 100644 index 0000000..6a50a20 --- /dev/null +++ b/packages/bumpy/.gitignore @@ -0,0 +1,2 @@ +dist +skills diff --git a/packages/bumpy/package.json b/packages/bumpy/package.json index cd6bfce..47bcc83 100644 --- a/packages/bumpy/package.json +++ b/packages/bumpy/package.json @@ -36,8 +36,9 @@ } }, "scripts": { - "build": "tsdown", - "prepack": "cp ../../README.md .", + "build": "bun run scripts/sync-skill.ts && tsdown", + "prepack": "bun run scripts/sync-skill.ts && cp ../../README.md .", + "sync-skill": "bun run scripts/sync-skill.ts", "check": "bun run tsc --noEmit", "test": "bun test" }, diff --git a/packages/bumpy/scripts/sync-skill.ts b/packages/bumpy/scripts/sync-skill.ts new file mode 100644 index 0000000..964aa5a --- /dev/null +++ b/packages/bumpy/scripts/sync-skill.ts @@ -0,0 +1,27 @@ +/** + * Copies the canonical agent skill from the repo root (`skills/`) into this + * package so it ships inside the published npm tarball. The skill then travels + * with the installed bumpy version, letting agents discover version-pinned + * guidance straight from `node_modules` (no separate install / registry). + * + * The canonical copy lives at the repo root so a single source of truth feeds + * both the npm bundle and any future discovery endpoints. This package copy is + * a generated artifact (gitignored) and is regenerated on every `build` / + * `prepack` / publish. It is also what the Claude Code plugin manifest + * (`.claude-plugin/plugin.json`) ships to agents. + */ +import { existsSync, rmSync, cpSync } from 'node:fs'; +import { resolve } from 'node:path'; + +const PKG_DIR = resolve(import.meta.dir, '..'); +const SRC = resolve(PKG_DIR, '../../skills'); +const DEST = resolve(PKG_DIR, 'skills'); + +if (!existsSync(SRC)) { + throw new Error(`[sync-skill] canonical skills dir not found at ${SRC}`); +} + +rmSync(DEST, { recursive: true, force: true }); +cpSync(SRC, DEST, { recursive: true }); + +console.log(`[sync-skill] copied ${SRC} -> ${DEST}`); diff --git a/packages/bumpy/src/cli.ts b/packages/bumpy/src/cli.ts index 4b55c24..698ea81 100644 --- a/packages/bumpy/src/cli.ts +++ b/packages/bumpy/src/cli.ts @@ -162,23 +162,6 @@ async function main() { break; } - case 'ai': { - const rootDir = await findRoot(); - const subcommand = args[1]; - const aiFlags = parseFlags(args.slice(2)); - - if (subcommand === 'setup') { - const { aiSetupCommand } = await import('./commands/ai.ts'); - await aiSetupCommand(rootDir, { - target: aiFlags.target as string | undefined, - }); - } else { - log.error(`Unknown ai subcommand: ${subcommand}. Use "ai setup".`); - process.exit(1); - } - break; - } - case '--version': case '-v': console.log(`bumpy ${__BUMPY_VERSION__}`); @@ -228,7 +211,6 @@ function printHelp() { ci plan Report what ci release would do (JSON + GitHub Actions outputs) ci release Release — create version PR or auto-publish ci setup Set up a token for triggering CI on version PRs - ai setup Install AI skill for creating bump files Add options: --packages Package bumps (e.g., "pkg-a:minor,pkg-b:patch") @@ -271,9 +253,6 @@ function printHelp() { --tag npm dist-tag for auto-publish --branch Branch name for version PR (default: bumpy/version-packages) - AI setup options: - --target Target AI tool: claude, opencode, cursor, codex - ${colorize('https://bumpy.varlock.dev', 'dim')} `); } diff --git a/packages/bumpy/src/commands/ai.ts b/packages/bumpy/src/commands/ai.ts deleted file mode 100644 index 5edc68c..0000000 --- a/packages/bumpy/src/commands/ai.ts +++ /dev/null @@ -1,138 +0,0 @@ -import { resolve, dirname } from 'node:path'; -import { readFile } from 'node:fs/promises'; -import { fileURLToPath } from 'node:url'; -import { execSync } from 'node:child_process'; -import { ensureDir, exists, writeText } from '../utils/fs.ts'; -import { log } from '../utils/logger.ts'; - -const SUPPORTED_TARGETS = ['claude', 'opencode', 'cursor', 'codex'] as const; -type AiTarget = (typeof SUPPORTED_TARGETS)[number]; - -interface AiSetupOptions { - target?: string; -} - -export async function aiSetupCommand(rootDir: string, opts: AiSetupOptions): Promise { - const target = opts.target as AiTarget | undefined; - - if (!target) { - log.error(`Please specify a target: bumpy ai setup --target <${SUPPORTED_TARGETS.join('|')}>`); - process.exit(1); - } - - if (!SUPPORTED_TARGETS.includes(target)) { - log.error(`Unknown target: "${target}". Supported: ${SUPPORTED_TARGETS.join(', ')}`); - process.exit(1); - } - - if (target === 'claude') { - setupClaude(); - return; - } - - // Read the prompt template bundled with bumpy - const promptContent = await loadPromptTemplate(); - - switch (target) { - case 'opencode': - await setupOpenCode(rootDir, promptContent); - break; - case 'cursor': - await setupCursor(rootDir, promptContent); - break; - case 'codex': - await setupCodex(rootDir, promptContent); - break; - } -} - -async function loadPromptTemplate(): Promise { - // The prompt file is the SKILL.md bundled with the plugin - const thisDir = dirname(fileURLToPath(import.meta.url)); - const promptPath = resolve(thisDir, '../../skills/add-change/SKILL.md'); - const content = await readFile(promptPath, 'utf-8'); - // Strip the YAML frontmatter (skill-specific metadata) - return content.replace(/^---\n[\s\S]*?\n---\n\n?/, ''); -} - -/** Install as a Claude Code plugin */ -function setupClaude(): void { - log.step('Installing Claude Code plugin...'); - try { - execSync('claude plugin install @varlock/bumpy', { stdio: 'inherit' }); - log.success('Installed Claude Code plugin'); - log.dim(' Usage: /bumpy:add-change in Claude Code'); - } catch { - log.error('Failed to install Claude Code plugin. Make sure `claude` is installed and available in your PATH.'); - process.exit(1); - } -} - -/** Install as an OpenCode custom command */ -async function setupOpenCode(rootDir: string, promptContent: string): Promise { - const commandsDir = resolve(rootDir, '.opencode', 'commands'); - const targetPath = resolve(commandsDir, 'add-bumpy-change.md'); - - await ensureDir(commandsDir); - - if (await exists(targetPath)) { - log.warn('.opencode/commands/add-bumpy-change.md already exists — overwriting'); - } - - // OpenCode commands use frontmatter with description - const openCodeContent = `--- -description: Create a bumpy bump file to track package version bumps ---- - -${promptContent}`; - - await writeText(targetPath, openCodeContent); - - log.success('Installed OpenCode command'); - log.dim(' Created .opencode/commands/add-bumpy-change.md'); - log.dim(' Usage: type /add-bumpy-change in OpenCode'); -} - -/** Install as a Cursor rule */ -async function setupCursor(rootDir: string, promptContent: string): Promise { - const rulesDir = resolve(rootDir, '.cursor', 'rules'); - const targetPath = resolve(rulesDir, 'add-bumpy-change.mdc'); - - await ensureDir(rulesDir); - - if (await exists(targetPath)) { - log.warn('.cursor/rules/add-bumpy-change.mdc already exists — overwriting'); - } - - // Cursor rules use .mdc format with frontmatter - const cursorContent = `--- -description: Create a bumpy bump file to track package version bumps -globs: -alwaysApply: false ---- - -${promptContent}`; - - await writeText(targetPath, cursorContent); - - log.success('Installed Cursor rule'); - log.dim(' Created .cursor/rules/add-bumpy-change.mdc'); - log.dim(' The rule will be suggested when relevant, or you can reference it manually'); -} - -/** Install as a Codex instruction */ -async function setupCodex(rootDir: string, promptContent: string): Promise { - const targetPath = resolve(rootDir, '.codex', 'add-bumpy-change.md'); - - await ensureDir(resolve(rootDir, '.codex')); - - if (await exists(targetPath)) { - log.warn('.codex/add-bumpy-change.md already exists — overwriting'); - } - - await writeText(targetPath, promptContent); - - log.success('Installed Codex instruction'); - log.dim(' Created .codex/add-bumpy-change.md'); - log.dim(' Reference this file in your AGENTS.md or pass it as context'); -} diff --git a/packages/bumpy/skills/add-change/SKILL.md b/skills/add-change/SKILL.md similarity index 100% rename from packages/bumpy/skills/add-change/SKILL.md rename to skills/add-change/SKILL.md From 2f85d9e8b1c9e0a48c07b350f85ec1cd97dacd5c Mon Sep 17 00:00:00 2001 From: Theo Ephraim Date: Fri, 19 Jun 2026 21:42:11 -0700 Subject: [PATCH 2/3] Only sync skill on prepack, not build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nothing at build time consumes the package-local skills/ copy now that the ai command is gone — prepack (which fires on npm pack/publish) is sufficient. --- .bumpy/skill-distribution.md | 2 +- packages/bumpy/package.json | 2 +- packages/bumpy/scripts/sync-skill.ts | 7 ++++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.bumpy/skill-distribution.md b/.bumpy/skill-distribution.md index ed3c5c4..39e7b2a 100644 --- a/.bumpy/skill-distribution.md +++ b/.bumpy/skill-distribution.md @@ -4,6 +4,6 @@ Streamline agent skill distribution and remove the `bumpy ai` command. -The canonical `add-change` skill now lives at the repo root (`skills/`) as a single source of truth and is synced into the package on `build`/`prepack` (gitignored copy), so it ships version-pinned in the npm tarball and via the Claude Code plugin (`claude plugin install @varlock/bumpy`). +The canonical `add-change` skill now lives at the repo root (`skills/`) as a single source of truth and is synced into the package on `prepack` (gitignored copy), so it ships version-pinned in the npm tarball and via the Claude Code plugin (`claude plugin install @varlock/bumpy`). The `bumpy ai setup` command has been removed. Its file-copying targets (`opencode`, `cursor`, `codex`) duplicated the skill into tool-specific directories that drifted from the canonical copy — and had silently been broken in the published package — while the `claude` target was a thin wrapper around `claude plugin install`. Install the skill via the Claude Code plugin, or reference the bundled `SKILL.md` directly from `node_modules/@varlock/bumpy/skills/add-change/SKILL.md`. diff --git a/packages/bumpy/package.json b/packages/bumpy/package.json index 47bcc83..08a7325 100644 --- a/packages/bumpy/package.json +++ b/packages/bumpy/package.json @@ -36,7 +36,7 @@ } }, "scripts": { - "build": "bun run scripts/sync-skill.ts && tsdown", + "build": "tsdown", "prepack": "bun run scripts/sync-skill.ts && cp ../../README.md .", "sync-skill": "bun run scripts/sync-skill.ts", "check": "bun run tsc --noEmit", diff --git a/packages/bumpy/scripts/sync-skill.ts b/packages/bumpy/scripts/sync-skill.ts index 964aa5a..be2b8d6 100644 --- a/packages/bumpy/scripts/sync-skill.ts +++ b/packages/bumpy/scripts/sync-skill.ts @@ -6,9 +6,10 @@ * * The canonical copy lives at the repo root so a single source of truth feeds * both the npm bundle and any future discovery endpoints. This package copy is - * a generated artifact (gitignored) and is regenerated on every `build` / - * `prepack` / publish. It is also what the Claude Code plugin manifest - * (`.claude-plugin/plugin.json`) ships to agents. + * a generated artifact (gitignored) and is regenerated on every `prepack` / + * publish (run `bun run sync-skill` to refresh it manually). It is also what + * the Claude Code plugin manifest (`.claude-plugin/plugin.json`) ships to + * agents. */ import { existsSync, rmSync, cpSync } from 'node:fs'; import { resolve } from 'node:path'; From 57761df82581eb25ecbf4aae18954ca2ea726d8d Mon Sep 17 00:00:00 2001 From: Theo Ephraim Date: Fri, 19 Jun 2026 22:30:51 -0700 Subject: [PATCH 3/3] docs: document skill install methods (npx skills, gh skill, plugin, npm) Now that the canonical skill lives at the repo root, npx skills add and gh skill install resolve it. List all install paths in the README. --- README.md | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 383a2b0..9804d58 100644 --- a/README.md +++ b/README.md @@ -102,17 +102,31 @@ bumpy publish # pack and publish, create git tags, push tags, and create GitHu ## AI Integration -Bumpy ships with an [agent skill](https://github.com/dmno-dev/bumpy/blob/main/skills/add-change/SKILL.md) that teaches LLMs how to create bump files. +Bumpy ships with an [agent skill](https://github.com/dmno-dev/bumpy/blob/main/skills/add-change/SKILL.md) that teaches LLMs how to create bump files. It teaches the AI to examine git changes, identify affected packages, choose bump levels, and create bump files with `bumpy add` — and to keep existing bump files up to date as work continues on a branch, updating packages, bump levels, and summaries to reflect the final state of changes. -For Claude Code, install it as a plugin: +### Installing the skill -```bash -claude plugin install @varlock/bumpy -``` +Pick whichever fits your setup: + +- **[`skills`](https://github.com/vercel-labs/skills) (any agent — recommended)** — works with Claude Code, Cursor, OpenCode, Codex, and others: + + ```bash + npx skills add dmno-dev/bumpy # update with: npx skills update + ``` + +- **GitHub CLI** (v2.90+): + + ```bash + gh skill install dmno-dev/bumpy add-change # update with: gh skill update add-change + ``` + +- **Claude Code plugin:** -The skill is also bundled in the published npm package, so once bumpy is installed it lives at `node_modules/@varlock/bumpy/skills/add-change/SKILL.md` — version-pinned to your installed bumpy. Agents and tools that support the [SKILL.md](https://github.com/dmno-dev/bumpy/blob/main/skills/add-change/SKILL.md) format can reference it directly. + ```bash + claude plugin install @varlock/bumpy + ``` -The skill teaches the AI to examine git changes, identify affected packages, choose bump levels, and create bump files with `bumpy add`. It also instructs the AI to keep existing bump files up to date as work continues on a branch - updating packages, bump levels, and summaries to reflect the final state of changes. +- **npm-bundled** — the skill ships inside the published package, so once `@varlock/bumpy` is installed it lives at `node_modules/@varlock/bumpy/skills/add-change/SKILL.md`, version-pinned to your installed bumpy. Point any tool that consumes a `SKILL.md` path at it directly. ## Documentation