Skip to content

Commit conventions

OpenCodeHub follows Conventional Commits. The commit log on main is the input to release-please — malformed messages break version bumps, changelog generation, and release notes. So we enforce the grammar three times: lefthook at commit-msg, the commitlint GitHub Action on every PR, and release-please itself.

<type>(<scope>): <subject>
[optional body]
[optional footer(s)]
  • Lowercase type.
  • Scope is a single workspace package name or a meta-scope.
  • Subject is imperative, ≤ 72 chars, no trailing period.
  • Body wraps at 100 cols. Explain why, not what — the diff tells you what.
  • Footers are standard (BREAKING CHANGE:, Refs: #123, Signed-off-by: ...).

If you are unsure of the type or scope:

Interactive Conventional Commit prompt
pnpm run commit

That wraps Commitizen and walks you through type, scope, subject, body, and breaking-change flags.

TypeUse forIn changelog?
featNew user-facing capability (CLI flag, MCP tool, indexer, etc.)Yes — “Features”
fixBug fixYes — “Bug Fixes”
perfPerformance improvement with no behaviour changeYes — “Performance”
revertRevert an earlier commitYes — “Reverts”
docsDocumentation-only change (this site, READMEs, ADRs, comments)Yes — “Documentation”
refactorInternal reshuffle, no behaviour changeYes — “Refactoring”
testAdding or fixing testsHidden
buildBuild system, dependency bumps, package metadataHidden
ciCI workflow changeHidden
choreHousekeeping that fits nowhere elseHidden
styleFormatting only — Biome runs on pre-commit, so this is rareHidden
releaseRelease-please-authored commits only (do not use by hand)

“Hidden” means the commit is still enforced and still shows up in the git log — it just does not appear in CHANGELOG.md. See .release-please-config.json for the source of truth on which sections are visible.

Workspace-package scopes map 1:1 to packages/<scope>/:

ScopePackage
analysis@opencodehub/analysis
cli@opencodehub/cli (bin: codehub)
cobol-proleap@opencodehub/cobol-proleap
core-types@opencodehub/core-types
embedder@opencodehub/embedder
frameworks@opencodehub/frameworks
ingestion@opencodehub/ingestion
mcp@opencodehub/mcp
pack@opencodehub/pack
policy@opencodehub/policy
sarif@opencodehub/sarif
scanners@opencodehub/scanners
scip-ingest@opencodehub/scip-ingest
search@opencodehub/search
storage@opencodehub/storage
summarizer@opencodehub/summarizer
wiki@opencodehub/wiki

Meta-scopes cover cross-cutting changes:

Meta-scopeUse for
depsDependency bumps not tied to one package
ci.github/workflows/*.yml changes
docspackages/docs/** or top-level Markdown
repoRoot-level repo files (.gitignore, mise.toml, etc.)
releaseRelease-please-authored PRs only

A feat! and a BREAKING CHANGE: footer both bump the major version.

The ! form is the short one:

feat(mcp)!: drop the `cypher` tool; use `sql` instead

The footer form is equivalent and plays nicer with long explanations:

feat(mcp): switch to SCIP-backed references
BREAKING CHANGE: the `lsp-unconfirmed` reason suffix is now
`scip-unconfirmed`. Consumers that pattern-match on the old suffix
must update.

Use either form, not both.

LayerToolTrigger
Local, pre-commitlefthook + commitlint --editcommit-msg hook
PR.github/workflows/commitlint.ymlEvery PR commit
Releaserelease-please action on push-to-mainNew commit on main

If commitlint rejects your message locally, re-run git commit with a fixed message — do not --no-verify. The tenet applies: every failure is a blocker.