| name | collect-commits |
| description | Collect commits since the last release tag, parse Conventional Commit prefixes, and return the messages grouped by type (feat, fix, perf, docs, chore, refactor, test, build, ci, style, revert, other). Use this when an agent needs raw release input. Returns a structured markdown summary the calling agent can format further.
|
| user-invocable | true |
Collect commits since the last tag
You are now in collect-commits mode. Your job is to produce a clean,
grouped list of commits ready for a release-notes agent (or a human) to
turn into prose.
Step 1 — Figure out the range
The caller will give you one of:
| Input the caller gave you | What to do |
|---|
| A version string ("v0.3") and a starting tag ("v0.2") | Range is v0.2..HEAD. Confirm both tags exist with git tag --list "v0.2" and "v0.3". |
| Just a version string ("v0.3") | Find the previous tag: git describe --tags --abbrev=0 HEAD^. Range is <prev>..HEAD. |
| A path to a fixture file | Skip git entirely. view the file — each line is already a commit in <shorthash> <subject> form. |
| Nothing | Use git log -n 50 HEAD as a default and tell the caller you picked a 50-commit window. |
Step 2 — Gather the commits
Run one git log invocation:
git log --no-merges --pretty=format:'%h%x09%s' <range>
--no-merges keeps merge commits out (they're never user-visible). The
output is one commit per line: <shorthash><TAB><subject>.
If you were given a fixture file, parse the file in the same shape: one
commit per line, fields separated by whitespace (shorthash first, then
subject).
Step 3 — Parse Conventional Commit prefixes
For each commit subject, extract the prefix using this regex:
^(?<type>feat|fix|perf|docs|chore|refactor|test|build|ci|style|revert)(\([^)]+\))?!?:\s*(?<rest>.+)$
type → the bucket (feat, fix, perf, etc.).
- A
! before the colon means the commit is a breaking change.
- Subjects that don't match the regex go in an
other bucket — they
may still be useful, but they need a human eye.
Step 4 — Group and order
Return a markdown document in exactly this shape:
## Commit summary — <range>
**Total commits:** N (after `--no-merges`)
**Breaking changes:** M (commits with `!:` or `BREAKING CHANGE:` in body)
### feat (N)
- <shorthash> <rest-of-subject>
### fix (N)
- <shorthash> <rest-of-subject>
### perf (N)
- ...
### docs (N)
- ...
### chore (N) ← if 0, omit the whole section
- ...
### refactor (N) ← if 0, omit the whole section
- ...
### test (N) ← if 0, omit the whole section
- ...
### build (N) ← if 0, omit the whole section
- ...
### ci (N) ← if 0, omit the whole section
- ...
### style (N) ← if 0, omit the whole section
- ...
### revert (N) ← if 0, omit the whole section
- ...
### other (N) ← if 0, omit the whole section. Otherwise list everything that didn't match the regex.
- <shorthash> <subject-as-is>
Sections always appear in the order listed above. Empty sections are
omitted entirely. Within each section, preserve the order returned by
git log (newest first).
Step 5 — Flag risk
After the grouped list, append one short paragraph titled
### Heads-up if any of the following are true:
- There are breaking changes (
!: or BREAKING CHANGE: markers).
- There are reverts.
- More than 30 commits in the window (probably worth chunking).
- The
other bucket has more than ~5 entries (suggests inconsistent
prefix discipline; humans should review).
Otherwise omit ### Heads-up entirely.
Output contract
Return only the markdown above. No preamble, no "Here's what I
found", no closing remarks. The calling agent will read your reply
directly and pass it through to the next skill.
Boundaries
- Do not write any files. You read git history (or a fixture) and
return text.
- Do not interpret or rewrite the commit subjects — leave them
verbatim. Rewriting is the release-notes agent's job, not yours.
- If
git log fails (not a git repo, bad range, etc.), report the
exact error and stop. Don't try to recover by changing the range.