commitai 0.1.16__py3-none-any.whl → 1.0.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
commitai/__init__.py CHANGED
@@ -0,0 +1,10 @@
1
+ # File: commitai/__init__.py
2
+ # -*- coding: utf-8 -*-
3
+
4
+ # This __version__ string is read by hatchling during the build process
5
+ # Make sure to update it for new releases.
6
+ __version__ = "0.3.0"
7
+
8
+ # The importlib.metadata approach is generally for reading the version
9
+ # of an *already installed* package at runtime. We don't need it here
10
+ # for defining the package's own version during build.
commitai/cli.py CHANGED
@@ -1,10 +1,23 @@
1
+ # File: commitai/cli.py
1
2
  # -*- coding: utf-8 -*-
3
+
2
4
  import os
5
+ from typing import Optional, Tuple, cast
3
6
 
4
7
  import click
5
8
  from langchain_anthropic import ChatAnthropic
9
+ from langchain_core.language_models.chat_models import BaseChatModel
10
+ from langchain_ollama import ChatOllama
6
11
  from langchain_openai import ChatOpenAI
7
12
 
13
+ # Keep SecretStr import in case it's needed elsewhere or for future refinement
14
+
15
+ # Conditional import for Google Generative AI
16
+ try:
17
+ from langchain_google_genai import ChatGoogleGenerativeAI
18
+ except ImportError:
19
+ ChatGoogleGenerativeAI = None # type: ignore
20
+
8
21
  from commitai.git import (
9
22
  create_commit,
10
23
  get_commit_template,
@@ -22,8 +35,133 @@ from commitai.template import (
22
35
  )
23
36
 
24
37
 
25
- @click.group(context_settings=dict(help_option_names=["-h", "--help"]))
26
- def cli():
38
+ def _get_google_api_key() -> Optional[str]:
39
+ """Gets the Google API key from environment variables in priority order."""
40
+ return (
41
+ os.getenv("GOOGLE_API_KEY")
42
+ or os.getenv("GEMINI_API_KEY")
43
+ or os.getenv("GOOGLE_GENERATIVE_AI_API_KEY")
44
+ )
45
+
46
+
47
+ def _initialize_llm(model: str) -> BaseChatModel:
48
+ """Initializes and returns the LangChain chat model based on the model name."""
49
+ google_api_key_str = _get_google_api_key()
50
+
51
+ try:
52
+ if model.startswith("gpt-"):
53
+ api_key = os.getenv("OPENAI_API_KEY")
54
+ if not api_key:
55
+ raise click.ClickException(
56
+ "Error: OPENAI_API_KEY environment variable not set."
57
+ )
58
+ return ChatOpenAI(model=model, api_key=api_key, temperature=0.7)
59
+
60
+ elif model.startswith("claude-"):
61
+ api_key = os.getenv("ANTHROPIC_API_KEY")
62
+ if not api_key:
63
+ raise click.ClickException(
64
+ "Error: ANTHROPIC_API_KEY environment variable not set."
65
+ )
66
+ return ChatAnthropic(model_name=model, api_key=api_key, temperature=0.7)
67
+
68
+ elif model.startswith("gemini-"):
69
+ if ChatGoogleGenerativeAI is None:
70
+ raise click.ClickException(
71
+ "Error: 'langchain-google-genai' is not installed. "
72
+ "Run 'pip install commitai[test]' or "
73
+ "'pip install langchain-google-genai'"
74
+ )
75
+ if not google_api_key_str:
76
+ raise click.ClickException(
77
+ "Error: Google API Key not found. Set GOOGLE_API_KEY, "
78
+ "GEMINI_API_KEY, or GOOGLE_GENERATIVE_AI_API_KEY."
79
+ )
80
+ return ChatGoogleGenerativeAI(
81
+ model=model,
82
+ google_api_key=google_api_key_str,
83
+ temperature=0.7,
84
+ convert_system_message_to_human=True,
85
+ )
86
+ elif model.startswith("llama"):
87
+ # Ollama models (e.g., llama2, llama3)
88
+ return cast(BaseChatModel, ChatOllama(model=model, temperature=0.7))
89
+ else:
90
+ raise click.ClickException(f"🚫 Unsupported model: {model}")
91
+
92
+ except Exception as e:
93
+ raise click.ClickException(f"Error initializing AI model: {e}") from e
94
+
95
+
96
+ def _prepare_context() -> str:
97
+ diff = get_staged_changes_diff()
98
+ if not diff:
99
+ raise click.ClickException("⚠️ Warning: No staged changes found. Exiting.")
100
+
101
+ repo_name = get_repository_name()
102
+ branch_name = get_current_branch_name()
103
+ return f"{repo_name}/{branch_name}\n\n{diff}"
104
+
105
+
106
+ def _build_prompt(
107
+ explanation: str, formatted_diff: str, template: Optional[str]
108
+ ) -> str:
109
+ system_message = default_system_message
110
+ if template:
111
+ system_message += adding_template
112
+ system_message += template
113
+
114
+ if explanation:
115
+ diff_message = build_user_message(explanation, formatted_diff)
116
+ else:
117
+ diff_message = formatted_diff
118
+
119
+ return f"{system_message}\n\n{diff_message}"
120
+
121
+
122
+ def _handle_commit(commit_message: str, commit_flag: bool) -> None:
123
+ repo_path = get_repository_name()
124
+ git_dir = os.path.join(repo_path, ".git")
125
+ try:
126
+ os.makedirs(git_dir, exist_ok=True)
127
+ except OSError as e:
128
+ raise click.ClickException(f"Error creating .git directory: {e}") from e
129
+
130
+ commit_msg_path = os.path.join(git_dir, "COMMIT_EDITMSG")
131
+
132
+ try:
133
+ with open(commit_msg_path, "w") as f:
134
+ f.write(commit_message)
135
+ except IOError as e:
136
+ raise click.ClickException(f"Error writing commit message file: {e}") from e
137
+
138
+ final_commit_message = commit_message
139
+ if not commit_flag:
140
+ try:
141
+ click.edit(filename=commit_msg_path)
142
+ with open(commit_msg_path, "r") as f:
143
+ final_commit_message = f.read().strip()
144
+ except click.UsageError as e:
145
+ click.secho(f"Could not open editor: {e}", fg="yellow")
146
+ click.secho(f"Using generated message:\n\n{commit_message}\n", fg="yellow")
147
+ except IOError as e:
148
+ raise click.ClickException(
149
+ f"Error reading commit message file after edit: {e}"
150
+ ) from e
151
+
152
+ if not final_commit_message:
153
+ raise click.ClickException("Aborting commit due to empty commit message.")
154
+
155
+ create_commit(final_commit_message)
156
+ click.secho(
157
+ f"\n\n✅ Committed message:\n\n{final_commit_message}\n\n",
158
+ fg="green",
159
+ bold=True,
160
+ )
161
+
162
+
163
+ @click.group(context_settings={"help_option_names": ["-h", "--help"]})
164
+ def cli() -> None:
27
165
  pass
28
166
 
29
167
 
@@ -39,7 +177,9 @@ def cli():
39
177
  "--template",
40
178
  "-t",
41
179
  default=None,
42
- help="Specify a commit message template",
180
+ help=(
181
+ "Specify a commit message template (DEPRECATED: Use env var or create-template)"
182
+ ),
43
183
  )
