Hooversion is a Bun/TypeScript CLI for Conventional Commit linting and semantic
release automation. It is designed to replace separate commitlint,
semantic-release, changelog, release-note, tag, and GitHub release glue.
hooversion init
hooversion lint --from origin/main --to HEAD
hooversion plan
hooversion release --dry-run
hooversion release
hooversion doctor
hooversion app
versionhoo-appfeatreleases a minor version.fixandperfrelease a patch version.!orBREAKING CHANGE:releases a major version.- Release commits and merge/revert noise are ignored.
- Single-package repos use
v${version}tags. - Independent multi-package repos use
${name}@v${version}tags. - Commits route to packages through changed paths and Conventional Commit scopes.
- Local dependents can release automatically through
dependenciesin config.
The packaged @openhoo/hooversion API is the supported Hootway-style commit-policy
parity surface. Use it for commit parsing and linting rather than importing
internal modules:
import { lintCommit, lintCommits, parseCommit, type CommitPolicy } from "@openhoo/hooversion";
const policy: CommitPolicy = {
allowedTypes: ["feat", "fix", "docs"],
releaseTypes: { docs: "patch" },
};
const commit = {
hash: "abc123",
subject: "docs: explain the public policy",
body: "",
files: [],
};
const issues = lintCommit(commit, policy);
const batchIssues = lintCommits([commit], policy);
const parsed = parseCommit(commit, policy);allowedTypes limits accepted Conventional Commit types; releaseTypes extends
or overrides the release-type mapping used by parseCommit. lintCommit,
lintCommits, and parseCommit all accept the same optional CommitPolicy.
Run hooversion init to generate hooversion.config.ts. See examples/ for a
single-package Node/Bun setup and an independent Rust workspace setup.
Packages can use node, rust, python, or version-file manifests. The
version-file type reads and writes a plain text file containing only the
semantic version, which fits container or Go repos that already keep release
versions in files such as transports/version.
init refuses to overwrite an existing configuration. --force can replace
one existing configuration but refuses duplicate config files; it overwrites
workflows only when they are recognized as Hooversion-generated. Use
--no-workflow to generate only the config.
Each release plan is bound to its checked-out source SHA. On the initial,
non-resumable attempt, Hooversion requires local HEAD and the remote release
branch to still match that SHA. It updates manifests and changelogs, runs
configured hooks, creates a release commit and tags, and pushes the branch and
all tags in one atomic Git push.
If GitHub publishing fails after that push, rerun the release from the exact release commit and tags: Hooversion rejects remote drift, reuses only a matching existing GitHub Release, and uploads only missing asset names. This makes the post-push GitHub Release/asset step retryable without another branch or tag push.
Release outputs are managed files. Each non-dry-run release clears prior
generated output, writes .hooversion/outputs.json and per-tag notes, and
writes .release-version only for a single release (removing it otherwise).
These paths are generated release state, not user-owned files. Corresponding CI
outputs are written to GITHUB_OUTPUT when available. In protected repositories
that allow GitHub Actions to bypass release-only branch protections, this keeps
releases automatic while human changes to main remain pull-request gated.
Hooversion ships composite actions for downstream CI:
jobs:
plan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: openhoo/hooversion/actions/setup@v0.2.0
with:
version: 0.2.0
- run: hooversion plan
commitlint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: openhoo/hooversion/actions/lint@v0.2.0
with:
version: 0.2.0
release:
runs-on: ubuntu-latest
if: github.event.workflow_run.conclusion == 'success'
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- id: release
uses: openhoo/hooversion/actions/release@v0.2.0
with:
version: 0.2.0
github-token: ${{ secrets.GITHUB_TOKEN }}actions/lint automatically uses the PR base/head range on pull requests and
--last on pushes. actions/release exposes published, version, tag, and
releases-json outputs for downstream package, Docker, or archive publishing
jobs.
The generated release workflow checks out the successful workflow run's immutable
head_sha and uses repository-scoped concurrency with
cancel-in-progress: false, so a later release never cancels an already-running
release.
Hooversion also ships versionhoo-app, a Bun server for running releases as an
installed GitHub App. It verifies GitHub webhook signatures, mints installation
tokens from the app private key, clones repositories, runs the same release
engine, pushes release commits and tags, creates GitHub Releases, and reports a
Versionhoo Release check back to GitHub.
Use this when main is pull-request gated for humans but a dedicated app should
be allowed to perform release-only writes. See docs/github-app.md for the app
permissions, webhook settings, ruleset bypass setup, and runtime environment.