Lazycommit is a TypeScript CLI that uses Git and an AI provider of your choice to generate commit subjects from your staged changes. Choose a suggestion, edit it, regenerate it, or cancel before committing. Use lazycommit or its shorter alias, lzc.
- Analyze large changes: use bounded code samples or opt into deeper analysis with
--thorough. - Choose your provider: OpenAI, Gemini, Anthropic, Kimi, DeepSeek, GLM, MiniMax, or Groq, then pick a model from a list with
lzc model. - Stage and push in one command: pick files when nothing is staged, and
lzc mainpushes after committing. - Control the result: choose the model, language, format, scope, length, and additional context.
- Preview first: inspect the diff context locally or generate messages without committing.
- Fit your workflow: use interactive review, an explicit noninteractive mode, or a Git hook.
You need Git, Node.js 22.13 or newer, and an API key for one supported provider.
npm install -g lazycommitt
lazycommit config set GROQ_API_KEY="gsk_your_key_here" # or another provider's keyThe npm package is lazycommitt (two t's). The commands are lazycommit and lzc.
Or with Homebrew:
brew tap KartikLabhshetwar/lazycommit https://github.com/KartikLabhshetwar/lazycommit
brew install lazycommitnpm update -g lazycommitt
# Homebrew:
brew update && brew upgrade lazycommitCheck your version with lazycommit --version. Coming from 1.x: --split was removed, and -s now means Git's --signoff.
Coming from 2.x: version 3 needs Node.js 22.13 or newer and supports multiple providers. Your saved GROQ_API_KEY keeps working, but a key for a provider earlier in the list (for example OPENAI_API_KEY in your shell) now wins. To stay on Groq, run lazycommit config set model=groq/openai/gpt-oss-20b.
New in 3.1: with nothing staged, lzc opens a file picker; lzc <branch> pushes after committing; lzc model picks a model from a list. Scripts are unaffected: --yes and runs without a terminal still need staged changes.
| Provider | Key | Default model |
|---|---|---|
| OpenAI | OPENAI_API_KEY |
openai/gpt-5.4-mini |
| Google Gemini | GOOGLE_API_KEY |
google/gemini-3.5-flash-lite |
| Anthropic | ANTHROPIC_API_KEY |
anthropic/claude-haiku-4-5 |
| Kimi (Moonshot AI) | MOONSHOT_API_KEY |
moonshotai/kimi-k2.6 |
| DeepSeek | DEEPSEEK_API_KEY |
deepseek/deepseek-flash |
| GLM (Z.AI) | ZHIPU_API_KEY |
zai/glm-5.3-flash |
| MiniMax | MINIMAX_API_KEY |
minimax/MiniMax-M3 |
| Groq | GROQ_API_KEY |
groq/openai/gpt-oss-20b |
Without a model setting, lazycommit uses the first provider in this table that has a key. To browse the models your keys can use and pick one, run:
lzc modelIt lists the text models of every provider you have a key for (environment or ~/.lazycommit), marks the current one, and saves your pick as the model setting. With several providers, you choose the provider first. Without a terminal, it prints the models as provider/model, one per line. The list comes from Mastra's model registry, so a provider's newest models may be missing; set those with provider/model directly.
Or set one explicitly with provider/model:
lazycommit config set ANTHROPIC_API_KEY="sk-ant-your_key_here"
lazycommit config set model=anthropic/claude-haiku-4-5
lzc --model google/gemini-3.5-flash-liteModels are routed through Mastra, so other Mastra providers also work; set their key as an environment variable, for example OPENROUTER_API_KEY. Groq model names from earlier versions, such as openai/gpt-oss-20b or llama-3.3-70b-versatile, still work.
Stage what you want to commit, then run lzc:
git add src/ README.md
lzcChoose Use as-is, Edit, Regenerate, or Cancel. Nothing is committed until you choose, and only staged changes are committed.
If nothing is staged, lzc lists every changed and untracked file (ignored files never appear), all selected. Press Enter to stage them all, or toggle files with space (a toggles all). If you cancel, or the commit doesn't happen, the files are unstaged again.
Add a branch name to push after committing:
lzc main # pick files → review → commit → git push -u origin main
lzc feature/login # same for a feature branch; -u sets its upstream on the first push- The branch must be the one you're on, and an
originremote must exist. Both are checked before any API call. - The push runs after a successful commit. With nothing to commit (a clean working tree), it just pushes, so
lzcthenlzc mainworks too. If the push fails, the commit is kept and git's error is shown. --yes, previews, and runs without a terminal never stage anything; they still need staged changes. Previews can't take a branch.- A branch named
config,hook, ormodelcan't be pushed this way, because those names are commands.
lzc --type conventional # fix(api): reject empty tokens
lzc --type conventional --scope api # require a specific scope
lzc --generate 3 # choose from up to 3 suggestions
lzc --context "Keep login behavior while replacing session storage"
lzc --locale ja # write the subject in Japanese
lzc --all # stage modified and deleted tracked files first
lzc --yes # commit the first suggestion without prompts
lzc --dry-run # print suggestions without committing
lzc --preview-diff # print the analysis context; no API call--type conventionalfollows Conventional Commits 1.0.0. Edited messages must keep that format.--alldoes not add untracked files.--generatesends one request per suggestion. Duplicates are removed, so you may get fewer than requested.--dry-runprints one subject per line to stdout and errors to stderr. Both preview modes need staged changes and reject--all.- Without an interactive terminal, pass
--yes,--dry-run, or--preview-diff.
By default, lazycommit sends file statistics and the full staged patch when it fits in 16,000 characters. Larger patches are sampled, with omission markers. Raise the budget with --max-diff-chars 24000.
When the file list does not fit either, lazycommit groups files into change areas: it splits the heaviest directories until the list fits, then shows the largest files. Code samples are spread across every area, largest files first, so a 1,000-file change still shows where the work happened.
For changes spread across many files, use --thorough. It summarizes the diff in batches of up to 16,000 characters, combines the notes, and writes the subject from them. It makes more API requests and takes longer; the input limit is 1.6 million characters.
lzc --thorough --type conventional --generate 3
lzc --preview-diff --thorough # inspect the batches locally firstCharacter budgets are not exact token counts, so API limits can still apply.
Lockfiles, minified files, and common build directories appear in the statistics, but their patches are skipped. Include them with --include-generated.
Exclude paths from analysis with repeatable, repository-root Git pathspecs:
lzc --exclude 'dist/**' --exclude '*.log'Exclusions affect analysis only. Excluded files that are staged are still committed. Binary changes and renames show up in the statistics; binary contents are not read.
These pass through to git commit: --signoff (-s), --no-signoff, --no-verify (-n), --author, --date, --trailer, --cleanup, --gpg-sign (-S), --no-gpg-sign, --quiet (-q), and --verbose (-v).
lzc --type conventional --signoff
lzc --author="Your Name <you@example.com>"Options that replace the message or change what gets committed (-m, --amend, paths) are rejected. Use git commit directly for those.
| Option | Behavior | Default / limits |
|---|---|---|
--generate, -g |
Number of suggestions | 1; range 1–5 |
--type, -t |
Plain or conventional subject | "" or conventional |
--scope |
Required conventional scope | Up to 40 characters; needs --type conventional |
--context |
Extra intent or constraints | One line, up to 2,000 characters |
--locale |
Subject language | en; e.g. ja, pt-BR |
--model |
Model as provider/model |
First provider with a key; see Providers |
--max-length |
Maximum subject length | 100; range 20–200 |
--max-diff-chars |
Normal-mode diff budget | 16000; range 1000–100000 |
--timeout |
Per-request timeout (ms) | 10000; range 500–300000 |
--thorough |
Summarize every diff batch first | Off |
--include-generated |
Include generated and lockfile patches | Off |
--exclude, -x |
Exclude a pathspec from analysis | Repeatable |
--all, -a |
Stage tracked modifications and deletions | Off |
--dry-run |
Print suggestions without committing | Off |
--preview-diff |
Print diff context without calling the API | Off |
--yes, -y |
Commit the first suggestion without prompts | Off |
Run lazycommit --help to see the options for your installed version.
Settings are stored in ~/.lazycommit (INI, owner-only permissions). CLI flags override them.
lazycommit config set type=conventional max-length=72 generate=3
lazycommit config get model type max-length
lazycommit config set scope= context= proxy= # clear values
lazycommit model # pick the model from a listKeys: the provider keys from Providers, proxy, model, locale, generate, type, scope, context, timeout, max-length, and max-diff-chars. Defaults and limits match the options table. Switches such as --thorough and --yes apply per run only.
Provider key environment variables override saved keys. Proxy variables override the saved proxy, in this order: https_proxy, HTTPS_PROXY, http_proxy, HTTP_PROXY.
lazycommit config set proxy=http://localhost:8080Generate messages from plain git commit:
lazycommit hook install
git add src/
git commit # the subject opens in your editor for review- With multiple suggestions, uncomment the one you want.
git commit -m "..."skips generation.git commit --no-edituses the first suggestion.
The hook uses normal-mode analysis and your saved settings; --thorough is CLI-only. It installs to .git/hooks/prepare-commit-msg and does not support core.hooksPath or linked worktrees. Remove it with lazycommit hook uninstall.
- Lazycommit snapshots the Git index and analyzes staged content only, including partially staged files. Unstaged edits are never sent.
- It sends that diff context and your instructions to your chosen provider.
--preview-diffbuilds the same context locally without sending it. - Each subject is checked for a single line, length, format, and scope. Invalid subjects get one retry and are never truncated. A subject that is only too long is shortened from a short change overview, without resending the diff. Transient API errors are retried up to twice.
- Before committing, lazycommit checks that the staged tree and HEAD still match what was analyzed. If either changed, it stops.
Always review the result. AI summaries can miss important details.
| Problem | What to try |
|---|---|
| No staged changes | Run lzc in a terminal to pick files, or stage with git add or --all. Also check your exclusions. |
| Subject is too vague | Add --context, try --thorough, or commit related changes separately. |
| No valid subject after retries | Raise --max-length or try another model with lzc model or --model. |
| Unknown model | Run lzc model to pick one your keys can use. |
| Request too large (413) | Lower --max-diff-chars, exclude files, or stage smaller commits. |
| Rate limit (429) | The error says how long to wait. Wait, lower --generate, or skip --thorough. |
| Request timed out | Raise --timeout (e.g. 30000) and check your connection. |
| Authentication (401/403) | Check your API key and its model permissions. |
| Staged content changed during review | Run lazycommit again. |
| Unknown option | Check lazycommit --version and upgrade. |
| Saved settings are ignored | Keys under a section such as [DEFAULT] are not read. Save them again with lazycommit config set. |
Built with TypeScript, cleye, @clack/prompts, execa, and Mastra, bundled with pkgroll.
git clone https://github.com/KartikLabhshetwar/lazycommit.git
cd lazycommit
pnpm install # Node from .nvmrc, pnpm 10.15.0
pnpm type-check && pnpm build && pnpm test
node dist/cli.mjs --helpTests run offline against temporary Git repositories and a mock API. Live Groq tests run when GROQ_API_KEY is set; proxy tests also need LAZYCOMMIT_TEST_PROXY.
| File | Responsibility |
|---|---|
src/utils/git.ts |
Index snapshots, statistics, samples, analysis batches, and staging |
src/utils/ai.ts |
Provider selection, model listing, batch summaries, generation, validation, and API errors |
src/utils/prompt.ts |
Message format and content instructions |
src/commands/lazycommit.ts |
File picking, review, editing, regeneration, previews, committing, and pushing |
src/commands/model.ts |
Interactive model picker |
src/utils/config.ts |
Persistent settings and validation |
tests/regressions.ts |
Offline regression checks |
See CONTRIBUTING.md for the development workflow.
Maintained by Kartik Labhshetwar. Licensed under Apache-2.0.