44
184
  @click.option(
45
185
  "--add",
@@ -50,18 +190,24 @@ def cli():
50
190
  @click.option(
51
191
  "--model",
52
192
  "-m",
53
- default="claude-opus",
54
- help="Set the engine model to be used",
193
+ default="gemini-2.5-pro-preview-03-25",
194
+ help=(
195
+ "Set the engine model (e.g., 'gpt-4', 'claude-3-opus-20240229', "
196
+ "'gemini-2.5-pro-preview-03-25'). Ensure API key env var is set "
197
+ "(OPENAI_API_KEY, ANTHROPIC_API_KEY, "
198
+ "GOOGLE_API_KEY/GEMINI_API_KEY/GOOGLE_GENERATIVE_AI_API_KEY)."
199
+ ),
55
200
  )
56
- def generate_message(description, commit, template, add, model):
201
+ def generate_message(
202
+ description: Tuple[str, ...],
203
+ commit: bool,
204
+ template: Optional[str],
205
+ add: bool,
206
+ model: str,
207
+ ) -> None:
57
208
  explanation = " ".join(description)
58
- if model == "gpt-4":
59
- llm = ChatOpenAI(model_name="gpt-4")
60
- elif model == "claude-opus":
61
- llm = ChatAnthropic(model="claude-3-opus-20240229")
62
- else:
63
- click.secho(f"🚫 Unsupported model: {model}", fg="red", bold=True)
64
- return
209
+
210
+ llm = _initialize_llm(model)
65
211
 
66
212
  if add:
67
213
  stage_all_changes()
@@ -71,82 +217,59 @@ def generate_message(description, commit, template, add, model):
71
217
  fg="blue",
72
218
  bold=True,
73
219
  )
74
-
75
220
  if not run_pre_commit_hook():
76
- click.secho(
77
- "🚫 Pre-commit hook failed. Aborting commit.",
78
- fg="red",
79
- bold=True,
80
- )
81
- return
221
+ raise click.ClickException("🚫 Pre-commit hook failed. Aborting commit.")
82
222
 
83
- diff = get_staged_changes_diff()
84
- if not diff:
223
+ formatted_diff = _prepare_context()
224
+
225
+ if template:
85
226
  click.secho(
86
- "⚠️ Warning: No staged changes found. Exiting.",
227
+ "⚠️ Warning: The --template/-t option is deprecated. Use environment "
228
+ "variable TEMPLATE_COMMIT or `commitai-create-template` command.",
87
229
  fg="yellow",
88
- bold=True,
89
230
  )
90
- return
231
+ final_template = template or get_commit_template()
91
232
 
