From a488ff576304e745f4703b169f8db3f5202a8f9c Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 21 Jun 2026 11:27:39 +0000 Subject: [PATCH 1/4] docs(blog): add three articles introducing commit-check Add three blog posts for the commit-check site: - One policy file for your Git history (overview / why commit-check) - From zero-config to org-wide policy (configuration & inherit_from) - AI-native: JSON output and a Python API (machine-readable usage) Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01GDSwJ4o6by3HrzUSzhFLJG --- docs/blog/posts/ai-native-commit-check.md | 116 +++++++++++++++++ docs/blog/posts/configuring-commit-check.md | 137 ++++++++++++++++++++ docs/blog/posts/introducing-commit-check.md | 89 +++++++++++++ 3 files changed, 342 insertions(+) create mode 100644 docs/blog/posts/ai-native-commit-check.md create mode 100644 docs/blog/posts/configuring-commit-check.md create mode 100644 docs/blog/posts/introducing-commit-check.md diff --git a/docs/blog/posts/ai-native-commit-check.md b/docs/blog/posts/ai-native-commit-check.md new file mode 100644 index 0000000..da65b1a --- /dev/null +++ b/docs/blog/posts/ai-native-commit-check.md @@ -0,0 +1,116 @@ +--- +date: + created: 2026-06-21 +readtime: 6 +categories: + - UPDATES +tags: + - commit-check + - automation + - ai +authors: + - shenxianpeng +--- + +# AI-native: JSON output and a Python API + +More and more commits are written — or at least drafted — by AI agents and +automation. So Commit Check is built to be *consumed* by machines, not only +read by humans squinting at ASCII art in a terminal. This post covers the two +features that make that possible: machine-readable JSON output and an +import-friendly Python API. + + + +## Structured output with `--format json` + +Add `--format json` to any invocation and Commit Check returns structured data +instead of decorated text. The exit code is unchanged (`0` = pass, `1` = fail), +so existing CI scripts keep working: + +```bash +echo "feat: add streaming support" | commit-check -m --format json +``` + +```json +{ + "status": "pass", + "checks": [ + { "check": "message", "status": "pass", "value": "", "error": "", "suggest": "" }, + { "check": "subject_imperative", "status": "pass", "value": "", "error": "", "suggest": "" } + ] +} +``` + +The interesting case is failure. Each failing check carries the full `error` +and `suggest` fields an agent needs to **self-correct** — no scraping required: + +```bash +echo "wip bad commit" | commit-check -m --format json +``` + +```json +{ + "status": "fail", + "checks": [ + { + "check": "message", + "status": "fail", + "value": "wip bad commit", + "error": "The commit message should follow Conventional Commits. See https://www.conventionalcommits.org", + "suggest": "Use (): , where is one of: feat, fix, docs, ..." + } + ] +} +``` + +Feed that `suggest` string straight back to an LLM and it has everything it +needs to rewrite the message and try again. + +## Quieter text, for humans + +If you live in a terminal but find the ASCII banner noisy, two modes dial it +down: + +- `--no-banner` keeps the failure details and suggestions but drops the + ASCII-art banner. +- `--compact` prints a single `[FAIL]` line per failing check (and implies + `--no-banner`). + +```bash +echo "wip bad commit" | commit-check -m --compact +``` + +```text +[FAIL] message: wip bad commit +``` + +## The Python API — no subprocess needed + +For tools and agents already running in Python, spawning a subprocess just to +validate a string is wasteful. The `commit_check.api` module exposes a +lightweight interface that returns plain dicts — easy to serialize, forward to +an LLM, or chain into a larger workflow: + +```python +from commit_check.api import validate_message, validate_branch, validate_all + +result = validate_message("feat: add streaming support") +if result["status"] != "pass": + # hand result straight back to your agent loop + ... +``` + +Because the functions return the same structured shape as the JSON output, +you can move between CLI and in-process validation without changing how you +handle results. + +## Why this matters + +The same policy that protects a human's `git commit` now protects an agent's +automated one — and gives that agent the precise feedback it needs to fix its +own mistakes. One `cchk.toml`, enforced identically whether the author is a +person, a CI job, or a model. + +Read the full AI-native guide in the +[README](https://github.com/commit-check/commit-check#ai-native-usage). diff --git a/docs/blog/posts/configuring-commit-check.md b/docs/blog/posts/configuring-commit-check.md new file mode 100644 index 0000000..df09ac4 --- /dev/null +++ b/docs/blog/posts/configuring-commit-check.md @@ -0,0 +1,137 @@ +--- +date: + created: 2026-06-21 +readtime: 7 +categories: + - UPDATES +tags: + - commit-check + - configuration +authors: + - shenxianpeng +--- + +# From zero-config to org-wide policy + +Commit Check works the moment you install it, but its real strength shows up +when you start shaping the policy to fit your team. This post walks from the +default behavior all the way to a configuration shared across an entire +organization. + + + +## Three places to configure + +Commit Check resolves configuration in order of priority: + +1. **Command-line arguments** — override settings for a single run +2. **Environment variables** — `CCHK_*` variables, ideal for CI +3. **Configuration files** — `cchk.toml` or `commit-check.toml` + +If none of these exist, the lenient defaults apply: Conventional Commits for +messages, Conventional Branch for branch names. + +## A real `cchk.toml` + +Drop a `cchk.toml` (or `.github/cchk.toml`) in your repository root to take +control: + +```toml +[commit] +# https://www.conventionalcommits.org +conventional_commits = true +subject_imperative = true +subject_max_length = 80 +subject_min_length = 5 +allow_commit_types = ["feat", "fix", "docs", "style", "refactor", "test", "chore", "ci"] +allow_merge_commits = true +allow_wip_commits = false +require_signed_off_by = false +# Bypass checks for bot/automation authors and co-authors: +ignore_authors = ["dependabot[bot]", "renovate[bot]", "copilot[bot]"] + +[branch] +# https://conventional-branch.github.io/ +conventional_branch = true +allow_branch_types = ["feature", "bugfix", "hotfix", "release", "chore", "feat", "fix"] +``` + +Every field maps to a rule that runs at commit, push, or CI time. Because the +file lives in your repo, the policy is reviewed and versioned like code. + +!!! tip "IDE autocompletion comes for free" + Commit Check's TOML schema is published on + [SchemaStore](https://www.schemastore.org/), so editors like VS Code (via + *Even Better TOML*), PyCharm, and IntelliJ give you autocompletion, + validation, and inline docs for `cchk.toml` — no manual schema path needed. + +## CLI and environment overrides + +For one-off checks or pipeline tweaks, skip the file entirely: + +```bash +# Override per run +commit-check --message --subject-imperative=true --subject-max-length=72 + +# Or via environment variables +export CCHK_SUBJECT_IMPERATIVE=true +export CCHK_SUBJECT_MAX_LENGTH=72 +commit-check --message +``` + +The same overrides work inside pre-commit hook `args`, so a single repo can +loosen a shared rule without forking the whole policy. + +## Share one policy across many repos + +The feature that turns Commit Check from a per-repo tool into an +organizational standard is `inherit_from`. Point each repository at a base +config and override only what differs: + +```toml +# .github/cchk.toml — inherit the org base, then adjust locally +inherit_from = "github:my-org/.github:cchk.toml" + +[commit] +subject_max_length = 72 # local override wins +``` + +`inherit_from` accepts several sources: + +- **GitHub shorthand:** `github:owner/repo:path/to/cchk.toml` +- **Pinned to a ref:** `github:owner/repo@main:path/to/cchk.toml` +- **Local path:** `../shared/cchk.toml` +- **HTTPS URL:** `https://example.com/cchk.toml` + +The `github:` shorthand fetches from `raw.githubusercontent.com`, and plain +HTTP URLs are rejected for security. Local settings always override the +inherited base — so the org sets the floor, and each repo customizes from +there. + +## Don't forget push safety + +Policy isn't only about message wording. Use `--no-force-push` in a `pre-push` +hook to catch history-rewriting pushes: + +```yaml +# .pre-commit-config.yaml +repos: + - repo: https://github.com/commit-check/commit-check + rev: v2.6.0 + hooks: + - id: check-no-force-push + stages: [pre-push] +``` + +One note worth repeating from the docs: piping `git push` into `commit-check` +is **not** a prevention mechanism. By then the push has already started, and +standard `git push` output doesn't carry the ref metadata the check relies on. +Use the `pre-push` hook instead. + +## The takeaway + +Start with zero config, add a `cchk.toml` when you want stricter rules, and +reach for `inherit_from` when you want one standard across every repository. +Same engine, same file format, growing with your team. + +Full reference: diff --git a/docs/blog/posts/introducing-commit-check.md b/docs/blog/posts/introducing-commit-check.md new file mode 100644 index 0000000..ddad8a3 --- /dev/null +++ b/docs/blog/posts/introducing-commit-check.md @@ -0,0 +1,89 @@ +--- +date: + created: 2026-06-21 +readtime: 6 +categories: + - ANNOUNCEMENTS +tags: + - commit-check +authors: + - shenxianpeng +--- + +# One policy file for your Git history + +Every team eventually writes the same wiki page: "How we write commit +messages." It lists a commit convention, a branch naming scheme, a rule about +signing off, and a plea to keep author emails consistent. Then nobody reads it, +and the rules quietly rot. + +**Commit Check** exists to turn that wiki page into something Git actually +enforces. + + + +## A policy engine, not a linter + +Commit Check is a lightweight policy engine for Git *metadata* — the parts of a +commit that live around your code rather than inside it: + +- **Commit messages** — Conventional Commits, subject length, imperative mood +- **Branch names** — Conventional Branch types like `feature/`, `bugfix/`, `release/` +- **Author identity** — name and email consistency +- **Sign-off trailers** — `Signed-off-by` for DCO workflows +- **Push safety** — catch accidental force-pushes before they rewrite history + +The important word is *policy*. Instead of scattering these rules across a CI +script here, a pre-commit hook there, and a half-remembered convention +everywhere, you write them **once** in a versioned `cchk.toml`. + +## Write it once, enforce it everywhere + +That single policy file is read by every enforcement point: + +```bash +pip install commit-check +commit-check --message --branch +``` + +The same `cchk.toml` then drives: + +- the **CLI** for local one-off checks, +- **pre-commit** hooks so problems are caught before a commit lands, +- **CI / GitHub Actions** so pull requests are validated for the whole team. + +Because the policy is committed alongside your code, it is reviewed, diffed, and +versioned like everything else. When the rules change, the change shows up in a +pull request — not in a Slack message that scrolls away. + +## Zero configuration to start + +You do not need a config file to begin. With no `cchk.toml`, Commit Check +applies lenient, sensible defaults: commit messages should follow +[Conventional Commits](https://www.conventionalcommits.org/) and branch names +should follow the [Conventional Branch](https://conventional-branch.github.io/) +convention. That is enough to get value on day one. + +```bash +echo "feat: add streaming support" | commit-check -m +``` + +When you are ready to tighten things up — a maximum subject length, required +sign-off, an allow-list of commit types — you add a `cchk.toml` and grow into +it. We will cover that in the next post. + +## Add the badge + +Once Commit Check is guarding your repository, let people know: + +```text +[![commit-check](https://img.shields.io/badge/commit--check-enabled-brightgreen?logo=Git&logoColor=white&color=%232c9ccd)](https://github.com/commit-check/commit-check) +``` + +## Where to go next + +- **Getting Started:** +- **GitHub Action:** +- **Source & issues:** + +Clean commits. Clear standards. One policy file. From 229075aab752db646dbc3d56b38e108bd22a7632 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Sun, 21 Jun 2026 22:46:34 +0300 Subject: [PATCH 2/4] fix: uncomment blog nav entry and remove exclude_docs to make blog posts visible --- mkdocs.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index ffc856b..f767755 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -8,10 +8,10 @@ copyright: "© Copyright 2022 - 2026, shenxianpeng." nav: - Home: index.md - Getting Started: getting-started.md - # - Blog: - # - blog/index.md -exclude_docs: | - blog/** + - Blog: + - blog/index.md +# exclude_docs: | +# blog/** theme: name: material From b5ae234d5e52f175d384bb4b860c88f957ad7994 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Sun, 21 Jun 2026 22:48:08 +0300 Subject: [PATCH 3/4] chore: remove placeholder blog posts (myfirst & mysecond) --- docs/blog/posts/myfirst.md | 18 ------------------ docs/blog/posts/mysecond.md | 20 -------------------- 2 files changed, 38 deletions(-) delete mode 100644 docs/blog/posts/myfirst.md delete mode 100644 docs/blog/posts/mysecond.md diff --git a/docs/blog/posts/myfirst.md b/docs/blog/posts/myfirst.md deleted file mode 100644 index a8ffa61..0000000 --- a/docs/blog/posts/myfirst.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -date: - created: 2025-06-26 - updated: 2025-06-26 -readtime: 15 -pin: true -links: - - Homepage: index.md - - Blog index: blog/index.md -categories: - - ANNOUNCEMENTS -tags: - - commit-check-action -authors: - - shenxianpeng ---- - -# commit-check-action supports xxx features diff --git a/docs/blog/posts/mysecond.md b/docs/blog/posts/mysecond.md deleted file mode 100644 index a783a1e..0000000 --- a/docs/blog/posts/mysecond.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -date: - created: 2025-06-26 - updated: 2025-06-26 -readtime: 15 -pin: true -links: - - Homepage: index.md - - Blog index: blog/index.md -categories: - - UPDATES -tags: - - commit-check -authors: - - shenxianpeng ---- - -# commit-check releases - -This is why we start to create commit-check with Rust. From 55c119b3a80cad2364473b4f1d360bbe91634d9a Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Sun, 21 Jun 2026 23:05:58 +0300 Subject: [PATCH 4/4] style: reduce AI writing patterns in all three blog posts --- docs/blog/posts/ai-native-commit-check.md | 20 +++++++++---------- docs/blog/posts/configuring-commit-check.md | 22 ++++++++++----------- docs/blog/posts/introducing-commit-check.md | 21 ++++++++++---------- 3 files changed, 30 insertions(+), 33 deletions(-) diff --git a/docs/blog/posts/ai-native-commit-check.md b/docs/blog/posts/ai-native-commit-check.md index da65b1a..3f9aee3 100644 --- a/docs/blog/posts/ai-native-commit-check.md +++ b/docs/blog/posts/ai-native-commit-check.md @@ -15,8 +15,8 @@ authors: # AI-native: JSON output and a Python API More and more commits are written — or at least drafted — by AI agents and -automation. So Commit Check is built to be *consumed* by machines, not only -read by humans squinting at ASCII art in a terminal. This post covers the two +automation. So Commit Check is also built for machines — not just humans reading +terminal output. This post covers the two features that make that possible: machine-readable JSON output and an import-friendly Python API. @@ -42,7 +42,7 @@ echo "feat: add streaming support" | commit-check -m --format json } ``` -The interesting case is failure. Each failing check carries the full `error` +When a check fails, each result carries the full `error` and `suggest` fields an agent needs to **self-correct** — no scraping required: ```bash @@ -64,8 +64,8 @@ echo "wip bad commit" | commit-check -m --format json } ``` -Feed that `suggest` string straight back to an LLM and it has everything it -needs to rewrite the message and try again. +Pass the `suggest` string back to an LLM, and it has what it needs to +rewrite the message and retry. ## Quieter text, for humans @@ -87,10 +87,10 @@ echo "wip bad commit" | commit-check -m --compact ## The Python API — no subprocess needed -For tools and agents already running in Python, spawning a subprocess just to -validate a string is wasteful. The `commit_check.api` module exposes a -lightweight interface that returns plain dicts — easy to serialize, forward to -an LLM, or chain into a larger workflow: +For tools and agents running in Python, spawning a subprocess to validate +a string adds unnecessary overhead. The `commit_check.api` module exposes +functions that return plain dicts — easy to serialize, forward to an LLM, +or chain into a larger workflow: ```python from commit_check.api import validate_message, validate_branch, validate_all @@ -112,5 +112,5 @@ automated one — and gives that agent the precise feedback it needs to fix its own mistakes. One `cchk.toml`, enforced identically whether the author is a person, a CI job, or a model. -Read the full AI-native guide in the +Read more in the [README](https://github.com/commit-check/commit-check#ai-native-usage). diff --git a/docs/blog/posts/configuring-commit-check.md b/docs/blog/posts/configuring-commit-check.md index df09ac4..ca3faa6 100644 --- a/docs/blog/posts/configuring-commit-check.md +++ b/docs/blog/posts/configuring-commit-check.md @@ -14,9 +14,8 @@ authors: # From zero-config to org-wide policy Commit Check works the moment you install it, but its real strength shows up -when you start shaping the policy to fit your team. This post walks from the -default behavior all the way to a configuration shared across an entire -organization. +when you start shaping the policy to fit your team. This post covers everything from the default behavior to organization-wide +shared configuration. @@ -84,9 +83,9 @@ loosen a shared rule without forking the whole policy. ## Share one policy across many repos -The feature that turns Commit Check from a per-repo tool into an -organizational standard is `inherit_from`. Point each repository at a base -config and override only what differs: +`inherit_from` is the feature that makes Commit Check work across an +organization. Point each repository at a base config and override only what +differs: ```toml # .github/cchk.toml — inherit the org base, then adjust locally @@ -123,15 +122,14 @@ repos: stages: [pre-push] ``` -One note worth repeating from the docs: piping `git push` into `commit-check` -is **not** a prevention mechanism. By then the push has already started, and -standard `git push` output doesn't carry the ref metadata the check relies on. -Use the `pre-push` hook instead. +A note: piping `git push` into `commit-check` is **not** a prevention +mechanism — by then the push has already started. Use the `pre-push` hook +instead. -## The takeaway +## Summary Start with zero config, add a `cchk.toml` when you want stricter rules, and reach for `inherit_from` when you want one standard across every repository. -Same engine, same file format, growing with your team. +Same engine, same file format, scaling with your team. Full reference: diff --git a/docs/blog/posts/introducing-commit-check.md b/docs/blog/posts/introducing-commit-check.md index ddad8a3..2515cf4 100644 --- a/docs/blog/posts/introducing-commit-check.md +++ b/docs/blog/posts/introducing-commit-check.md @@ -12,10 +12,9 @@ authors: # One policy file for your Git history -Every team eventually writes the same wiki page: "How we write commit -messages." It lists a commit convention, a branch naming scheme, a rule about -signing off, and a plea to keep author emails consistent. Then nobody reads it, -and the rules quietly rot. +Most teams have a wiki page titled something like "How we write commit +messages." It covers commit conventions, branch naming, sign-offs, and +author email consistency — and then nobody reads it. **Commit Check** exists to turn that wiki page into something Git actually enforces. @@ -33,9 +32,9 @@ commit that live around your code rather than inside it: - **Sign-off trailers** — `Signed-off-by` for DCO workflows - **Push safety** — catch accidental force-pushes before they rewrite history -The important word is *policy*. Instead of scattering these rules across a CI -script here, a pre-commit hook there, and a half-remembered convention -everywhere, you write them **once** in a versioned `cchk.toml`. +That word — *policy* — matters. Instead of scattering rules across a CI +script, a pre-commit hook, and a stale convention doc, you write them +**once** in a versioned `cchk.toml`. ## Write it once, enforce it everywhere @@ -54,7 +53,7 @@ The same `cchk.toml` then drives: Because the policy is committed alongside your code, it is reviewed, diffed, and versioned like everything else. When the rules change, the change shows up in a -pull request — not in a Slack message that scrolls away. +pull request. ## Zero configuration to start @@ -68,9 +67,9 @@ convention. That is enough to get value on day one. echo "feat: add streaming support" | commit-check -m ``` -When you are ready to tighten things up — a maximum subject length, required -sign-off, an allow-list of commit types — you add a `cchk.toml` and grow into -it. We will cover that in the next post. +When you need stricter rules — a maximum subject length, required sign-off, +or an allow-list of commit types — add a `cchk.toml`. The next post walks +through the details. ## Add the badge