Merlin Commit follows the Conventional Commits specification. Every commit has a type that communicates the nature of the change at a glance.
| Type | Emoji | When to use |
|---|---|---|
feat |
β¨ | New functionality visible to users |
fix |
π | Resolves incorrect or broken behavior |
docs |
π | Changes to documentation only |
style |
π | Code formatting, whitespace - no logic changes |
refactor |
π§ | Restructuring code without changing external behavior |
perf |
π | Measurable performance improvement |
test |
π¨ | Adding, updating, or fixing test cases |
build |
π¨ | Build system, bundler, or dependency changes |
ci |
βοΈ | CI/CD pipeline or configuration |
chore |
β»οΈ | Tooling, maintenance - no production code |
revert |
βͺ | Undo a previous commit |
Add new capabilities that end users can observe or use. This is the primary driver of minor version bumps in semantic versioning.
Use for:
- New API endpoints or CLI options
- New UI components or interactions
- New integrations or supported platforms
Do not use for:
- Internal refactoring with no user-visible effect (use
refactor) - Bug fixes that restore existing behavior (use
fix)
Examples:
feat(auth): add OAuth 2.0 login with GitHub
feat: export data as CSV from dashboard
Correct something that was broken, incorrect, or producing unexpected results.
Use for:
- Runtime errors and exceptions
- Wrong output or calculated values
- UI rendering issues
Do not use for:
- Adding new capabilities to fix a limitation (use
feat) - Updating tests to pass after a previous change (use
test)
Examples:
fix(api): handle null response from payment gateway
fix: prevent duplicate submissions on slow connections
Changes to README files, inline comments, JSDoc, wiki pages, or any prose documentation. No production code is modified.
Use for:
- README updates
- JSDoc / docstring additions
- Changelog entries
- Inline code comments
Do not use for:
- Code that only changes types or interfaces (use
refactororfeat)
Examples:
docs(api): document rate limiting behavior
docs: add prerequisites to installation guide
Formatting changes that do not affect runtime behavior: whitespace, indentation, semicolons, trailing commas, bracket alignment.
Use for:
- Running a formatter (Prettier, Black, gofmt) on existing files
- Fixing lint rule violations that are purely stylistic
Do not use for:
- Renaming variables or functions (use
refactor) - Any change that affects runtime output
Examples:
style: apply prettier formatting to src/
style(config): fix inconsistent indentation
Internal restructuring that does not change external behavior or fix a bug. The public API, outputs, and side effects remain identical.
Use for:
- Extracting functions or modules
- Renaming variables and functions for clarity
- Simplifying logic while preserving behavior
Do not use for:
- Changes that add new behavior (use
feat) - Changes that fix broken behavior (use
fix)
Examples:
refactor(auth): extract token validation to separate module
refactor: simplify retry logic with exponential backoff helper
Changes that measurably improve speed, memory usage, or resource consumption. The external behavior remains identical.
Use for:
- Caching results that were previously recomputed
- Replacing an algorithm with a faster equivalent
- Reducing database query count
Examples:
perf(db): add index on user_id for order lookups
perf: memoize expensive config resolution
Adding test cases, updating existing tests, or fixing broken tests. No production code changes.
Use for:
- New unit or integration tests
- Fixing flaky tests
- Improving test coverage for an existing feature
Examples:
test(validators): add edge cases for email validation
test: increase coverage for payment retry logic
Changes to the build configuration, bundler, dependency management, or project tooling that affect how the project is compiled or packaged.
Use for:
- Updating
package.jsondependencies - Changing TypeScript, Webpack, Rollup, or Vite config
- Updating lockfiles
Examples:
build(deps): upgrade TypeScript to 5.7
build: switch from webpack to esbuild
Changes to CI/CD pipeline configuration, automated test workflows, or deployment scripts.
Use for:
- GitHub Actions, GitLab CI, CircleCI workflows
- Deployment pipeline changes
- Automated testing matrix updates
Examples:
ci: add Node 22 to test matrix
ci(deploy): configure staging environment release
Routine maintenance that does not affect production behavior or tests. Catch-all for changes that do not fit other types.
Use for:
- Updating
.gitignore,.editorconfig, linting config - Releasing a new version (
chore(release): bump version to 2.0.0) - Removing unused files
Examples:
chore(deps): update eslint to v9
chore: remove unused helper script
Reverting a previous commit. The subject should reference the commit being reverted.
Examples:
revert: revert "feat(auth): add OAuth login"
revert: revert commit abc123
Use this decision flow when you are unsure:
Does this add new user-visible functionality?
Yes β feat
Does this fix broken or incorrect behavior?
Yes β fix
Does this only change documentation or comments?
Yes β docs
Does this only change formatting (whitespace, style)?
Yes β style
Does this improve speed or memory without changing behavior?
Yes β perf
Does this only change tests?
Yes β test
Does this change the build system or dependencies?
Yes β build
Does this change CI/CD pipelines only?
Yes β ci
Does this undo a previous commit?
Yes β revert
Does it restructure code without changing behavior or fixing bugs?
Yes β refactor
Catch-all β chore
Any type can be marked as a breaking change. Breaking changes represent incompatible API or behavior changes that require consumers to update their code.
How breaking changes work in merlin:
- When prompted "Are there any breaking changes?", answer yes.
- Describe the breaking change in the editor that opens.
- Merlin automatically:
- Adds
!after the scope in the commit header:feat(auth)!: - Adds
BREAKING CHANGE:prefix to your description in the footer - Shows a
β οΈ indicator in the preview (visual only, not in the commit)
- Adds
Example output:
feat(auth)!: replace session tokens with JWTs
All clients must update their authentication flow.
BREAKING CHANGE: Session cookies are no longer issued. Clients
must send a Bearer token in the Authorization header.
You do not need to type "BREAKING CHANGE:" yourself - merlin adds it automatically.
When the built-in types do not fit your workflow, you can define a custom set in .merlinrc.json. Custom types replace the built-in 11 entirely.
{
"types": [
{
"value": "feat",
"name": "feat",
"description": "A new feature",
"emoji": "β¨"
},
{
"value": "release",
"name": "release",
"description": "A production release commit",
"emoji": "π’"
}
]
}See [Config Schema] for the full type definition format.
- Configuration - Defining custom types and project settings
- CLI Reference - The commit command and flags
- Glossary - Wizard-theme vocabulary reference