From cellm
Bump project version and sync across all targets. Auto-discovers VERSION, package.json, plugin.json. Use when: 'bump version', 'bump', 'version bump', 'bump 0.36.0', or /sk-git delegates. NEVER during implement, orchestrate, asclepius, argus, hefesto, arena, or any code work.
How this skill is triggered — by the user, by Claude, or both
Slash command
/cellm:bumpThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
This skill is ONLY activated when:
This skill is ONLY activated when:
/sk-git bump or /sk-git sync delegates bumpThis skill is NEVER activated during:
cellm:implement, cellm:orchestrate, cellm:asclepius, cellm:argus, cellm:hefesto, cellm:arena, cellm:swarmIf unsure whether to activate: do not activate. Ask the user.
Search in order (first found wins):
VERSION file at project root (plain text, trimmed)package.json root -> version field[-] No version source found — ABORT| Argument | Behavior |
|---|---|
(none) / patch | Increment patch: 0.35.94 -> 0.35.95 |
minor | Increment minor, reset patch: 0.35.94 -> 0.36.0 |
major | Increment major, reset minor+patch: 0.35.94 -> 1.0.0 |
x.y.z (explicit) | Set exactly to x.y.z |
x.y.z-tag (pre-release) | Set exactly to x.y.z-tag (e.g. 1.0.0-alpha.1, 0.36.0-rc.1) |
Parse SemVer: MAJOR.MINOR.PATCH or MAJOR.MINOR.PATCH-prerelease. Reject input that does not start with digits in X.Y.Z format.
Auto-discover from project root:
| Target | Detection | Sync Method |
|---|---|---|
VERSION | File exists at root | Write plain text |
package.json (root) | Always exists | JSON: update version field |
**/package.json (workspaces + siblings) | First: read root package.json -> check workspaces array -> Glob each pattern. Second: if no workspaces field, Glob */package.json (direct subdirectories only, exclude node_modules) to find sibling packages like oracle/package.json | JSON: update version field |
**/.claude-plugin/plugin.json | Glob (exclude node_modules) | JSON: update version field |
**/.claude-plugin/marketplace.json | Glob | JSON: Read file, parse JSON, iterate plugins[] array, update each entry's version field individually, write back. Do NOT use replace_all — entries may have different versions for independent sub-plugins. |
VERSION.md | File exists at root | Regex: **Current Version**: X.Y.Z |
CLAUDE.md | File exists at root | Regex: > Version: X.Y.Z |
Then load project-specific targets from ~/.cellm/bump/bump-{project}.json (if exists).
~/.cellm/bump/bump-{project}.json
Project identity detection (try in order until config file found):
basename(cwd) — e.g. cellm-private -> ~/.cellm/bump/bump-cellm-private.jsonpackage.json#name — e.g. cellm -> ~/.cellm/bump/bump-cellm.json{
"project": "cellm-private",
"versionTargets": [
{
"path": "oracle/server/utils/server-state.ts",
"pattern": "version: '{{VERSION}}'",
"type": "regex"
}
]
}
Validation:
project field does not match detected project name: warn and ask confirmationpath values must be relative (no .., no absolute paths). Reject violating paths.type: "json" (update version field) or "regex" (find pattern with {{VERSION}} placeholder, replace)If config file does not exist: use only auto-discovered targets. This is normal for most projects.
Preferred: single Bash call with inline python for atomic execution:
Bash: python3 -c "..." that reads all targets, applies version, reports results
This avoids N sequential Edit tool calls (12+ calls vs 1). The python script should:
Fallback: individual Edit tool calls (when Bash is not available or not permitted):
Write targets in this order:
package.json as source of truth instead. Write package.json first and treat it as the abort-on-fail target.After all writes, verify sync is complete:
scripts/sync-version.sh exists in the project: run bash scripts/sync-version.sh --check-onlySuccess:
[+] Version bumped: 0.35.94 -> 0.35.95
[+] Updated 8 targets:
- VERSION
- package.json
- oracle/package.json
- VERSION.md
- CLAUDE.md
- cellm-plugin/cellm/.claude-plugin/plugin.json
- cellm-plugin/.claude-plugin/marketplace.json
- oracle/server/utils/server-state.ts
[+] Self-validation: all targets in sync
[+] Changelog: 12 conventional + 3 AI = 15 entries generated for v0.35.95
Partial:
[!] Partial sync: VERSION updated to 0.35.95 but 1 target failed:
[-] oracle/server/utils/server-state.ts — pattern not found
[+] 7 targets updated successfully
[+] Run /sk-git check to verify sync status
After bump completes, output:
Next steps (or let /sk-git handle):
git add VERSION package.json [other changed files]
git commit -m "chore(scripts): bump version to X.Y.Z"
git push
The commit message chore(scripts): bump version to X.Y.Z is the recommended format.
The changelog pipeline (getVersionTimeline()) accepts all of these formats:
bump version to X.Y.Z (default, recommended)bump version X.Y.Z -> X.Y.Z (ASCII arrow)bump version X.Y.Z \u2192 X.Y.Z (unicode arrow)bump version X.Y.Z (bare)bump deps + version X.Y.ZDetection regex: bump.*version + last semver extraction from subject.
This step is MANDATORY. Every bump closes a version interval. The skill MUST classify and submit changelog entries before finishing — regardless of how the skill was invoked (direct, /sk-git, or NL request).
Run: git tag --sort=-version:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+' | head -2
The second result is {PREV_TAG} (the tag before the one just created). If no previous tag exists, use the first commit: git rev-list --max-parents=0 HEAD.
Run: git log --oneline {PREV_TAG}..HEAD
Each line has format: {HASH} {SUBJECT}
For each commit, apply the Changelog Entry Classification rules below. Produce a list of classified entries; skip all excluded commits.
Call spec_get_tree with no arguments to list all specs. Filter specs whose status is completed and whose version field matches v{NEW_VERSION}. For each matched spec, produce one entry using the spec-to-changelog mapping rules below.
Call the changelog_submit MCP tool once with all entries:
changelog_submit({
project: "{project}",
version: "v{NEW_VERSION}",
entries: [
{
commitHash: "{HASH}",
category: "added" | "changed" | "fixed",
title: "{entry title}",
component: "{component}" (optional),
breaking: true | false (optional, default false)
},
...
]
})
project: basename(cwd) or package.json#nameversion: v{NEW_VERSION} with leading vchangelog_submit call and report [i] No changelog entries for this version[+] Changelog: {N} entries submitted for v{NEW_VERSION}
If zero entries: [i] No classified commits for this version (bump-only or all excluded by policy)
This is what makes each version release self-documenting.
^(feat|fix|refactor|perf|docs|style|revert)(\(.*\))?!?: (.+)
feat, fix, etc.)(oracle) — used for component inference! before : indicates a breaking change → set breaking: truetitle| Commit type | category |
|---|---|
feat | added |
fix | fixed |
refactor, perf, docs, style, revert | changed |
| (no match / freeform) | changed |
| Rule | Detection |
|---|---|
| Merge commits | Subject starts with Merge or has ^Merge branch |
| Bump commits | Subject matches bump.*version (case-insensitive) |
| Lock file changes | Subject contains lock, yarn.lock, bun.lock, package-lock |
| Bot authors | Author email contains [bot] or [email protected] (check via git log --format="%ae" -1 {HASH}) |
Resolve component in this priority order:
(oracle) → oracle)git show --stat {HASH} | head -20, check changed paths:
oracle/ → oraclecellm-plugin/ → pluginapp/ or server/ → dashboardcellm-core/ → core.claude/ → claudecomponentFor each completed spec matched to v{NEW_VERSION}:
| Spec tag | category |
|---|---|
bugfix, fix, cure | fixed |
feat, feature | added |
| (anything else) | changed |
commitHash: use the spec's id field prefixed with spec- (e.g. spec-b4cd96f3)title: use the spec's title fieldcomponent: use the spec's scope or component field if presentAfter step 9 completes, generate an editorial release summary:
POST http://localhost:{ORACLE_PORT}/api/changelog/release-notes
Body: { "project": "{project}", "version": "v{NEW_VERSION}" }
[!] Oracle offline — release notes skipped.[i] No entries for release notes (version has no classified changes)This step synthesizes the granular changelog entries into a human-readable narrative summary with thematic synthesis, breaking changes, and migration notes.
.. or absolute paths from config — reject and report.MAJOR.MINOR.PATCH).npx claudepluginhub murillodutt/cellm --plugin cellmBumps semantic version (patch/minor/major) atomically, updates CHANGELOG.md with changes summary, syncs across files like package.json/pyproject.toml/Cargo.toml, commits. Use for releases.
Bumps versions in package.json, pyproject.toml, Cargo.toml including nested dirs, updates changelogs, README, and docs for releases. Use after git-workspace-review.
Determines the correct SemVer 2.0.0 version bump by analyzing git history and classifying changes as major, minor, or patch. Use when preparing a release, after merging changes, or resolving version disagreements.