Turn a working tree into well-formed Conventional Commits — group changes, review, commit. AI-assisted.
Project description
ncomm
One command, well-formed commits. The natural sibling of nlsh: nlsh proposes a command, ncomm proposes your commits.
ncomm reads your working tree, asks an LLM (DeepSeek) to split the changes into one or more Conventional Commits, shows you each proposed commit, and commits the ones you approve.
$ ncomm
working tree on feature/x
st file ±
M src/auth/oauth.py +142 -4
A src/auth/__init__.py +3
?? tests/test_oauth.py new
M pyproject.toml +1 -1
Proposed 2 commit(s).
commit 1/2 feat(auth): add OAuth2 login flow
Wires the OAuth2 device-code grant into the login view.
files: src/auth/oauth.py, src/auth/__init__.py, tests/test_oauth.py
Commit this? (y)es (n)o (e)dit (d)iff (r)egroup (q)uit (y): y
✓ a1b2c3d feat(auth): add OAuth2 login flow
At each commit you can press y to accept, n to skip, e to edit the
message in $EDITOR, d to show the actual diff for that group, r to ask
the model to regroup (optionally with a one-line hint like "split tests out"),
or q to stop.
Why
A real working tree is rarely one logical change — it's a feature, a bugfix, and
a dependency bump tangled together. Stuffing them into one commit makes
git bisect, revert, and review harder. ncomm groups them for you, then
commits each group with only its explicit file list.
Install
ncomm ships a uv.lock and a pinned requirements.txt, so you can install
with either uv or pip — whichever your environment prefers.
Option A — uv (recommended)
git clone https://github.com/decajoin/ncomm
cd ncomm
uv sync # creates .venv, installs pinned runtime deps from uv.lock
uv run ncomm --version
Or install it as a global tool:
uv tool install ncomm
Option B — pip
Runtime dependencies are pinned in requirements.txt (runtime only — no
pytest/ruff), so a plain pip install is reproducible without uv:
git clone https://github.com/decajoin/ncomm
cd ncomm
python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt # pinned runtime deps
pip install -e . # install ncomm itself (editable)
ncomm --version
Or from PyPI:
pip install ncomm
Regenerating the lockfile / requirements
Both files are kept in sync. If you change pyproject.toml:
uv lock # refresh uv.lock
uv export --format requirements-txt --no-hashes --no-emit-project --no-dev \
-o requirements.txt # refresh runtime-only requirements.txt
First-time setup
ncomm config set-key # paste your DeepSeek API key (stored mode 0600)
ncomm config show
Or via env: export DEEPSEEK_API_KEY=sk-...
Usage
ncomm # group, review each commit, commit approved ones
ncomm -y # commit all proposed groups without prompting
ncomm -n # dry run: show proposed commits, commit nothing
ncomm --no-group # force a single commit covering all changes
ncomm --pro # use the stronger model for this run
ncomm -m <model> # override the model id
ncomm --lang en # messages in English (default: en; use zh for Chinese)
Safety contract
ncomm only ever runs three things on your behalf:
git add <explicit paths>— nevergit add -A/git add .git commit -m <message>— hooks are never bypassed- (future)
git commit --amend— gated behind a typedyes
It never pushes, force-pushes, resets, or rebases. After committing, review
with git log and push when you're ready.
If the model's file assignment doesn't cover every changed file exactly, ncomm
aborts rather than commit a wrong grouping — re-run, or use --no-group.
How it works
git diff HEAD+ untracked file contents are gathered into one diff bundle, with per-file patches truncated (head + tail) so a generated/lockfile doesn't blow the token budget.- The bundle goes to DeepSeek with a Conventional Commits system prompt; the
model returns
{"groups": [...]}. - ncomm validates that the union of group files == the set of changed files.
- For each approved group:
git add <its files>thengit commit -m <msg>.
Configuration
~/.config/ncomm/config.toml (or $NCOMM_CONFIG):
api_key = "sk-..."
base_url = "https://api.deepseek.com"
model = "deepseek-v4-flash"
Env overrides: DEEPSEEK_API_KEY / NCOMM_API_KEY, DEEPSEEK_BASE_URL,
NCOMM_MODEL, NCOMM_LANG.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ncomm-0.1.0.tar.gz.
File metadata
- Download URL: ncomm-0.1.0.tar.gz
- Upload date:
- Size: 34.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7d43364c523c583474362f6851d3407e3612cab646d1ec4e8dc1730cc8eced07
|
|
| MD5 |
8c57e119a8be7833219c311d8d13063b
|
|
| BLAKE2b-256 |
a05432d521384844b384573e164623859990cc62d12d3ead30ac979abe527a78
|
File details
Details for the file ncomm-0.1.0-py3-none-any.whl.
File metadata
- Download URL: ncomm-0.1.0-py3-none-any.whl
- Upload date:
- Size: 19.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
31905295d331cf0ed26e647e7dead22dfd4eb3598f1addafefd06bdb4aeeae62
|
|
| MD5 |
4008762210deb5bc856c1ee584b3f00e
|
|
| BLAKE2b-256 |
1018a868647c625a44f96b54c4c545b3949c83486bc9e759b0b936a29c2b68b1
|