Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

46 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

⚡ Quick Commitlint

A very fast, dependency-free commit message linter built with Zig.

npm version Zig 0.16.0 License: MIT

Documentation · Source

Quick Commitlint terminal demo

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.

✨ Why use it?

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.

🔎 Quick Commitlint vs Commitlint

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.

📊 Performance

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.

🚀 Install

With npm:

npm install quick-commitlint --save-dev

With pnpm:

pnpm add -D quick-commitlint

With Bun:

bun add --dev quick-commitlint

The package includes native executables for macOS arm64/x64, Linux arm64/x64, and Windows x64. The launcher requires Node.js 24 or 25.

🪝 Use in a commit hook

Pass the commit-message file as the only positional argument:

quick-commitlint "$1"

Husky 9

Install and initialize Husky with npm:

npm install husky --save-dev
npx husky init

Or with Bun:

bun add --dev husky
bunx husky init

husky 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-commitlint

Every 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.

⚙️ Configuration

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.

🧰 Presets and rules

The conventional and angular presets model the corresponding commitlint 21.2 presets. The supported rule union is:

  • body-leading-blank, body-max-line-length
  • footer-leading-blank, footer-max-line-length
  • header-max-length, header-trim
  • scope-case
  • subject-case, subject-empty, subject-exclamation-mark, subject-full-stop
  • type-case, type-empty, type-enum

Unlike commitlint, generated messages such as merges, reverts, fixups, tags, and initial commits are not ignored.

🧭 CLI

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.

📚 Documentation portal

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:start

Validate or build the prerendered site:

bun run portal:validate
bun run portal:build:pages

Every 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.

🏗️ Development

Requirements:

  • Zig 0.16.0
  • Node.js 24
  • Bun 1.3.14
bun install
bun run validate

Build the publishable cross-platform package and test its tarball:

bun run clean
bun run validate
bun run package

Build 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:render

The render script validates the GIF type and size, then extracts representative frames for visual inspection.

📄 License

Copyright © 2026 Dominik Hladík.

Licensed under the MIT License.

About

A very fast native commit message linter built with Zig

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages