| name | conventional-commits |
| description | Construct a valid Conventional Commits message for this repo before running `git commit`, covering type/scope, the "!" breaking-change marker, description rules, and the required trailing beads issue id. Use whenever writing or reviewing a commit message, or when a commit is rejected by the commit-msg/beads-commit-msg hooks. |
Conventional Commits
Scope
Owns constructing a single-line commit subject that passes this repo's commit-msg and
beads-commit-msg git hooks on the first attempt.
It is not for:
- Deciding whether to commit, what to stage, or how to split a diff (see
tool-git).
- Creating or managing beads issues (see
tool-br); this skill only covers referencing
an existing id in the message.
- Body/footer content — the hooks here only validate the subject line.
Inputs
- The change being committed (already staged, or about to be).
- An existing (or just-created) beads issue id — see
tool-br to resolve or create one.
Outputs
- A single commit subject line that passes
commit-msg.py and beads-commit-msg.py on
the first attempt, with no --no-verify needed.
Format
type(scope)!: description (issue-id[, issue-id...])
type — one of: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert.
(scope) — optional, lowercase-kebab-case, e.g. (basicly).
! — optional, immediately before the colon, marks a breaking change.
description — required: entirely lowercase, not just the first letter — proper
nouns and acronyms get lowercased too ("json", "conventional commits", not "JSON",
"Conventional Commits"). Letters/digits/space/hyphen only — no underscores (write
test-cli, not test_cli) and no other punctuation. No trailing punctuation, at
least 3 characters. This means version strings, filenames, and proper nouns
(0.2.0, AGENTS.md, Font Awesome) can never appear verbatim in the subject —
dots and uppercase are rejected. Keep the exact form in the free-form commit body
(the hooks validate only the subject line), or reword the subject ("the first
release", "agents-md", "font awesome"). A rejected commit prints the offending
character(s) — lowercase them or move them to the body.
(issue-id[, issue-id...]) — required by this repo's beads-commit-msg hook: one or
more known beads (br) issue ids, comma-separated in a single trailing parenthetical.
An id is <prefix>-<base> with optional dotted hierarchy levels — e.g. basicly-q49,
basicly-zrj.8, basicly-zrj.4.1 — where <prefix> is your repo's configured beads
prefix. The dotted forms are how br names child issues and are accepted here. The hook
matches the id prefix-anchored, by word boundary anywhere in the message (mirroring
br's own commit scanner), so ordinary hyphenated words in the description are never
mistaken for ids, and a git-trailer footer (Refs: basicly-q49) is recognized too — the
trailing parenthetical above stays the default.
Workflow
- Pick the type that matches the change's intent (feat/fix/docs/...).
- Resolve or create a beads issue first (see
tool-br) — never invent an id.
- Add
! only when the change is a breaking API/behavior change.
- Write the description in the imperative, lowercase, no trailing period.
- Append the issue id(s) as a single trailing parenthetical.
- Run
git commit -m "..." — the hooks re-validate; if rejected, read the hook's error
output rather than guessing at the fix.
Examples
Valid:
feat(basicly): add fragment loader (basicly-idr)
fix: correct sorting order in planner (basicly-abc)
feat(basicly)!: remove deprecated config format (basicly-idr)
fix: correct sorting order (basicly-idr, basicly-abc)
docs: document the update flow (basicly-zrj.8) — dotted child id is allowed.
Invalid:
Fixed the bug — no type/colon.
chore(scope): Message — description starts uppercase.
feat: support Conventional Commits marker — description has an uppercase proper
noun mid-string; must be feat: support conventional commits marker.
fix: fix test_cli mutation bug — underscore isn't allowed; must be
fix: fix test-cli mutation bug.
docs: update AGENTS.md for v0.1.0 — dots and uppercase aren't allowed; must be
reworded, e.g. docs: update agents-md for the first release.
feat: add Font Awesome v4 icons — capitals aren't allowed; lowercase the subject
(feat: add font awesome v4 icons) and keep the exact "Font Awesome v4" in the body.
chore: restamp the install to 0.2.0 — the dots aren't allowed; move the version to
the body, e.g. chore: restamp the install with Restamp to 0.2.0. in the body.
fix: correct sorting order (not an id) — trailing parenthetical isn't an issue-id list.
chore(word description): message — scope contains a space.
Guardrails
- This is a stricter-than-spec profile: it enforces the Conventional Commits v1.0.0
header structure plus the house description rules above (lowercase, restricted
charset, no trailing punctuation). Passing plain CC is necessary but not sufficient.
- The same
commit-msg.py and beads-commit-msg.py run as your local git hook and
in CI, so a subject that passes locally passes CI — but only if the hooks are actually
installed. Run pre-commit install -t pre-commit -t commit-msg -t pre-push once per
clone/worktree; an uninstalled hook silently lets a bad message through to CI.
- Never bypass the hooks (
--no-verify) to force a non-conforming message through.
- Never invent a beads issue id that doesn't exist in
.beads/issues.jsonl.
- Merge commits and
Revert "..." auto-generated subjects are exempt from this format.
Enforcement
This format is mechanically enforced by:
.basicly/core/hooks/commit-msg.py — type/scope/!/description rules.
.basicly/core/hooks/beads-commit-msg.py — issue id presence and existence.
This skill exists to get the message right on the first attempt; the hooks are the
actual gate.