Skip to main content

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)

# Path filtering (fnmatch globs, repeatable) — leave WIP out of the commit:
ncomm --only 'src/auth/**' --only 'tests/test_auth*'   # only this slice
ncomm --exclude '*.lock' --exclude 'tmp/*'             # everything but these

--only / --exclude filter the changed set before grouping, so excluded files stay untouched in your working tree and never need to be committed.

Safety contract

ncomm only ever runs three things on your behalf:

  • git add <explicit paths> — never git add -A / git add .
  • git commit -m <message> — hooks are never bypassed
  • (future) git commit --amend — gated behind a typed yes

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

  1. 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.
  2. The bundle goes to DeepSeek with a Conventional Commits system prompt; the model returns {"groups": [...]}.
  3. ncomm validates that the union of group files == the set of changed files.
  4. For each approved group: git add <its files> then git commit -m <msg>.

Configuration

~/.config/ncomm/config.toml (or $NCOMM_CONFIG):

api_key = "sk-..."
base_url = "https://api.deepseek.com"
model = "deepseek-v4-flash"
learn_style = true   # show recent commits to the model to match repo style

With learn_style on (the default), ncomm passes your last few commit subjects to the model so generated messages follow the repo's existing conventions (type/scope habits, language, casing). Disable per run with --no-style.

Env overrides: DEEPSEEK_API_KEY / NCOMM_API_KEY, DEEPSEEK_BASE_URL, NCOMM_MODEL, NCOMM_LANG, NCOMM_LEARN_STYLE.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ncomm-0.1.1.tar.gz (38.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ncomm-0.1.1-py3-none-any.whl (21.4 kB view details)

Uploaded Python 3

File details

Details for the file ncomm-0.1.1.tar.gz.

File metadata

  • Download URL: ncomm-0.1.1.tar.gz
  • Upload date:
  • Size: 38.4 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

Hashes for ncomm-0.1.1.tar.gz
Algorithm Hash digest
SHA256 fd495b29bfd7c184b0a6bd8396fa9370feae8acb49ce1277b6da8de1c20126b1
MD5 4257ee4e2c1941c6d53d74a18c04bb2e
BLAKE2b-256 a1e538afda462137f12cbc2bf01d49d7a79a685ac01a355b1b7fea47e7ce675c

See more details on using hashes here.

File details

Details for the file ncomm-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: ncomm-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 21.4 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

Hashes for ncomm-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e14fd7b92eb8782f33bbb5df73951f206620bda50e3e169bc8f1021b11dfc74d
MD5 68ae7325727aeca1ee80ffcc0b8de007
BLAKE2b-256 0d3a6ca32b52e182889d6a002e50ee607ae472ab1ffb318c1d922bb2f6d6357a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page