Kanso commit
Use when the user asks to commit changes, stage their work, write commit messages, or split the working tree into logical commits.From its SKILL.md
npx -y skills add blakecyze/kanso --skill kanso-commitAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
- runs commandsInstructs the agent to run 6 commands, including `git status --short` and 5 more.
SKILL.md
7.8 KB, ~1.8k tokens by cl100k_base, as published. Nobody here has run it
kanso-commit
Splits the working tree into logically atomic commits and writes messages that answer why rather than what. Detects and matches the repo's existing convention.
The principles from kanso-principles apply. Messages earn their place the same way code does.
The atomic unit
An atomic commit is one logical change. Not one line, not one file — one thought. The test: can the commit be described in a single short imperative sentence without using "and"?
Each atomic commit must be:
- Independently revertable. Reverting it doesn't cause collateral damage.
- Independently cherry-pickable. It can move to another branch cleanly.
- Stable. Tests pass (or at least don't newly fail) at this commit.
- Single-concern. Refactor and feature are separate commits, always. Formatting and logic are separate commits.
Over-atomising is a real failure mode. A three-line bug fix does not need three commits.
Before doing anything
- Check the status.
!git status --shortand!git diff --statto see what's staged and unstaged. - Detect the convention.
!git log -n 30 --onelineand read 3-5 recent commits in full. The repo's existing style wins over any default. - Detect the tooling. Look for
commitlint.config.*,.commitlintrc*,cz-config*,package.jsonscripts mentioningcommit. These hard-constrain the format.
Convention detection
The repo's commit history dictates the format. In priority order:
- commitlint config present → use whatever it enforces. No exceptions.
- Conventional Commits pattern in recent history (
feat:,fix:,chore:) → match it. - Custom scoped pattern (
[Component] subject,subsystem: subject,Fixed #NNNNN --) → match it exactly. Don't modernise. - Plain imperative subjects with no prefix → match that. Don't introduce prefixes.
- No clear pattern, fewer than 10 commits in history → use Conventional Commits as a sensible default and tell the user.
Don't impose a new convention onto an existing repo. If the history is messy, match the least-bad recent pattern rather than inventing a new one.
Django uses past tense (Fixed #NNNNN --). Linux kernel uses subsystem: summary. React uses [Component] description. All valid. All match-what's-there.
Splitting the working tree
If multiple logical changes are staged or unstaged together:
- List them. Show the user: "I see three logical changes — a typo fix in
README.md, a newgetUserendpoint insrc/api/user.ts, and a refactor of the auth middleware. Split into three commits?" - Get confirmation before splitting. The user decides the granularity.
- Use
git add -porgit add <file>to stage each unit. Never bulk-stage withgit add .when splitting. - Commit each unit with its own message. One message per logical change.
If the working tree is a single logical change, stage and commit directly.
The seven rules for the message
- Subject and body separated by a blank line.
- Subject under 50 chars. Hard limit at 72.
- Capitalise the subject (unless the convention is Conventional Commits lowercase).
- No period at the end of the subject.
- Imperative mood: "Add X", "Fix Y", "Remove Z". Never past tense (unless the repo is Django-style).
- Body wrapped at 72 chars.
- Body explains what and why, not how. The diff shows how.
Imperative test: "If applied, this commit will _____". Fill the blank with the subject. If it doesn't grammatically fit, rewrite.
Body content
Body is optional for trivial changes (typo, formatting, rename of a local variable). Required for:
- Any bug fix (explain the bug, its impact, the fix)
- Any architectural change (explain the reasoning, alternatives considered, tradeoffs)
- Anything that changes behaviour visible to users or API consumers
- Anything removing code that isn't obviously dead
Good body content:
- What problem existed before this commit
- Why this approach was chosen over alternatives
- What side effects or unintuitive consequences exist
- Links to issues, RFCs, or prior discussion
Bad body content:
- Line-by-line walkthrough of the diff
- Restatement of the subject in longer form
- Filler like "This commit does X" (just say X)
- "As per the user's request" or similar AI artefacts
Breaking changes
If the change breaks an API:
- Conventional Commits:
feat(api)!: remove deprecated endpoint+BREAKING CHANGE:footer - Other conventions: use whatever the repo's history shows for breaking changes. Usually explicit in the body.
Always explain the migration path in the body.
Trailers and references
Fixes: #NNNorCloses: #NNN— link to issue trackersCo-authored-by:— when pairing or when the user names collaboratorsSigned-off-by:— if the repo uses DCO (check for.gitsignoffor CONTRIBUTING notes)
Don't invent trailers the repo doesn't use. Don't add Co-authored-by: Claude or any AI attribution unless the user explicitly asks for it.
Writing from the diff
The message must answer what the diff cannot:
- Why was the change needed? (The diff shows what changed, not why.)
- What alternative was considered and rejected? (Often invisible in the code.)
- What business constraint, SLA, regulation, or downstream consequence is at play?
- What invariant is being preserved or established?
If the user hasn't explained any of this, ask before committing. A good commit message cannot be generated from the diff alone. AI-generated messages are consistently weak on why because why lives outside the code.
The working process
- Run
!git status --shortand!git diff --stat. - Detect the convention (history + tooling).
- Identify logical groups in the working tree.
- If more than one group, ask the user whether to split.
- For each group: a. Stage the files/hunks. b. Draft the subject (imperative, under 50 chars, matching convention). c. If body is needed, draft it — ask the user for the why if it's not obvious. d. Show the user the full message before committing. e. Commit on approval.
- Report: show the final
git log -n <N> --onelinefor what was committed.
Output format
Before any commit, show:
Proposed commit 1 of 2:
fix(auth): reject tokens older than 24h
The previous implementation only checked the signature, not the
issuance time, allowing replay attacks with captured tokens.
The 24h window matches the session timeout in src/config/auth.ts.
Fixes: #312
Files: src/auth/verify.ts, src/auth/verify.test.ts
Approve? (y/n/edit)
Wait for the user's approval before running git commit.
What this skill never does
- Force-push, rebase, or rewrite public history.
- Amend a commit that's been pushed to a shared branch.
- Commit code that the user hasn't seen and approved (always show the message first).
- Invent a why the user didn't provide. Ask.
- Run linters, formatters, or tests as part of committing. Those are pre-commit hooks' job.
- Add AI co-authorship attribution unless explicitly requested.
- Use emoji unless the repo's recent history uses emoji.
Failure modes to avoid
- "fix: bug" and similar empty messages that pass linting but say nothing.
- Messages that restate the diff ("Changed X constant from 5 to 10").
- Tense inconsistency (imperative in some, past tense in others).
- Massive commits that touch five unrelated concerns.
- Over-atomised commits that fragment a single thought.
- Introducing Conventional Commits into a repo that never used it.
- Silently bulk-staging with
git add .when splits were warranted.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.
Gives 0 of the 12 instructions most pr commit review skills give in ~1.8k tokens
Counted across 1,055 of the 1,911 authors here whose files we hold, read 2026-09-06
- Use conventional commit message formatin 150 of 1055, across 145 files
- Announce skill usage at startin 78 of 1055
- Use imperative mood for commit descriptionsin 54 of 1055, across 51 files
- Add directory to gitignore if not ignoredin 52 of 1055, across 41 files
- Use imperative mood for commit subjectin 52 of 1055
- Run tests to verify clean baselinein 42 of 1055, across 32 files
- Push branch to originin 40 of 1055, across 38 files
- Verify worktree directory is ignored before creationin 39 of 1055, across 32 files
- Delete branches after mergingin 38 of 1055, across 30 files
- Create worktree with new branchin 37 of 1055, across 32 files
- Wrap body text at 72 charactersin 36 of 1055, across 34 files
- Auto-detect and run project setupin 35 of 1055, across 27 files
Said here and by no other author read
- detect existing commit convention from history and tooling
- identify logical groups in the working tree
- stage files or hunks individually for each logical unit
- ensure subject is imperative and under 50 characters
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.