{"id":46479850,"url":"https://github.com/zcube/commit-checker","last_synced_at":"2026-06-12T23:01:51.889Z","repository":{"id":342476808,"uuid":"1174086971","full_name":"zcube/commit-checker","owner":"zcube","description":"Git pre-commit hook tool: 주석 언어, 바이너리 파일, 인코딩, lint, editorconfig, 커밋 메시지 정책 검사","archived":false,"fork":false,"pushed_at":"2026-06-12T13:43:23.000Z","size":521,"stargazers_count":0,"open_issues_count":3,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-12T15:19:57.367Z","etag":null,"topics":["code-review","commit-message","conventional-commits","developer-tools","editorconfig","git","golang","lefthook","linter","pre-commit"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zcube.png","metadata":{"files":{"readme":"README.en.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-06T03:51:46.000Z","updated_at":"2026-06-12T13:34:41.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/zcube/commit-checker","commit_stats":null,"previous_names":["zcube/commit-checker"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/zcube/commit-checker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zcube%2Fcommit-checker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zcube%2Fcommit-checker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zcube%2Fcommit-checker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zcube%2Fcommit-checker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zcube","download_url":"https://codeload.github.com/zcube/commit-checker/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zcube%2Fcommit-checker/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34265491,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-12T02:00:06.859Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["code-review","commit-message","conventional-commits","developer-tools","editorconfig","git","golang","lefthook","linter","pre-commit"],"created_at":"2026-03-06T08:04:51.993Z","updated_at":"2026-06-12T23:01:51.881Z","avatar_url":"https://github.com/zcube.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"[한국어](./README.md) | [English](./README.en.md) | [日本語](./README.ja.md) | [中文](./README.zh.md)\n\n# commit-checker\n\nA CLI tool that automatically enforces policies on Git commit messages and source code.\nWorks with [lefthook](https://github.com/evilmartians/lefthook), husky, or any Git hook manager.\n\n## Features\n\n| Check | Description |\n|---|---|\n| **Comment language** | Verify comments are written in the required language (Korean/English/Japanese/Chinese) |\n| **Allowed words** | Register technical terms and proper nouns to prevent false positives |\n| **Co-authored-by** | Block AI co-author trailers (with email allow-list support) |\n| **Unicode spaces** | Block invisible/non-standard Unicode space characters (NBSP, EM SPACE, ZWSP, BiDi, etc.) |\n| **Ambiguous chars** | Block Unicode characters that look like ASCII (e.g., Cyrillic A vs Latin A) |\n| **File Unicode check** | Detect invisible/ambiguous Unicode characters in source and markdown files |\n| **Invalid UTF-8** | Block invalid byte sequences |\n| **Emoji ban** | Block emojis in commit messages and comments (optional) |\n| **Binary file policy** | Per-extension block / allow / lfs policy (images allowed by default, git-LFS verification) |\n| **Encoding check** | Block non-UTF-8 encoded files (chardet-based) |\n| **Data file lint** | YAML, JSON (with JSON5/JSONC support), XML syntax validation |\n| **EditorConfig** | Validate files against .editorconfig rules |\n| **Conventional Commits** | Enforce commit message format (optional) |\n| **Append-only paths** | Block file deletion, content modification, and mid-file insertion (e.g. DB migrations) |\n| **Cache / build dirs** | Block commits inside node_modules, dist, build, target, __pycache__, .venv, etc. (parent-indicator validation) |\n| **clean command** | Remove untracked files inside cache/build dirs (tracked files preserved) |\n| **Repository analysis** | Detect development languages and warn about missing lint configs |\n| **Auto-fix** | Batch-fix unicode/encoding violations across git history |\n| **Config migration** | Auto-detect old config versions and migrate to the latest schema |\n| **Progress indicator** | Bubbletea TUI spinner (TTY-aware, plain text fallback) |\n\n## Installation\n\n### Homebrew (macOS / Linux)\n\n```bash\nbrew install zcube/tap/commit-checker\n```\n\n### go install\n\n```bash\ngo install github.com/zcube/commit-checker@latest\n```\n\nRequires Go 1.22+. Verify with `commit-checker version`.\n\n### Binary download\n\nDownload the file for your platform from [GitHub Releases](https://github.com/zcube/commit-checker/releases).\n\n```bash\n# Linux (amd64)\ncurl -L https://github.com/zcube/commit-checker/releases/latest/download/commit-checker_linux_amd64.tar.gz | tar xz\nsudo mv commit-checker /usr/local/bin/\n\n# macOS (Apple Silicon)\ncurl -L https://github.com/zcube/commit-checker/releases/latest/download/commit-checker_darwin_arm64.tar.gz | tar xz\nsudo mv commit-checker /usr/local/bin/\n\n# macOS (Intel)\ncurl -L https://github.com/zcube/commit-checker/releases/latest/download/commit-checker_darwin_amd64.tar.gz | tar xz\nsudo mv commit-checker /usr/local/bin/\n```\n\n### Docker\n\n```bash\ndocker pull ghcr.io/zcube/commit-checker:latest\n\n# Check staged diff\ndocker run --rm -v \"$(pwd):/repo\" -w /repo ghcr.io/zcube/commit-checker diff\n\n# Check commit message\ndocker run --rm -v \"$(pwd):/repo\" -w /repo \\\n  ghcr.io/zcube/commit-checker msg /repo/.git/COMMIT_EDITMSG\n```\n\n## Git Hook Integration (lefthook)\n\n### 1. Install lefthook\n\n```bash\n# macOS\nbrew install lefthook\n\n# npm\nnpm install --save-dev lefthook\n\n# go install\ngo install github.com/evilmartians/lefthook@latest\n```\n\n### 2. Install commit-checker\n\n```bash\ngo install github.com/zcube/commit-checker@latest\n```\n\n### 3. Create lefthook.yml\n\nCreate `lefthook.yml` in your project root:\n\n```yaml\npre-commit:\n  commands:\n    commit-checker:\n      run: commit-checker diff\n\ncommit-msg:\n  commands:\n    message-policy:\n      run: commit-checker msg {1}\n```\n\n### 4. Install hooks\n\n```bash\nlefthook install\n```\n\nChecks run automatically on every `git commit`.\n\n### Optional hooks (add only what you need)\n\nThe blocks below are independent of each other; append only the ones you need to `lefthook.yml`.\n\n#### Auto-fix before checking (fix)\n\n`fix` re-stages the files it modifies via `git add` by itself, so formatting (emoji removal, NBSP cleanup, etc.) is applied before the check. Replace the `pre-commit` block from the base setup with the one below (lefthook runs commands in name order, so `auto-fix` runs before `commit-checker`):\n\n```yaml\npre-commit:\n  commands:\n    auto-fix:\n      run: commit-checker fix\n      stage_fixed: true\n    commit-checker:\n      run: commit-checker diff\n```\n\n#### Prevent merge bypass (pre-merge-commit)\n\nMerge commits do not trigger the pre-commit hook, so feature-branch violations can slip in via merge. To prevent this, register the check on pre-merge-commit as well:\n\n```yaml\npre-merge-commit:\n  commands:\n    commit-checker:\n      run: commit-checker diff\n```\n\n#### Commit message policy hints (prepare-commit-msg)\n\nShows active policy hints as `#` comments at the bottom of the commit message editor (no-op for -m/merge/squash/amend; git strips `#` lines at commit time). Be sure to use `{0}` — `{1}` `{2}` `{3}` are left as literals when the argument is absent and break the hook (verified with lefthook 2.1.9):\n\n```yaml\nprepare-commit-msg:\n  commands:\n    policy-hint:\n      run: commit-checker prepare-msg {0}\n```\n\n#### Check commit messages before push (pre-push)\n\n```yaml\npre-push:\n  commands:\n    check-commits:\n      run: commit-checker push\n```\n\n### 5. Check all existing files (initial adoption)\n\nWhen commit-checker is adopted in an existing repository, files committed before the\nhooks were installed are never checked. To check every file once at adoption time,\nuse the `run` command:\n\n```bash\ncommit-checker run\n```\n\nIt checks all files tracked by `git ls-files`, regardless of staged state.\nTo fix violations automatically, combine it with the `fix` command:\n\n```bash\n# Preview changes\ncommit-checker fix --dry-run\n\n# Apply the fixes\ncommit-checker fix\n```\n\n### husky (Node.js projects)\n\n```bash\nnpx husky init\n```\n\n`.husky/pre-commit`:\n```bash\n#!/bin/sh\ncommit-checker diff\n```\n\n`.husky/commit-msg`:\n```bash\n#!/bin/sh\ncommit-checker msg \"$1\"\n```\n\n### Git 2.54+ config-based hooks (no hook manager)\n\nStarting with Git 2.54, you can integrate commit-checker with git configuration alone, without a hook manager like lefthook.\n\n```bash\n# Base: check staged changes (pre-commit)\ngit config set hook.commit-checker-diff.command \"commit-checker diff\"\ngit config set --append hook.commit-checker-diff.event pre-commit\n\n# Base: check commit messages (commit-msg) — git passes the message file path automatically\ngit config set hook.commit-checker-msg.command \"commit-checker msg\"\ngit config set --append hook.commit-checker-msg.event commit-msg\n\n# ── Optional from here: register only what you need ──\n\n# Optional: check commit messages before push (pre-push)\ngit config set hook.commit-checker-push.command \"commit-checker push\"\ngit config set --append hook.commit-checker-push.event pre-push\n\n# Optional: check merge commits (pre-merge-commit) — merge commits do not trigger the pre-commit hook\ngit config set hook.commit-checker-merge.command \"commit-checker diff\"\ngit config set --append hook.commit-checker-merge.event pre-merge-commit\n\n# Optional: show policy hints in the commit message editor (prepare-commit-msg) — git passes the arguments automatically\ngit config set hook.commit-checker-prepare.command \"commit-checker prepare-msg\"\ngit config set --append hook.commit-checker-prepare.event prepare-commit-msg\n```\n\n- Add `--global` to apply the hooks to every repository at once (useful for a personal global policy). See the [Global Installation](#global-installation) section for the full guide, including the global config file, per-directory policies, and per-repository opt-out.\n- Verify registration: `git hook list pre-commit`\n- Multiple hooks for the same event run in configuration order, and existing `.git/hooks/` scripts (e.g. lefthook) run last, so they can coexist.\n- Note: `.git/config` is not committed, so a manager like lefthook is still the better fit for team-wide enforcement. Config-based hooks suit personal setups and global policies.\n\n### Other hook integrations\n\n#### git am workflow\n\nThe same policies can be enforced in a `git am` (patch mail) workflow:\n\n```bash\n# Check the patch's commit message — git passes the message file path automatically\ngit config set hook.commit-checker-am-msg.command \"commit-checker msg\"\ngit config set --append hook.commit-checker-am-msg.event applypatch-msg\n\n# Check the applied patch content — at pre-applypatch time the patch is staged\ngit config set hook.commit-checker-am-diff.command \"commit-checker diff\"\ngit config set --append hook.commit-checker-am-diff.event pre-applypatch\n```\n\n#### Server-side enforcement (update hook)\n\nThe `update` hook on the server (bare repository) receives `\u003crefname\u003e \u003cold\u003e \u003cnew\u003e` arguments per ref.\nWith `push --range`, commit message policies can be enforced on the server without installing any client-side hooks:\n\n```bash\n#!/bin/sh\n# hooks/update — arguments: \u003crefname\u003e \u003cold\u003e \u003cnew\u003e\nexec commit-checker push --range \"$2..$3\"\n```\n\nNew branches (where old is all zeros) print a warning and are skipped.\n\n## Global Installation\n\nRegister the hooks and the configuration once, and commit-checker runs in every repository.\n\n### Global hooks + global config\n\n```bash\n# Register global hooks (Git 2.54+)\ngit config set --global hook.commit-checker-diff.command \"commit-checker diff\"\ngit config set --global --append hook.commit-checker-diff.event pre-commit\ngit config set --global hook.commit-checker-msg.command \"commit-checker msg\"\ngit config set --global --append hook.commit-checker-msg.event commit-msg\n```\n\nThe global config file is resolved in the following order; the **first existing file** is used:\n\n| Order | Location |\n|---|---|\n| 1 | `$COMMIT_CHECKER_GLOBAL_CONFIG` environment variable (explicit; warns and is ignored when the file is missing) |\n| 2 | `$XDG_CONFIG_HOME/commit-checker/config.yml` |\n| 3 | OS standard config directory — Linux `~/.config/commit-checker/config.yml`, macOS `~/Library/Application Support/commit-checker/config.yml`, Windows `%AppData%\\commit-checker\\config.yml` |\n| 4 | `~/.commit-checker.yml` (legacy, backward compatibility) |\n\n```yaml\n# ~/.config/commit-checker/config.yml — minimal global config example\ncomment_language:\n  locale: en\ncommit_message:\n  no_ai_coauthor: true\n  locale: en\n```\n\n### Per-directory policies (gitdir include)\n\nConditional includes corresponding to git's `[includeIf \"gitdir:...\"]` are supported.\nDifferent policies for work repositories (`~/work/`) and personal ones can be managed in one global place:\n\n```yaml\n# ~/.config/commit-checker/config.yml\ninclude:\n  - path: ~/.config/commit-checker/base.yml   # no condition → always included (shared base)\n  - path: ~/.config/commit-checker/work.yml\n    gitdir: ~/work/                            # only for repos under ~/work/\ncomment_language:\n  locale: en\n```\n\n- Precedence: main body \u003e later includes \u003e earlier includes — includes provide the base and the body overrides it.\n- `gitdir`: `~` expands to the home directory, and a trailing `/` matches the entire subtree (same as git).\n- Available in both global and project configs. Nested includes are ignored, and includes in remote presets are ignored for security.\n\n### Per-repository control (override·opt-out·opt-in)\n\n**override** — if a repository has `.commit-checker.yml`, the global config is ignored entirely\nand only the repository config applies (the same checks are guaranteed regardless of each member's global config).\nThe global config is used only when the repository has no config file.\nIf you need a partial override, declare a [gitdir include](#per-directory-policies-gitdir-include) pointing to a shared base file directly in the repository config.\n\n**opt-out** — to disable every check in a specific repository, add a single line to the project `.commit-checker.yml`:\n\n```yaml\nenabled: false\n```\n\n**opt-in operation** — register the global hook command as `commit-checker diff --require-config`,\nand only repositories that have a project config file are checked. In repositories without one,\nnothing happens and the exit code is 0:\n\n```bash\ngit config set --global hook.commit-checker-diff.command \"commit-checker diff --require-config\"\ngit config set --global hook.commit-checker-msg.command \"commit-checker msg --require-config\"\n```\n\n## Configuration\n\nCreate `.commit-checker.yml` in your project root.\nRun `commit-checker init` to generate a default config file automatically.\nUse `.commit-checker.schema.json` for IDE autocompletion in VS Code.\n\n```yaml\n# yaml-language-server: $schema=./.commit-checker.schema.json\n\ncomment_language:\n  enabled: true\n  required_language: english  # korean | english | japanese | chinese | any\n  min_length: 5\n  check_mode: diff            # diff | full\n  no_emoji: false             # true to ban emojis in comments\n  extensions:\n    - .go\n    - .ts\n    - .py\n    - .tf\n\n  # Allowed words: English terms to ignore during language detection\n  allowed_words:\n    - TypeScript\n    - JavaScript\n    - API\n  # allowed_words_file: .commit-checker-words.txt\n  # allowed_words_url: https://example.com/allowed-words.txt\n  # allowed_words_cache:\n  #   enabled: true\n  #   ttl: 24h\n\nbinary_file:\n  enabled: true\n  # default_policy: block       # block | allow | lfs (default: block)\n  # rules:                      # per-extension policy rules\n  #   - extensions: [.psd, .ai]\n  #     policy: lfs              # allow PSD etc. only when tracked by LFS\n  #   - extensions: [.mp4, .mov]\n  #     policy: lfs\n  # ignore_files:\n  #   - \"**/*.png\"\n\nlint:\n  enabled: true\n  yaml:\n    enabled: true\n    # comment_filter: true    # opt out per file via in-file skip-lint comment\n  json:\n    enabled: true\n    # allow_json5: true       # allow JSON5 comments/trailing commas\n    # comment_filter: true    # check .json in JSONC mode (strict JSON after stripping comments)\n  xml:\n    enabled: true\n\nencoding:\n  enabled: true\n  require_utf8: true\n  # no_invisible_chars: true   # Detect invisible Unicode chars in file content\n  # no_ambiguous_chars: true   # Detect ASCII-confusable Unicode chars in file content\n\neditorconfig:\n  enabled: true\n  # ignore_files:\n  #   - \"vendor/**\"\n\ncommit_message:\n  # enabled: true  # false to disable all commit message checks\n  no_ai_coauthor: true\n  no_unicode_spaces: true\n  no_ambiguous_chars: true\n  no_bad_runes: true\n  no_emoji: false             # true to ban emojis in commit messages\n  locale: en\n  conventional_commit:\n    enabled: false\n  language_check:\n    enabled: false\n    required_language: english\n\nappend_only:\n  enabled: false\n  # paths:\n  #   - \"migrations/**\"\n  #   - \"db/migrations/**\"\n\n# protected_paths:\n#   enabled: true\n#   paths:\n#     - \"legacy/**\"            # block all staged changes (add/modify/delete) under matching paths\n\ncache_dir:\n  enabled: true                # enabled by default\n  # ignore_dirs:\n  #   - vendor                 # e.g. Go projects that intentionally commit vendor\n\n# guide:\n#   enabled: false             # disable the remediation guide output on violations (enabled by default)\n```\n\nDefaults apply when the config file is absent.\n\n### Binary file policy\n\nThree policies can be assigned per extension:\n\n| Policy | Behaviour |\n|---|---|\n| `block` | Reject (default) |\n| `allow` | Accept |\n| `lfs` | Accept only when tracked by git LFS (checks `filter=lfs` in `.gitattributes`) |\n\nBuilt-in image extensions (`.png`, `.jpg`, `.jpeg`, `.gif`, `.webp`, `.bmp`, `.ico`, `.tiff`,\n`.tif`, `.heic`, `.heif`, `.avif`) default to **`allow`** when no rule matches.\n\n```yaml\nbinary_file:\n  enabled: true\n  default_policy: block          # unmatched binaries: block by default\n  rules:\n    # To force LFS for images:\n    - extensions: [.png, .jpg, .jpeg, .gif, .webp]\n      policy: lfs\n    # Design source files like PSD/AI:\n    - extensions: [.psd, .ai, .sketch]\n      policy: lfs\n    # Videos:\n    - extensions: [.mp4, .mov, .webm]\n      policy: lfs\n  ignore_files:\n    - \"assets/icons/**\"          # skip the policy check entirely\n```\n\nResolution order: `rules` match \u003e built-in image (`allow`) \u003e `default_policy` (or `block`).\n\n### Data file lint\n\nValidates the syntax of YAML / JSON / XML files.\nFiles with the `.jsonc` extension are always checked in JSON5 mode\n(`//` comments and trailing commas allowed), regardless of configuration.\n\n```yaml\nlint:\n  enabled: true\n  yaml:\n    enabled: true\n    comment_filter: true     # support in-file skip-lint comment\n  json:\n    enabled: true\n    # allow_json5: true      # allow JSON5 comments/trailing commas\n    comment_filter: true     # check .json files in JSONC mode\n  xml:\n    enabled: true\n```\n\n- `json.comment_filter: true` — strips `//` and `/* */` comments from `.json` files, then validates as strict JSON (trailing commas are not allowed).\n- `yaml.comment_filter: true` — a `# commit-checker: skip-lint` comment anywhere in a file disables linting for that file.\n\n### Append-only paths\n\nSpecify paths whose committed content must never change, such as DB migration files.\nViolations only raise errors; data is preserved.\n\n```yaml\nappend_only:\n  enabled: true\n  paths:\n    - \"migrations/**\"\n    - \"db/migrations/**\"\n  # filename_order: none   # defaults to numeric; set to none to disable order check\n```\n\nAllowed changes:\n- Adding new files (only names sorting after existing files; disable with `filename_order: none`)\n- Appending content at the end of existing files\n\nBlocked changes:\n- Deleting files\n- Modifying or deleting existing lines\n- Inserting content in the middle of a file\n- Adding new files that sort before existing files or share a name (allowed with `filename_order: none`)\n\nFile name order uses natural numeric sorting, so `9 \u003c 10` (default).\n\n### protected_paths (frozen paths)\n\nBlocks every staged change (add, modify, delete) under paths matching the glob patterns.\nUnlike append_only, which allows appending content at the end of a file, protected_paths is a full-freeze policy that allows no change at all.\n\n```yaml\nprotected_paths:\n  enabled: true\n  paths:\n    - \"legacy/**\"\n```\n\n| Check | Allowed changes |\n|---|---|\n| `append_only` | Adding new files, appending at the end of existing files |\n| `protected_paths` | None (full freeze) |\n\nFiles matching `exceptions.global_ignore` are excluded from the check.\n\n### Build artifact / cache directories\n\nBlock build artifact or cache directories such as `node_modules`, `dist`, `build`,\n`target`, `__pycache__`, `.venv` from being committed or staged in git.\n\n**Parent-indicator validation** reduces false positives:\n\n| Directory | Indicator |\n|---|---|\n| `node_modules` | parent has `package.json` / lockfile |\n| `dist` | parent has `package.json` / `go.mod` / `Cargo.toml` |\n| `build` | parent has `package.json` / `Cargo.toml` / `build.gradle` / `pubspec.yaml` / `CMakeLists.txt`, or `CMakeCache.txt` inside |\n| `target` | parent has `Cargo.toml` / `pom.xml` / `build.sbt` |\n| `vendor` | parent has `go.mod` / `Cargo.toml` / `Gemfile`, etc. |\n| `__pycache__` | parent has `.py` files |\n| `.venv` etc. | `pyvenv.cfg` inside (any name) |\n\nSupported directories: `node_modules`, `dist`, `out`, `build`, `target`, `vendor`,\n`.gradle`, `.next`, `.nuxt`, `.output`, `.svelte-kit`, `.yarn`, `.bun`,\n`__pycache__`, `.pytest_cache`, `.mypy_cache`, `.ruff_cache`, `.turbo`,\n`.parcel-cache`, `.venv` (+pyvenv virtualenvs), `.tox`, `.nox`, `.embuild`, `.dart_tool`.\n\n```yaml\ncache_dir:\n  enabled: true               # enabled by default\n  ignore_dirs:                # directories committed intentionally\n    - vendor                  # e.g. Go vendor directory\n```\n\n#### clean command\n\nRemove untracked files inside cache/build directories. **Tracked files are\nnever deleted** (based on `git ls-files --others`).\n\n```bash\n# List found items only (dry-run)\ncommit-checker clean\n\n# Actually delete untracked files\ncommit-checker clean --yes\n```\n\n### Allowed words dictionary\n\nExclude technical terms and proper nouns from language detection:\n\n```yaml\ncomment_language:\n  # Inline list\n  allowed_words:\n    - TypeScript\n    - JavaScript\n    - API\n    - URL\n\n  # Local file (one word per line, # comments supported)\n  allowed_words_file: .commit-checker-words.txt\n\n  # URL (same format, HTTP/HTTPS)\n  allowed_words_url: https://example.com/allowed-words.txt\n\n  # URL caching (optional)\n  allowed_words_cache:\n    enabled: true\n    ttl: 24h                  # Cache TTL\n    # dir: ~/.cache/commit-checker  # Cache directory (default)\n```\n\nAll three sources (inline, file, URL) are merged.\n\n### Per-file language rules\n\nSpecify exception paths such as i18n/locale files:\n\n```yaml\ncomment_language:\n  required_language: english\n  file_languages:\n    - pattern: \"locales/**\"\n      language: any\n    - pattern: \"i18n/**\"\n      language: english\n    - pattern: \"locale/ja/**\"\n      language: ja\n```\n\n### In-source directives\n\nOverride language rules per file or per region:\n\n```go\n// commit-checker:ignore\n// This English comment is intentional (next comment only)\n\n// commit-checker:file-lang=english  \u003c- applies to the whole file\n\n// commit-checker:disable:lang=english\n// This block is intentionally in English\n// commit-checker:enable\n```\n\nSupported directives:\n\n| Directive | Description |\n|---|---|\n| `commit-checker:ignore` | Skip the next comment only |\n| `commit-checker:disable` | Disable checking from this line |\n| `commit-checker:disable:lang=\u003cL\u003e` | Disable and use language L for this region |\n| `commit-checker:enable` | Re-enable checking |\n| `commit-checker:lang=\u003cL\u003e` | Switch required language from this point |\n| `commit-checker:file-lang=\u003cL\u003e` | Set required language for the entire file |\n\n`\u003cL\u003e` values: `korean` `english` `japanese` `chinese` `any` (or `ko` `en` `ja` `zh`)\n\n### Remediation guide\n\nWhen a check fails, a **per-category fix guide** is printed once per failed category, after the violation list and the summary line.\nThe guides are imperative fix instructions that AI agents can read from the output and act on immediately:\n\n```\nconfig/bad.json:3: invalid character '}' looking for beginning of value\n\nRemediation guide (AI agents: follow the instructions below to fix the violations above):\n  [lint] Fix the syntax errors at the reported file:line locations. For JSON files that need comments, consider using the .jsonc extension or setting lint.json.comment_filter: true.\n```\n\nEnabled by default; it can be turned off in the config:\n\n```yaml\nguide:\n  enabled: false\n```\n\nThe global `--no-guide` flag disables it regardless of the config.\nWith `--format json`, the guides are included as a `\"guides\": {\"\u003ccategory\u003e\": \"\u003ctext\u003e\"}` field, which is omitted when disabled.\n\n## Commands\n\n```\ncommit-checker init          Generate default config file (.commit-checker.yml)\ncommit-checker diff          Check staged diff (comments/encoding/lint/binary/unicode)\ncommit-checker run           Check all tracked files for policy compliance\ncommit-checker msg \u003cfile\u003e    Check commit message file\ncommit-checker prepare-msg   For the prepare-commit-msg hook: show active policy hints in the editor\ncommit-checker fix           Auto-fix git history (supports --dry-run)\ncommit-checker migrate       Migrate config file to the latest schema\ncommit-checker analyze       Analyze repository (language detection, lint config check)\ncommit-checker clean         Remove untracked files inside cache/build directories\ncommit-checker version       Print version info\n```\n\n### diff command (CI-friendly `from..to`)\n\n`commit-checker diff` accepts the same positional argument forms as `git diff`.\nWithout arguments, it checks staged changes (HEAD ↔ index) as before.\n\n```bash\ncommit-checker diff                      # default: staged (pre-commit)\ncommit-checker diff --staged             # explicit (alias: --cached)\ncommit-checker diff HEAD                 # HEAD ↔ working tree (all uncommitted)\ncommit-checker diff origin/main          # origin/main ↔ working tree\ncommit-checker diff A B                  # A ↔ B\ncommit-checker diff A..B                 # A ↔ B (range)\ncommit-checker diff A...B                # merge-base(A,B) ↔ B\n```\n\nThe `--only` flag runs only the specified checks (`run` supports it the same way).\nChecks set to `enabled: false` in the config are force-enabled when selected via `--only`.\n\n```bash\ncommit-checker diff --only comment_language   # check comment language only\ncommit-checker diff --only lint,encoding      # multiple categories\n```\n\n- Categories shared by run and diff: `binary` `encoding` `unicode` `lint` `editorconfig` `comment_language` `cache_dir`\n- diff-only categories: `custom_rules` `append_only` `protected_paths`\n\nTypical CI usage (GitHub Actions, GitLab CI, etc.):\n\n```yaml\n# GitHub Actions: check the PR diff\n- run: commit-checker diff ${{ github.event.pull_request.base.sha }}..HEAD\n\n# GitLab CI: check the MR diff\n- commit-checker diff ${CI_MERGE_REQUEST_DIFF_BASE_SHA}..HEAD\n```\n\n### init command\n\n```bash\n# Generate the default config file (auto-detects system locale)\ncommit-checker init\n\n# Generate with a specific locale\ncommit-checker init --lang en\n\n# Overwrite an existing file\ncommit-checker init --force\n```\n\n### run command\n\n```bash\n# Check all tracked files (regardless of staged state)\ncommit-checker run\n\n# Run specific checks only (--only)\ncommit-checker run --only lint\n```\n\nUnlike `diff`, this checks all files tracked by `git ls-files`, regardless of staged state.\n\n### prepare-msg command\n\nA command for the `prepare-commit-msg` hook. It shows the active policy hints as `#` comments in the commit message editor.\nGit strips `#` lines at commit time, so the hints never end up in the message.\nIt is a no-op for `-m`/merge/squash/amend commits.\n\n```bash\n# Accepts the arguments git passes as-is: \u003cfile\u003e [source] [sha]\ncommit-checker prepare-msg .git/COMMIT_EDITMSG\n```\n\n### fix command\n\n```bash\n# Preview changes\ncommit-checker fix --dry-run\n\n# Fix the last 5 commits\ncommit-checker fix --range HEAD~5..HEAD\n\n# Fix only my commits\ncommit-checker fix --mine --dry-run\n```\n\n### migrate command\n\n```bash\n# Detect schema version and migrate to latest\ncommit-checker migrate\n\n# Preview changes without modifying the file\ncommit-checker migrate --dry-run\n```\n\nAutomatically migrates old config files (e.g., `no_coauthor` → `no_ai_coauthor`) to the latest schema.\nComments and formatting are preserved.\n\n### analyze command\n\n```bash\n# Analyze the current repository\ncommit-checker analyze\n```\n\nDetects development languages and warns when lint config files (`.golangci.yml`, `.eslintrc.*`, `pyproject.toml`, etc.)\nare missing. Also checks for `.editorconfig`, `.gitattributes`, `.gitignore`.\n\n## Supported Languages\n\n| Language | Extensions |\n|---|---|\n| Go | `.go` |\n| TypeScript | `.ts` `.tsx` |\n| JavaScript | `.js` `.jsx` `.mjs` `.cjs` |\n| Java | `.java` |\n| Kotlin | `.kt` `.kts` |\n| Python | `.py` |\n| C / C++ | `.c` `.h` `.cpp` `.cc` `.hpp` |\n| C# | `.cs` |\n| Swift | `.swift` |\n| Rust | `.rs` |\n| Dockerfile | `Dockerfile` `Dockerfile.*` `*.dockerfile` |\n| Markdown | `.md` `.markdown` |\n| HCL (Terraform) | `.hcl` `.tf` `.tfvars` |\n\n## i18n Support\n\nCLI output is available in:\n\n- Korean (ko) - default\n- English (en)\n- Japanese (ja)\n- Chinese (zh)\n\nSet via `COMMIT_CHECKER_LANG`, `LC_ALL`, `LC_MESSAGES`, `LANG` environment variables, or the `locale` config field.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzcube%2Fcommit-checker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzcube%2Fcommit-checker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzcube%2Fcommit-checker/lists"}