Skip to content

Commit 566b9ff

Browse files
committed
Fix Gemini API, increase OpenAI temperature, and bug fixes
1 parent cccd517 commit 566b9ff

File tree

4 files changed

+200
-24
lines changed

4 files changed

+200
-24
lines changed

.gitignore

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Dependencies
2+
node_modules/
3+
4+
# Lock files
5+
package-lock.json
6+
bun.lock
7+
8+
# Environment variables
9+
.env
10+
.env.local
11+
.env.development.local
12+
.env.test.local
13+
.env.production.local
14+
15+
# Logs
16+
*.log
17+
npm-debug.log*
18+
yarn-debug.log*
19+
yarn-error.log*
20+
21+
# Runtime data
22+
pids
23+
*.pid
24+
*.seed
25+
*.pid.lock
26+
27+
# Coverage directory used by tools like istanbul
28+
coverage/
29+
30+
# OS generated files
31+
.DS_Store
32+
.DS_Store?
33+
._*
34+
.Spotlight-V100
35+
.Trashes
36+
ehthumbs.db
37+
Thumbs.db
38+
39+
# IDE files
40+
.vscode/
41+
.idea/
42+
*.swp
43+
*.swo
44+
*~
45+
46+
# Temporary files
47+
*.tmp
48+
*.temp

CLAUDE.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
GIMS (Git Made Simple) is an AI-powered Git CLI tool that automatically generates meaningful commit messages from code changes. It's a Node.js package published to npm that integrates with OpenAI GPT-4 and Google Gemini APIs.
8+
9+
## Architecture
10+
11+
- **Single-file CLI**: All functionality is contained in `bin/gims.js`
12+
- **AI Integration**: Supports both OpenAI and Google Gemini APIs with intelligent fallback strategies
13+
- **Git Wrapper**: Built on top of `simple-git` library for Git operations
14+
- **Token Management**: Implements sophisticated content chunking to handle large diffs within AI token limits
15+
16+
## Key Components
17+
18+
- **Command System**: Uses `commander.js` for CLI argument parsing with aliases (e.g., `g o` for `gims online`)
19+
- **AI Message Generation**: Multi-strategy approach that falls back from full diff → summary → status → truncated content
20+
- **Commit Resolution**: Supports both commit hashes and numbered indices for referencing commits
21+
- **Safe Operations**: Includes error handling for empty repositories and edge cases
22+
23+
## Environment Setup
24+
25+
Required environment variables (at least one):
26+
- `OPENAI_API_KEY` - For OpenAI GPT-4o-mini integration
27+
- `GEMINI_API_KEY` - For Google Gemini 2.0 Flash integration
28+
29+
## Common Commands
30+
31+
- **Install globally**: `npm install -g .`
32+
- **Test locally**: `node bin/gims.js --help`
33+
- **Test specific command**: `node bin/gims.js suggest`
34+
- **Run with alias**: `g o` (after global install)
35+
36+
## Development Notes
37+
38+
- No test framework is currently configured (package.json shows placeholder test script)
39+
- Node.js version requirement: >=20.0.0
40+
- Uses CommonJS modules (`require`/`module.exports`)
41+
- Dependencies are minimal and focused on core functionality
42+
- Token estimation uses 4 characters per token approximation
43+
- Maximum context limit set conservatively at 100,000 tokens

