commitai 0.1.15__py3-none-any.whl → 1.0.4__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,22 @@
1
+ # File: commitai/cli.py
1
2
  # -*- coding: utf-8 -*-
3
+
2
4
  import os
5
+ from typing import Optional, Tuple
3
6
 
4
7
  import click
5
8
  from langchain_anthropic import ChatAnthropic
9
+ from langchain_core.language_models.chat_models import BaseChatModel
6
10
  from langchain_openai import ChatOpenAI
7
11
 
12
+ # Keep SecretStr import in case it's needed elsewhere or for future refinement
13
+
14
+ # Conditional import for Google Generative AI
15
+ try:
16
+ from langchain_google_genai import ChatGoogleGenerativeAI
17
+ except ImportError:
18
+ ChatGoogleGenerativeAI = None # type: ignore
19
+
8
20
  from commitai.git import (
9
21
  create_commit,
10
22
  get_commit_template,
@@ -22,8 +34,153 @@ from commitai.template import (
22
34
  )
23
35
 
24
36
 
25
- @click.group(context_settings=dict(help_option_names=["-h", "--help"]))
26
- def cli():
37
+ # Helper function to get API key with priority
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
+ # Helper function to initialize the LLM
48
+ def _initialize_llm(model: str) -> BaseChatModel:
49
+ """Initializes and returns the LangChain chat model based on the model name."""
50
+ google_api_key_str = _get_google_api_key()
51
+
52
+ try:
53
+ if model.startswith("gpt-"):
54
+ api_key = os.getenv("OPENAI_API_KEY")
55
+ if not api_key:
56
+ raise click.ClickException(
57
+ "Error: OPENAI_API_KEY environment variable not set."
58
+ )
59
+ # Pass raw string and ignore Mypy SecretStr complaint
60
+ return ChatOpenAI(model=model, api_key=api_key, temperature=0.7)
61
+ elif model.startswith("claude-"):
62
+ api_key = os.getenv("ANTHROPIC_API_KEY")
63
+ if not api_key:
64
+ raise click.ClickException(
65
+ "Error: ANTHROPIC_API_KEY environment variable not set."
66
+ )
67
+ # Pass raw string and ignore Mypy SecretStr complaint
68
+ # Also ignore missing timeout argument if it's optional
69
+ return ChatAnthropic(model_name=model, api_key=api_key, temperature=0.7)
70
+ elif model.startswith("gemini-"):
71
+ if ChatGoogleGenerativeAI is None:
72
+ raise click.ClickException(
73
+ "Error: 'langchain-google-genai' is not installed. "
74
+ "Run 'pip install commitai[test]' or "
75
+ "'pip install langchain-google-genai'"
76
+ )
77
+ if not google_api_key_str:
78
+ raise click.ClickException(
79
+ "Error: Google API Key not found. Set GOOGLE_API_KEY, "
80
+ "GEMINI_API_KEY, or GOOGLE_GENERATIVE_AI_API_KEY."
81
+ )
82
+ # Pass raw string and ignore Mypy SecretStr complaint
83
+ # Also ignore missing optional arguments
84
+ return ChatGoogleGenerativeAI(
85
+ model=model,
86
+ google_api_key=google_api_key_str,
87
+ temperature=0.7,
88
+ convert_system_message_to_human=True,
89
+ )
90
+ else:
91
+ raise click.ClickException(f"🚫 Unsupported model: {model}")
92
+ except Exception as e:
93
+ raise click.ClickException(f"Error initializing AI model: {e}") from e
94
+
95
+
96
+ # Helper function to prepare context (diff, repo, branch)
97
+ def _prepare_context() -> str:
98
+ """
99
+ Gets the repository context (name, branch, diff).
100
+
101
+ Returns:
102
+ str: The formatted diff string.
103
+ Raises:
104
+ click.ClickException: If no staged changes are found.
105
+ """
106
+ diff = get_staged_changes_diff()
107
+ if not diff:
108
+ raise click.ClickException("⚠️ Warning: No staged changes found. Exiting.")
109
+
110
+ repo_name = get_repository_name()
111
+ branch_name = get_current_branch_name()
112
+ return f"{repo_name}/{branch_name}\n\n{diff}"
113
+
114
+
115
+ # Helper function to build the final prompt
116
+ def _build_prompt(
117
+ explanation: str, formatted_diff: str, template: Optional[str]
118
+ ) -> str:
119
+ """Builds the complete prompt for the AI model."""
120
+ system_message = default_system_message
121
+ if template:
122
+ system_message += adding_template
123
+ system_message += template
124
+
125
+ if explanation:
126
+ diff_message = build_user_message(explanation, formatted_diff)
127
+ else:
128
+ diff_message = formatted_diff
129
+
130
+ return f"{system_message}\n\n{diff_message}"
131
+
132
+
133
+ # Helper function to handle commit message editing and creation
134
+ def _handle_commit(commit_message: str, commit_flag: bool) -> None:
135
+ """
136
+ Writes message, optionally opens editor, and creates the commit.
137
+
138
+ Raises:
139
+ click.ClickException: On file I/O errors or if the commit is aborted.
140
+ """
141
+ repo_path = get_repository_name()
142
+ git_dir = os.path.join(repo_path, ".git")
143
+ try:
144
+ os.makedirs(git_dir, exist_ok=True)
145
+ except OSError as e:
146
+ raise click.ClickException(f"Error creating .git directory: {e}") from e
147
+
148
+ commit_msg_path = os.path.join(git_dir, "COMMIT_EDITMSG")
149
+
150
+ try:
151
+ with open(commit_msg_path, "w") as f:
152
+ f.write(commit_message)
153
+ except IOError as e:
154
+ raise click.ClickException(f"Error writing commit message file: {e}") from e
155
+
156
+ final_commit_message = commit_message
157
+ if not commit_flag:
158
+ try:
159
+ click.edit(filename=commit_msg_path)
160
+ with open(commit_msg_path, "r") as f:
161
+ final_commit_message = f.read().strip()
162
+ except click.UsageError as e:
163
+ click.secho(f"Could not open editor: {e}", fg="yellow")
164
+ click.secho(f"Using generated message:\n\n{commit_message}\n", fg="yellow")
165
+ except IOError as e:
166
+ raise click.ClickException(
167
+ f"Error reading commit message file after edit: {e}"
168
+ ) from e
169
+
170
+ if not final_commit_message:
171
+ raise click.ClickException("Aborting commit due to empty commit message.")
172
+
173
+ create_commit(final_commit_message)
174
+ click.secho(
175
+ f"\n\n✅ Committed message:\n\n{final_commit_message}\n\n",
176
+ fg="green",
177
+ bold=True,
178
+ )
179
+
180
+
181
+ @click.group(context_settings={"help_option_names": ["-h", "--help"]})
182
+ def cli() -> None:
183
+ """CommitAi CLI group."""
27
184
  pass
28
185
 
29
186
 
@@ -39,7 +196,9 @@ def cli():
39
196
  "--template",
40
197
  "-t",
41
198
  default=None,
42
- help="Specify a commit message template",
199
+ help=(
200
+ "Specify a commit message template (DEPRECATED: Use env var or create-template)"
201
+ ),
43
202
  )
