|
1 | 1 | # lazycommit |
2 | 2 |
|
3 | | -AI-powered Git commit message generator that analyzes your staged changes and outputs conventional commit messages. |
4 | | - |
5 | | -<video src="https://github-production-user-asset-6210df.s3.amazonaws.com/88824957/518189972-f9819b7b-f33b-4544-9d65-ffee2b7c4244.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAVCODYLSA53PQK4ZA%2F20251124%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20251124T154151Z&X-Amz-Expires=300&X-Amz-Signature=9ad6523cf92ecbe4fad3b218333c036f3a9a56c88bb630a4d53239c4b20ffa78&X-Amz-SignedHeaders=host" controls title="demo"> |
6 | | - Your browser does not support the video tag. |
7 | | -</video> |
| 3 | +AI-powered Git commit message generator. It reads your staged diff, asks an |
| 4 | +LLM through any OpenAI-compatible API, and prints clean commit message |
| 5 | +suggestions — one per line, ready to pipe into lazygit, fzf, or any TUI menu. |
8 | 6 |
|
| 7 | +> [!IMPORTANT] |
| 8 | +> **v2 is a full rewrite and a breaking change.** The v1 configuration format |
| 9 | +> and providers (opencode, Claude Code CLI, Copilot, Gemini) are gone. v2 |
| 10 | +> talks to exactly one backend family: any endpoint speaking the OpenAI |
| 11 | +> chat-completions protocol. Run `lazycommit config set` to start fresh. |
9 | 12 |
|
10 | 13 | ## Features |
11 | 14 |
|
12 | | -- Generates configurable number of commit message suggestions from your staged diff |
13 | | -- Generates 10 pull request titles based on the diff between the current branch and a target branch |
14 | | -- Providers: opencode (default, free models), GitHub Copilot, OpenAI, Anthropic (Claude Code CLI), Gemini CLI |
15 | | -- Multi-language support: Any language (English, Arabic, Korean, etc.) |
16 | | -- Interactive config to pick provider/model/language and set keys |
17 | | -- Simple output suitable for piping into TUI menus (one message per line) |
| 15 | +- Suggests a configurable number of commit messages from `git diff --cached` |
| 16 | +- Suggests pull request titles from the merge-base diff against a target branch |
| 17 | +- Works with any OpenAI-compatible endpoint: OpenAI, Ollama (local, keyless), OpenRouter, LM Studio, enterprise proxies |
| 18 | +- Model fallback chain, request retry, and timeouts built in |
| 19 | +- Any output language (English, Arabic, Korean, ...) |
| 20 | +- Plain-line output designed for piping into TUI menus |
18 | 21 |
|
19 | 22 | ## Installation |
20 | 23 |
|
21 | 24 | ```bash |
22 | 25 | go install github.com/m7medvision/lazycommit@latest |
23 | 26 | ``` |
24 | 27 |
|
25 | | -The default provider is `opencode`, so install and authenticate the `opencode` CLI before running `lazycommit commit`. |
26 | | - |
27 | 28 | Or build from source: |
28 | 29 |
|
29 | 30 | ```bash |
30 | 31 | git clone https://github.com/m7medvision/lazycommit.git |
31 | 32 | cd lazycommit |
32 | | -go build -o lazycommit main.go |
| 33 | +make build |
33 | 34 | ``` |
34 | 35 |
|
35 | | -## CLI |
36 | | - |
37 | | -- Root command: `lazycommit` |
38 | | -- Subcommands: |
39 | | - - `lazycommit commit` — prints 10 suggested commit messages to stdout, one per line, based on `git diff --cached`. |
40 | | - - `lazycommit pr <target-branch>` — prints 10 suggested pull request titles to stdout, one per line, based on diff between current branch and `<target-branch>`. |
41 | | - - `lazycommit config get` — prints the active provider, model and language. |
42 | | - - `lazycommit config set` — interactive setup for provider, API key, model, and language. |
43 | | - |
44 | | -Exit behaviors: |
45 | | -- If no staged changes: prints "No staged changes to commit." and exits 0. |
46 | | -- On config/LLM errors: prints to stderr and exits non‑zero. |
47 | | - |
48 | | -### Examples |
49 | | - |
50 | | -Generate suggestions after staging changes: |
| 36 | +## Quick start |
51 | 37 |
|
52 | 38 | ```bash |
| 39 | +lazycommit config set # choose model, endpoint, key, language |
53 | 40 | git add . |
54 | 41 | lazycommit commit |
55 | 42 | ``` |
56 | 43 |
|
57 | | -Pipe the first suggestion to commit (bash example): |
58 | | - |
59 | | -```bash |
60 | | -MSG=$(lazycommit commit | sed -n '1p') |
61 | | -[ -n "$MSG" ] && git commit -m "$MSG" |
62 | | -``` |
63 | | - |
64 | | -Pick interactively with `fzf`: |
| 44 | +## CLI |
65 | 45 |
|
66 | | -```bash |
67 | | -git add . |
68 | | -lazycommit commit | fzf --prompt='Pick commit> ' | xargs -r -I {} git commit -m "{}" |
69 | | -``` |
| 46 | +- `lazycommit commit` — prints commit message suggestions for the staged diff, one per line. |
| 47 | +- `lazycommit pr <target-branch>` — prints pull request title suggestions for the diff against `<target-branch>`. |
| 48 | +- `lazycommit config set` — interactive setup (model, endpoint, API key, language). |
| 49 | +- `lazycommit config get` — shows the active backend, model, and language; API keys are masked. |
70 | 50 |
|
71 | | -Generate PR titles against `main` branch: |
| 51 | +Exit behavior: |
72 | 52 |
|
73 | | -```bash |
74 | | -lazycommit pr main |
75 | | -``` |
| 53 | +- No staged changes: prints `No staged changes to commit.` and exits 0. |
| 54 | +- Configuration or backend errors: message on stderr, non-zero exit, stdout stays clean. |
76 | 55 |
|
77 | 56 | ## Configuration |
78 | 57 |
|
79 | | -lazycommit uses a two-file configuration system to separate sensitive provider settings from shareable prompt configurations: |
| 58 | +Two files, deliberately split: |
| 59 | + |
| 60 | +### 1. Backend settings — `~/.config/lazycommit/config.yaml` |
80 | 61 |
|
81 | | -### 1. Provider Configuration (`~/.config/.lazycommit.yaml`) |
82 | | -Contains API keys, tokens, and provider-specific settings. **Do not share this file.** |
| 62 | +API keys and endpoints. **Do not commit this file.** It is written with |
| 63 | +owner-only permissions. |
83 | 64 |
|
84 | 65 | ```yaml |
85 | | -active_provider: opencode # default; uses opencode CLI free models |
86 | | -providers: |
87 | | - opencode: |
88 | | - model: "opencode/minimax-m2.5-free" # Uses opencode CLI - no API key needed |
89 | | - fallback_models: |
90 | | - - "opencode/minimax-m2.5-free" |
91 | | - - "opencode/ling-2.6-flash-free" |
92 | | - - "opencode/hy3-preview-free" |
93 | | - - "opencode/nemotron-3-super-free" |
94 | | - num_suggestions: 10 |
95 | | - copilot: |
96 | | - api_key: "$GITHUB_TOKEN" # Uses GitHub token; token is exchanged internally |
97 | | - model: "gpt-4o" # or "openai/gpt-4o"; both accepted |
98 | | - # endpoint_url: "https://api.githubcopilot.com" # Optional - uses default if not specified |
99 | | - openai: |
100 | | - api_key: "$OPENAI_API_KEY" |
101 | | - model: "gpt-4o" |
102 | | - # endpoint_url: "https://api.openai.com/v1" # Optional - uses default if not specified |
103 | | - anthropic: |
104 | | - model: "claude-haiku-4-5" # Uses Claude Code CLI - no API key needed |
105 | | - num_suggestions: 10 # Number of commit suggestions to generate |
106 | | - gemini: |
107 | | - model: "flash" # Uses Gemini CLI - no API key needed |
108 | | - num_suggestions: 10 # Number of commit suggestions to generate |
| 66 | +active_backend: openai-compatible |
| 67 | +backends: |
| 68 | + openai-compatible: |
| 69 | + model: gpt-4o-mini |
| 70 | + api_key: "$OPENAI_API_KEY" # plain value or $ENV_VAR reference |
| 71 | + # base_url: https://api.openai.com/v1 # optional, default is official OpenAI |
| 72 | + # fallback_models: # tried in order when the model fails |
| 73 | + # - gpt-4o |
109 | 74 | ``` |
110 | 75 |
|
111 | | -> [!NOTE] |
112 | | -> `.lazycommit.yaml: language` is removed and please use `.lazycommit.prompts.yaml` instead. |
| 76 | +### 2. Prompt settings — `~/.config/lazycommit/prompts.yaml` |
113 | 77 |
|
114 | | -### 2. Prompt Configuration (`~/.config/.lazycommit.prompts.yaml`) |
115 | | -Contains prompt templates and message configurations. **Safe to share in dotfiles and Git.** |
| 78 | +Shareable, safe for dotfiles: |
116 | 79 |
|
117 | 80 | ```yaml |
118 | | -language: English # commit message language (e.g., "English", "Arabic", "Korean") |
119 | | -system_message: "You are a helpful assistant that generates git commit messages, and pull request titles." |
120 | | -commit_message_template: "Based on the following git diff, generate 10 conventional commit messages. Each message should be on a new line, without any numbering or bullet points:\n\n%s" |
121 | | -pr_title_template: "Based on the following git diff, generate 10 pull request title suggestions. Each title should be on a new line, without any numbering or bullet points:\n\n%s" |
| 81 | +language: English |
| 82 | +num_suggestions: 10 |
| 83 | +# system_message: ... |
| 84 | +# commit_message_template: "... %s" # %s is replaced by the diff |
| 85 | +# pr_title_template: "... %s" |
122 | 86 | ``` |
123 | 87 |
|
124 | | -### Per-Repository Configuration |
| 88 | +Any repository can override prompt settings with a `lazycommit.prompts.yaml` |
| 89 | +in its root; unset fields fall through to the global file, then to built-in |
| 90 | +defaults: |
125 | 91 |
|
126 | | -You can override the prompt configuration on a per-repository basis by creating a `.lazycommit.prompts.yaml` file in the root of your git repository. This is useful for projects that require different languages or commit message formats. |
127 | | - |
128 | | -If a field is missing in your repository-local configuration, the value from the global configuration will be used. |
129 | | - |
130 | | -Example `.lazycommit.prompts.yaml` for a Korean project: |
131 | 92 | ```yaml |
| 93 | +# my-korean-project/lazycommit.prompts.yaml |
132 | 94 | language: Korean |
133 | | -commit_message_template: "Based on the following git diff, generate 5 conventional commit messages:\n\n%s" |
| 95 | +num_suggestions: 5 |
134 | 96 | ``` |
135 | | -This file is automatically created on first run in the global config directory with sensible defaults: |
136 | 97 |
|
137 | | -```yaml |
138 | | -system_message: "You are a helpful assistant that generates git commit messages, and pull request titles." |
139 | | -commit_message_template: "Based on the following git diff, generate 10 conventional commit messages. Each message should be on a new line, without any numbering or bullet points:\n\n%s" |
140 | | -pr_title_template: "Based on the following git diff, generate 10 pull request title suggestions. Each title should be on a new line, without any numbering or bullet points:\n\n%s" |
141 | | -``` |
| 98 | +### Endpoint examples |
142 | 99 |
|
| 100 | +**Ollama (local, no key):** |
143 | 101 |
|
144 | | -### Custom Endpoints |
145 | | - |
146 | | -You can configure custom API endpoints for any provider, which is useful for: |
147 | | -- **Local AI models**: Ollama, LM Studio, or other local inference servers |
148 | | -- **Enterprise proxies**: Internal API gateways or proxy servers |
149 | | -- **Alternative providers**: Any OpenAI-compatible API endpoint |
150 | | - |
151 | | -The `endpoint_url` field is optional. If not specified, the official endpoint for that provider will be used. |
152 | | - |
153 | | -#### Examples |
154 | | - |
155 | | -**Ollama (local):** |
156 | 102 | ```yaml |
157 | | -active_provider: openai # Use openai provider for Ollama compatibility |
158 | | -providers: |
159 | | - openai: |
160 | | - api_key: "ollama" # Ollama doesn't require real API keys |
161 | | - model: "llama3.1:8b" |
162 | | - endpoint_url: "http://localhost:11434/v1" |
| 103 | +active_backend: openai-compatible |
| 104 | +backends: |
| 105 | + openai-compatible: |
| 106 | + model: llama3.1:8b |
| 107 | + base_url: http://localhost:11434/v1 |
163 | 108 | ``` |
164 | 109 |
|
165 | | -<!-- **Z.AI (GLM models):** --> |
166 | | -<!-- ```yaml --> |
167 | | -<!-- active_provider: openai --> |
168 | | -<!-- providers: --> |
169 | | -<!-- openai: --> |
170 | | -<!-- api_key: "$ZAI_API_KEY" --> |
171 | | -<!-- model: "glm-4.6" --> |
172 | | -<!-- endpoint_url: "https://api.z.ai/api/paas/v4/" --> |
173 | | -<!-- ``` --> |
174 | | - |
175 | | -### Language Configuration |
176 | | - |
177 | | -lazycommit supports generating commit messages in any language. Set the `language` field in your prompt config (`.lazycommit.prompts.yaml`): |
| 110 | +**OpenRouter:** |
178 | 111 |
|
179 | 112 | ```yaml |
180 | | -language: Spanish |
181 | | -# or |
182 | | -language: Arabic |
183 | | -# or |
184 | | -language: English # (default) |
| 113 | +active_backend: openai-compatible |
| 114 | +backends: |
| 115 | + openai-compatible: |
| 116 | + model: openai/gpt-4o-mini |
| 117 | + api_key: "$OPENROUTER_API_KEY" |
| 118 | + base_url: https://openrouter.ai/api/v1 |
185 | 119 | ``` |
186 | 120 |
|
187 | | -You can also configure it interactively: |
188 | | - |
189 | | -```bash |
190 | | -lazycommit config set # Select language in the interactive menu |
191 | | -``` |
| 121 | +## Integration with TUI Git clients |
192 | 122 |
|
193 | | -The language setting automatically instructs the AI to generate commit messages in the specified language, regardless of the provider used. |
| 123 | +`lazycommit commit` prints plain lines, so it plugs directly into menu UIs. |
194 | 124 |
|
195 | | -## Integration with TUI Git clients |
| 125 | +### fzf |
196 | 126 |
|
197 | | -Because `lazycommit commit` prints plain lines, it plugs nicely into menu UIs. |
| 127 | +```bash |
| 128 | +git add . |
| 129 | +lazycommit commit | fzf --prompt='Pick commit> ' | xargs -r -I {} git commit -m "{}" |
| 130 | +``` |
198 | 131 |
|
199 | | -### Lazygit custom command |
| 132 | +### Lazygit |
200 | 133 |
|
201 | | -Add this to `~/.config/lazygit/config.yml`: |
| 134 | +Add to `~/.config/lazygit/config.yml`: |
202 | 135 |
|
203 | 136 | ```yaml |
204 | 137 | customCommands: |
205 | | - - key: "<c-a>" # ctrl + a |
| 138 | + - key: "<c-a>" |
206 | 139 | description: "pick AI commit" |
207 | 140 | command: 'git commit -m "{{.Form.Msg}}"' |
208 | 141 | context: "files" |
209 | 142 | prompts: |
210 | 143 | - type: "menuFromCommand" |
211 | | - title: "ai Commits" |
| 144 | + title: "AI commits" |
212 | 145 | key: "Msg" |
213 | 146 | command: "lazycommit commit" |
214 | | - filter: '^(?P<raw>.+)$' |
| 147 | + filter: "^(?P<raw>.+)$" |
215 | 148 | valueFormat: "{{ .raw }}" |
216 | 149 | labelFormat: "{{ .raw | green }}" |
217 | 150 | ``` |
218 | 151 |
|
219 | | -This config will allows you to edit the commit message after picking from lazycommit suggestions. |
| 152 | +Variant that lets you edit the message before committing: |
| 153 | + |
220 | 154 | ```yaml |
221 | | - - key: "<c-b>" # ctrl + b |
| 155 | + - key: "<c-b>" |
222 | 156 | description: "Pick AI commit (edit before committing)" |
223 | 157 | context: "files" |
224 | 158 | command: > |
225 | 159 | bash -c 'msg="{{.Form.Msg}}"; echo "$msg" > .git/COMMIT_EDITMSG && ${EDITOR:-nvim} .git/COMMIT_EDITMSG && if [ -s .git/COMMIT_EDITMSG ]; then |
226 | | -
|
227 | 160 | git commit -F .git/COMMIT_EDITMSG; |
228 | 161 | else |
229 | | -
|
230 | 162 | echo "Commit message is empty, commit aborted."; |
231 | 163 | fi' |
232 | | -
|
233 | 164 | prompts: |
234 | 165 | - type: "menuFromCommand" |
235 | | - title: "ai Commits" |
| 166 | + title: "AI commits" |
236 | 167 | key: "Msg" |
237 | 168 | command: "lazycommit commit" |
238 | | - filter: '^(?P<raw>.+)$' |
| 169 | + filter: "^(?P<raw>.+)$" |
239 | 170 | valueFormat: "{{ .raw }}" |
240 | 171 | labelFormat: "{{ .raw | green }}" |
241 | 172 | output: terminal |
242 | 173 | ``` |
243 | 174 |
|
244 | | - |
245 | | - |
246 | | -### Commitizen |
247 | | - |
248 | | -First, install the Commitizen plugin: |
249 | | - |
250 | | -```bash |
251 | | -pip install cz-lazycommit |
252 | | -# or if you are using Arch Linux: |
253 | | -uv tool install commitizen --with cz-lazycommit |
254 | | -``` |
255 | | - |
256 | | -Then use the plugin with the following command: |
257 | | - |
258 | | -```bash |
259 | | -git cz --name cz_lazycommit commit |
260 | | -``` |
261 | | - |
262 | | -If you are using Commitizen with Lazygit, you can add this custom command: |
263 | | - |
264 | | -```yaml |
265 | | - - key: "C" |
266 | | - command: "git cz --name cz_lazycommit commit" |
267 | | - description: "Commit with Commitizen" |
268 | | - context: "files" |
269 | | - loadingText: "Opening Commitizen commit tool" |
270 | | - output: terminal |
271 | | -``` |
272 | | - |
273 | | - |
274 | 175 | ## Troubleshooting |
275 | 176 |
|
276 | | -- "No staged changes to commit." — run `git add` first. |
277 | | -- "opencode CLI not found" — install `opencode` or switch providers with `lazycommit config set`. |
278 | | -- "API key not set" — set the appropriate key in `.lazycommit.yaml` or env var and rerun. |
279 | | -- Copilot errors about token exchange — ensure your GitHub token has models scope or is valid; try setting `GITHUB_TOKEN`. |
| 177 | +- `No staged changes to commit.` — run `git add` first. |
| 178 | +- `has no model configured` — run `lazycommit config set`. |
| 179 | +- `environment variable X is not set` — your config references `$X`; export it or store the key directly. |
| 180 | +- Found v1 config note — v2 uses a new format; run `lazycommit config set` once and delete the old `~/.config/.lazycommit.yaml`. |
280 | 181 |
|
281 | 182 | ## License |
282 | 183 |
|
|
0 commit comments