open source · python · no api · mit

commit messages from your diff, without an llm.

commitgen reads your staged diff and suggests a conventional-commit message using rule-based heuristics. no prompts, no api key, no tokens. regexes, path matching, and roughly 400 lines of python doing the boring part well enough.

1 static analysis
template fill 2
    ╭─────────────────╮           ╭──────────────────────╮
      git diff         ──────▶    commitgen analyzes  
      (staged)                                        
                                  · file paths        
      + def login()               · added symbols     
      + import                    · imports           
        bcrypt                    · test coverage     
    ╰────────┬────────╯           ╰──────────┬───────────╯
                                            
             └──────────────┬────────────────┘
                            
                 ╭───────────────────────╮
                   feat(auth): add      
                   login flow           
                 ╰───────────────────────╯

                          rev. 0.1 · cg-2026-04-19
§ 01

how a run looks.

stage a file, run commitgen, read what it thinks, accept or edit. same keystrokes you use now.

rev. 0.1 · cg-2026-04-19
01  $ git add src/auth/login.py
02  $ commitgen
03
04  suggested:
05    feat(auth): add login flow
06
07  why:
08    · new function login_user() in src/auth/login.py
09    · imports bcrypt suggest password handling
10    · no test file touched  consider adding one
11
12  accept? [y/n/e]  e
13  (opens your $EDITOR with the suggestion pre-filled)
commitgen --explain
01  $ commitgen --explain
02
03  heuristics matched (ranked):
04    [type]
05      feat     new symbol `def login_user`         +0.80
06      fix      no bug-ish keywords in diff           +0.05
07      refactor no pure-rename rows                   +0.02
08
09    [scope]
10      auth     path prefix `src/auth/` on 1/1 files +0.95
11
12    [subject]
13      add login flow
14        · verb `add`     from net-add vs net-delete ratio
15        · noun `login`   from symbol name `login_user`
16        · noun `flow`    from import graph (bcrypt + http handler)
17
18  final → feat(auth): add login flow
19  disagree? use --type / --scope to lock, or press `e` to edit.
§ 02

what's inside.

four moving parts. together they suggest something usable more often than not.

01

rule-based, no api calls

works on a plane, in a tunnel, in a faraday cage. no tokens burned. no rate limits. the tool is a few hundred lines of python and a lookup table.

02

types from diff structure

reads conventional-commit types from the shape of your diff. new symbol added → feat. test-only changes → test. docs folder → docs. pure renames → refactor.

03

--explain shows its work

every heuristic that fired gets printed with a weight. agree, disagree, or learn from what it saw. no black box, no vibes.

04

overrides when wrong

heuristics miss sometimes. lock the type with --type fix, lock the scope with --scope api, or skip review with --no-edit. tool stays out of your way.

"why not just call an llm?" because i already know what changed. i staged it. i don't need a 7-billion-parameter model to read +def login_user and guess feat(auth).
§ 03

install.

for people who can't trust a model but will trust a regex.

not public yet

python 3.9+, macos and linux when it ships. repo isn't up yet, i'm still polishing it. ping bennett@frkhd.com if you want early access.