{"id":51532447,"url":"https://github.com/andrey-fomin/ccval","last_synced_at":"2026-07-09T04:30:32.105Z","repository":{"id":267507968,"uuid":"899911844","full_name":"andrey-fomin/ccval","owner":"andrey-fomin","description":"Validate commit messages using Conventional Commits format with YAML configuration","archived":false,"fork":false,"pushed_at":"2026-03-22T19:43:59.000Z","size":158,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-26T16:06:33.947Z","etag":null,"topics":["cli","commit-validation","conventional-commits","developer-tools","git","lint","rust"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/andrey-fomin.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2024-12-07T11:03:35.000Z","updated_at":"2026-04-12T16:10:58.000Z","dependencies_parsed_at":"2024-12-10T19:36:40.230Z","dependency_job_id":"7154f4d8-468a-41f0-9dff-0dbb90912963","html_url":"https://github.com/andrey-fomin/ccval","commit_stats":null,"previous_names":["andrey-fomin/conventional-commits-validator","andrey-fomin/ccval"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/andrey-fomin/ccval","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrey-fomin%2Fccval","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrey-fomin%2Fccval/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrey-fomin%2Fccval/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrey-fomin%2Fccval/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/andrey-fomin","download_url":"https://codeload.github.com/andrey-fomin/ccval/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrey-fomin%2Fccval/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35287396,"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-07-09T02:00:07.329Z","response_time":57,"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":["cli","commit-validation","conventional-commits","developer-tools","git","lint","rust"],"created_at":"2026-07-09T04:30:30.947Z","updated_at":"2026-07-09T04:30:32.089Z","avatar_url":"https://github.com/andrey-fomin.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Conventional Commits Validator\n\n[![CI](https://github.com/andrey-fomin/ccval/actions/workflows/ci.yml/badge.svg)](https://github.com/andrey-fomin/ccval/actions/workflows/ci.yml)\n[![Release](https://img.shields.io/github/v/release/andrey-fomin/ccval)](https://github.com/andrey-fomin/ccval/releases)\n[![Docker](https://img.shields.io/badge/docker-andreyfomin%2Fccval-blue)](https://hub.docker.com/r/andreyfomin/ccval)\n\nValidate commit messages locally, in CI, or from stdin using Conventional Commits rules.\n\n`ccval` helps you:\n- catch invalid commit messages before merge or release\n- enforce team rules for types, scopes, headers, and footers\n- validate one commit, a branch range, or a message from stdin or a file\n\n## Quickstart\n\nOnce `ccval` is installed, validate the last commit in the current repository:\n\n```bash\nccval\n```\n\nValidate all commits on your branch:\n\n```bash\nccval -- origin/main..HEAD\n```\n\nUse the built-in strict preset:\n\n```bash\nccval -p strict\n```\n\nValidate a commit message from stdin:\n\n```bash\nprintf 'feat: add validation\\n' | ccval --stdin\n```\n\n## Install\n\nChoose the option that fits your workflow.\n\n### crates.io\n\n```bash\ncargo install ccval\n```\n\n### Homebrew\n\n```bash\nbrew install andrey-fomin/tap/ccval\n```\n\n### GitHub Releases\n\nDownload prebuilt binaries for Linux, macOS, and Windows from [GitHub Releases](https://github.com/andrey-fomin/ccval/releases).\n\n### Docker\n\nRun `ccval` without installing it locally:\n\n```bash\nprintf 'feat: add validation\\n' | docker run --rm -i andreyfomin/ccval:distroless --stdin\n```\n\nAvailable image tags (moving convenience tags):\n\n- `andreyfomin/ccval:latest` - Alpine-based, includes Git support, about 11 MB\n- `andreyfomin/ccval:distroless` - minimal image, no Git support, about 1 MB\n\n- Use `:distroless` when you only need stdin or file validation\n- Use `:latest` when you need to validate commits from a Git repository\n\nThe release workflow also publishes versioned tags, including `:1`, `:1.2`, `:1.2.3`, and matching `-distroless` variants such as `:1.2.3-distroless`.\n\nFor Git-based validation in a mounted repository, use `--trust-repo` only when you control the repository and Git fails with a `detected dubious ownership` warning:\n\n```bash\ndocker run --rm -v \"$(pwd)\":/repo -w /repo andreyfomin/ccval --trust-repo\n```\n\n### macOS note\n\nIf macOS blocks a downloaded binary, remove the quarantine attribute:\n\n```bash\nxattr -d com.apple.quarantine /path/to/ccval\n```\n\nYou can also right-click the binary, choose Open, and confirm the prompt.\n\n## Common Tasks\n\n### Validate the latest commit\n\n```bash\nccval\n```\n\n### Validate a commit range\n\n```bash\nccval -- origin/main..HEAD\n```\n\n### Validate commits in another repository\n\n```bash\nccval -r /path/to/repo -- HEAD~10..HEAD\n```\n\n`--repository` changes where Git reads commits from. Config auto-discovery still happens in the current working directory, so use `--config` too when the target repository has its own config file:\n\n```bash\nccval -r /path/to/repo -c /path/to/repo/conventional-commits.yaml -- HEAD~10..HEAD\n```\n\n### Validate a message file\n\n```bash\nccval --file .git/COMMIT_EDITMSG\n```\n\n### Validate in a container or ownership-mismatch environment\n\n```bash\nccval -T\n```\n\nOr with an explicit repository path:\n\n```bash\nccval -r /repo -T -- HEAD~5..HEAD\n```\n\n## Git Hook\n\nUse a `commit-msg` hook to validate each commit message before Git creates the commit.\n\nCreate `.git/hooks/commit-msg` with this content:\n\n```sh\n#!/bin/sh\n\nset -eu\n\nexec ccval --file \"$1\"\n```\n\nThen make it executable:\n\n```bash\nchmod +x .git/hooks/commit-msg\n```\n\nThis hook expects `ccval` to be installed and available on your `PATH`.\n\n## Configuration in 30 Seconds\n\nBy default, if no config file is found and no preset is specified, `ccval` only checks whether the commit message is parseable as a Conventional Commit.\n\nWhen a config file is present or a preset is provided, `ccval` also applies the validation rules defined there so you can enforce team-specific rules.\n\nTo enforce team-specific rules, add a config file such as `conventional-commits.yaml`.\n\nMinimal example:\n\n```yaml\npreset: strict\n\ntype:\n  values:\n    - feat\n    - fix\n    - docs\n\nscope:\n  required: true\n```\n\nThe same idea in TOML:\n\n```toml\npreset = \"strict\"\n\n[type]\nvalues = [\"feat\", \"fix\", \"docs\"]\n\n[scope]\nrequired = true\n```\n\nWith this config:\n\n- `strict` enables useful default formatting rules\n- only `feat`, `fix`, and `docs` are allowed\n- every commit must include a scope such as `feat(api): add endpoint`\n\nWhen `--config` is not provided, `ccval` looks for these files in order:\n\n- `conventional-commits.yaml`\n- `conventional-commits.yml`\n- `conventional-commits.toml`\n- `conventional-commits.json`\n\nUse a custom config path when needed:\n\n```bash\nccval -c .github/conventional-commits.yaml -- origin/main..HEAD\n```\n\n## Presets\n\n`ccval` includes two built-in presets:\n\n- `default` - formatting rules for description spacing and newline handling in body and footer values\n- `strict` - `default` plus header length limits and common type and scope restrictions\n\nWhen a config file and preset are both used:\n\n- `-p/--preset` takes precedence over `preset:` in the config file\n- rules omitted in your config inherit from the preset\n- `regexes: []` clears preset regex rules for that field\n\nUse a preset from the command line without changing your config file:\n\n```bash\nccval -p strict\n```\n\n## GitHub Action\n\nUse `ccval` in GitHub Actions to validate pull request commit ranges or pushed commits.\n\n```yaml\non: pull_request\n\njobs:\n  validate:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n        with:\n          fetch-depth: 0\n      - uses: andrey-fomin/ccval@v0\n```\n\nCommon options:\n\nUse a custom config:\n\n```yaml\n- uses: andrey-fomin/ccval@v0\n  with:\n    config: .github/conventional-commits.yaml\n```\n\nUse a built-in preset:\n\n```yaml\n- uses: andrey-fomin/ccval@v0\n  with:\n    preset: strict\n```\n\nOverride git arguments:\n\n```yaml\n- uses: andrey-fomin/ccval@v0\n  with:\n    git-args: origin/main..HEAD --no-merges\n```\n\nNote: `git-args` is parsed as a whitespace-separated list of arguments by the action; shell-style quoting/escaping is not supported, and arguments that contain spaces cannot be passed as a single argument. Auto-detected behavior such as adding `--no-merges` applies only when `git-args` is not set.\n\nLimit checked commits:\n\n```yaml\n- uses: andrey-fomin/ccval@v0\n  with:\n    max-commits: \"250\"\n```\n\nThe action supports `push` and `pull_request` events, discovers `conventional-commits.yaml` or `.github/conventional-commits.yaml`, skips merge commits in its auto-detected ranges, skips deleted-ref and zero-commit pushes, and limits validation to 100 commits by default.\n\nFor push events, it prefers the exact pushed range from local history. If the pushed `before` commit is not available locally, it falls back to the default-branch merge-base when possible and otherwise fails with a clear error.\n\nIf either the push event itself or the selected commit range exceeds `max-commits`, the action skips validation, emits a warning, and exits successfully.\n\nMake sure your workflow fetches enough history, for example with `fetch-depth: 0`, so the required commit range is available.\n\nUse `@v0` to track the latest compatible `v0.x.y` release, or pin a specific release tag such as `@v0.3.1`. For a fully immutable reference, pin a commit SHA.\n\n## Parsing vs Validation\n\n`ccval` checks commit messages in two steps:\n\n1. Parse the message structure\n2. Apply validation rules from your config\n\nA message can be parseable and still fail validation.\n\nFor example, `feat:  add api ` may parse successfully but fail stricter formatting rules.\n\nRead more:\n\n- [`PARSING.md`](PARSING.md) for commit message structure and parse errors\n- [`VALIDATION.md`](VALIDATION.md) for available fields, rules, and configuration examples\n\n## Command Reference\n\n```text\nUsage: ccval [-c \u003cpath\u003e] [-p \u003cpreset\u003e] [-r \u003cpath\u003e] [-T] [-- \u003cgit-log-args\u003e...]\n       ccval [-c \u003cpath\u003e] [-p \u003cpreset\u003e] --stdin\n       ccval [-c \u003cpath\u003e] [-p \u003cpreset\u003e] -f \u003cpath\u003e\n       ccval -h\n\nValidates commit messages from stdin, a file, or Git.\n\nModes:\n  (default)            Validate commit(s) from git log\n                       Use -- \u003cgit-log-args\u003e... to pass arguments to git log\n                       Default: -1 (last commit)\n\n  --stdin              Read commit message from stdin\n  -f, --file \u003cpath\u003e    Read commit message from a file\n  -h, --help           Show this help message\n\nOptions:\n  -c, --config \u003cpath\u003e  Use a custom config file path\n  -p, --preset \u003cname\u003e  Use a built-in preset (default or strict)\n  -r, --repository \u003cpath\u003e\n                       Path to Git repository working tree\n                       Cannot be used with --stdin or --file\n  -T, --trust-repo     Trust the repository despite ownership mismatch\n                       Useful when running in containers or accessing\n                       repositories owned by other users\n                       Requires git mode (cannot use with --stdin or --file)\n\nExamples:\n  ccval                              # validate last commit\n  ccval -- origin/main..HEAD         # validate commits on branch\n  ccval -p strict                    # validate last commit with strict preset\n  ccval -r /path/to/repo             # validate last commit in specific repo\n  ccval -T                           # validate last commit, trusting repo\n  ccval -r /repo -T                  # validate in container\n  printf 'feat: msg\\n' | ccval --stdin\n  ccval --file .git/COMMIT_EDITMSG\n  ccval -c config.yaml --stdin\n```\n\n## Exit Codes\n\n- `0` success\n- `64` usage error\n- `65` content invalid\n- `66` input unavailable\n- `70` internal error\n- `74` I/O error\n- `77` permission error\n- `78` config error\n\n## Reference\n\n- [`PARSING.md`](PARSING.md) explains the supported commit message structure\n- [`VALIDATION.md`](VALIDATION.md) lists fields, rule types, presets, and examples\n- [`CHANGELOG.md`](CHANGELOG.md) tracks release history\n- [`RELEASING.md`](RELEASING.md) documents the release process\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandrey-fomin%2Fccval","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandrey-fomin%2Fccval","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandrey-fomin%2Fccval/lists"}