Moved from the root
CLAUDE.md, which keeps a pointer here. What SemVer covers is defined indocs/versioning-policy.md. The root file's Session Safety rules (branch check, explicit paths, nevergit add -A) apply to every step.
When user says "COM":
-
Determine bump type:
COM= patch (default),COM minor= minor,COM major= major -
Create a changeset file (no interactive prompts). Write a
.mdfile in.changeset/with a random filename:cat > .changeset/$(openssl rand -hex 4).md << 'CHANGESET' --- "aicodeman": patch --- Detailed description of ALL changes since last release (not just the most recent commit — review full git log since last version tag) CHANGESET
Replace
patchwithminorormajoras needed. Include"xterm-zerolag-input": patchon a separate line if that package changed too. -
Consume the changeset:
npm run version-packages(auto-bumpspackage.jsonfiles, updatesCHANGELOG.md, runsnpm install --package-lock-only, and verifies lockfile sync viascripts/check-lockfile-sync.mjs— all in one command; never hand-editCHANGELOG.mdorpackage-lock.jsonversions. It also writessrc/web/public/whats-new.json(scripts/generate-whats-new.mjs): the bold lead-in of each change in the newCHANGELOG.mdsection, which the browser announces once per version in a toast. Commit it with the release;test/whats-new.test.tsfails when its version differs frompackage.json, so a hand bump needsnode scripts/generate-whats-new.mjs && npx prettier --write src/web/public/whats-new.jsontoo. A release whose notes have no bold lead-ins ships an empty list and shows no toast) -
Sync CLAUDE.md version: Update the
**Version**line in the rootCLAUDE.md(under COM Shorthand) to match the new version frompackage.json -
Commit and deploy: verify the branch first (
git branch --show-current), then stage EXPLICIT paths — nevergit add -A, which has swept another session's WIP into a release.git status --shortand account for every line before committing:git add <paths> && git commit -m "chore: version packages" && git push && npm run build && systemctl --user restart codeman-web -
Refresh the getcodeman.com version badge: the landing page's status bar carries the release version (
v<x.y.z> · getcodeman.com · MIT), so it goes stale on every release if nobody bumps it. The site source and its deploy script are maintained outside this repository, on the maintainer's machine only; follow the local site handbook there, which also covers the numbers strip andsitemap.xmlrefresh that belong in the same pass. Poll production (curl -s https://getcodeman.com/ | grep v<x.y.z>) before calling it done, since the edge lags a deploy by up to a minute. Not applicable to contributor clones — skip it and say so. -
Wait for CI: after
git push, TWO workflows fire per master push —CIandRelease(the npm publish + GitHub release). List both runs for the pushed commit withgh run list --commit $(git rev-parse HEAD) --json databaseId,workflowNameand watch EACH withgh run watch <id> --exit-status. Confirm both pass before considering the release done (gh run list -L 1returns only one of the two). -
Publish the new version to the MCP registry:
codeman mcpis listed in the official MCP registry asio.github.Ark0N/codeman, and the registry does not follow npm, so every release is published there by hand or the listing stays on the old version.npm run version-packageshas already written the new version intoconfig/mcp-registry/server.json(scripts/sync-plugin.mjs). Wait until npm serves it (npm view aicodeman version; it can lag the greenReleaserun by several minutes), because the registry checks that the npm package exists and carriesmcpName: io.github.Ark0N/codeman. Then runcd config/mcp-registry && mcp-publisher publish, preceded bymcp-publisher login githubwhen the saved login has expired, signed in as the account that owns theio.github.Ark0N/namespace. Use mcp-publisher 1.8.1 or newer (mcp-publisher --version), the release binary from https://github.com/modelcontextprotocol/registry/releases: the Snap Store package is stuck at 1.1.0 and rejects the current$schemawith a false "deprecated schema detected", so never editserver.jsonfor that error. Older publishers also save their login as.mcpregistry_github_tokenand.mcpregistry_registry_token(live tokens) in the current directory; move those out of the repo, never commit them. Confirm withcurl -s 'https://registry.modelcontextprotocol.io/v0/servers?search=io.github.Ark0N/codeman' | jq -r '.servers[] | "\(.server.version) latest=\(._meta["io.modelcontextprotocol.registry/official"].isLatest)"': the new version must be the one withlatest=true. Maintainer only (it needs that GitHub account); contributor clones skip it and say so. -
Announce it in Discussions: every release gets a post in the Announcements category, shaped like #418 and #302: the short version first (one bold lead-in per theme, features before fixes, what it does for the user rather than how it works), contributor @-mentions inline where their work is described (a mention notifies them, and a contributor reposting is the cheapest reach this project has), a link to the release, and the Thanks names at the end. Casual first-person voice, no em-dashes, humanizer pass when the skill is available. A same-day follow-on patch (1.28.1 after 1.28.0) is folded into the previous post as an edit, never a second thread. Post it with
gh api graphql -F body=@<file> -f title='Codeman <x.y.z>: <hook>' -f repo=R_kgDOQ-SMDg -f cat=DIC_kwDOQ-SMDs4DCHZE -f query='mutation($repo:ID!,$cat:ID!,$title:String!,$body:String!){createDiscussion(input:{repositoryId:$repo,categoryId:$cat,title:$title,body:$body}){discussion{number url}}}'(the repo's node id and its Announcements category id;pinDiscussiondoes not exist in the API, so pinning stays a click in the UI). This step exists because announcements stopped at 1.18 (#302) while ten releases shipped with nobody notified; #418 is the backfill covering 1.19.0 to 1.28.1, and release notes only count as content once they reach a surface people are subscribed to.
CI runs npm run check:lockfile on every push/PR, so lockfile drift fails the build even if the version-packages script is bypassed.