92
- # Clear the terminal using click
93
- click.clear()
94
-
95
- repo_name = get_repository_name()
96
- branch_name = get_current_branch_name()
97
- formatted_diff = f"{repo_name}/{branch_name}\n\n{diff}"
98
-
99
- if not template:
100
- template = get_commit_template()
101
- system_message: str = ""
102
- if template:
103
- system_message += default_system_message
104
- system_message += adding_template
105
- system_message += template
106
-
107
- if explanation:
108
- diff = build_user_message(explanation, formatted_diff)
233
+ input_message = _build_prompt(explanation, formatted_diff, final_template)
109
234
 
110
- input_message = f"{system_message}\n\n{diff}"
235
+ click.clear()
111
236
  click.secho(
112
237
  "\n\n🧠 Analyzing the changes and generating a commit message...\n\n",
113
238
  fg="blue",
114
239
  bold=True,
115
- ),
116
- ai_message = llm.invoke(input=input_message)
117
- commit_message = ai_message.content
118
-
119
- repo_path = get_repository_name()
120
- commit_msg_path = os.path.join(repo_path, ".git", "COMMIT_EDITMSG")
121
- with open(commit_msg_path, "w") as f:
122
- f.write(commit_message)
240
+ )
241
+ try:
242
+ assert llm is not None
243
+ ai_message = llm.invoke(input=input_message)
244
+ commit_message = ai_message.content
245
+ if not isinstance(commit_message, str):
246
+ commit_message = str(commit_message)
123
247
 
124
- if not commit:
125
- click.edit(filename=commit_msg_path)
248
+ except Exception as e:
249
+ raise click.ClickException(f"Error during AI generation: {e}") from e
126
250
 
127
- with open(commit_msg_path, "r") as f:
128
- final_commit_message = f.read().strip()
129
-
130
- create_commit(final_commit_message)
131
- click.secho(
132
- f"\n\n✅ Committed message:\n\n{final_commit_message}\n\n",
133
- fg="green",
134
- bold=True,
135
- )
251
+ _handle_commit(commit_message, commit)
136
252
 
137
253
 
138
254
  @cli.command(name="create-template")
139
255
  @click.argument("template_content", nargs=-1, type=click.UNPROCESSED)
140
- def create_template_command(template_content):
141
- template_content = " ".join(template_content)
142
- if template_content:
143
- save_commit_template(template_content)
256
+ def create_template_command(template_content: Tuple[str, ...]) -> None:
257
+ """Saves a repository-specific commit template."""
258
+ content = " ".join(template_content)
259
+ if content:
260
+ save_commit_template(content)
144
261
  click.secho("📝 Template saved successfully.", fg="green")
145
262
  else:
146
263
  click.secho("❗ Please provide the template content.", fg="red")
147
264
 
148
265
 
149
- @click.command(name="commitai")
266
+ # --- Alias Commands ---
267
+
268
+
269
+ @click.command(
270
+ name="commitai",
271
+ context_settings={"ignore_unknown_options": True},
272
+ )
150
273
  @click.argument("description", nargs=-1, type=click.UNPROCESSED)
151
274
  @click.option(
152
275
  "--add",
@@ -160,27 +283,38 @@ def create_template_command(template_content):
160
283
  is_flag=True,
161
284
  help="Commit the changes with the generated message",
162
285
  )
286
+ @click.option(
287
+ "--model",
288
+ "-m",
289
+ default="gemini-2.5-pro-preview-03-25",
290
+ help="Set the engine model to be used.",
291
+ )
163
292
  @click.pass_context