README.md

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
[![npm version](https://img.shields.io/npm/v/gims.svg)](https://npmjs.org/package/gims)
66
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
77
[![Node.js Version](https://img.shields.io/node/v/gims.svg)](https://nodejs.org/)
8-
[![AI Powered](https://img.shields.io/badge/AI-Powered-blueviolet.svg)](https://github.com/yourusername/gims)
8+
[![AI Powered](https://img.shields.io/badge/AI-Powered-blueviolet.svg)](https://github.com/s41r4j/gims)
99

1010
**The AI-powered Git CLI that writes your commit messages for you**
1111

@@ -34,10 +34,10 @@ g o # AI analyzes changes, commits with perfect message, and pushes!
3434
## 🌟 Features
3535

3636
### 🤖 **AI-Powered Commit Messages**
37-
- **OpenAI GPT-4** integration for intelligent commit message generation
38-
- **Google Gemini** support for lightning-fast analysis
37+
- **OpenAI GPT-4o-mini** integration for intelligent commit message generation
38+
- **Google Gemini 2.0 Flash** support for lightning-fast analysis
3939
- Smart diff analysis that understands your code changes
40-
- Handles large codebases with intelligent summarization
40+
- Handles large codebases with intelligent summarization and token management
4141

4242
### **Lightning Fast Workflow**
4343
- **One command commits**: `g o` - analyze, commit, and push in seconds
@@ -95,6 +95,7 @@ g o
9595
| `gims init` | `g i` | Initialize new Git repo | `g i` |
9696
| `gims clone <repo>` | `g c` | Clone repository | `g c https://github.com/user/repo` |
9797
| `gims suggest` | `g s` | Generate & copy commit message | `g s` |
98+
| `gims commit` | `g cm` | Interactive commit message generation | `g cm` |
9899
| `gims local` | `g l` | AI commit locally | `g l` |
99100
| `gims online` | `g o` | AI commit + push | `g o` |
100101
| `gims pull` | `g p` | Pull latest changes | `g p` |
@@ -144,7 +145,7 @@ g p # Pull latest changes
144145
g s # Preview AI suggestion
145146
g l # Commit locally first
146147
# ... test your changes ...
147-
g push # Push when ready
148+
g o # Push with AI commit message
148149
```
149150

150151
### 🧠 **Smart Branching**
@@ -180,6 +181,7 @@ GIMS handles edge cases gracefully:
180181
- **📊 Massive changes**: Falls back to status-based analysis
181182
- **🛜 No API key**: Uses sensible default messages
182183
- **⚠️ API failures**: Graceful degradation with helpful errors
184+
- **🪙 Token limits**: Intelligent content chunking with 100K token limit
183185

184186
## 🤝 Contributing
185187

@@ -194,8 +196,8 @@ We love contributions! Here's how to get involved:
194196

195197
### 🐛 Found a Bug?
196198

197-
1. Check [existing issues](https://github.com/yourusername/gims/issues)
198-
2. Create a [new issue](https://github.com/yourusername/gims/issues/new) with:
199+
1. Check [existing issues](https://github.com/s41r4j/gims/issues)
200+
2. Create a [new issue](https://github.com/s41r4j/gims/issues/new) with:
199201
- Clear description
200202
- Steps to reproduce
201203
- Expected vs actual behavior
@@ -248,7 +250,7 @@ MIT © [GIMS](https://github.com/s41r4j/gims)
248250

249251
**⭐ Star this repo if GIMS makes your Git workflow awesome!**
250252

251-
[Report Bug](https://github.com/yourusername/gims/issues)[Request Feature](https://github.com/yourusername/gims/issues)[Documentation](https://github.com/yourusername/gims/wiki)
253+
[Report Bug](https://github.com/s41r4j/gims/issues)[Request Feature](https://github.com/s41r4j/gims/issues)[Documentation](https://github.com/s41r4j/gims#readme)
252254

253255
*Made with ❤️ by developers who hate writing commit messages*
254256

bin/gims.js

Lines changed: 99 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
*/
66
const { Command } = require('commander');
77
const simpleGit = require('simple-git');
8-
const clipboard = require('clipboardy');
98
const process = require('process');
109
const { OpenAI } = require('openai');
1110
const { GoogleGenAI } = require('@google/genai');
@@ -116,6 +115,11 @@ async function generateCommitMessage(rawDiff) {
116115
return 'Update multiple files';
117116
}
118117

118+
// Check if API key is available
119+
if (!process.env.GEMINI_API_KEY && !process.env.OPENAI_API_KEY) {
120+
return null; // Signal that no API key is available
121+
}
122+
119123
let message = 'Update project code'; // Default fallback
120124

121125
try {
@@ -125,13 +129,13 @@ async function generateCommitMessage(rawDiff) {
125129
model: 'gemini-2.0-flash',
126130
contents: prompt
127131
});
128-
message = (await res.response.text()).trim();
132+
message = res.text.trim();
129133
} else if (process.env.OPENAI_API_KEY) {
130134
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
131135
const res = await openai.chat.completions.create({
132136
model: 'gpt-4o-mini',
133137
messages: [{ role: 'user', content: prompt }],
134-
temperature: 0.5,
138+
temperature: 0.75,
135139
max_tokens: 100 // Limit response length
136140
});
137141
message = res.choices[0].message.content.trim();
@@ -176,7 +180,7 @@ program.command('clone <repo>').alias('c')
176180
});
177181

178182
program.command('suggest').alias('s')
179-
.description('Suggest commit message and copy to clipboard')
183+
.description('Suggest commit message')
180184
.action(async () => {
181185
if (!(await hasChanges())) {
182186
return console.log('No changes to suggest.');
@@ -185,23 +189,92 @@ program.command('suggest').alias('s')
185189
const { all } = await safeLog();
186190
const isFirst = all.length === 0;
187191

188-
// Always add changes first
189-
await git.add('.');
190-
191-
// Get the appropriate diff
192-
const rawDiff = await git.diff(['--cached']);
192+
// Get diff of unstaged changes
193+
let rawDiff = await git.diff();
193194

195+
// If no diff from tracked files, check for untracked files
194196
if (!rawDiff.trim()) {
195-
return console.log('No changes to suggest.');
197+
const status = await git.status();
198+
if (status.not_added.length > 0) {
199+
// For untracked files, show file list since we can't diff them
200+
rawDiff = `New files:\n${status.not_added.join('\n')}`;
201+
} else {
202+
return console.log('No changes to suggest.');
203+
}
196204
}
197205

198206
const msg = await generateCommitMessage(rawDiff);
199207

200-
try {
201-
clipboard.writeSync(msg);
202-
console.log(`Suggested: "${msg}" (copied to clipboard)`);
203-
} catch (error) {
204-
console.log(`Suggested: "${msg}" (clipboard copy failed)`);
208+
if (msg === null) {
209+
return console.log('Please set GEMINI_API_KEY or OPENAI_API_KEY environment variable');
210+
}
211+
212+
console.log(`git add . && git commit -m "${msg}"`);
213+
});
214+
215+
program.command('commit').alias('cm')
216+
.description('Interactive commit message generation')
217+
.action(async () => {
218+
if (!(await hasChanges())) {
219+
return console.log('No changes to commit.');
220+
}
221+
222+
// Get diff for message generation
223+
let rawDiff = await git.diff();
224+
225+
// If no diff from tracked files, check for untracked files
226+
if (!rawDiff.trim()) {
227+
const status = await git.status();
228+
if (status.not_added.length > 0) {
229+
rawDiff = `New files:\n${status.not_added.join('\n')}`;
230+
} else {
231+
return console.log('No changes to commit.');
232+
}
233+
}
234+
235+
if (!process.env.GEMINI_API_KEY && !process.env.OPENAI_API_KEY) {
236+
return console.log('Please set GEMINI_API_KEY or OPENAI_API_KEY environment variable');
237+
}
238+
239+
const readline = require('readline');
240+
const rl = readline.createInterface({
241+
input: process.stdin,
242+
output: process.stdout
243+
});
244+
245+
const askForInput = () => {
246+
return new Promise((resolve) => {
247+
rl.question('> ', (answer) => {
248+
resolve(answer.toLowerCase().trim());
249+
});
250+
});
251+
};
252+
253+
let currentMessage = await generateCommitMessage(rawDiff);
254+
console.log(`\n=== Interactive Commit ===`);
255+
console.log(`┌──────────────────────────────────────────────────────────────────────┐`);
256+
console.log(`│ Press "Enter" to generate new message, "c" to commit, or "q" to quit │`);
257+
console.log(`└──────────────────────────────────────────────────────────────────────┘\n`);
258+
console.log(`Suggested: "${currentMessage}"`);
259+
260+
while (true) {
261+
const input = await askForInput();
262+
263+
if (input === 'q' || input === 'quit') {
264+
console.log('Cancelled.');
265+
rl.close();
266+
return;
267+
} else if (input === 'c' || input === 'commit') {
268+
await git.add('.');
269+
await git.commit(currentMessage);
270+
console.log(`Committed: "${currentMessage}"`);
271+
rl.close();
272+
return;
273+
} else {
274+
// Generate new message
275+
currentMessage = await generateCommitMessage(rawDiff);
276+
console.log(`Suggested: "${currentMessage}"`);
277+
}
205278
}
206279
});
207280

@@ -226,6 +299,11 @@ program.command('local').alias('l')
226299
}
227300

228301
const msg = await generateCommitMessage(rawDiff);
302+
303+
if (msg === null) {
304+
return console.log('Please set GEMINI_API_KEY or OPENAI_API_KEY environment variable');
305+
}
306+
229307
await git.commit(msg);
230308
console.log(`Committed locally: "${msg}"`);
231309
});
@@ -251,6 +329,11 @@ program.command('online').alias('o')
251329
}
252330

253331
const msg = await generateCommitMessage(rawDiff);
332+
333+
if (msg === null) {
334+
return console.log('Please set GEMINI_API_KEY or OPENAI_API_KEY environment variable');
335+
}
336+
254337
await git.commit(msg);
255338
await git.push();
256339
console.log(`Committed & pushed: "${msg}"`);
@@ -302,4 +385,4 @@ program.command('revert <c>').alias('rv')
302385
catch (e) { console.error('Revert error:', e.message); }
303386
});
304387

305-
program.parse(process.argv);
388+
program.parse(process.argv);

0 commit comments

Comments
 (0)