CLI · commit 30f3bd5

commitcraft

AI commit messages that follow your repo's conventions

Download commitcraft.zip
Quickstart
unzip commitcraft.zip && cd commitcraft
uv venv .venv && uv pip install -p .venv/bin/python -e '.[dev]'
.venv/bin/python -m pytest -q

commitcraft

AI commit messages that follow your repo's conventions. commitcraft reads your staged diff, does the heavy lifting deterministically (filtering lockfiles and binaries, ranking hunks, fitting a token budget, learning your history's style) and then asks Claude Haiku 5.5 for one small structured answer, which it validates and formats locally into a Conventional Commits message.

Features

Install

uv venv .venv && uv pip install -p .venv/bin/python -e '.[dev]'
export ANTHROPIC_API_KEY=sk-ant-...   # or: ant auth login

Credentials come only from the environment. Without them, commitcraft prints setup instructions; --dry-run never needs a key.

Quickstart

git add -p
commitcraft              # print a message
commitcraft -c           # edit in $EDITOR, then commit
commitcraft -n 3         # three alternatives
commitcraft --hook install

Usage

commitcraft [-c] [-n 1-5] [--dry-run] [--lang TEXT] [--max-diff-tokens N]
            [--model ID] [--no-cache] [-v] [--hook install|uninstall [--force]]

--dry-run output (real, from examples/demo.sh --dry-run, a throwaway repo with a lockfile change, a new binary and a new function; the fixed system prompt is omitted here):

Number of alternatives: 1
Language: English
Allowed types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
Scope candidates inferred from paths: api
Branch: feature/ABC-123-users
Repository style: 100% of the last 3 commits are Conventional Commits; common types: fix, docs, feat; common scopes: web, api; subjects start lowercase; branch ticket: ABC-123

Staged changes:
### packages/api/server.py (modified, +3 -0)
@@ -1,2 +1,5 @@
 def health():
     return "ok"
+
+def list_users(limit=50):
+    return []
### Skipped files
package-lock.json: generated/lock file modified (+1 -1), content omitted
packages/web/logo.png: binary file added

--- estimate ---
model: claude-haiku-5-5
estimated input tokens: ~366
hunks omitted: 0, skipped files: 2

Example of a generated message (needs a real key; shape shown from the formatter, not a captured live call):

feat(api): add list_users endpoint

Clients need to page through users instead of fetching them one by one;
limit defaults to 50 to keep responses small.

Refs: ABC-123

Hook

commitcraft --hook install writes .git/hooks/prepare-commit-msg. It fills the message only when it is empty (ignoring comments) and the commit is not a merge, squash, amend, -m or -F/template commit. Failures never block the commit. Installing twice is a no-op; a foreign hook is left alone unless --force (it is backed up to .bak). --hook uninstall removes it.

Configuration

.commitcraft.toml at the repo root (see examples/.commitcraft.toml):

key meaning
ignore extra globs summarized instead of sent (added to the defaults)
types allowed Conventional Commits types
scopes allowed scopes; anything else is dropped with a warning
ticket_pattern regex for ticket ids in the branch name; adds a Refs: footer
max_diff_tokens default diff budget (6000)

Environment: ANTHROPIC_API_KEY, COMMITCRAFT_MODEL, COMMITCRAFT_CACHE_DIR (default ~/.cache/commitcraft).

Cost

Haiku 5.5 costs $0.10 per 1M input and $0.50 per 1M output tokens. A typical commit sends 500 to 3000 input tokens and gets about 150 back, so roughly $0.0001 to $0.0004 per message (the 6000-token cap bounds the worst case near $0.0007). Repeating a command on the same staged diff is free thanks to the cache.

Architecture

module role
diff.py unified diff parser, ignore globs, hunk scoring
budget.py filtering, summaries, budget fitting, elision
scope.py scope candidates from paths
style.py history/branch style learning
config.py .commitcraft.toml
llm.py prompt, structured call, disk cache, cost
message.py validation and formatting
hook.py hook install/uninstall/fill rules
git.py, cli.py git plumbing and the click CLI

See docs/design.md for the algorithms.

Tests

.venv/bin/pytest

All model calls use an injected fake client. Live API calls were not exercised when this was written (no key available).

Limitations