
Helmor Release
- 2 installs
- 1.3k repo stars
- Updated August 4, 2026
- dohooo/helmor
Prepare Helmor releases by inspecting the branch, drafting a concise Changesets entry and version bump, and creating pending in-app release announcements.
About
A release-prep skill that turns a branch's real changes into a clean .changeset entry plus an optional .announcements fragment, then offers adjustment options. A developer uses it to decide patch/minor/major, draft release notes, and cut a Helmor release.
- Collects commits and changed files via scripts/collect_release_context.py
- Brevity-biased changeset drafting with a conservative default patch bump
Helmor Release by the numbers
- 2 all-time installs (skills.sh)
- Ranked #199 of 248 Release Management skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/dohooo/helmor --skill helmor-releaseAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 2 |
|---|---|
| repo stars | ★ 1.3k |
| Last updated | August 4, 2026 |
| Repository | dohooo/helmor ↗ |
What it does
Prepare Helmor releases by inspecting the branch, drafting a concise Changesets entry and version bump, and creating pending in-app release announcements.
Files
Helmor Release
Use this skill to turn a branch's real changes into release metadata for Helmor:
- a clean
.changeset/*.mdentry - a pending
.announcements/*.jsonfragment when the change deserves an in-app "New in vX" toast
Workflow
1. Inspect the branch before asking the user anything. 2. Run scripts/collect_release_context.py to gather:
- commits since the base branch
- changed files grouped by area
- a short suggested summary
3. Draft the full changeset yourself, without asking the user upfront. Decide:
- the bump (
patch/minor/major) using the Versioning Guidance below - the body shape — one prose sentence when one sentence is genuinely enough, or summary line + bullets when there are multiple distinct user-visible changes (see Default Changeset Format)
- the actual prose / bullets
Prefer a conservative bump (patch unless there is a clear new user-visible capability). If you genuinely cannot decide the bump from the diff alone, default to patch and flag it in the confirmation step.
Brevity bias. Aim for the shortest sentence that names the user-visible change — if a clause can be dropped without losing meaning, drop it. Reserve summary+bullets for releases with ≥2 distinct user-visible items. 4. Write the changeset to a single file under .changeset/ right away. Do not wait for approval before creating the file — the user will adjust from a real draft, not a hypothetical one. 5. Decide whether an in-app release announcement is warranted.
- Create one pending file under
.announcements/only for new user-visible features or workflow changes. - Skip bug fixes, internal refactors, routine performance work, and release plumbing unless users need to learn a new behavior.
- Do not write an id or version.
bun run release:versionconsumes all pending announcement files and merges them into one catalog entry for the final version.
6. Then, and only then, show the user what you created and offer the adjustment menu described in "Confirmation Style".
Confirmation Style
Do not ask the user anything before the draft is written. Once the changeset file exists, report what you created and offer a short menu of adjustments.
Preferred pattern:
1. State the file path you created. 2. If you created a release announcement fragment, state that file path too. 3. Echo back the chosen bump, the changeset body, and the announcement text if present. 4. Present a numbered menu of the things the user might want to change. The user picks any subset (e.g. "1 and 3") or says nothing / "looks good" to accept. Never phrase this as an open question like "do you approve?".
Example (Shape A — single sentence):
I've written .changeset/brave-otters-smile.md:
bump: patch
body: Fix the context-usage ring resetting to zero when switching the active model.
If you want to adjust anything, tell me which:
1. Version bump (currently: patch — say "make it minor" / "make it major")
2. Rewrite the body
3. Add or revise an in-app release announcement
4. Expand into summary + bullets
5. Add a thanks/credits line
Otherwise we're done — no reply needed.Example (Shape B — multi-change):
I've written .changeset/brave-otters-smile.md:
I've also written .announcements/release-and-updates.json:
bump: minor
summary: Ship a round of release and auto-update improvements:
bullets:
- Add in-app update checks that download updates in the background ...
- Add a signed and notarized macOS release pipeline ...
- Add release planning automation ...
If you want to adjust anything, tell me which:
1. Version bump (currently: minor — say "make it patch" / "make it major")
2. Summary line
3. The bullet list (add / remove / rewrite specific items)
4. In-app announcement text
5. Collapse to a single sentence
6. Add a thanks/credits line
Otherwise we're done — no reply needed.If structured choice tools are unavailable, present the menu in plain text and let the user reply naturally.
Changeset Rules
Write changesets for users, not for maintainers.
Do:
- explain what changed from the user's point of view, as briefly as possible
- use one sentence when one sentence cleanly conveys the change
- use summary line + bullets only when there are multiple distinct user-visible changes
- keep prose / bullets concrete and outcome-focused
- mention new workflows or capabilities
- include a short thanks line only if the user explicitly wants credits
Do not:
- dump commit messages verbatim
- list internal refactors unless they changed release behavior
- mention implementation-only details like exact file names
- create multiple changesets for one coordinated release task unless the user asks
- pad a single-change PR with bullets just to fit the summary+bullets template
- start the changeset body with a
-bullet (see format rule below)
Default Changeset Format
The body has two allowed shapes. Pick the smallest one that fits.
Shape A — single sentence. Use this when one self-contained sentence captures the entire user-visible change. This is the default for most patch-level fixes and small polish PRs. Keep it as short as possible.
Shape B — summary line + bullets. Use this only when there are ≥2 distinct user-visible changes worth enumerating. The first line is a prose summary (usually ending with :); each concrete change is a - sub-item underneath.
@changesets/changelog-github inlines the first line of the body after Thanks @user! - when rendering CHANGELOG.md / GitHub Release. A single prose sentence renders cleanly. A leading - would produce ! - - Fix X with the first item glued to the attribution. Never start the body with `- `.
Decision rule: if you find yourself writing a summary that just restates the one bullet underneath it, collapse to Shape A. If a single sentence would force you to cram multiple ideas with "and"/";", expand to Shape B.
Shape A example (single sentence)
---
"helmor": patch
---
Fix a Chinese IME regression in the composer so pressing Enter to confirm an IME candidate no longer accidentally sends the message.Shape B example (multi-change)
First line is a prose summary ending with :. Bullets start from the next line:
---
"helmor": minor
---
Ship a round of release and auto-update improvements:
- Add in-app update checks that download updates in the background and prompt once the update is ready to install.
- Add a signed and notarized macOS release pipeline for GitHub Releases.
- Add release planning automation so Helmor can publish user-facing release notes through Changesets.This renders cleanly as:
- [#NN] [`hash`] Thanks @user! - Ship a round of release and auto-update improvements:
- Add in-app update checks ...
- Add a signed and notarized macOS release pipeline ...
- Add release planning automation ...If the user wants credits, append a final bullet such as:
- Thanks @username for helping validate the release flow.GitHub Release Notes
Helmor already uses @changesets/changelog-github in .changeset/config.json.
That means:
- merged PRs and GitHub context are handled by Changesets
- GitHub Release body is derived from
CHANGELOG.md - this skill should focus on writing a strong user-facing changeset body
Do not invent a separate release-note format unless the user asks for one.
In-App Release Announcements
Create a pending announcement fragment when the PR adds a user-visible feature or workflow change that users should learn about in the app.
Do:
- write one short, concrete toast item per user-visible capability
- add an action only when there is a useful direct destination
- use a short kebab-case filename under
.announcements/ - keep the JSON shape exactly within the schema below
Do not:
- include
idorreleaseVersion - announce ordinary bug fixes, internal refactors, or routine performance work
- edit
src/features/announcements/release-announcement-catalog.jsonby hand during feature work
Schema:
type PendingReleaseAnnouncement = {
items: Array<{
text: string;
action?: {
label: string;
value:
| { type: "openSettings"; section?: SettingsSection }
| { type: "setRightSidebarMode"; mode: WorkspaceRightSidebarMode };
};
}>;
};Allowed openSettings.section values come from src/features/settings. Allowed setRightSidebarMode.mode values come from WorkspaceRightSidebarMode in src/lib/settings.ts.
Plain text example:
{
"items": [
{
"text": "You can now drag workspaces in the sidebar to keep each section in your preferred order."
}
]
}Action example:
{
"items": [
{
"text": "You can now group workspaces in the sidebar by repository.",
"action": {
"label": "Open General",
"value": { "type": "openSettings", "section": "general" }
}
},
{
"text": "Add Context now supports GitLab too.",
"action": {
"label": "Open Context",
"value": { "type": "setRightSidebarMode", "mode": "context" }
}
}
]
}At release-plan time, bun run release:version consumes every pending fragment, merges all items into one entry for the final package version, and deletes the pending files.
Versioning Guidance
Recommend:
patchfor fixes, polish, and invisible release improvementsminorfor new user-visible features or workflowsmajoronly when behavior changes incompatibly
For Helmor's current early lifecycle, prefer patch or minor. Escalate to major only with a concrete breaking change.
Resources
- Use
scripts/collect_release_context.pyto inspect the current branch before drafting the changeset. - Use
references/release-format.mdif you need the exact Helmor release flow or writing guidance.
Helmor Release Format
Use this reference when preparing a Helmor changeset or walking the user through release prep.
Normal Iteration Flow
1. Finish the feature branch. 2. Add or update one changeset that describes the user-visible outcome. 3. Add a .announcements/*.json fragment when the PR deserves an in-app "New in vX" toast. 4. Push the branch and open the feature PR. 5. Merge the PR into main. 6. Let Release Plan create or update the release PR. It consumes pending announcement fragments into one entry for the final version. 7. Review the generated CHANGELOG.md, version bump, and release announcement catalog entry. 8. Merge the release PR. 9. Run Publish macOS Release when ready to publish the signed build.
What the Changeset Should Capture
Prefer these categories:
- new capability
- changed workflow
- fix or reliability improvement
- release/distribution improvement that matters to users
Avoid these unless the user explicitly asks for them:
- internal refactors
- file renames
- dependency bumps without user impact
- internal docs-only changes
Bump Heuristics
patch: bug fixes, polish, packaging, small workflow fixesminor: new features, new user-visible workflows, notable release improvementsmajor: breaking behavior changes
Writing Style
Good:
- "Add in-app update checks that download updates in the background and prompt once the update is ready to install."
- "Add signed and notarized macOS release publishing through GitHub Releases."
Bad:
- "Refactor updater state machine and reorganize release scripts."
- "Update Cargo.toml, tauri.conf.json, and workflow files."
Body Structure
Pick the smallest shape that fits the change.
Shape A — single sentence. Default for most patch-level fixes and small polish PRs. One self-contained sentence is the entire body.
Shape B — summary line + bullets. Use only when there are ≥2 distinct user-visible changes worth enumerating. A prose summary line (no leading - ) followed by - sub-items.
Decision rule: if the summary would just restate the only bullet underneath, collapse to Shape A. If a single sentence forces "and"/";" cramming, expand to Shape B.
Hard rule for both shapes: never start the body with `- `. @changesets/changelog-github inlines the first line of the body onto the same line as Thanks @user! - when rendering CHANGELOG.md / GitHub Release; a leading - produces ! - - Fix X with the first item glued to the attribution line.
Shape A — single sentence:
Fix a composer IME regression so the caret no longer jumps to the start of the paragraph after an IME buffer is stripped.Shape B — summary line ends with :, bullets follow:
Harden Chinese / Japanese / Korean IME handling in the composer:
- Pressing Enter to confirm a candidate no longer sends the message.
- Segmentation spaces no longer leak when switching IME mid-composition.Credits
If the user wants credits, keep them short and explicit in the body. Example:
- "Thanks @username for helping validate the release flow on macOS."
Do not invent credits automatically.
In-App Announcement Fragments
Use .announcements/*.json for user-visible features or workflow changes that should appear in the compact in-app release toast. Do not include an id or version; release planning binds all pending fragments to the final package version.
Example:
{
"items": [
{
"text": "You can now drag workspaces in the sidebar to keep each section in your preferred order."
}
]
}#!/usr/bin/env python3
import subprocess
import sys
from collections import defaultdict
def run(*args: str) -> str:
result = subprocess.run(
args,
check=True,
capture_output=True,
text=True,
)
return result.stdout.strip()
def try_run(*args: str) -> str:
try:
return run(*args)
except subprocess.CalledProcessError:
return ""
def detect_base() -> str:
for candidate in ("origin/main", "main", "origin/master", "master"):
if try_run("git", "rev-parse", "--verify", candidate):
return candidate
return "HEAD~1"
def group_path(path: str) -> str:
if path.startswith("src-tauri/src/updater/") or path.endswith(
"updater_commands.rs",
):
return "App updater runtime"
if path.startswith(".github/workflows/") or path.startswith("scripts/"):
return "Release automation"
if path.startswith(".changeset/") or path == "CHANGELOG.md":
return "Release notes and versioning"
if path.startswith("src/features/settings/") or path.startswith(
"src/features/updater/",
):
return "Settings and update UI"
if path.startswith("src/") or path.startswith("src-tauri/"):
return "Application code"
if path.startswith("docs/"):
return "Documentation"
if path.startswith("sidecar/"):
return "Sidecar and bundled tooling"
return "Other"
def main() -> int:
branch = run("git", "branch", "--show-current")
base = detect_base()
commits_raw = try_run("git", "log", "--oneline", f"{base}..HEAD")
commits = [line for line in commits_raw.splitlines() if line]
files_raw = try_run("git", "diff", "--name-only", f"{base}...HEAD")
files = [line for line in files_raw.splitlines() if line]
grouped: dict[str, list[str]] = defaultdict(list)
for file_path in files:
grouped[group_path(file_path)].append(file_path)
print(f"Branch: {branch}")
print(f"Base: {base}")
print()
print("Commits:")
if commits:
for commit in commits:
print(f"- {commit}")
else:
print("- No commits ahead of base")
print()
print("Changed areas:")
if grouped:
for area in sorted(grouped):
print(f"- {area}:")
for file_path in grouped[area][:8]:
print(f" - {file_path}")
remaining = len(grouped[area]) - 8
if remaining > 0:
print(f" - ... and {remaining} more")
else:
print("- No changed files")
print()
suggestions = []
if "App updater runtime" in grouped or "Settings and update UI" in grouped:
suggestions.append(
"Add background app-update checks and a ready-to-install prompt.",
)
if "Release automation" in grouped or "Release notes and versioning" in grouped:
suggestions.append(
"Add release automation for signed macOS builds and GitHub Releases.",
)
if "Sidecar and bundled tooling" in grouped:
suggestions.append(
"Improve bundled tooling so packaged releases can pass signing and notarization.",
)
print("Suggested user-facing bullets:")
if suggestions:
for item in suggestions:
print(f"- {item}")
else:
print("- No obvious user-facing bullets detected; inspect commits manually.")
return 0
if __name__ == "__main__":
sys.exit(main())