git-aic 1.0.0 → 1.1.0
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.
- package/LICENSE +15 -0
- package/README.md +269 -0
- package/dist/cli.js +53 -12
- package/dist/config.js +41 -0
- package/dist/confirm.js +12 -6
- package/dist/llm.js +7 -4
- package/dist/prompt.js +43 -43
- package/package.json +4 -7
- package/t.txt +32 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Spectra
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
10
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
11
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
12
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
13
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
14
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
15
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
# Git Aic
|
|
2
|
+
|
|
3
|
+
**git-aic** is a command-line interface (CLI) tool built in TypeScript that upgrades your Git workflow by automatically generating high-quality, conventional commit messages.
|
|
4
|
+
|
|
5
|
+
Powered by Google Gemini, it analyzes your staged code changes and produces concise, descriptive, and standard-compliant commit messages, helping you maintain a clean and consistent Git history.
|
|
6
|
+
|
|
7
|
+
You define the rules.
|
|
8
|
+
You customize the system prompt.
|
|
9
|
+
You decide when it runs.
|
|
10
|
+
|
|
11
|
+
Your workflow. Your control.
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- **AI-Powered Message Generation**
|
|
16
|
+
Uses Google Gemini API to generate commit messages from your Git diff.
|
|
17
|
+
|
|
18
|
+
- **Self-Hosted & On-Demand**
|
|
19
|
+
Runs locally in your terminal. No background processes. No editor lock-in.
|
|
20
|
+
|
|
21
|
+
- **Full Control Over Rules**
|
|
22
|
+
Modify the system prompt to enforce your own commit conventions and formatting style.
|
|
23
|
+
|
|
24
|
+
- **Conventional Commits Compliance**
|
|
25
|
+
Strictly follows formats like `feat:`, `fix:`, `refactor:`, `chore:`.
|
|
26
|
+
|
|
27
|
+
- **Commit Confirmation & Editing**
|
|
28
|
+
Before committing, you can:
|
|
29
|
+
- Accept the suggested commit message
|
|
30
|
+
- Edit the message
|
|
31
|
+
- Reject it
|
|
32
|
+
- Retry generation
|
|
33
|
+
|
|
34
|
+
- **Issue Linking**
|
|
35
|
+
Attach commits to GitHub issues with `--issue <number>`.
|
|
36
|
+
|
|
37
|
+
- **Optional Push After Commit**
|
|
38
|
+
Use `-p` or `--push` to push after committing.
|
|
39
|
+
|
|
40
|
+
- **Config Management**
|
|
41
|
+
Set your Gemini API key or view your config:
|
|
42
|
+
- `git aic config --key <key>`
|
|
43
|
+
- `git aic config`
|
|
44
|
+
|
|
45
|
+
- **TypeScript & Type Safety**
|
|
46
|
+
Built with TypeScript for maintainability and reliability.
|
|
47
|
+
|
|
48
|
+
- **Seamless Git Integration**
|
|
49
|
+
Directly integrates with Git using a CLI.
|
|
50
|
+
|
|
51
|
+
## Why Not Just Use Copilot?
|
|
52
|
+
|
|
53
|
+
Many AI commit tools:
|
|
54
|
+
|
|
55
|
+
- Depend on editor integrations
|
|
56
|
+
- Limit customization
|
|
57
|
+
- Enforce their defaults
|
|
58
|
+
- Restrict usage
|
|
59
|
+
- Run continuously in the background
|
|
60
|
+
|
|
61
|
+
This tool is different.
|
|
62
|
+
|
|
63
|
+
It runs only when you call it.
|
|
64
|
+
It follows your prompt rules.
|
|
65
|
+
It generates commits exactly how you define them.
|
|
66
|
+
It stays out of your way.
|
|
67
|
+
|
|
68
|
+
There are no forced conventions.
|
|
69
|
+
No hidden behavior.
|
|
70
|
+
No unnecessary background processes.
|
|
71
|
+
|
|
72
|
+
If needed, you can rotate API keys later. You stay in control.
|
|
73
|
+
|
|
74
|
+
This is controlled automation — not passive AI assistance.
|
|
75
|
+
|
|
76
|
+
## User Installation
|
|
77
|
+
|
|
78
|
+
To install `git-aic` globally via npm:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
npm i -g git-aic
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
git aic --help
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Developer Installation (For Contributors)
|
|
89
|
+
|
|
90
|
+
### 1. Clone the Repository
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
git clone https://github.com/Spectra010s/git-aic.git
|
|
94
|
+
cd git-aic
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 2. Install Dependencies
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
npm install
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### 3. Build the Project
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
npm run build
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Configuration
|
|
110
|
+
|
|
111
|
+
### Set API Key (Primary)
|
|
112
|
+
|
|
113
|
+
Use the CLI config command to save your Google Gemini API key:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
git aic config --key <your_api_key>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
To view your current config:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
git aic config
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
> "\*Note:\*\* it's masked by default for security reasons
|
|
126
|
+
|
|
127
|
+
To view the whole current config api key
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
git aic config --show
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Environment Variable (Fallback)
|
|
134
|
+
|
|
135
|
+
If you prefer not to use the config system, you can set it manually in your environment:
|
|
136
|
+
|
|
137
|
+
- **macOS / Linux:**
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
export GEMINI_COMMIT_MESSAGE_API_KEY=your_api_key_here
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
- **Windows (PowerShell):**
|
|
144
|
+
|
|
145
|
+
```powershell
|
|
146
|
+
setx GEMINI_COMMIT_MESSAGE_API_KEY "your_api_key_here"
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
After setting the variable, restart your terminal.
|
|
150
|
+
|
|
151
|
+
> **Note:** This method works, but using the CLI config is safer and easier for long-term usage.
|
|
152
|
+
|
|
153
|
+
## Usage
|
|
154
|
+
|
|
155
|
+
### Commit With AI Assistance
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
git aic
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
- Prompts you with a generated commit message.
|
|
162
|
+
- You can **accept, edit, reject, or retry** the message.
|
|
163
|
+
|
|
164
|
+
### Commit and Link to Issue
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
git aic --issue 123
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
- Attaches the commit to GitHub issue #123.
|
|
171
|
+
|
|
172
|
+
### Commit and Push
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
git aic -p
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
- Pushes automatically after committing.
|
|
179
|
+
|
|
180
|
+
### Configure API Key
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
git aic config --key <key>
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
- Saves your Google Gemini API key.
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
git aic config
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
- Displays your saved config.
|
|
193
|
+
|
|
194
|
+
That’s it.
|
|
195
|
+
|
|
196
|
+
No need to manually write commit messages anymore.
|
|
197
|
+
|
|
198
|
+
## How It Works
|
|
199
|
+
|
|
200
|
+
1. Captures your staged Git diff
|
|
201
|
+
2. Builds a strict system prompt
|
|
202
|
+
3. Sends the diff to Gemini
|
|
203
|
+
4. Enforces Conventional Commit formatting
|
|
204
|
+
5. Prompts for commit confirmation (accept, edit, retry, reject)
|
|
205
|
+
6. Executes `git commit` automatically
|
|
206
|
+
7. Optionally pushes if `-p` flag is used
|
|
207
|
+
|
|
208
|
+
You can modify commit behavior by editing:
|
|
209
|
+
|
|
210
|
+
```
|
|
211
|
+
src/prompt.ts
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Technologies Used
|
|
217
|
+
|
|
218
|
+
| Technology | Purpose |
|
|
219
|
+
| ----------------- | ---------------------- |
|
|
220
|
+
| TypeScript | Core language |
|
|
221
|
+
| Node.js | Runtime |
|
|
222
|
+
| Axios | HTTP client |
|
|
223
|
+
| Chalk | Styled terminal output |
|
|
224
|
+
| Commander.js | CLI framework |
|
|
225
|
+
| Simple-Git | Git integration |
|
|
226
|
+
| Google Gemini API | LLM text generation |
|
|
227
|
+
|
|
228
|
+
## Final Takeaway
|
|
229
|
+
|
|
230
|
+
Automating repetitive tasks like **commit messages** saves time — but the real win here is ownership.
|
|
231
|
+
|
|
232
|
+
git-aic:
|
|
233
|
+
|
|
234
|
+
- **Self-hosted** — runs entirely on your machine
|
|
235
|
+
- **On-demand** — only runs when you call it
|
|
236
|
+
- **Fully customizable** — prompts, commit format, workflow
|
|
237
|
+
- **Under your control** — you decide every step
|
|
238
|
+
|
|
239
|
+
It runs when you need it, follows your rules, and generates commits the way **you** want.
|
|
240
|
+
|
|
241
|
+
_Choose your model. Define your prompt. Control the format. Extend or optimize anytime._
|
|
242
|
+
|
|
243
|
+
Instead of adapting to someone else's defaults, _you built a system tailored to your workflow._
|
|
244
|
+
|
|
245
|
+
You are not just using AI tools.
|
|
246
|
+
You are **building them to fit your process.**
|
|
247
|
+
|
|
248
|
+
## License
|
|
249
|
+
|
|
250
|
+
[**ISC License**](https://github.com/Spectra010s/git-aic/main/#license)
|
|
251
|
+
|
|
252
|
+
## Author
|
|
253
|
+
|
|
254
|
+
Spectra010s
|
|
255
|
+
|
|
256
|
+
- [Twitter](https://x.com/Spectra010s)
|
|
257
|
+
- [LinkedIn](https://www.linkedin.com/in/adeloye-adetayo-273723253)
|
|
258
|
+
|
|
259
|
+
## Parent Repository
|
|
260
|
+
|
|
261
|
+
This project is a fork and standalone version of:
|
|
262
|
+
|
|
263
|
+
[https://github.com/samueltuoyo15/Commit-Message-Tool](https://github.com/samueltuoyo15/Commit-Message-Tool)
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+

|
|
268
|
+

|
|
269
|
+

|
package/dist/cli.js
CHANGED
|
@@ -5,13 +5,45 @@ import chalk from "chalk";
|
|
|
5
5
|
import { getGitDiff } from "./git.js";
|
|
6
6
|
import { generateCommitMessage } from "./llm.js";
|
|
7
7
|
import { getUserConfirmation } from "./confirm.js";
|
|
8
|
+
import { getConfig, setApiKey } from "./config.js";
|
|
9
|
+
process.on("SIGINT", () => {
|
|
10
|
+
process.exit(0);
|
|
11
|
+
});
|
|
8
12
|
const git = simpleGit();
|
|
9
13
|
const program = new Command();
|
|
10
14
|
program
|
|
11
|
-
.name("
|
|
15
|
+
.name("git aic")
|
|
12
16
|
.description("AI-powered Git commit generator using Google Gemini")
|
|
13
17
|
.version("1.0.0")
|
|
14
|
-
.option("-p, --push", "push after committing")
|
|
18
|
+
.option("-p, --push", "push after committing")
|
|
19
|
+
.option("-i, --issue <number>", "Link commit to GitHub issue");
|
|
20
|
+
program
|
|
21
|
+
.command("config")
|
|
22
|
+
.description("Configure the Gemini API Key settings")
|
|
23
|
+
.option("-k, --key <key>", "Set your Gemini API Key")
|
|
24
|
+
.option("--show", "Show the full API key")
|
|
25
|
+
.action(async (options) => {
|
|
26
|
+
const cfg = await getConfig();
|
|
27
|
+
if (options.key) {
|
|
28
|
+
await setApiKey(options.key);
|
|
29
|
+
console.log(chalk.green("API Key saved successfully!"));
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (cfg.apiKey) {
|
|
33
|
+
if (options.show) {
|
|
34
|
+
console.log(chalk.green("Current API Key:"), cfg.apiKey);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
const styled = cfg.apiKey.slice(0, 4) +
|
|
38
|
+
chalk.dim("*".repeat(cfg.apiKey.length - 8)) +
|
|
39
|
+
cfg.apiKey.slice(-4);
|
|
40
|
+
console.log(chalk.green("Current API Key:"), styled);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
console.log(chalk.yellow("No API key set"));
|
|
45
|
+
}
|
|
46
|
+
});
|
|
15
47
|
program.action(async (options) => {
|
|
16
48
|
try {
|
|
17
49
|
const diff = await getGitDiff();
|
|
@@ -23,17 +55,20 @@ program.action(async (options) => {
|
|
|
23
55
|
console.log(chalk.blue("\nFiles being committed:"));
|
|
24
56
|
status.staged.forEach((file) => console.log(chalk.cyan(`- ${file}`)));
|
|
25
57
|
console.log("");
|
|
26
|
-
let
|
|
58
|
+
let currentMsg = "";
|
|
27
59
|
let confirmed = false;
|
|
60
|
+
let finalMsg = "";
|
|
61
|
+
const issueSuffix = options.issue ? `, closes #${options.issue}` : "";
|
|
28
62
|
console.log(chalk.blue("Analyzing staged changes...\n"));
|
|
29
63
|
while (!confirmed) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
64
|
+
let currentMsg = await generateCommitMessage(diff);
|
|
65
|
+
currentMsg = `${currentMsg}${issueSuffix}`;
|
|
66
|
+
const { choice, message } = await getUserConfirmation(currentMsg);
|
|
67
|
+
if (choice === "y") {
|
|
68
|
+
finalMsg = message;
|
|
34
69
|
confirmed = true;
|
|
35
70
|
}
|
|
36
|
-
else if (choice ===
|
|
71
|
+
else if (choice === "r") {
|
|
37
72
|
console.log(chalk.yellow("Regenerating...\n"));
|
|
38
73
|
continue;
|
|
39
74
|
}
|
|
@@ -42,8 +77,8 @@ program.action(async (options) => {
|
|
|
42
77
|
process.exit(0);
|
|
43
78
|
}
|
|
44
79
|
}
|
|
45
|
-
console.log(chalk.blue(`> ran: git commit -m "${
|
|
46
|
-
await git.commit(
|
|
80
|
+
console.log(chalk.blue(`> ran: git commit -m "${finalMsg}"`));
|
|
81
|
+
await git.commit(finalMsg);
|
|
47
82
|
console.log(chalk.green("\nCommit successful"));
|
|
48
83
|
if (options.push) {
|
|
49
84
|
console.log(chalk.blue("> ran: git push"));
|
|
@@ -52,8 +87,14 @@ program.action(async (options) => {
|
|
|
52
87
|
}
|
|
53
88
|
}
|
|
54
89
|
catch (error) {
|
|
55
|
-
|
|
56
|
-
|
|
90
|
+
let isAbort = false;
|
|
91
|
+
if (typeof error === "object" && error !== null && "code" in error) {
|
|
92
|
+
const e = error;
|
|
93
|
+
isAbort = e.code === "ABORT_ERR";
|
|
94
|
+
}
|
|
95
|
+
const msg = isAbort ? "Operation cancelled" : error;
|
|
96
|
+
console.error(chalk.red("\n\nCommit failed:"), msg);
|
|
97
|
+
process.exit(isAbort ? 0 : 1);
|
|
57
98
|
}
|
|
58
99
|
});
|
|
59
100
|
program.parse(process.argv);
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import fs from "fs/promises";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import os from "os";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
function getConfigPath() {
|
|
6
|
+
const toolName = "git-aic";
|
|
7
|
+
if (process.platform === "win32") {
|
|
8
|
+
const appData = process.env.APPDATA;
|
|
9
|
+
if (!appData)
|
|
10
|
+
throw new Error("APPDATA not defined");
|
|
11
|
+
return path.join(appData, toolName, "config.json");
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
const configDir = path.join(os.homedir(), ".config", toolName);
|
|
15
|
+
return path.join(configDir, "config.json");
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export async function getConfig() {
|
|
19
|
+
const configPath = getConfigPath();
|
|
20
|
+
try {
|
|
21
|
+
const content = await fs.readFile(configPath, "utf-8");
|
|
22
|
+
return JSON.parse(content);
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
if (err.code === "ENOENT")
|
|
26
|
+
return {};
|
|
27
|
+
console.error(chalk.red("Failed to read config:"), err.message);
|
|
28
|
+
return {};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export async function saveConfig(data) {
|
|
32
|
+
const configPath = getConfigPath();
|
|
33
|
+
const dir = path.dirname(configPath);
|
|
34
|
+
await fs.mkdir(dir, { recursive: true });
|
|
35
|
+
const current = await getConfig();
|
|
36
|
+
const newConfig = { ...current, ...data };
|
|
37
|
+
await fs.writeFile(configPath, JSON.stringify(newConfig, null, 2), "utf-8");
|
|
38
|
+
}
|
|
39
|
+
export async function setApiKey(key) {
|
|
40
|
+
await saveConfig({ apiKey: key });
|
|
41
|
+
}
|
package/dist/confirm.js
CHANGED
|
@@ -6,20 +6,26 @@ export const getUserConfirmation = async (message) => {
|
|
|
6
6
|
output: process.stdout,
|
|
7
7
|
});
|
|
8
8
|
console.log(chalk.green(`\nProposed: "${message}"`));
|
|
9
|
-
const answer = await rl.question(chalk.blue(
|
|
9
|
+
const answer = await rl.question(chalk.blue("Confirm commit? [y=yes, n=no, r=retry, e=edit]: "));
|
|
10
10
|
rl.close();
|
|
11
|
-
const choice = (answer.toLowerCase() ||
|
|
12
|
-
if (choice ===
|
|
11
|
+
const choice = (answer.toLowerCase() || "y").trim();
|
|
12
|
+
if (choice === "e") {
|
|
13
13
|
const editRl = readline.createInterface({
|
|
14
14
|
input: process.stdin,
|
|
15
15
|
output: process.stdout,
|
|
16
|
-
terminal: true
|
|
16
|
+
terminal: true,
|
|
17
17
|
});
|
|
18
18
|
console.log(chalk.cyan("\nEdit the message:"));
|
|
19
19
|
editRl.write(message);
|
|
20
|
-
|
|
20
|
+
let editedMessage = "";
|
|
21
|
+
while (!editedMessage.trim()) {
|
|
22
|
+
editedMessage = await editRl.question("> ");
|
|
23
|
+
if (!editedMessage.trim()) {
|
|
24
|
+
console.log(chalk.red("Commit message cannot be empty. Please type something."));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
21
27
|
editRl.close();
|
|
22
|
-
return { choice:
|
|
28
|
+
return { choice: "y", message: editedMessage };
|
|
23
29
|
}
|
|
24
30
|
return { choice, message };
|
|
25
31
|
};
|
package/dist/llm.js
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import axios from "axios";
|
|
2
2
|
import chalk from "chalk";
|
|
3
3
|
import { buildPrompt } from "./prompt.js";
|
|
4
|
+
import { getConfig } from "./config.js";
|
|
4
5
|
export const generateCommitMessage = async (rawDiff) => {
|
|
5
6
|
const API_URL = "https://generativelanguage.googleapis.com/v1/models/gemini-2.5-flash:generateContent";
|
|
6
|
-
const
|
|
7
|
+
const config = await getConfig();
|
|
8
|
+
const API_KEY = config.apiKey || process.env.GEMINI_COMMIT_MESSAGE_API_KEY;
|
|
7
9
|
if (!API_KEY) {
|
|
8
10
|
console.error(chalk.red("\nMissing GEMINI_COMMIT_MESSAGE_API_KEY environment variable.\n"));
|
|
9
11
|
console.log("Please set your API key before running this command.\n");
|
|
10
12
|
console.log(chalk.yellow("How to fix this:\n"));
|
|
11
|
-
console.log(chalk.
|
|
13
|
+
console.log(chalk.gray("Recommended: use the config helper to save it permanently:\n git-aic config --key <your_api_key>\n"));
|
|
14
|
+
console.log(chalk.cyan("macOS / Linux (temporary):"));
|
|
12
15
|
console.log(" export GEMINI_COMMIT_MESSAGE_API_KEY=your_api_key_here\n");
|
|
13
|
-
console.log(chalk.cyan("Windows (PowerShell):"));
|
|
16
|
+
console.log(chalk.cyan("Windows (PowerShell, temporary):"));
|
|
14
17
|
console.log(' setx GEMINI_COMMIT_MESSAGE_API_KEY "your_api_key_here"\n');
|
|
15
|
-
console.log(chalk.gray("After setting the
|
|
18
|
+
console.log(chalk.gray("After setting the key, restart your terminal.\n"));
|
|
16
19
|
process.exit(1);
|
|
17
20
|
}
|
|
18
21
|
const prompt = buildPrompt(rawDiff);
|
package/dist/prompt.js
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
export const buildPrompt = (diff) => `
|
|
2
|
-
CRITICAL INSTRUCTIONS - READ CAREFULLY:
|
|
3
|
-
You are an expert Git commit message writer. You MUST follow ALL these rules:
|
|
4
|
-
|
|
5
|
-
1. FORMAT: Use Conventional Commits format: <type>(<scope>): <description>
|
|
6
|
-
- type: MUST be one of: feat, fix, refactor, chore, docs, style, test, perf
|
|
7
|
-
- scope: Should be the module/file affected (e.g., "auth", "api", "ui", "config")
|
|
8
|
-
- description: Clear, imperative description in present tense
|
|
9
|
-
|
|
10
|
-
2. DESCRIPTION REQUIREMENTS:
|
|
11
|
-
- Start with an imperative verb (add, fix, remove, update, refactor, etc.)
|
|
12
|
-
- Be specific about what changed
|
|
13
|
-
- Keep it under 72 characters total (including type and scope)
|
|
14
|
-
- NO trailing punctuation
|
|
15
|
-
- NO emojis ever
|
|
16
|
-
- MUST be a complete sentence
|
|
17
|
-
|
|
18
|
-
3. MESSAGE STRUCTURE:
|
|
19
|
-
- The entire commit message must be exactly one line
|
|
20
|
-
- Format: type(scope): description
|
|
21
|
-
- Example: "feat(auth): add password reset functionality"
|
|
22
|
-
- Example: "fix(api): handle null response in user endpoint"
|
|
23
|
-
- Example: "refactor(ui): simplify component state management"
|
|
24
|
-
|
|
25
|
-
4. QUALITY CHECKS - YOUR OUTPUT MUST PASS:
|
|
26
|
-
- Contains opening and closing parentheses
|
|
27
|
-
- Has a colon after the parentheses
|
|
28
|
-
- Description exists and is not empty
|
|
29
|
-
- Total length ≤ 72 characters
|
|
30
|
-
- No markdown formatting
|
|
31
|
-
- No code blocks
|
|
32
|
-
- No explanations or notes
|
|
33
|
-
|
|
34
|
-
5. FAILURE MODE:
|
|
35
|
-
- If you cannot generate a proper message, return exactly: "chore: update code"
|
|
36
|
-
|
|
37
|
-
YOUR TASK:
|
|
38
|
-
Analyze this git diff and generate exactly ONE proper commit message following all rules above.
|
|
39
|
-
|
|
40
|
-
Git diff:
|
|
41
|
-
${diff}
|
|
42
|
-
|
|
43
|
-
Commit message:
|
|
1
|
+
export const buildPrompt = (diff) => `
|
|
2
|
+
CRITICAL INSTRUCTIONS - READ CAREFULLY:
|
|
3
|
+
You are an expert Git commit message writer. You MUST follow ALL these rules:
|
|
4
|
+
|
|
5
|
+
1. FORMAT: Use Conventional Commits format: <type>(<scope>): <description>
|
|
6
|
+
- type: MUST be one of: feat, fix, refactor, chore, docs, style, test, perf
|
|
7
|
+
- scope: Should be the module/file affected (e.g., "auth", "api", "ui", "config")
|
|
8
|
+
- description: Clear, imperative description in present tense
|
|
9
|
+
|
|
10
|
+
2. DESCRIPTION REQUIREMENTS:
|
|
11
|
+
- Start with an imperative verb (add, fix, remove, update, refactor, etc.)
|
|
12
|
+
- Be specific about what changed
|
|
13
|
+
- Keep it under 72 characters total (including type and scope)
|
|
14
|
+
- NO trailing punctuation
|
|
15
|
+
- NO emojis ever
|
|
16
|
+
- MUST be a complete sentence
|
|
17
|
+
|
|
18
|
+
3. MESSAGE STRUCTURE:
|
|
19
|
+
- The entire commit message must be exactly one line
|
|
20
|
+
- Format: type(scope): description
|
|
21
|
+
- Example: "feat(auth): add password reset functionality"
|
|
22
|
+
- Example: "fix(api): handle null response in user endpoint"
|
|
23
|
+
- Example: "refactor(ui): simplify component state management"
|
|
24
|
+
|
|
25
|
+
4. QUALITY CHECKS - YOUR OUTPUT MUST PASS:
|
|
26
|
+
- Contains opening and closing parentheses
|
|
27
|
+
- Has a colon after the parentheses
|
|
28
|
+
- Description exists and is not empty
|
|
29
|
+
- Total length ≤ 72 characters
|
|
30
|
+
- No markdown formatting
|
|
31
|
+
- No code blocks
|
|
32
|
+
- No explanations or notes
|
|
33
|
+
|
|
34
|
+
5. FAILURE MODE:
|
|
35
|
+
- If you cannot generate a proper message, return exactly: "chore: update code"
|
|
36
|
+
|
|
37
|
+
YOUR TASK:
|
|
38
|
+
Analyze this git diff and generate exactly ONE proper commit message following all rules above.
|
|
39
|
+
|
|
40
|
+
Git diff:
|
|
41
|
+
${diff}
|
|
42
|
+
|
|
43
|
+
Commit message:
|
|
44
44
|
`.trim();
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "git-aic",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "AI-powered Git commit generator using Google Gemini",
|
|
5
|
-
"homepage": "https://github.com/
|
|
5
|
+
"homepage": "https://github.com/Spectra010s/git-aic",
|
|
6
6
|
"bugs": {
|
|
7
|
-
"url": "https://github.com/
|
|
7
|
+
"url": "https://github.com/Spectra010s/git-aic/issues"
|
|
8
8
|
},
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
11
|
-
"url": "git+https://github.com/
|
|
11
|
+
"url": "git+https://github.com/Spectra010s/git-aic.git"
|
|
12
12
|
},
|
|
13
13
|
"license": "ISC",
|
|
14
14
|
"author": "Spectra010s",
|
|
@@ -17,9 +17,6 @@
|
|
|
17
17
|
"bin": {
|
|
18
18
|
"git-aic": "./dist/cli.js"
|
|
19
19
|
},
|
|
20
|
-
"files": [
|
|
21
|
-
"dist"
|
|
22
|
-
],
|
|
23
20
|
"scripts": {
|
|
24
21
|
"build": "tsc",
|
|
25
22
|
"prepare": "npm run build"
|
package/t.txt
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Git Aic v1.1.0
|
|
2
|
+
|
|
3
|
+
## Highlights
|
|
4
|
+
- Fully standalone CLI — removed dependency on the original form network.
|
|
5
|
+
- AI-powered commit message generation with Google Gemini.
|
|
6
|
+
- Commit confirmation now gracefully exits if canceled.
|
|
7
|
+
- Empty commit messages are prevented during editing in confirmation prompt.
|
|
8
|
+
- `--issue` option added to link commits to GitHub issues.
|
|
9
|
+
- Flattened project structure for cleaner code organization.
|
|
10
|
+
- Axios errors for LLM requests are now handled properly to avoid crashes.
|
|
11
|
+
- CLI config system for managing your API key.
|
|
12
|
+
- Environment variable fallback supported.
|
|
13
|
+
- README updated with full usage, installation, and features.
|
|
14
|
+
|
|
15
|
+
## Improvements
|
|
16
|
+
- TypeScript & type-safe implementation.
|
|
17
|
+
- Improved user experience — prompts only run when called.
|
|
18
|
+
- Conventional commit compliance enforced.
|
|
19
|
+
- Clear separation between developer install (contributors) and user install (global npm).
|
|
20
|
+
|
|
21
|
+
## Notes
|
|
22
|
+
- Editable prompt system is not yet included — planned for v1.2.0.
|
|
23
|
+
- Users can now run `git aic` globally via npm.
|
|
24
|
+
|
|
25
|
+
## What's Changed
|
|
26
|
+
• refactor(project): flatten project structure and update config by @Spectra010s in https://github.com/Spectra010s/git-aic/pull/1
|
|
27
|
+
• feat(cli): add --issue option to link commit to an issue, closes #3 by @Spectra010s in https://github.com/Spectra010s/git-aic/pull/4
|
|
28
|
+
• prevent empty commit message when editing in confirmation prompt by @Spectra010s in https://github.com/Spectra010s/git-aic/pull/6
|
|
29
|
+
• fix(cli): handle graceful process exit on cancellation, closes #7 by @Spectra010s in https://github.com/Spectra010s/git-aic/pull/8
|
|
30
|
+
• fix(llm): handle Axios errors for LLM requests by @Spectra010s in https://github.com/Spectra010s/git-aic/pull/10
|
|
31
|
+
|
|
32
|
+
Full Changelog: https://github.com/Spectra010s/git-aic/commits/v1.1.0
|