commit
Create a Conventional Commits-compliant git commit — analyzes staged changes, drafts a message, and confirms before executing.
SKILL.md.claude/skills/commit/SKILL.md
GitHub/commit
Create a git commit following the Conventional Commits specification. Analyze staged changes, infer the best commit message, show it for confirmation, then execute.
Invocation format
/commit [hint?]
- No args — analyze staged (or unstaged) changes and infer everything automatically.
- With hint — use the hint as extra context when generating the message (e.g.,
/commit fixes the null-ref on startup).
Conventional Commits structure
Every commit message follows this shape:
<type>(<scope>): <subject>
[optional body]
[optional footer(s)]
Type — required
| Type | When to use |
|---|---|
feat |
A new feature visible to users or callers of the module |
fix |
A bug fix |
docs |
Documentation only (comments, markdown, XML docs) |
test |
Adding or correcting tests — no production code changes |
refactor |
Code change that is neither a bug fix nor a new feature |
perf |
Performance improvement |
build |
Changes to build system, project files, Directory.Build.props, NuGet |
ci |
CI/CD pipeline changes (GitHub Actions, scripts) |
chore |
Maintenance tasks that don't fit elsewhere (dependency bumps, cleanup) |
style |
Formatting, whitespace — no logic change |
Scope — optional but preferred
Use the module or layer affected. Keep it lowercase and short.
Examples: sample-collection, test-orders, domain, infra, outbox, startup
Subject — required
- Imperative mood, present tense: "add barcode command" not "added" or "adds"
- No capital first letter
- No period at the end
- Max ~72 characters on the first line
Body — optional
Use when the why is not obvious from the subject. Wrap at 100 characters.
Footer — optional
| Footer key | Usage |
|---|---|
BREAKING CHANGE: <description> |
Any breaking API or contract change — triggers a major version bump |
Closes #<n> / Fixes #<n> |
Link to an issue |
Co-Authored-By: Name <email> |
Co-author attribution |
A commit with BREAKING CHANGE: in the footer (or a ! after the type/scope) is a breaking change, regardless of type.
Phase 1 — Understand what changed
Run these in parallel:
git status --short— see staged vs unstaged filesgit diff— full diff of all unstaged changes (includes untracked viagit diff HEAD)git log --oneline -5— recent commits (to match the project's style and scope vocabulary)
If something is staged, treat staged changes as the intended commit and proceed to Phase 2.
If nothing is staged, inspect all unstaged + untracked changes, then go to Phase 1b.
Phase 1b — Group changes into logical commits
When nothing is staged, do not ask the user to choose files. Instead, analyze the full diff and group changed files into the smallest possible cohesive commits where each one:
- Builds and passes tests on its own (never leaves the codebase broken)
- Represents a single logical concern (e.g., "add migration files" is one commit; "register events in MartenConfig" is another)
- Has a clear, standalone commit message
Grouping heuristics:
- Files that only make sense together (e.g., a command + its handler + its test) → same commit
- Infrastructure wiring that enables a feature (e.g., project reference + Marten init) → can be split if each layer is independently meaningful
- Test changes that accompany production code → same commit as the production change, unless they test a previously committed feature
- Migrations → one commit per module; group all migration files for a module together
- Build/config changes (
.csproj,Directory.Build.props) that are prerequisites → commit first, before the code that depends on them
Present the proposed grouping to the user before staging anything:
I found N groups of changes:
1. build(database): add SampleCollection project reference
→ HC.LIS.Database.csproj
2. feat(sample-collection): register domain events in MartenConfig
→ Infrastructure/Configurations/DataAccess/MartenConfig.cs
3. feat(database): add SampleCollection migration files
→ Database/SampleCollection/*.cs
Commit them in this order? (yes / edit / cancel)
- yes — stage and commit each group sequentially, showing the message and confirming before each one
- edit — ask what to change in the grouping, then re-present before proceeding
- cancel — stop; do not stage or commit anything
Phase 2 — Analyze and draft
For each group (or for the staged diff):
- Identify the type — is this new behaviour, a fix, docs, test-only, etc.?
- Identify the scope — which module or layer is touched? Use the folder name as a guide (
SampleCollection→sample-collection). - Write the subject — one concise imperative phrase describing what changed.
- Decide if a body is needed — add one only if the why is non-obvious (e.g., a workaround, a deliberate design choice, a tricky fix).
- Check for breaking changes — if any public interface, integration event contract, or module facade method signature changed incompatibly, add
BREAKING CHANGE:to the footer. - Add
Co-Authored-By— always append:Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Phase 3 — Show and confirm (per commit)
Display the full proposed commit message in a code block, like this:
feat(sample-collection): add CreateBarcode command and handler
Implements step 5 of the collection workflow. The command carries
tubeType, barcodeValue, technicianId, and createdAt — all required
by CollectionRequest.CreateBarcode().
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Then ask the user:
Commit with this message? (yes / edit / cancel)
- yes — proceed to Phase 4
- edit — ask what to change and regenerate; show again before committing
- cancel — stop; do not commit
Phase 4 — Execute (per commit)
Stage only the files for this commit using explicit paths — never git add -A or git add .:
git add path/to/file1 path/to/file2
Then run the commit using a HEREDOC to preserve formatting exactly:
git commit -m "$(cat <<'EOF'
<full message here>
EOF
)"
After the commit succeeds, show the one-line output from git log --oneline -1.
If there are more groups remaining, move to the next one (Phase 2 → 3 → 4) until all groups are committed.
If the pre-commit hook fails:
- Read the hook output carefully.
- Fix the reported issues.
- Re-stage affected files.
- Create a new commit — never use
--amendunless the user explicitly asks for it.
Rules — never violate
- Never use
git add -Aorgit add .without explicit user approval. - Never skip hooks (
--no-verify). - Never amend unless the user explicitly requests it.
- Never push; only commit.
- Never commit files that likely contain secrets (
.env,*credentials*,*secret*). Warn the user instead. - Never create a commit that leaves the codebase in a broken state (missing dependency, unresolved reference, failing build).