conventional-commits¶
Writes and checks git commit messages and pull request titles so they follow Conventional Commits (a type, an optional scope, and a short imperative description). Use when writing a commit message, naming or opening a pull request, squash-merging, or checking whether a message or title is correct.
Plugin: emad-coding ยท Source on GitHub
Writes and checks commit messages and pull request titles in the Conventional Commits format.
When it triggers¶
- You ask the agent to commit, or to write a commit message.
- You ask for a pull request title, or the agent opens a pull request.
- You ask whether a message or a title is correct.
Before and after¶
| Before | After |
|---|---|
Update auth |
fix(auth): reject expired tokens on refresh |
Added login endpoint. |
feat(api): add login endpoint |
Remove v1 API |
feat(api)!: remove v1 endpoints, with a BREAKING CHANGE: footer |
Why pull request titles matter¶
When a pull request is squash-merged, its title becomes the commit on the main branch. Release tools such as release-please read that commit to choose the next version.
Install¶
/plugin marketplace add EmadMokhtar/agents-skills
/plugin install emad-coding@emad-skills
Then run /emad-coding:conventional-commits, or let Claude load it when a task needs it.
copilot plugin install EmadMokhtar/agents-skills:plugins/emad-coding
codex plugin marketplace add EmadMokhtar/agents-skills
Then open /plugins in Codex and install emad-coding.
npx skills add EmadMokhtar/agents-skills --skill conventional-commits
Add -a <tool> to choose the tool, for example -a cursor.
What the agent reads (SKILL.md)
---
name: conventional-commits
description: >-
Writes and checks git commit messages and pull request titles so they follow
Conventional Commits (a type, an optional scope, and a short imperative
description). Use when writing a commit message, naming or opening a pull
request, squash-merging, or checking whether a message or title is correct.
license: MIT
---
# Conventional Commits
Every commit message and every pull request title follows
[Conventional Commits 1.0.0](https://www.conventionalcommits.org/en/v1.0.0/).
## Format
```text
<type>[optional scope][!]: <description>
[optional body]
[optional footer(s)]
```
## Rules
1. **Type** is one of these:
- `feat`: a new capability for the user.
- `fix`: a bug fix.
- `docs`: documentation only.
- `refactor`: a code change that neither fixes a bug nor adds a feature.
- `test`: tests only.
- `perf`: makes something faster or use fewer resources.
- `build`: the build system or dependencies.
- `ci`: continuous integration configuration.
- `chore`: maintenance that fits nothing above.
- `style`: formatting only, no change in behaviour.
- `revert`: undoes an earlier commit.
2. **Scope** is optional. It names the area that changed, in lowercase: `feat(auth): ...`.
3. **Description** uses the imperative mood. It starts with a lowercase letter and has no
trailing period. Aim for 50 characters, at most 72. Write `add token refresh`, not
`Added token refresh.`
4. **Breaking change**: mark it with `!` after the type or scope (`feat(api)!: ...`), with a
footer `BREAKING CHANGE: <what breaks and how to migrate>`, or with both. Either marker
alone is valid. When you write a message, use both: `!` makes the break visible in the
subject, and the footer says how to migrate.
5. **Body** is optional. It explains *why* the change is needed; the diff already shows
*what* changed. Leave one blank line after the subject and wrap at 72 characters.
6. **Footers** come after one blank line: `Refs: #123`, `BREAKING CHANGE: ...`, and any
trailer the project requires, such as `Co-Authored-By:`.
## Pull request titles
A pull request title follows the same format as a commit subject. When a pull request is
squash-merged, its title becomes the commit on the main branch, and release tools read that
commit to choose the next version. A title such as `Update auth` silently breaks releases.
## Choosing the type
- Judge what the change does for a user of the project, not which files it touches.
- If one change mixes several types, prefer to split it. If it cannot be split, choose the
type with the biggest effect on users: `feat`, then `fix`, then the rest.
- A dependency update is `build(deps): ...`. A dependency update that fixes a security
problem for users is `fix(deps): ...`.
## Steps
1. Read the diff, or the description of the change.
2. Pick the type. Add a scope when one area clearly owns the change.
3. Write the description: an imperative verb first, lowercase, no period.
4. Decide whether anything breaks for users. If it does, add `!` and a `BREAKING CHANGE:`
footer. (When you check someone else's message, either marker alone is enough.)
5. Add a body only when the reason is not clear from the subject.
6. Output only the commit message or title, as plain text without a code block, unless the
user asks for an explanation.
## Examples
| Wrong | Right |
| --- | --- |
| `Update auth` | `fix(auth): reject expired tokens on refresh` |
| `Added login endpoint.` | `feat(api): add login endpoint` |
| `M0+M1 engine` | `feat(engine): add query planner and executor` |
| `Remove v1 API` | `feat(api)!: remove v1 endpoints`, with the footer `BREAKING CHANGE: clients must call /v2` |
## Checking an existing message
When asked whether a message or title is correct, say whether it follows the rules. If it
does not, name each broken rule and give a corrected version. A breaking change marked only
with `!`, or only with a `BREAKING CHANGE:` footer, follows the rules.