Sitemd release
Stage changelog entries and doc updates between releases, then publish them atomically. Usage: /release [add|sync|bump|status|docs-list|docs-discard|finalize [version]].
git clone https://github.com/sitemd-cc/sitemd
T=$(mktemp -d) && git clone --depth=1 https://github.com/sitemd-cc/sitemd "$T" && mkdir -p ~/.claude/skills && cp -r "$T/.agents/skills/release" ~/.claude/skills/sitemd-cc-sitemd-release && rm -rf "$T"
.agents/skills/release/SKILL.mdRelease
Accumulate a running log of user-impact changes and pending docs updates between releases of your site or product, then publish them atomically when you ship.
The standard flow is: do work → run
/release at the end of the session → repeat → run /release finalize when you're ready to ship the next release.
Storage
All staging state lives at
sitemd/staging/release/ inside the project root. This is an agent-agnostic location — visible to any coding agent without hiding inside .claude/ or .agents/.
sitemd/staging/release/ UNRELEASED.md # running log of bullets for the next release docs-staged/ # mirrors pages/docs/ — pending doc page updates
UNRELEASED.md format:
# Unreleased — targeting v0.1.1 Base: v0.1.0 (commit abc1234, 2026-04-03) ### Added - new feature description in user-impact voice Docs: docs/new-feature.md ### Fixed - bug description --- Pending nav additions: - docs/new-feature.md → group: docs - Overview: #overview - Usage: #usage - Syntax Reference: #syntax-reference --- Last synced: <commit-sha> <iso-timestamp>
Section names mirror whatever style the project's existing changelog page uses. Default fallback: Keep a Changelog conventions (
Added, Changed, Fixed, Removed).
Bullets are written in user-impact voice: present tense, lowercase first word, no trailing period. Internal-only refactors and chores are skipped.
Path discovery
Before doing anything, the skill discovers project conventions:
- Changelog page: glob
and look for any page withpages/**/*.md
in frontmatter. Fall back toslug: /changelog
. If neither exists, ask the user where the changelog should live and offer to create one with a basic template (pages/changelog.md
).# Changelog\n\nA running log of everything shipped.\n - Docs section: check whether
exists. If not, ask the user where docs live, or skip docs staging entirely if the project has none.pages/docs/ - Current version: read the latest
heading from the changelog page to determine the base version. If the changelog has no entries yet, default base to## vX.Y.Z
.v0.0.0
Subcommands
/release
(no args, default — end-of-session ritual)
/releaseFull wrap-up in one command:
-
Scan session work. Sources:
- Files modified during the current agent session
for committed work since the last rungit log <Last synced>..HEAD
marker at the bottom ofLast synced:
is updated after each successful run, preventing double-loggingUNRELEASED.md
-
Draft changelog bullets in user-impact voice, grouped by section, matching the style of the project's existing changelog page. Skip internal-only changes (refactors with no user-visible effect, formatting, comment edits, test-only changes, dev-tooling tweaks).
-
Invoke the
skill in staged mode to draft any docs page updates the session's work warrants. Pass an output-directory override so writes land inwrite
(mirroringsitemd/staging/release/docs-staged/
) instead of the live tree:pages/docs//write docs --output sitemd/staging/release/docs-staged/Existing docs that need edits are first copied to staging, then modified there. If a staged copy already exists from a previous
run, it's edited in place. If the project has no docs section, skip this step./release -
Classify each staged doc as new or updated. For each file in
, check whether the same path exists underdocs-staged/
:pages/docs/- Updated — already in
. Nav entry presumed to exist; finalize won't touch the sidebar.pages/docs/ - New — doesn't exist in
. Will need a sidebar entry inserted at finalize. Read the staged doc's frontmatter (pages/docs/
,groupMember
) and extract itsslug
headings to draft the planned sub-anchor list (## H2
).- {Title}: #{slug-from-title}
- Updated — already in
-
Present the full proposal to the user: new bullets, list of doc files to be created/updated in staging (clearly marking which are new vs updated), the planned sidebar nav additions for new docs (group + sub-anchor list), and the current state of
. Ask for confirmation before writing anything.UNRELEASED.md -
On confirmation: append bullets to
(withUNRELEASED.md
sub-lines linking each bullet to its staged doc files), persist the staged docs, advance theDocs:
marker to the currentLast synced:
SHA + ISO timestamp. Append aHEAD
block at the bottom ofPending nav additions:
(above theUNRELEASED.md
marker) listing each new doc and its planned group + sub-anchors, so the same plan survives across sessions and is auditable viaLast synced:
. If there are no new docs, omit the block./release status -
Print the updated
and a summary of what's now staged, including the count of pending nav additions.UNRELEASED.md
Direct-edit guard: while scanning, if you notice files were edited directly under
pages/docs/ (bypassing staging), warn the user and offer to move them into sitemd/staging/release/docs-staged/.
/release add <description>
/release add <description>Manual append, bypassing session/git scanning. Useful when the user wants to log something specific in their own words. Rewrite the description in changelog voice, infer the appropriate section, and append to
UNRELEASED.md. If the user is logging an internal-only change, push back and skip rather than logging it.
/release sync
/release syncSame as the default but ignores the
Last synced: marker and rebuilds proposed bullets from git log <Base>..HEAD. Recovery path for when the running log has drifted from reality (e.g. work was done without running /release).
/release bump [patch|minor|major]
/release bump [patch|minor|major]Update the target version in the
UNRELEASED.md header. Default patch. Computes the next version from the base version. Does not modify package.json — version bumps to package metadata happen at ship time, not during release planning.
/release status
/release statusRead-only print of
UNRELEASED.md plus a summary: target version, number of bullets per section, number of staged doc files (split into new vs updated), number of pending sidebar nav additions, and number of commits since base.
/release docs-list
/release docs-listShow what's currently in
sitemd/staging/release/docs-staged/, so the user can audit before finalize. Mark each entry as new (no matching file in pages/docs/ — will get a sidebar entry at finalize) or updated (overwrites an existing doc, no nav change). For new entries, also print the planned sub-anchor list parsed from H2 headings.
/release docs-discard <path>
/release docs-discard <path>Remove a single staged doc file without applying it. Path is relative to
docs-staged/.
/release finalize [version]
/release finalize [version]When the user is ready to ship the next release. Optional
version argument (e.g. /release finalize v0.4.2 or /release finalize 0.4.2) overrides the targeting vX.Y.Z header in UNRELEASED.md — useful when an upstream command (like /ship) is authoritative on the version. If omitted, the version is read from the UNRELEASED.md header.
If
UNRELEASED.md has no staged bullets, abort with a message rather than writing an empty section. The caller can decide whether to proceed without finalizing.
-
Read
and format the contents into a newUNRELEASED.md
section, matching the format used by existing entries on the project's changelog page. Use the explicit## vX.Y.Z — <date>
argument if provided, otherwise the header's target version. Use today's date.version -
Prepend the new section to the discovered changelog page, directly under any existing intro / above the previous most-recent version.
-
For every file in
, copy it to its matching path undersitemd/staging/release/docs-staged/
(overwriting). Then emptypages/docs/
.docs-staged/ -
Insert sidebar nav entries for newly-copied docs. Read the
block fromPending nav additions:
(populated during the staging step). For each entry:UNRELEASED.md- Call the
MCP tool to insert the page into its declared group(s) with the staged sub-anchor list. This tool handles the indent-sensitive YAML insitemd_groups_add_pages
correctly — never hand-editgroups.md
directly, because validation hooks may strip entries that don't match expected formatting.groups.md - Insertion order: append to the end of the group's
list. Users can manually reorder later if needed.items:
If the
block is missing (e.g. staging happened in an older version of the skill, or was hand-edited), fall back to the discovery method: for each file copied in step 3, check whether its slug is already inPending nav additions:
; if not, read its frontmatter (settings/groups.md
,groupMember
) and H2 headings, then callslug
as above.sitemd_groups_add_pagesThis step must run after step 3 (the doc copy) — validation hooks reject nav entries pointing at pages that don't yet exist under
.pages/docs/ - Call the
-
Reset
to a fresh template seeded with:UNRELEASED.md
— the next patch bump from the version just releasedtargeting v<next-patch>Base: vX.Y.Z (commit <new-HEAD-sha>, <today>)- Empty section list
- Updated
markerLast synced:
-
Invoke the
skill (deploy
) so the new changelog entry, docs updates, and nav additions go live in a single deploy./deploy -
Print confirmation including the new version, the number of bullets shipped, the number of doc files updated, the number of nav entries inserted, and the deploy result. Does not commit, push, or modify
.package.json
Voice rules
- User-impact voice. Lead with what the user gets or what changed for them, not implementation details.
- Present tense, lowercase first word, no trailing period. Match the style of existing entries on the project's changelog page exactly — read it before writing.
- Skip internal-only changes. Refactors, test-only edits, formatting, build tooling, comment changes, and chores never get logged. If the user explicitly tries to log one via
, push back./release add - One bullet per user-visible change, not one per commit. If a feature took five commits, it's still one bullet.
Rules
- No permission required for read-only subcommands (
,status
). All other subcommands present a proposal and ask for confirmation before writing.docs-list - Never commits, never pushes, never bumps
. This skill stages and publishes content, not version metadata.package.json - Path discovery is mandatory — never hardcode paths. Different projects use different conventions for where the changelog and docs live.
- Idempotent. Running
twice in a row with no work in between should produce no new bullets (the/release
marker prevents double-logging).Last synced: