A very fast, dependency-free commit message linter built with Zig.
quick-commitlint checks Conventional Commit messages with native Zig executables for macOS, Linux, and Windows. A small Node.js launcher selects the executable bundled for the current platform; the package has no runtime npm dependencies.
| Feature | Details |
|---|---|
| ⚡ Fast native linting | A thin launcher hands all linting work to the bundled Zig executable. |
| 📦 Zero package dependencies | All supported native executables ship in the npm package. |
| 🧩 Familiar configuration | Uses commitlint-style rule tuples with built-in conventional and Angular presets. |
| 🔒 Strict and predictable | Rejects malformed JSON, unknown options, duplicate keys, and invalid UTF-8. |
| 🌍 International subjects | Counts Unicode code points while keeping syntax checks fast and ASCII-based. |
This comparison uses @commitlint/cli 21.2.1 and the @commitlint/config-conventional and @commitlint/config-angular 21.2.0 packages pinned by this repository.
| Area | Quick Commitlint | Commitlint |
|---|---|---|
| Conventional preset | Built in as conventional and used by default |
Available through @commitlint/config-conventional or the CLI's --default-config fallback |
| Angular preset | Built in as angular and selected in strict JSON |
Available as the shareable @commitlint/config-angular package |
| Runtime and dependencies | Small Node.js launcher plus a bundled native Zig executable; no runtime npm dependencies | Node.js CLI with its JavaScript configuration, parsing, formatting, and rule dependencies |
| Configuration | One strict .quick-commitlint.json format, two presets, and 14 supported rule overrides |
JS, TS, JSON, YAML, and package configuration with shareable configs, plugins, and custom behavior |
| Inputs and ignored commits | Reads standard input or one commit-message file and lints every message | Also reads Git ranges, tags, the last commit, and edit/environment files; supports default ignores |
| Best fit | Projects using the included presets that value predictable configuration and native linting | Projects needing broader rules, custom parsers, plugins, shareable configs, ignores, or history linting |
The supported Conventional and Angular defaults are protected by differential tests, but Quick Commitlint is not a drop-in replacement for every Commitlint setup. Read the full compatibility guide for the exact boundary.
Reference cold-process benchmark:
| Preset | Quick Commitlint median | Commitlint median | Improvement |
|---|---|---|---|
| Conventional | 20.686 ms | 250.597 ms | 12.1× |
| Angular | 20.535 ms | 250.228 ms | 12.2× |
These are median wall-clock results from 40 measured launches after 3 warmups on Linux x64 under WSL2, using a 13th Gen Intel Core i9-13900H and Node.js 24.18.0. See the dedicated Performance documentation for the complete method and reproduction steps.
With npm:
npm install quick-commitlint --save-devWith pnpm:
pnpm add -D quick-commitlintWith Bun:
bun add --dev quick-commitlintThe package includes native executables for macOS arm64/x64, Linux arm64/x64, and Windows x64. The launcher requires Node.js 24 or 25.
Pass the commit-message file as the only positional argument:
quick-commitlint "$1"Install and initialize Husky with npm:
npm install husky --save-dev
npx husky initOr with Bun:
bun add --dev husky
bunx husky inithusky init configures Git hooks and creates an example .husky/pre-commit hook. Customize or remove that example hook if you do not need it.
Then create .husky/commit-msg:
quick-commitlint "$1"Husky adds local node_modules/.bin commands to the hook's PATH, so this runs the installed Quick Commitlint development dependency. Git supplies the proposed commit-message file as $1.
You can also make the package-manager lookup explicit. Choose the command that matches your project:
- npm:
npm exec --no -- quick-commitlint "$1" - pnpm:
pnpm exec quick-commitlint "$1" - Yarn:
yarn run quick-commitlint "$1" - Bun:
bunx --no-install quick-commitlint "$1"
These alternatives prefer the project-installed, lockfile-controlled version and do not download Quick Commitlint when the executable is missing. A missing installation or misspelled command therefore fails the hook instead of silently fetching a package. Using the project package manager also supports manager-specific dependency resolution, including Yarn Plug'n'Play. The bare command remains the simplest option for standard node_modules installations because Husky already adds local binaries to PATH.
Or lint a message from standard input:
echo "feat(parser): add fast validation" | quick-commitlintEvery lint result includes the elapsed lint time in milliseconds. Valid messages and warning-only results exit with status 0; rule errors exit with status 1; command, file, UTF-8, and configuration errors exit with status 2.
Without configuration, the built-in conventional preset is used. Quick Commitlint searches for the nearest .quick-commitlint.json from the current directory upward. Use --config to select a file explicitly.
{
"preset": "angular",
"rules": {
"header-max-length": [2, "always", 80],
"subject-full-stop": [0]
}
}Configuration is strict JSON. Unknown keys, duplicate keys, unsupported rules, and invalid values are errors. Supported severities are 0 (disabled), 1 (warning), and 2 (error); conditions are always and never.
The conventional and angular presets model the corresponding commitlint 21.2 presets. The supported rule union is:
body-leading-blank,body-max-line-lengthfooter-leading-blank,footer-max-line-lengthheader-max-length,header-trimscope-casesubject-case,subject-empty,subject-exclamation-mark,subject-full-stoptype-case,type-empty,type-enum
Unlike commitlint, generated messages such as merges, reverts, fixups, tags, and initial commits are not ignored.
quick-commitlint [options] [commit-message-file]
-c, --config <path> Use an explicit JSON configuration file.
-h, --help Display usage information.
-V, --version Display the installed version.
Input must be UTF-8 and may use LF or CRLF line endings. Length rules count Unicode code points. Case rules use ASCII semantics so international subjects remain valid.
The documentation site is an English-only Angular 22 static application in projects/portal. It uses Angular Material/CDK, plain CSS with Material 3 system tokens, Tailwind CSS v4 helpers, and build-time Markdown rendering.
Run it locally:
bun run portal:startValidate or build the prerendered site:
bun run portal:validate
bun run portal:build:pagesEvery public route is prerendered for SEO. Pushing a v* tag that points at the current master commit runs .github/workflows/main.yml, publishes the native packages, and then deploys dist/portal/browser to the gh-pages branch as the workflow's final step. The repository must provide the ACTIONS_DEPLOY_KEY secret and configure GitHub Pages to publish from gh-pages.
Requirements:
- Zig 0.16.0
- Node.js 24
- Bun 1.3.14
bun install
bun run validateBuild the publishable cross-platform package and test its tarball:
bun run clean
bun run validate
bun run packageBuild artifacts are kept as sibling outputs with no overlap between the website and published native package:
dist/
├── portal/
│ └── browser/ # Angular SSG output for GitHub Pages
└── quick-commitlint/
├── bin/
│ ├── quick-commitlint.js # Platform launcher
│ └── native/ # Five platform-specific Zig executables
├── LICENSE
├── README.md
└── package.json # Publishable npm manifest
bun run clean removes the complete dist tree. Portal builds recreate only dist/portal; the release packaging scripts recreate only dist/quick-commitlint.
Run the cold-process benchmark against @commitlint/cli:
bun run benchmark🎬 Regenerate the terminal demo
The README animation is defined in docs/terminal-demo.tape and rendered with the official VHS Docker image:
bun run demo:renderThe render script validates the GIF type and size, then extracts representative frames for visual inspection.
Copyright © 2026 Dominik Hladík.
Licensed under the MIT License.