164
- def commitai(ctx, description, add, commit):
165
- if add:
166
- stage_all_changes()
167
- ctx.invoke(
168
- generate_message,
169
- description=description,
170
- add=add,
171
- commit=commit,
293
+ def commitai_alias(
294
+ ctx: click.Context,
295
+ description: Tuple[str, ...],
296
+ add: bool,
297
+ commit: bool,
298
+ model: str,
299
+ ) -> None:
300
+ """Alias for the 'generate' command."""
301
+ ctx.forward(
302
+ generate_message, description=description, add=add, commit=commit, model=model
172
303
  )
173
304
 
174
305
 
175
306
  @click.command(name="commitai-create-template")
176
307
  @click.argument("template_content", nargs=-1, type=click.UNPROCESSED)
177
308
  @click.pass_context
178
- def commitai_create_template(ctx, template_content):
179
- ctx.invoke(create_template_command, template_content=template_content)
309
+ def commitai_create_template_alias(
310
+ ctx: click.Context, template_content: Tuple[str, ...]
311
+ ) -> None:
312
+ """Alias for the 'create-template' command."""
313
+ ctx.forward(create_template_command, template_content=template_content)
180
314
 
181
315
 
182
- cli.add_command(commitai)
183
- cli.add_command(commitai_create_template)
316
+ cli.add_command(commitai_alias)
317
+ cli.add_command(commitai_create_template_alias)
184
318
 
185
319
 
186
320
  if __name__ == "__main__":
commitai/template.py CHANGED
@@ -14,12 +14,12 @@ default_system_message = (
14
14
  "Footer can contain references to issues, pull requests, or breaking changes."
15
15
  "Avoid generic messages like 'update', 'fix bugs', or 'improve code'."
16
16
  "Focus on the specific changes made and their impact."
17
+ "Don't wrap the text in the commit message, or anything like that this text is a commit message directed sent to the user editor in commit process"
18
+ "Don't include codeblock on the response as ``` or anything like that we need raw git message as raw txt"
17
19
  )
18
20
 
19
21
  adding_template = " The message should follow this template: "
20
22
 
21
23
 
22
24
  def build_user_message(explanation, diff):
23
- return (
24
- f"Here is a high-level explanation of the commit: {explanation}" f"\n\n{diff}"
25
- )
25
+ return f"Here is a high-level explanation of the commit: {explanation}\n\n{diff}"
@@ -0,0 +1,316 @@
1
+ Metadata-Version: 2.4
2
+ Name: commitai
3
+ Version: 1.0.5
4
+ Summary: Commitai helps you generate git commit messages using AI
5
+ Project-URL: Bug Tracker, https://github.com/lguibr/commitai/issues
6
+ Project-URL: Documentation, https://github.com/lguibr/commitai/blob/main/README.md
7
+ Project-URL: Source Code, https://github.com/lguibr/commitai
8
+ Author-email: Luis Guilherme <lgpelin92@gmail.com>
9
+ License: # File: LICENSE
10
+ MIT License
11
+
12
+ Copyright (c) 2024 Luis Guilherme
13
+
14
+ Permission is hereby granted, free of charge, to any person obtaining a copy
15
+ of this software and associated documentation files (the "Software"), to deal
16
+ in the Software without restriction, including without limitation the rights
17
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18
+ copies of the Software, and to permit persons to whom the Software is
19
+ furnished to do so, subject to the following conditions:
20
+
21
+ The above copyright notice and this permission notice shall be included in all
22
+ copies or substantial portions of the Software.
23
+
24
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
+ SOFTWARE.
31
+ License-File: LICENSE
32
+ Classifier: Development Status :: 4 - Beta
33
+ Classifier: Intended Audience :: Developers
34
+ Classifier: License :: OSI Approved :: MIT License
35
+ Classifier: Operating System :: OS Independent
36
+ Classifier: Programming Language :: Python :: 3
37
+ Classifier: Programming Language :: Python :: 3.9
38
+ Classifier: Programming Language :: Python :: 3.10
39
+ Classifier: Programming Language :: Python :: 3.11
40
+ Classifier: Programming Language :: Python :: 3.12
41
+ Classifier: Topic :: Software Development :: Version Control :: Git
42
+ Classifier: Topic :: Utilities
43
+ Requires-Python: >=3.9
44
+ Requires-Dist: click<9.0,>=8.0
45
+ Requires-Dist: langchain-anthropic<=0.3.12,>=0.1.0
46
+ Requires-Dist: langchain-community<=0.3.23,>=0.0.20
47
+ Requires-Dist: langchain-core<=0.3.58,>=0.1.0
48
+ Requires-Dist: langchain-google-genai~=2.1.4
49
+ Requires-Dist: langchain-ollama~=0.3.2
50
+ Requires-Dist: langchain-openai<=0.3.16,>=0.1.0
51
+ Requires-Dist: langchain<=0.3.25,>=0.1.0
52
+ Requires-Dist: pydantic<3.0,>=2.0
53
+ Provides-Extra: test
54
+ Requires-Dist: langchain-google-genai~=2.1.4; extra == 'test'
55
+ Requires-Dist: mypy>=1.9.0; extra == 'test'
56
+ Requires-Dist: pytest-cov>=3.0; extra == 'test'
57
+ Requires-Dist: pytest>=7.0; extra == 'test'
58
+ Requires-Dist: ruff==0.4.4; extra == 'test'
59
+ Requires-Dist: types-setuptools; extra == 'test'
60
+ Description-Content-Type: text/markdown
61
+
62
+ # CommitAi - Your AI-Powered Commit Assistant
63
+
64
+ [![CI and Publish](https://github.com/lguibr/commitai/actions/workflows/main.yml/badge.svg)](https://github.com/lguibr/commitai/actions/workflows/main.yml)
65
+ [![codecov](https://codecov.io/gh/lguibr/commitai/graph/badge.svg?token=MXZKCXO6LA)](https://codecov.io/gh/lguibr/commitai) <!-- Added Codecov Badge -->
66
+ [![PyPI](https://img.shields.io/pypi/v/CommitAi.svg)](https://pypi.org/project/CommitAi/)
67
+ [![Python Version](https://img.shields.io/pypi/pyversions/CommitAi.svg)](https://pypi.org/project/CommitAi/)
68
+ [![License](https://img.shields.io/pypi/l/CommitAi.svg)](https://github.com/lguibr/CommitAi/blob/main/LICENSE)
69
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
70
+
71
+
72
+ <img
73
+ src="https://raw.githubusercontent.com/lguibr/commitai/main/bitmap.png"
74
+ alt="screenshot"
75
+ width="400"
76
+ />
77
+
78
+
79
+ **Tired of writing Git commit messages? Let AI do the heavy lifting!**
80
+
81
+ **CommitAi** streamlines your Git workflow by leveraging powerful AI models (OpenAI's GPT, Anthropic's Claude, Google's Gemini) to automatically generate clear, concise, and conventional commit messages based on your staged changes.
82
+
83
+ Simply stage your files and run `commitai`. It analyzes the diff, optionally takes your high-level explanation, and crafts a commit message adhering to the [Conventional Commits](https://www.conventionalcommits.org/) standard. Review the message in your default Git editor, make any tweaks, save, and you're done!
84
+
85
+ ## Table of Contents
86
+
87
+ - [CommitAi - Your AI-Powered Commit Assistant](#commitai---your-ai-powered-commit-assistant)
88
+ - [Table of Contents](#table-of-contents)
89
+ - [Features](#features)
90
+ - [Demo](#demo)
91
+ - [Installation](#installation)
92
+ - [Configuration](#configuration)
93
+ - [API Keys](#api-keys)
94
+ - [Commit Templates (Optional)](#commit-templates-optional)
95
+ - [Usage](#usage)
96
+ - [Basic Workflow](#basic-workflow)
97
+ - [Command-Line Options](#command-line-options)
98
+ - [Creating Repository Templates](#creating-repository-templates)
99
+ - [Examples](#examples)
100
+ - [Contributing](#contributing)
101
+ - [License](#license)
102
+
103
+ ## Features
104
+
105
+ * 🧠 **Intelligent Commit Generation**: Analyzes staged code differences (`git diff --staged`) using state-of-the-art AI models (GPT, Claude, Gemini) to create meaningful commit messages.
106
+ * 📄 **Conventional Commits**: Automatically formats messages according to the Conventional Commits specification (e.g., `feat(auth): add JWT authentication`). This improves readability and enables automated changelog generation.
107
+ * 📝 **Optional Explanations**: Provide a high-level description of your changes as input to guide the AI, or let it infer the context solely from the code diff.
108
+ * ✅ **Pre-commit Hook Integration**: Automatically runs your existing native Git pre-commit hook (`.git/hooks/pre-commit`) before generating the message, ensuring code quality and style checks pass.
109
+ * 🔧 **Customizable Prompts via Templates**: Add custom instructions or context to the AI prompt using global environment variables or repository-specific template files.
110
+ * 🤖 **Multiple AI Provider Support**: Choose your preferred AI model from OpenAI, Anthropic, Google or local AI models with Ollama.
111
+ * ⚙️ **Flexible Workflow**:
112
+ * Stages all changes automatically (`-a` flag).
113
+ * Reviews message in your default Git editor (default behavior).
114
+ * Commits directly without editor review (`-c` flag).
115
+ * ✨ **Modern Tooling**: Built with `pyproject.toml` and formatted/linted with `ruff`.
116
+
117
+ ## Demo
118
+
119
+ ![CommitAi Demo](./assets/commitaai.gif)
120
+
121
+ *(Demo shows generating a commit message using Claude 3 Opus without providing an explicit explanation)*
122
+
123
+ ## Installation
124
+
125
+ Ensure you have Python 3.8+ and Git installed.
126
+
127
+ Install **CommitAi** directly from PyPI:
128
+
129
+ ```bash
130
+ pip install commitai
131
+ ```
132
+
133
+ ## Configuration
134
+
135
+ ### API Keys
136
+
137
+ CommitAi requires API keys for the AI provider you intend to use. Set these as environment variables:
138
+
139
+ * **OpenAI (GPT models):**
140
+ ```bash
141
+ export OPENAI_API_KEY="your_openai_api_key_here"
142
+ ```
143
+
144
+ * **Anthropic (Claude models):**
145
+ ```bash
146
+ export ANTHROPIC_API_KEY="your_anthropic_api_key_here"
147
+ ```
148
+
149
+ * **Google (Gemini models):**
150
+ Set **one** of the following (CommitAi checks in this priority order):
151
+ 1. `GOOGLE_API_KEY` (Recommended)
152
+ 2. `GEMINI_API_KEY`
153
+ 3. `GOOGLE_GENERATIVE_AI_API_KEY`
154
+
155
+ Example:
156
+ ```bash
157
+ export GOOGLE_API_KEY="your_google_api_key_here"
158
+ ```
159
+
160
+ You only need to set the key for the provider corresponding to the model you select (or the default, Gemini).
161
+
162
+ ### Ollama
163
+
164
+ CommitAi can also work with Ollama models:
165
+ ```bash
166
+ export OLLAMA_HOST="your_ollama_base_url"
167
+ ```
168
+
169
+
170
+ ### Commit Templates (Optional)
171
+
172
+ You can add custom instructions to the default system prompt used by the AI. This is useful for enforcing project-specific guidelines (e.g., mentioning ticket numbers).
173
+
174
+ * **Global Template:** Set an environment variable. This applies to all repositories unless overridden locally.
175
+ ```bash
176
+ # Example: Always ask the AI to reference a JIRA ticket format
177
+ export TEMPLATE_COMMIT="Ensure the commit footer includes a JIRA reference like 'Refs: PROJECT-123'."
178
+ ```
179
+
180
+ * **Repository-Specific Template:** Use the `commitai-create-template` command within your repository. This creates a `.git/commit_template.txt` file and overrides the global `TEMPLATE_COMMIT` variable for this repo only.
181
+ ```bash
182
+ # Example: Instruct the AI to focus on UI changes for this specific repo
183
+ commitai-create-template "Focus the commit message body on user-facing UI changes."
184
+ ```
185
+
186
+ **Note:** These templates *add* to the default system prompt, which already instructs the AI to follow Conventional Commits format. You are providing supplementary instructions.
187
+
188
+ ## Usage
189
+
190
+ ### Basic Workflow
191
+
192
+ 1. **Make your code changes.**
193
+ 2. **Stage the changes** you want to include in the commit:
194
+ ```bash
195
+ git add <file1> <file2> ...
196
+ # or stage all changes in tracked files
197
+ git add .
198
+ # or stage all changes including untracked files
199
+ git add --all
200
+ ```
201
+ 3. **Run `commitai`:**
202
+ ```bash
203
+ # Option 1: Let CommitAi infer the message from the diff
204
+ commitai
205
+
206
+ # Option 2: Provide a high-level explanation to guide the AI
207
+ commitai "Refactor user authentication to use JWT tokens"
208
+ ```
209
+ 4. **Review & Edit:** CommitAi runs pre-commit hooks, generates the message, and opens it in your default Git editor (e.g., Vim, Nano, VS Code). Review the message, make any necessary edits.
210
+ 5. **Save & Close:** Save the file and close the editor. CommitAi will then create the commit with the final message. If you close without saving or clear the message, the commit will be aborted.
211
+
212
+ ### Command-Line Options
213
+
214
+ The `commitai` command (which is an alias for `commitai generate`) accepts the following options:
215
+
216
+ * `-a`, `--add`:
217
+ * Automatically stages *all* unstaged changes (`git add --all`) before generating the commit message.
218
+ * Useful for quickly committing everything in the working directory.
219
+ * Example: `commitai -a "Implement user profile page"`
220
+
221
+ * `-c`, `--commit`:
222
+ * Skips opening the Git editor for review. The generated message is used to create the commit directly.
223
+ * **Use with caution!** Reviewing AI-generated messages is recommended.
224
+ * Example: `commitai -c "Fix typo in documentation"` (for minor changes)
225
+ * Can be combined with `-a`: `commitai -a -c "Quick fix and commit all"`
226
+
227
+ * `-m <model_name>`, `--model <model_name>`:
228
+ * Specifies which AI model to use.
229
+ * Defaults to `gemini-2.5-pro-preview-03-25`.
230
+ * Ensure the corresponding API key environment variable is set.
231
+ * Examples:
232
+ * `commitai -m gpt-4 "Use OpenAI's GPT-4"`
233
+ * `commitai -m claude-3-opus-20240229 "Use Anthropic's Claude 3 Opus"`
234
+ * `commitai -m gemini-2.5-flash-preview-04-17 "Use Google's Gemini 1.5 Flash"`
235
+
236
+ ### Creating Repository Templates
237
+
238
+ The `commitai-create-template` command sets a repository-specific template instruction.
239
+
240
+ ```bash
241
+ commitai-create-template "Add a 'Co-authored-by:' line if applicable."
242
+ ```
243
+
244
+ This creates/overwrites the `.git/commit_template.txt` file in the current repository.
245
+
246
+ ## Examples
247
+
248
+ **1. Simple commit, inferred message:**
249
+
250
+ ```bash
251
+ # Stage changes
252
+ git add src/utils.py tests/test_utils.py
253
+
254
+ # Run commitai - AI infers message from diff
255
+ commitai
256
+ ```
257
+ *(Editor opens with a message like `feat(utils): add helper function for data validation`)*
258
+
259
+ **2. Commit with explanation:**
260
+
261
+ ```bash
262
+ # Stage changes
263
+ git add src/auth.py
264
+
265
+ # Run commitai with explanation
266
+ commitai "Implement password reset functionality using email tokens"
267
+ ```
268
+ *(Editor opens with a message like `feat(auth): implement password reset via email token`)*
269
+
270
+ **3. Stage all and commit directly (no editor):**
271
+
272
+ ```bash
273
+ # Stage all changes and commit immediately using GPT-4
274
+ commitai -a -c -m gpt-4 "Minor refactoring and cleanup"
275
+ ```
276
+ *(Commit is created directly)*
277
+
278
+ **4. Using a Template:**
279
+
280
+ * First, set a template:
281
+ ```bash
282
+ commitai-create-template "Mention the related issue number from GitHub, e.g., Fixes #123."
283
+ ```
284
+ * Then, run commitai:
285
+ ```bash
286
+ git add src/parser.py
287
+ commitai "Fix bug in CSV parsing logic"
288
+ ```
289
+ *(Editor opens with a message potentially like `fix(parser): correct handling of quoted commas\n\nFixes #123`)*
290
+
291
+ ## Contributing
292
+
293
+ Contributions are highly welcome! Please follow these steps:
294
+
295
+ 1. Fork the repository on GitHub.
296
+ 2. Clone your fork locally: `git clone <your-fork-url>`
297
+ 3. Navigate to the project directory: `cd commitai`
298
+ 4. Create a virtual environment: `python -m venv .venv && source .venv/bin/activate` (or `.\.venv\Scripts\activate` on Windows)
299
+ 5. Install dependencies, including development tools: `pip install -e ".[test]"`
300
+ 6. **(Optional but Recommended)** Set up pre-commit hooks: `pre-commit install`
301
+ 7. Create a new branch for your feature or bug fix: `git checkout -b my-feature-branch`
302
+ 8. Make your changes.
303
+ 9. Run checks locally before committing:
304
+ * Format code: `ruff format .`
305
+ * Lint code: `ruff check .`
306
+ * Run type checks: `mypy commitai tests`
307
+ * Run tests: `pytest`
308
+ 10. Commit your changes (you can use `commitai`!).
309
+ 11. Push your branch to your fork: `git push origin my-feature-branch`
310
+ 12. Open a pull request on the main `lguibr/commitai` repository.
311
+
312
+ The CI pipeline will automatically run all checks on your pull request.
313
+
314
+ ## License
315
+
316
+ **CommitAi** is open-source software licensed under the MIT License. See the [LICENSE](https://github.com/lguibr/CommitAi/blob/main/LICENSE) file for more details.
@@ -0,0 +1,9 @@
1
+ commitai/__init__.py,sha256=Z5hB8NLKlfi7oPDRcDSQmtPSo_arLjoa6jwjFt3Pb9o,388
2
+ commitai/cli.py,sha256=ClIF6hLekc4gRg9IAUDK9d-y4ee7kvJcZuTt9NCfFRg,9732
3
+ commitai/git.py,sha256=XWAloZWQuLrFHUyfh3SkOgLsL4kfKRtgj3fzuJjcL2A,1649
4
+ commitai/template.py,sha256=q4AO64hKhJP2y9DCc5-ePFoRZfOQBkbkB6vt8CnoMh8,1379
5
+ commitai-1.0.5.dist-info/METADATA,sha256=_wO_IflHPj969OHjwzuQ-kCgV0DPgJ9ChPi8qPjBJPs,13710
6
+ commitai-1.0.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
+ commitai-1.0.5.dist-info/entry_points.txt,sha256=qzWJQdPoR38mjQgRPRCB3tA7Kojtj3WrozlFWR4KhLY,128
8
+ commitai-1.0.5.dist-info/licenses/LICENSE,sha256=wVkmSz0UMpGw0xYxk4AmkPLd_tVFcuszTdNIoq02tJA,1087
9
+ commitai-1.0.5.dist-info/RECORD,,
@@ -1,5 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: hatchling 1.27.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
-
@@ -1,3 +1,3 @@
1
1
  [console_scripts]
2
- commitai = commitai.cli:commitai
3
- commitai-create-template = commitai.cli:commitai_create_template
2
+ commitai = commitai.cli:commitai_alias
3
+ commitai-create-template = commitai.cli:commitai_create_template_alias
@@ -0,0 +1,22 @@
1
+ # File: LICENSE
2
+ MIT License
3
+
4
+ Copyright (c) 2024 Luis Guilherme
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
@@ -1,119 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: commitai
3
- Version: 0.1.16
4
- Summary: Commitai helps you generate git commit messages using AI
5
- Home-page: https://github.com/lguibr/commitai
6
- Author: Luis Guilherme
7
- Author-email: lgpelin92@gmail.com
8
- Project-URL: Bug Tracker, https://github.com/lguibr/commitai/issues
9
- Project-URL: Documentation, https://github.com/lguibr/commitai/blob/main/README.md
10
- Project-URL: Source Code, https://github.com/lguibr/commitai
11
- Classifier: Development Status :: 3 - Alpha
12
- Classifier: Intended Audience :: Developers
13
- Classifier: License :: OSI Approved :: MIT License
14
- Classifier: Operating System :: OS Independent
15
- Classifier: Programming Language :: Python :: 3
16
- Classifier: Programming Language :: Python :: 3.6
17
- Classifier: Programming Language :: Python :: 3.7
18
- Classifier: Programming Language :: Python :: 3.8
19
- Classifier: Programming Language :: Python :: 3.9
20
- Requires-Python: >=3.6
21
- Description-Content-Type: text/markdown
22
- Requires-Dist: langchain
23
- Requires-Dist: click
24
- Requires-Dist: langchain-community
25
- Requires-Dist: langchain-anthropic
26
- Requires-Dist: langchain-openai
27
- Requires-Dist: setuptools
28
-
29
- # CommitAi - Your AI-Powered Commit Assistant
30
-
31
- [![CI](https://github.com/lguibr/commitai/workflows/CI/badge.svg)](https://github.com/lguibr/commitai/actions)
32
- [![codecov](https://codecov.io/gh/lguibr/commitai/graph/badge.svg?token=MXZKCXO6LA)](https://codecov.io/gh/lguibr/commitai)
33
- [![PyPI](https://img.shields.io/pypi/v/CommitAi.svg)](https://pypi.org/project/CommitAi/)
34
- [![Python Version](https://img.shields.io/pypi/pyversions/CommitAi.svg)](https://pypi.org/project/CommitAi/)
35
- [![License](https://img.shields.io/pypi/l/CommitAi.svg)](https://github.com/lguibr/CommitAi/blob/main/LICENSE)
36
-
37
- **CommitAi** simplifies the Git commit message creation process by leveraging AI technologies, including GPT-4 and Claude. Designed for developers who value clarity and precision in commit histories, **CommitAi** offers a streamlined workflow that transforms your staged changes and high-level explanations into informative commit messages. Enhance your project documentation and streamline your development process with commit messages that truly reflect your changes.
38
-
39
- ## Demo
40
-
41
- ![CommitAi Demo](./assets/commitaai.gif)
42
-
43
- This demo GIF shows CommitAi in action, demonstrating how it generates a commit without any additional input, using Claude 3 Opus.
44
-
45
- ## Features
46
-
47
- - **Intelligent Commit Generation**: Leverages state-of-the-art AI models to generate meaningful commit messages from your changes.
48
- - **Pre-commit Checks**: Automatically runs configured pre-commit hooks to ensure quality and consistency before generating messages.
49
- - **Template Support**: Utilizes both global and repository-specific commit message templates to maintain a consistent style across your projects.
50
- - **AI Model Integration**: Supports multiple AI models, including GPT-4 by OpenAI and Claude by Anthropic, ensuring versatility in natural language processing capabilities.
51
-
52
- ## Getting Started
53
-
54
- ### Prerequisites
55
-
56
- - Python 3.6 or later
57
- - API keys for GPT-4 and Claude, as required
58
-
59
- ### Installation
60
-
61
- Install **CommitAi** directly from PyPI:
62
-
63
- ```bash
64
- pip install commitai
65
- ```
66
-
67
- ### Configuration
68
-
69
- #### API Keys
70
-
71
- Set the necessary API keys as environment variables:
72
-
73
- ```bash
74
- export OPENAI_API_KEY="your_openai_api_key"
75
- export ANTHROPIC_API_KEY="your_anthropic_api_key"
76
- ```
77
-
78
- #### Commit Templates
79
-
80
- Set a global commit template environment variable:
81
-
82
- ```bash
83
- export TEMPLATE_COMMIT="My global custom template: {message}"
84
- ```
85
-
86
- Or, create a repository-specific template using:
87
-
88
- ```bash
89
- commitai-create-template "My repository-specific template: {message}"
90
- ```
91
-
92
- This creates a hidden template file within the `.git` directory of your repository.
93
-
94
- ## Usage
95
-
96
- To generate a commit message, provide a high-level explanation of your changes:
97
-
98
- ```bash
99
- commitai "This is a high-level explanation of my commit"
100
- ```
101
-
102
- #### Options
103
-
104
- - `-a, --add`: Stage all changes before generating the commit message.
105
- - `-c, --commit`: Automatically create the commit using the generated message.
106
- - `-t, --template`: Specify a commit template. Defaults to the global template if available.
107
- - `-m, --model`: Choose the AI model (`gpt-4` by default).
108
-
109
- ### Additional Commands
110
-
111
- - `commitai-create-template`: Set a custom template specific to your repository.
112
-
113
- ## Contributing
114
-
115
- Contributions are welcome! Feel free to fork the repository, push your changes to a branch, and open a pull request. For bugs, questions, or feature requests, please open an issue through the GitHub issue tracker.
116
-
117
- ## License
118
-
119
- **CommitAi** is open-source software licensed under the MIT License. See the [LICENSE](https://github.com/lguibr/CommitAi/blob/main/LICENSE) file for more details.
@@ -1,9 +0,0 @@
1
- commitai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- commitai/cli.py,sha256=e6AxBnTBRW4yjl8lmzYBYWaVDdpZQ97UV3k81IvjLzY,4766
3
- commitai/git.py,sha256=XWAloZWQuLrFHUyfh3SkOgLsL4kfKRtgj3fzuJjcL2A,1649
4
- commitai/template.py,sha256=KlAhYUgea1rXpih6TyFeZ2rU8qN1H-VfZpMt7Wi8dZA,1137
5
- commitai-0.1.16.dist-info/METADATA,sha256=b4NT4tsnKlVFoyH3SrJyjeHG2ctwJdms7H9ngh2xvvM,4711
6
- commitai-0.1.16.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
7
- commitai-0.1.16.dist-info/entry_points.txt,sha256=KS-RBWo8XGrU1a11k6FgRCIwjGq8X5Zs-OuY8ri9BYU,116
8
- commitai-0.1.16.dist-info/top_level.txt,sha256=X76OfoBOic7IkaMkIgobuZxsVlsmcY_WMtBrtXtfn_w,9
9
- commitai-0.1.16.dist-info/RECORD,,
@@ -1 +0,0 @@
1
- commitai