44
203
  @click.option(
45
204
  "--add",
@@ -50,18 +209,25 @@ def cli():
50
209
  @click.option(
51
210
  "--model",
52
211
  "-m",
53
- default="claude-opus",
54
- help="Set the engine model to be used",
212
+ default="gemini-2.5-pro-preview-03-25",
213
+ help=(
214
+ "Set the engine model (e.g., 'gpt-4', 'claude-3-opus-20240229', "
215
+ "'gemini-2.5-pro-preview-03-25'). Ensure API key env var is set "
216
+ "(OPENAI_API_KEY, ANTHROPIC_API_KEY, "
217
+ "GOOGLE_API_KEY/GEMINI_API_KEY/GOOGLE_GENERATIVE_AI_API_KEY)."
218
+ ),
55
219
  )
56
- def generate_message(description, commit, template, add, model):
220
+ def generate_message(
221
+ description: Tuple[str, ...],
222
+ commit: bool,
223
+ template: Optional[str],
224
+ add: bool,
225
+ model: str,
226
+ ) -> None:
227
+ """Generates a commit message based on staged changes and description."""
57
228
  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
229
+
230
+ llm = _initialize_llm(model)
65
231
 
66
232
  if add:
67
233
  stage_all_changes()
@@ -71,82 +237,59 @@ def generate_message(description, commit, template, add, model):
71
237
  fg="blue",
72
238
  bold=True,
73
239
  )
