
Commit & Changelog Composer
Commit & Changelog Composer — clean commits, release notes, and the right version bump
Two of the highest-frequency git chores, done right: writing a Conventional Commit message for a change, and turning a batch of merged work into a changelog entry with the correct Semantic Versioning bump. Paste what changed — staged diff, a full diff, or a list of commits/PR titles — and get commit messages, grouped release notes, and a version recommendation with a one-line justification.
It follows the two standards teams actually automate against: the Conventional Commits spec (so tools like semantic-release, commitizen, and git-cliff can read your history) and the Keep a Changelog format (so humans can read your releases).
⚠️ Before you start (please read)
- The output is text you paste into a commit message, a
CHANGELOG.md, or a release note. This skill does not run git, does not commit, tag, or push, and does not connect to any API or hosting service. - It reads only the changes and titles you provide. It never invents a feature, fix, or breaking change that the input does not show. Anything it cannot determine is marked
[FILL IN]. - The version-bump suggestion is a recommendation based on SemVer rules applied to what you pasted, not a guarantee. You decide the final version; the skill explains its reasoning so you can override it.
- No API key, no account, no personal data. Do not paste real secrets or customer data inside a diff — redact first. If the skill sees what looks like a live secret in the input, it stops and asks you to remove it.
What you get
| Output | What it is |
|---|---|
| Conventional Commit message(s) | A properly typed commit: type(scope): summary, an optional body explaining why, and a BREAKING CHANGE: footer when the change warrants it. One commit for a single logical change, or split suggestions if you pasted several unrelated changes. |
| Type + scope classification | Each change mapped to the right type (feat, fix, docs, refactor, perf, test, build, ci, chore, revert) with a scope derived from the touched area. |
| CHANGELOG entry | A Keep a Changelog block grouped into Added / Changed / Fixed / Deprecated / Removed / Security, written as user-facing notes (not raw commit text), with internal-only changes filtered out. |
| SemVer bump + reason | A recommended MAJOR.MINOR.PATCH bump: major for a breaking change, minor for a new backward-compatible feature, patch for a fix — with the one-line reason it chose that level. |
| Release-note summary (optional) | A short human paragraph for a GitHub Release or announcement, if you're cutting a version rather than a single commit. |
How to use
- Choose your input:
- For a commit message: paste
git diff --staged(or a plain diff) for the change you're about to commit. - For a changelog / release: paste the list of merged commit subjects or PR titles since the last release (e.g.
git log v1.3.0..HEAD --oneline), or a diff of the whole range.
- For a commit message: paste
- Paste it here. Optionally add: the current version (so the bump is concrete, e.g.
1.4.2 → ?), the scope naming your project uses, and whether the project already follows Conventional Commits. - Say what you want: commit message, changelog entry, version bump, or all three.
- Read back the output, fix any
[FILL IN], and paste it into your commit /CHANGELOG.md/ release.
How it works (the compose workflow)
Step 1 — Read the changes into a typed model
Parse the input (diff or commit/PR list) and, for each logical change, determine:
- Type — is it a feature, a fix, docs, a refactor, a perf change, tests, tooling/CI, or a chore? Infer from what the code does, not from wording alone.
- Scope — the module/area touched (e.g.
auth,api,parser), derived from file paths. - User-facing? — does this change something a user or a downstream consumer would notice, or is it internal-only (refactor, test, formatting)?
- Breaking? — does it remove or change a public interface, a stored format, or a default value?
If the input is a bare list of subjects with no diff, classify from the subjects and mark anything ambiguous[FILL IN].
Step 2 — Write Conventional Commit message(s)
For each logical change produce type(scope): imperative summary under ~72 characters:
- Summary is imperative and specific ("add retry to upload client", not "updated code").
- Add a body only when the why isn't obvious from the summary; keep it to the reasoning, not a diff restatement.
- Add a
BREAKING CHANGE:footer describing the break and the migration when Step 1 flagged it. - If you pasted several unrelated changes in one diff, recommend splitting them into separate commits and give a message for each — don't cram unrelated work into one commit.
Step 3 — Build the CHANGELOG entry (Keep a Changelog)
Turn the user-facing changes into release notes:
- Group into Added / Changed / Fixed / Deprecated / Removed / Security.
- Rewrite each as a user-facing sentence ("Retries failed uploads up to 3 times"), not the raw commit ("fix: add retry loop").
- Filter out internal-only changes (pure refactors, test-only, formatting, CI) — they don't belong in user-facing notes.
- Put anything that changes behavior for existing users clearly under Changed or Removed, and security-relevant fixes under Security.
Step 4 — Recommend the SemVer bump
Apply the rules to what the changes actually are:
- MAJOR — any breaking change (removed/changed public API, changed default, incompatible format).
- MINOR — at least one new backward-compatible feature, no breaking change.
- PATCH — only fixes and internal changes, nothing new and nothing breaking.
State the resulting version (using the current version if you gave one) and the one-line reason. If pre-1.0.0 semantics apply, note that a "breaking" change may only warrant a minor bump under0.y.z.
Step 5 — Optional release-note paragraph
If you're cutting a release, add a short, honest human summary of the headline changes — no hype, no invented benefits, just what shipped.
Conventional Commit type reference (used in Step 2)
| Type | Use for | Affects version |
|---|---|---|
feat |
A new capability for users | MINOR (or MAJOR if breaking) |
fix |
A bug fix | PATCH |
perf |
A performance improvement | PATCH (or MINOR if it adds behavior) |
refactor |
Internal restructure, no behavior change | none (internal) |
docs |
Documentation only | none |
test |
Adding or fixing tests | none |
build / ci |
Build system or pipeline | none |
chore |
Maintenance, deps housekeeping | none (deps that affect users → note them) |
revert |
Reverts a previous commit | depends on what was reverted |
A BREAKING CHANGE: footer (or a ! after the type/scope) forces a MAJOR bump regardless of type.
Guardrails (this skill's own behavior)
- Uses only the pasted changes and titles. It never invents a feature, fix, or breaking change the input doesn't support — unknowns are
[FILL IN]. - Does not run git or touch the repo. Output is text for the human to place into a commit, changelog, or release.
- The version bump is a SemVer-based recommendation with its reasoning shown, not a decision made for you; you can override it.
- Keeps user-facing notes honest: no hype, no invented benefits, and internal-only churn is filtered out of the changelog rather than dressed up.
- Requests no personal data and no live credentials. If the input appears to contain a real secret, the skill stops and asks for redaction before composing.
- If the input is too thin to classify (e.g. an empty diff or a single vague subject line), it asks for more detail instead of guessing a type, scope, or bump.


