| name | release |
| description | Prepare a codegraph release — update CHANGELOG, ROADMAP, BACKLOG, README, create PR |
| argument-hint | [version e.g. 3.1.1] (optional — auto-detects from commits) |
| allowed-tools | Bash, Read, Write, Edit, Glob, Grep, Agent |
Release
You are preparing a release for @optave/codegraph.
Version argument: $ARGUMENTS
- If a version was provided (e.g.
3.1.1), use it as the target version.
- If no version was provided (empty or blank
$ARGUMENTS), you will auto-detect it in Step 1b.
Important: this skill does NOT bump versions. The publish workflow (publish.yml) handles version bumping in package.json, Cargo.toml, package-lock.json, and optionalDependencies atomically — after building native binaries and publishing to npm. Bumping versions in the release PR would cause CI failures because the native prebuilt binary wouldn't exist at the new version yet.
Step 0: Isolate and sync
- Create a worktree — run
/worktree to get an isolated copy of the repo. All subsequent steps run inside the worktree.
- Sync with main — fetch origin and check how far behind the current branch is:
git fetch origin
git rev-list --count HEAD..origin/main
If the count is > 0 (behind main), detach to origin/main so all subsequent work starts from the latest main:
git checkout origin/main
Do not create the release/VERSION branch here — Step 7 creates it once VERSION is known.
Step 1a: Gather context
Run these in parallel:
git log --oneline v<previous-tag>..HEAD — all commits since the last release tag (use git describe --tags --match "v*" --abbrev=0 to find the previous tag)
- Read
CHANGELOG.md (first 80 lines) — understand the format
- Read
package.json — current version
git describe --tags --match "v*" --abbrev=0 — find the previous stable release tag
Step 1b: Determine version (if not provided)
If $ARGUMENTS is empty or blank, determine the semver bump from the commits gathered in Step 1a.
The conventional commit prefix (feat:, fix:, perf:, etc.) is a hint, not the verdict. Contributors frequently use feat(scope): for internal refactors, perf improvements, or extractor/engine accuracy fixes that don't actually add any user-facing feature. The version bump is determined by what users observe, not by the commit prefix.
The real test for a minor bump
A commit only counts as minor if a user running codegraph could observe a genuinely new capability — specifically, one of:
- A new CLI command (new top-level subcommand registered in
cli.ts)
- A new CLI flag on an existing command that unlocks behavior previously unavailable
- A new MCP tool (new entry in the MCP tool list)
- A new output format / field (new JSON schema field, new export format, new column in table output)
- A new configuration option (new
.codegraphrc.json field that changes behavior)
- A new public programmatic API export from
index.ts
Things that are NOT minor bumps even if prefixed feat::
- Extractor/parser accuracy improvements ("resolve named function references", "track class instantiation") — these make existing queries more accurate but add no new CLI surface. Classify as Bug Fixes in the CHANGELOG.
- Native/engine performance refactors ("port X to Rust", "move Y to native") — these are perf improvements. Classify as Performance.
- Internal plumbing changes (build pipeline, DB schema migrations, cache tuning) — patch.
Decision procedure
Scan every commit between the last tag and HEAD. For each feat: or feat(scope): commit:
- Read the PR body (
gh pr view <N> --json title,body) or the commit body
- Ask: does this add a new command, flag, MCP tool, output format, config option, or public API export that didn't exist before?
- If yes → counts toward minor
- If no → treat as patch (and re-categorize in the CHANGELOG: accuracy → Bug Fixes, speed → Performance, internals → Chores)
Apply these rules in priority order:
| Condition | Bump |
|---|
Any commit has a BREAKING CHANGE: / BREAKING-CHANGE: footer, or uses ! suffix (feat!:, fix!:, etc.) | major |
Any feat: commit passes the "real test" above (adds new CLI command/flag/MCP tool/output field/config/public API export) | minor |
Everything else — including feat: commits that are really accuracy fixes, perf refactors, or internal plumbing | patch |
Given the current version MAJOR.MINOR.PATCH from package.json, compute the new version:
- major →
(MAJOR+1).0.0
- minor →
MAJOR.(MINOR+1).0
- patch →
MAJOR.MINOR.(PATCH+1)
Before committing to the bump
When the detection lands on minor, state the specific new CLI surface before proceeding — e.g.:
Detected minor bump. New user-facing surface:
- New CLI command:
codegraph trends (#920)
- New
--architecture flag on codegraph check (#925)
Version: 3.9.3 → 3.10.0
If you cannot name a specific new command/flag/tool/output/config/public API export, the bump is patch, not minor. Example:
Detected patch bump. The feat(js-extractor) commit (#947) is an extractor accuracy improvement — it adds edges but no new CLI surface. The feat(native) commit (#937) is a perf refactor — no new commands or flags. Both belong under Bug Fixes / Performance in the CHANGELOG.
Version: 3.9.3 → 3.9.4
Use the resolved version as VERSION for all subsequent steps.
If $ARGUMENTS was provided, use it directly as VERSION.
Step 2: Update CHANGELOG.md
The CHANGELOG doubles as release notes — it's what users see on the GitHub release page. Write it for humans, not machines.
Add a new section at the top (below the header) following the existing format:
## [X.Y.Z](https://github.com/optave/ops-codegraph-tool/compare/vPREVIOUS...vX.Y.Z) (YYYY-MM-DD)
**One-line summary.** Expanded description of the release highlights — what's new, what's better, what's fixed. This paragraph should tell a user whether they should upgrade and why.
### Features
* **scope:** description ([#PR](url))
### Bug Fixes
* **scope:** description ([#PR](url))
### Performance
* **scope:** description ([#PR](url))
### Refactors
* description ([#PR](url))
### Chores
* **scope:** description ([#PR](url))
Rules:
- Write for users, not developers. Describe what changed from the user's perspective, not the implementation details. "MCP server connects reliably on first attempt" beats "defer heavy imports in MCP server"
- The bold summary paragraph at the top is the most important part — it's the TL;DR that appears in release notifications
- Categorize every commit since the last tag (skip docs-only and benchmark-only commits unless they're notable)
- Use the conventional commit scope as the bold prefix
- Link every PR number
- Include a Performance section if there are performance improvements
- Read previous CHANGELOG entries to match the tone and detail level
Step 3: Update ROADMAP.md
Read docs/roadmap/ROADMAP.md and update:
- Version header — update
Current version: X.Y.Z
- Phase status table — if any phase moved from Planned to In Progress (or completed), update the status column
- Task-level progress — for any roadmap tasks that have been completed or partially completed by commits in this release:
- Add a progress note with version and PR links
- Add checklist items:
- ✅ for done, - 🔲 for remaining
- Check actual code exists (glob/grep for new files/directories mentioned in PRs) before marking tasks complete
Step 4: Update BACKLOG.md
Read docs/roadmap/BACKLOG.md and check if any backlog items were completed or partially completed by commits in this release.
- Backlog items are organized into tiers (1, 1b–1g, 2, 3) with an ID, title, and description per row
- Completed items are marked with strikethrough title (
~~Title~~) and a **DONE** suffix with a description of what was shipped and PR links
- If a feature in this release matches a backlog item:
- Strike through the title:
~~Title~~
- Add
**DONE** — description of what shipped (PR links) at the end of the row
- Check the "Depends on" column of other items — if they depended on the newly completed item, note that they are now unblocked
- Update the
Last updated date at the top of the file
Step 5: Update README.md and repo "about" text
This step runs every release regardless of whether features changed.
README.md
Read README.md and check if any new user-facing features from this release need to be documented:
- Commands table — if a new CLI command was added, add it to the commands section
- MCP tools table — if new MCP tools were added, add them to the AI integration section
- Feature descriptions — if a major new capability was added (new analysis type, new output format, etc.), add it to the relevant section
- Roadmap section — if a phase status changed, update the roadmap summary at the bottom
- Roadmap ordering cross-check — verify the README roadmap list matches
docs/roadmap/ROADMAP.md in phase order, phase names, and phase count. ROADMAP.md is the source of truth. Specifically:
- Extract the phase sequence from both files
- If any phases are reordered, missing, renamed, or merged in README relative to ROADMAP.md, fix README to match
- Completed phases should keep their historical version markers (e.g., "Complete (v3.0.0)")
- This check runs every release, not only when phase status changes — drift accumulates silently
- Version references — only update version-specific references (e.g., install commands). Historical milestone markers like "Complete (v3.0.0)" should stay as-is
- If nothing user-facing changed (pure refactors, bug fixes, internal improvements), no README content update is needed — but still run the roadmap ordering cross-check (item 5)
Repo "about" text
Fetch the current GitHub repository metadata and review whether it still accurately describes the project:
gh api repos/optave/ops-codegraph-tool --jq '{description: .description, homepage: .homepage, topics: .topics}'
Check:
- Description — does the one-line repo description match what codegraph actually is and does today? Update if it's stale, vague, or missing newly supported languages/capabilities.
- Topics/tags — are the labels current? For example, if a new language was added this release, add it. Common topics to keep in sync: language names,
cli, code-analysis, dependency-graph, tree-sitter, sqlite, mcp.
- Homepage — is the URL still correct?
If any field needs updating, apply it directly via the API (no file change needed — this is a GitHub metadata update, not a committed file):
gh api --method PATCH repos/optave/ops-codegraph-tool \
-f description="NEW DESCRIPTION" \
-f homepage="https://..."
gh api --method PUT repos/optave/ops-codegraph-tool/topics \
-f "names[]=cli" -f "names[]=code-analysis" -f "names[]=dependency-graph" -f "names[]=tree-sitter"
Note: "about" text changes are applied directly to GitHub — they don't require a commit. Record any changes made in the PR description so reviewers know what was updated.
Step 6: Verify libc fields in package-lock.json
Some npm versions (notably v11+) silently strip the libc field from Linux entries in package-lock.json. Without libc, npm may install glibc binaries on musl systems (Alpine) and vice versa.
Even though this skill does not bump versions, check that libc fields are present — they can go missing after any npm install run:
grep -A12 'codegraph-linux' package-lock.json | grep -c libc
If the count is less than 3, restore the missing fields in a separate commit:
-gnu packages: "libc": ["glibc"]
-musl packages: "libc": ["musl"]
Place the libc array after the cpu array in each entry.
Step 7: Create branch, commit, push, PR
- Create branch:
git checkout -b release/VERSION (if on detached HEAD from Step 0, this creates the branch at the current commit)
- Stage only the files you changed:
CHANGELOG.md, docs/roadmap/ROADMAP.md, docs/roadmap/BACKLOG.md if changed, README.md if changed, package-lock.json if libc fields were fixed
- Commit:
docs: prepare release notes for vVERSION
- Push:
git push -u origin release/VERSION
- Create PR (include a note if repo "about" text was updated directly on GitHub):
gh pr create --title "docs: prepare release notes for vVERSION" --body "$(cat <<'EOF'
## Summary
- Add CHANGELOG entry for vVERSION (all commits since previous release)
- Update ROADMAP progress
- Review README and repo "about" text for accuracy
- Repo "about" updated: <!-- describe what changed (description / homepage / topics), or "no changes needed" -->
**After merging:** create a GitHub Release with tag `vVERSION` to trigger the publish workflow, which handles version bumping, native binary builds, and npm publishing.
## Test plan
- [ ] CHANGELOG renders correctly on GitHub
- [ ] ROADMAP checklist items match actual codebase state
- [ ] README roadmap order matches ROADMAP.md
- [ ] Repo "about" description and topics are current
EOF
)"
Step 8: Post-merge instructions
After the PR is merged, remind the user:
Next step: Go to GitHub → Releases → "Draft a new release" → tag vVERSION → target main → title vVERSION → auto-generate release notes or paste the CHANGELOG section → Publish.
This triggers the publish workflow which will:
- Build native binaries for all 6 platforms with the correct version
- Publish platform packages and main package to npm
- Push a version bump PR (
package.json, Cargo.toml, package-lock.json) back to main
Important reminders
- No version bumps in this PR — the publish workflow handles
package.json, Cargo.toml, package-lock.json, and optionalDependencies atomically after building native binaries
- No co-author lines in commit messages
- No Claude Code references in commit messages or PR descriptions
- If you find
libc field issues in package-lock.json, fix them in a separate commit with a descriptive message