74
-
75
240
  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
241
+ raise click.ClickException("🚫 Pre-commit hook failed. Aborting commit.")
82
242
 
83
- diff = get_staged_changes_diff()
84
- if not diff:
243
+ formatted_diff = _prepare_context()
244
+
245
+ if template:
85
246
  click.secho(
86
- "⚠️ Warning: No staged changes found. Exiting.",
247
+ "⚠️ Warning: The --template/-t option is deprecated. Use environment "
248
+ "variable TEMPLATE_COMMIT or `commitai-create-template` command.",
87
249
  fg="yellow",
88
- bold=True,
89
250
  )
90
- return
251
+ final_template = template or get_commit_template()
91
252
 
92
- # Clear the terminal using click
93
- click.clear()
253
+ input_message = _build_prompt(explanation, formatted_diff, final_template)
94
254
 
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)
109
-
110
- input_message = f"{system_message}\n\n{diff}"
255
+ click.clear()
111
256
  click.secho(
112
257
  "\n\n🧠 Analyzing the changes and generating a commit message...\n\n",
113
258
  fg="blue",
114
259
  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)
123
-
124
- if not commit:
125
- click.edit(filename=commit_msg_path)
260
+ )
261
+ try:
262
+ assert llm is not None
263
+ ai_message = llm.invoke(input=input_message)
264
+ commit_message = ai_message.content
265
+ if not isinstance(commit_message, str):
266
+ commit_message = str(commit_message)
126
267
 
127
- with open(commit_msg_path, "r") as f:
128
- final_commit_message = f.read().strip()
268
+ except Exception as e:
269
+ raise click.ClickException(f"Error during AI generation: {e}") from e
129
270
 
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
- )
271
+ _handle_commit(commit_message, commit)
136
272
 
137
273
 
138
274
  @cli.command(name="create-template")
139
275
  @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)
276
+ def create_template_command(template_content: Tuple[str, ...]) -> None:
277
+ """Saves a repository-specific commit template."""
278
+ content = " ".join(template_content)
279
+ if content:
280
+ save_commit_template(content)
144
281
  click.secho("📝 Template saved successfully.", fg="green")
145
282
  else:
146
283
  click.secho("❗ Please provide the template content.", fg="red")
147
284
 
148
285
 
149
- @click.command(name="commitai")
286
+ # --- Alias Commands ---
287
+
288
+
289
+ @click.command(
290
+ name="commitai",
291
+ context_settings={"ignore_unknown_options": True},
292
+ )
150
293
  @click.argument("description", nargs=-1, type=click.UNPROCESSED)
151
294
  @click.option(
152
295
  "--add",
@@ -160,27 +303,38 @@ def create_template_command(template_content):
160
303
  is_flag=True,
161
304
  help="Commit the changes with the generated message",
162
305
  )
306
+ @click.option(
307
+ "--model",
308
+ "-m",
309
+ default="gemini-2.5-pro-preview-03-25",
310
+ help="Set the engine model to be used.",
311
+ )
163
312
  @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,
313
+ def commitai_alias(
314
+ ctx: click.Context,
315
+ description: Tuple[str, ...],
316
+ add: bool,
317
+ commit: bool,
318
+ model: str,
319
+ ) -> None:
320
+ """Alias for the 'generate' command."""
321
+ ctx.forward(
322
+ generate_message, description=description, add=add, commit=commit, model=model
172
323
  )
173
324
 
174
325
 
175
326
  @click.command(name="commitai-create-template")
176
327
  @click.argument("template_content", nargs=-1, type=click.UNPROCESSED)
177
328
  @click.pass_context
178
- def commitai_create_template(ctx, template_content):
179
- ctx.invoke(create_template_command, template_content=template_content)
329
+ def commitai_create_template_alias(
330
+ ctx: click.Context, template_content: Tuple[str, ...]
331
+ ) -> None:
332
+ """Alias for the 'create-template' command."""
333
+ ctx.forward(create_template_command, template_content=template_content)
180
334
 
181
335
 
182
- cli.add_command(commitai)
183
- cli.add_command(commitai_create_template)
336
+ cli.add_command(commitai_alias)
337
+ cli.add_command(commitai_create_template_alias)
184
338
 
185
339
 
186
340
  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,303 @@
1
+ Metadata-Version: 2.4
2
+ Name: commitai
3
+ Version: 1.0.4
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.0,>=0.1.0
46
+ Requires-Dist: langchain-community<0.2.0,>=0.0.20
47
+ Requires-Dist: langchain-core<0.3.0,>=0.1.0
48
+ Requires-Dist: langchain-google-genai~=0.0.9
49
+ Requires-Dist: langchain-openai<0.3.0,>=0.1.0
50
+ Requires-Dist: langchain<0.3.0,>=0.1.0
51
+ Requires-Dist: pydantic<3.0,>=2.0
52
+ Provides-Extra: test
53
+ Requires-Dist: langchain-google-genai~=0.0.9; extra == 'test'
54
+ Requires-Dist: mypy>=1.9.0; extra == 'test'
55
+ Requires-Dist: pytest-cov>=3.0; extra == 'test'
56
+ Requires-Dist: pytest>=7.0; extra == 'test'
57
+ Requires-Dist: ruff==0.4.4; extra == 'test'
58
+ Requires-Dist: types-setuptools; extra == 'test'
59
+ Description-Content-Type: text/markdown
60
+
61
+ # CommitAi - Your AI-Powered Commit Assistant
62
+
63
+ [![CI and Publish](https://github.com/lguibr/commitai/actions/workflows/main.yml/badge.svg)](https://github.com/lguibr/commitai/actions/workflows/main.yml)
64
+ [![codecov](https://codecov.io/gh/lguibr/commitai/graph/badge.svg?token=MXZKCXO6LA)](https://codecov.io/gh/lguibr/commitai) <!-- Added Codecov Badge -->
65
+ [![PyPI](https://img.shields.io/pypi/v/CommitAi.svg)](https://pypi.org/project/CommitAi/)
66
+ [![Python Version](https://img.shields.io/pypi/pyversions/CommitAi.svg)](https://pypi.org/project/CommitAi/)
67
+ [![License](https://img.shields.io/pypi/l/CommitAi.svg)](https://github.com/lguibr/CommitAi/blob/main/LICENSE)
68
+ [![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)
69
+
70
+ <p align="center">
71
+ <img src="bitmap.png" alt="Logo" width="300"/>
72
+ </p>
73
+
74
+ **Tired of writing Git commit messages? Let AI do the heavy lifting!**
75
+
76
+ **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.
77
+
78
+ 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!
79
+
80
+ ## Table of Contents
81
+
82
+ - [CommitAi - Your AI-Powered Commit Assistant](#commitai---your-ai-powered-commit-assistant)
83
+ - [Table of Contents](#table-of-contents)
84
+ - [Features](#features)
85
+ - [Demo](#demo)
86
+ - [Installation](#installation)
87
+ - [Configuration](#configuration)
88
+ - [API Keys](#api-keys)
89
+ - [Commit Templates (Optional)](#commit-templates-optional)
90
+ - [Usage](#usage)
91
+ - [Basic Workflow](#basic-workflow)
92
+ - [Command-Line Options](#command-line-options)
93
+ - [Creating Repository Templates](#creating-repository-templates)
94
+ - [Examples](#examples)
95
+ - [Contributing](#contributing)
96
+ - [License](#license)
97
+
98
+ ## Features
99
+
100
+ * 🧠 **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.
101
+ * 📄 **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.
102
+ * 📝 **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.
103
+ * ✅ **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.
104
+ * 🔧 **Customizable Prompts via Templates**: Add custom instructions or context to the AI prompt using global environment variables or repository-specific template files.
105
+ * 🤖 **Multiple AI Provider Support**: Choose your preferred AI model from OpenAI, Anthropic, or Google.
106
+ * ⚙️ **Flexible Workflow**:
107
+ * Stages all changes automatically (`-a` flag).
108
+ * Reviews message in your default Git editor (default behavior).
109
+ * Commits directly without editor review (`-c` flag).
110
+ * ✨ **Modern Tooling**: Built with `pyproject.toml` and formatted/linted with `ruff`.
111
+
112
+ ## Demo
113
+
114
+ ![CommitAi Demo](./assets/commitaai.gif)
115
+
116
+ *(Demo shows generating a commit message using Claude 3 Opus without providing an explicit explanation)*
117
+
118
+ ## Installation
119
+
120
+ Ensure you have Python 3.8+ and Git installed.
121
+
122
+ Install **CommitAi** directly from PyPI:
123
+
124
+ ```bash
125
+ pip install commitai
126
+ ```
127
+
128
+ ## Configuration
129
+
130
+ ### API Keys
131
+
132
+ CommitAi requires API keys for the AI provider you intend to use. Set these as environment variables:
133
+
134
+ * **OpenAI (GPT models):**
135
+ ```bash
136
+ export OPENAI_API_KEY="your_openai_api_key_here"
137
+ ```
138
+
139
+ * **Anthropic (Claude models):**
140
+ ```bash
141
+ export ANTHROPIC_API_KEY="your_anthropic_api_key_here"
142
+ ```
143
+
144
+ * **Google (Gemini models):**
145
+ Set **one** of the following (CommitAi checks in this priority order):
146
+ 1. `GOOGLE_API_KEY` (Recommended)
147
+ 2. `GEMINI_API_KEY`
148
+ 3. `GOOGLE_GENERATIVE_AI_API_KEY`
149
+
150
+ Example:
151
+ ```bash
152
+ export GOOGLE_API_KEY="your_google_api_key_here"
153
+ ```
154
+
155
+ You only need to set the key for the provider corresponding to the model you select (or the default, Gemini).
156
+
157
+ ### Commit Templates (Optional)
158
+
159
+ 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).
160
+
161
+ * **Global Template:** Set an environment variable. This applies to all repositories unless overridden locally.
162
+ ```bash
163
+ # Example: Always ask the AI to reference a JIRA ticket format
164
+ export TEMPLATE_COMMIT="Ensure the commit footer includes a JIRA reference like 'Refs: PROJECT-123'."
165
+ ```
166
+
167
+ * **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.
168
+ ```bash
169
+ # Example: Instruct the AI to focus on UI changes for this specific repo
170
+ commitai-create-template "Focus the commit message body on user-facing UI changes."
171
+ ```
172
+
173
+ **Note:** These templates *add* to the default system prompt, which already instructs the AI to follow Conventional Commits format. You are providing supplementary instructions.
174
+
175
+ ## Usage
176
+
177
+ ### Basic Workflow
178
+
179
+ 1. **Make your code changes.**
180
+ 2. **Stage the changes** you want to include in the commit:
181
+ ```bash
182
+ git add <file1> <file2> ...
183
+ # or stage all changes in tracked files
184
+ git add .
185
+ # or stage all changes including untracked files
186
+ git add --all
187
+ ```
188
+ 3. **Run `commitai`:**
189
+ ```bash
190
+ # Option 1: Let CommitAi infer the message from the diff
191
+ commitai
192
+
193
+ # Option 2: Provide a high-level explanation to guide the AI
194
+ commitai "Refactor user authentication to use JWT tokens"
195
+ ```
196
+ 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.
197
+ 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.
198
+
199
+ ### Command-Line Options
200
+
201
+ The `commitai` command (which is an alias for `commitai generate`) accepts the following options:
202
+
203
+ * `-a`, `--add`:
204
+ * Automatically stages *all* unstaged changes (`git add --all`) before generating the commit message.
205
+ * Useful for quickly committing everything in the working directory.
206
+ * Example: `commitai -a "Implement user profile page"`
207
+
208
+ * `-c`, `--commit`:
209
+ * Skips opening the Git editor for review. The generated message is used to create the commit directly.
210
+ * **Use with caution!** Reviewing AI-generated messages is recommended.
211
+ * Example: `commitai -c "Fix typo in documentation"` (for minor changes)
212
+ * Can be combined with `-a`: `commitai -a -c "Quick fix and commit all"`
213
+
214
+ * `-m <model_name>`, `--model <model_name>`:
215
+ * Specifies which AI model to use.
216
+ * Defaults to `gemini-2.5-pro-preview-03-25`.
217
+ * Ensure the corresponding API key environment variable is set.
218
+ * Examples:
219
+ * `commitai -m gpt-4 "Use OpenAI's GPT-4"`
220
+ * `commitai -m claude-3-opus-20240229 "Use Anthropic's Claude 3 Opus"`
221
+ * `commitai -m gemini-2.5-flash-preview-04-17 "Use Google's Gemini 1.5 Flash"`
222
+
223
+ ### Creating Repository Templates
224
+
225
+ The `commitai-create-template` command sets a repository-specific template instruction.
226
+
227
+ ```bash
228
+ commitai-create-template "Add a 'Co-authored-by:' line if applicable."
229
+ ```
230
+
231
+ This creates/overwrites the `.git/commit_template.txt` file in the current repository.
232
+
233
+ ## Examples
234
+
235
+ **1. Simple commit, inferred message:**
236
+
237
+ ```bash
238
+ # Stage changes
239
+ git add src/utils.py tests/test_utils.py
240
+
241
+ # Run commitai - AI infers message from diff
242
+ commitai
243
+ ```
244
+ *(Editor opens with a message like `feat(utils): add helper function for data validation`)*
245
+
246
+ **2. Commit with explanation:**
247
+
248
+ ```bash
249
+ # Stage changes
250
+ git add src/auth.py
251
+
252
+ # Run commitai with explanation
253
+ commitai "Implement password reset functionality using email tokens"
254
+ ```
255
+ *(Editor opens with a message like `feat(auth): implement password reset via email token`)*
256
+
257
+ **3. Stage all and commit directly (no editor):**
258
+
259
+ ```bash
260
+ # Stage all changes and commit immediately using GPT-4
261
+ commitai -a -c -m gpt-4 "Minor refactoring and cleanup"
262
+ ```
263
+ *(Commit is created directly)*
264
+
265
+ **4. Using a Template:**
266
+
267
+ * First, set a template:
268
+ ```bash
269
+ commitai-create-template "Mention the related issue number from GitHub, e.g., Fixes #123."
270
+ ```
271
+ * Then, run commitai:
272
+ ```bash
273
+ git add src/parser.py
274
+ commitai "Fix bug in CSV parsing logic"
275
+ ```
276
+ *(Editor opens with a message potentially like `fix(parser): correct handling of quoted commas\n\nFixes #123`)*
277
+
278
+ ## Contributing
279
+
280
+ Contributions are highly welcome! Please follow these steps:
281
+
282
+ 1. Fork the repository on GitHub.
283
+ 2. Clone your fork locally: `git clone <your-fork-url>`
284
+ 3. Navigate to the project directory: `cd commitai`
285
+ 4. Create a virtual environment: `python -m venv .venv && source .venv/bin/activate` (or `.\.venv\Scripts\activate` on Windows)
286
+ 5. Install dependencies, including development tools: `pip install -e ".[test]"`
287
+ 6. **(Optional but Recommended)** Set up pre-commit hooks: `pre-commit install`
288
+ 7. Create a new branch for your feature or bug fix: `git checkout -b my-feature-branch`
289
+ 8. Make your changes.
290
+ 9. Run checks locally before committing:
291
+ * Format code: `ruff format .`
292
+ * Lint code: `ruff check .`
293
+ * Run type checks: `mypy commitai commitai/tests`
294
+ * Run tests: `pytest`
295
+ 10. Commit your changes (you can use `commitai`!).
296
+ 11. Push your branch to your fork: `git push origin my-feature-branch`
297
+ 12. Open a pull request on the main `lguibr/commitai` repository.
298
+
299
+ The CI pipeline will automatically run all checks on your pull request.
300
+
301
+ ## License
302
+
303
+ **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=-uM5xYOvQ8NUDQM4fJ1Ktk3st9d5QxtT55rbTFP7e_o,10620
3
+ commitai/git.py,sha256=XWAloZWQuLrFHUyfh3SkOgLsL4kfKRtgj3fzuJjcL2A,1649
4
+ commitai/template.py,sha256=q4AO64hKhJP2y9DCc5-ePFoRZfOQBkbkB6vt8CnoMh8,1379
5
+ commitai-1.0.4.dist-info/METADATA,sha256=iOijXC_ZayBVdArer0z-htp9mso3iqhBHwpRQyXSB0U,13487
6
+ commitai-1.0.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
+ commitai-1.0.4.dist-info/entry_points.txt,sha256=qzWJQdPoR38mjQgRPRCB3tA7Kojtj3WrozlFWR4KhLY,128
8
+ commitai-1.0.4.dist-info/licenses/LICENSE,sha256=wVkmSz0UMpGw0xYxk4AmkPLd_tVFcuszTdNIoq02tJA,1087
9
+ commitai-1.0.4.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,97 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: commitai
3
- Version: 0.1.15
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 - Commit Message AI
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 is a command-line tool that helps you generate informative and relevant commit messages for your Git repositories using AI language models like GPT-4 and Claude. It analyzes your staged changes, combines them with a high-level explanation provided by you, and creates a commit message based on this information. Additionally, it supports custom commit message templates. This not only saves you time and effort but also ensures a consistent and meaningful commit history.
38
-
39
- ## Features
40
-
41
- - Automatically runs the repository's pre-commit hook (if it exists) before generating the commit message to avoid discarded commit costs.
42
- - Generates informative and relevant commit messages based on staged changes and user-provided explanations.
43
- - Supports custom commit message templates.
44
- - Integrates with AI language models like GPT-4 and Claude for intelligent commit message generation.
45
-
46
- ## Prerequisites
47
-
48
- - Python 3.x
49
- - API keys for the desired language models (e.g., OpenAI API key for GPT-4, Anthropic API key for Claude)
50
-
51
- ## Installation
52
-
53
- You can install commitai using pip:
54
-
55
- pip install commitai
56
-
57
- ## Configuration
58
-
59
- ### Environment Variables
60
-
61
- Before using commitai, you need to set the API key environment variables for the language models you want to use. For example:
62
-
63
- export OPENAI_API_KEY="your_openai_api_key"
64
- export ANTHROPIC_API_KEY="your_anthropic_api_key"
65
-
66
- You can also set the `TEMPLATE_COMMIT` environment variable to define a global template for your commit messages:
67
-
68
- export TEMPLATE_COMMIT="My global custom template: {message}"
69
-
70
- ### Template Configuration
71
-
72
- #### Creating a Template for the Repository
73
-
74
- You can create a custom template specific to the repository using the `create-template` command. This template will override the global template set in the `TEMPLATE_COMMIT` environment variable if present.
75
-
76
- commitai create-template "My repository-specific template: {message}"
77
-
78
- This command will create a hidden file inside the `.git` directory to store the template.
79
-
80
- ## Usage
81
-
82
- ### Generating Commit Messages
83
-
84
- commitai generate "This is a high-level explanation of my commit"
85
-
86
- - Use the `-a` or `--add` flag to stage all changes.
87
- - Use the `-c` or `--commit` flag to automatically create the commit.
88
- - Use the `-t` or `--template` flag for custom templates or utilize the `TEMPLATE_COMMIT` environment variable. If no template is provided, a default or global template will be used.
89
- - Use the `-m` or `--model` flag to specify the language model to use (default: `gpt-4`).
90
-
91
- ## Contributing
92
-
93
- We welcome contributions to the commitai project! Please feel free to submit issues, feature requests, or pull requests.
94
-
95
- ## License
96
-
97
- This project is released under the MIT License.
@@ -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.15.dist-info/METADATA,sha256=OY1TmzjiCPg6NAwFsGW25hFQ8an79s_Wo5Ug5W2a8ro,4382
6
- commitai-0.1.15.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
7
- commitai-0.1.15.dist-info/entry_points.txt,sha256=KS-RBWo8XGrU1a11k6FgRCIwjGq8X5Zs-OuY8ri9BYU,116
8
- commitai-0.1.15.dist-info/top_level.txt,sha256=X76OfoBOic7IkaMkIgobuZxsVlsmcY_WMtBrtXtfn_w,9
9
- commitai-0.1.15.dist-info/RECORD,,
@@ -1 +0,0 @@
1
- commitai