gims 0.4.2
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/README.md +150 -0
- package/bin/gims.js +167 -0
- package/package.json +44 -0
package/README.md
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
Hereβs a **complete usage guide** for `gims` (Git Made Simple) CLI tool:
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## π Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g gims
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
This installs the `gims` command and a shortcut alias:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
g # shortcut for gims
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## π§ Environment Setup (Optional for AI)
|
|
20
|
+
|
|
21
|
+
To enable AI-generated commit messages:
|
|
22
|
+
|
|
23
|
+
### β
Option 1: Gemini API
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
export GEMINI_API_KEY='your_gemini_api_key'
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### β
Option 2: OpenAI API (used if Gemini key not found)
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
export OPENAI_API_KEY='your_openai_api_key'
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
If neither is set, it defaults to a generic commit message.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## π§ AI Commit Modes
|
|
40
|
+
|
|
41
|
+
### 1. Commit Locally with AI Message
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
g l # or gims local
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
β Adds and commits current changes locally with a descriptive commit message generated by AI.
|
|
48
|
+
|
|
49
|
+
### 2. Commit & Push with AI Message
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
g o # or gims online
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
β Adds, commits, and pushes the current changes to the remote branch.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## π Version History Navigation
|
|
60
|
+
|
|
61
|
+
### View Git Logs (Short)
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
g ls # or gims list
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
β Shows a numbered short log:
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
1. 1234abc Added login feature
|
|
71
|
+
2. 5678def Fixed bug in auth flow
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### View Git Logs (Full)
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
g ll # or gims largelist
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
β Full `git log` (without pager).
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## πΏ Branching & Resetting
|
|
85
|
+
|
|
86
|
+
### Create Branch from a Commit or Number
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
g b 2 try-new-idea
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
β Branches off from commit #2 (resolved via `g ls`) into a new branch `try-new-idea`.
|
|
93
|
+
|
|
94
|
+
### Reset to a Commit or Number
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
g r 1 --hard
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
β Resets the current branch to commit #1 permanently (`--hard` is optional).
|
|
101
|
+
|
|
102
|
+
### Revert a Commit or Number
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
g rv 3
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
β Reverts changes made by commit #3 (safe, non-destructive).
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## π Git Init
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
g i # or gims init
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
β Initializes a new Git repository.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## π Example Workflow
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
cd myproject/
|
|
126
|
+
g i # Initialize repository
|
|
127
|
+
touch index.js # Add file
|
|
128
|
+
g l # Auto commit locally with AI
|
|
129
|
+
g ls # See commit history
|
|
130
|
+
g b 1 try-feature # Branch out from earlier version
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## π¦ Dependencies Used
|
|
136
|
+
|
|
137
|
+
* [`simple-git`](https://www.npmjs.com/package/simple-git) β Git CLI wrapper
|
|
138
|
+
* [`openai`](https://www.npmjs.com/package/openai) β OpenAI SDK
|
|
139
|
+
* [`@google-ai/gemini`](https://www.npmjs.com/package/@google-ai/gemini) β Gemini SDK
|
|
140
|
+
* [`commander`](https://www.npmjs.com/package/commander) β CLI argument parser
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
Let me know if youβd like to:
|
|
145
|
+
|
|
146
|
+
* Add auto-push branch creation
|
|
147
|
+
* Show full diff preview
|
|
148
|
+
* Add emojis, scopes, or conventional commits
|
|
149
|
+
* Bundle this as a GUI as well!
|
|
150
|
+
|
package/bin/gims.js
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
gims (Git Made Simple) CLI
|
|
5
|
+
Features:
|
|
6
|
+
- Initialize repository (init alias: i)
|
|
7
|
+
- Auto commit with AI-generated messages (Gemini or OpenAI)
|
|
8
|
+
Modes:
|
|
9
|
+
* local (alias: l)
|
|
10
|
+
* online (alias: o)
|
|
11
|
+
- Navigation:
|
|
12
|
+
* list (alias: ls): numbered git log --oneline
|
|
13
|
+
* largelist (alias: ll): full git log --no-pager
|
|
14
|
+
* branch <commit|#> [name] (alias: b)
|
|
15
|
+
* reset <commit|#> [--hard] (alias: r)
|
|
16
|
+
* revert <commit|#> (alias: rv)
|
|
17
|
+
|
|
18
|
+
Env vars:
|
|
19
|
+
- GEMINI_API_KEY: use Google Gemini API
|
|
20
|
+
- OPENAI_API_KEY: fallback to OpenAI if Gemini not set
|
|
21
|
+
- none: fallback to generic commit messages
|
|
22
|
+
|
|
23
|
+
Usage:
|
|
24
|
+
npm install -g gims
|
|
25
|
+
export GEMINI_API_KEY=...
|
|
26
|
+
export OPENAI_API_KEY=...
|
|
27
|
+
gims init # or g i
|
|
28
|
+
gims local # or g l
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
const { Command } = require('commander');
|
|
32
|
+
const simpleGit = require('simple-git');
|
|
33
|
+
const process = require('process');
|
|
34
|
+
const { OpenAI } = require('openai');
|
|
35
|
+
const { GoogleGenAI } = require('@google/genai');
|
|
36
|
+
|
|
37
|
+
const program = new Command();
|
|
38
|
+
const git = simpleGit();
|
|
39
|
+
|
|
40
|
+
// Setup AI clients
|
|
41
|
+
const hasGemini = !!process.env.GEMINI_API_KEY;
|
|
42
|
+
const hasOpenAI = !hasGemini && !!process.env.OPENAI_API_KEY;
|
|
43
|
+
let genai, openai;
|
|
44
|
+
|
|
45
|
+
if (hasGemini) {
|
|
46
|
+
genai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
|
|
47
|
+
} else if (hasOpenAI) {
|
|
48
|
+
openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async function generateCommitMessage(diff) {
|
|
52
|
+
if (hasGemini) {
|
|
53
|
+
const res = await genai.models.generateContent({
|
|
54
|
+
model: 'gemini-2.0-flash',
|
|
55
|
+
contents: `Write a concise git commit message for these changes:\n${diff}`,
|
|
56
|
+
});
|
|
57
|
+
return res.text.trim();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (hasOpenAI) {
|
|
61
|
+
const res = await openai.chat.completions.create({
|
|
62
|
+
model: 'gpt-4o-mini',
|
|
63
|
+
messages: [{ role: 'user', content: `Write a concise git commit message for these changes:\n${diff}` }],
|
|
64
|
+
temperature: 0.5,
|
|
65
|
+
});
|
|
66
|
+
return res.choices[0].message.content.trim();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// fallback generic
|
|
70
|
+
return 'Update project code';
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async function resolveCommit(input) {
|
|
74
|
+
if (/^\d+$/.test(input)) {
|
|
75
|
+
const { all } = await git.log();
|
|
76
|
+
const idx = parseInt(input, 10) - 1;
|
|
77
|
+
if (idx < 0 || idx >= all.length) throw new Error('Index out of range');
|
|
78
|
+
return all[idx].hash;
|
|
79
|
+
}
|
|
80
|
+
return input;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
program.name('gims').alias('g').version('0.4.2');
|
|
84
|
+
|
|
85
|
+
program.command('init').alias('i')
|
|
86
|
+
.description('Initialize a new Git repository')
|
|
87
|
+
.action(async () => {
|
|
88
|
+
await git.init();
|
|
89
|
+
console.log('Initialized repo.');
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Local commit: stage all, get staged diff, AI message, commit
|
|
93
|
+
program.command('local').alias('l')
|
|
94
|
+
.description('AI-powered local commit')
|
|
95
|
+
.action(async () => {
|
|
96
|
+
// stage all changes first
|
|
97
|
+
await git.add('.');
|
|
98
|
+
// get diff of staged changes
|
|
99
|
+
const diff = await git.diff(['--cached']);
|
|
100
|
+
if (!diff) return console.log('No changes to commit.');
|
|
101
|
+
console.log('Generating commit message...');
|
|
102
|
+
const msg = await generateCommitMessage(diff);
|
|
103
|
+
await git.commit(msg);
|
|
104
|
+
console.log(`Committed locally: "${msg}"`);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Online commit: stage, diff, message, commit, push
|
|
108
|
+
program.command('online').alias('o')
|
|
109
|
+
.description('AI commit + push')
|
|
110
|
+
.action(async () => {
|
|
111
|
+
await git.add('.');
|
|
112
|
+
const diff = await git.diff(['--cached']);
|
|
113
|
+
if (!diff) return console.log('No changes to commit.');
|
|
114
|
+
console.log('Generating commit message...');
|
|
115
|
+
const msg = await generateCommitMessage(diff);
|
|
116
|
+
await git.commit(msg);
|
|
117
|
+
await git.push();
|
|
118
|
+
console.log(`Committed & pushed: "${msg}"`);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
program.command('list').alias('ls')
|
|
122
|
+
.description('Short numbered git log')
|
|
123
|
+
.action(async () => {
|
|
124
|
+
const { all } = await git.log();
|
|
125
|
+
all.forEach((c, i) => console.log(`${i+1}. ${c.hash.slice(0,7)} ${c.message}`));
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
program.command('largelist').alias('ll')
|
|
129
|
+
.description('Full git log without pager')
|
|
130
|
+
.action(async () => {
|
|
131
|
+
console.log(await git.raw(['--no-pager', 'log']));
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
program.command('branch <c> [name]').alias('b')
|
|
135
|
+
.description('Branch from commit/index')
|
|
136
|
+
.action(async (c, name) => {
|
|
137
|
+
try {
|
|
138
|
+
const sha = await resolveCommit(c);
|
|
139
|
+
const br = name || `branch-${sha.slice(0,7)}`;
|
|
140
|
+
await git.checkout(['-b', br, sha]);
|
|
141
|
+
console.log(`Switched to branch ${br} at ${sha}`);
|
|
142
|
+
} catch (e) { console.error(e.message); }
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
program.command('reset <c>').alias('r')
|
|
146
|
+
.description('Reset branch to commit/index')
|
|
147
|
+
.option('--hard', 'hard reset')
|
|
148
|
+
.action(async (c, opts) => {
|
|
149
|
+
try {
|
|
150
|
+
const sha = await resolveCommit(c);
|
|
151
|
+
const mode = opts.hard ? '--hard' : '--soft';
|
|
152
|
+
await git.raw(['reset', mode, sha]);
|
|
153
|
+
console.log(`Reset (${mode}) to ${sha}`);
|
|
154
|
+
} catch (e) { console.error(e.message); }
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
program.command('revert <c>').alias('rv')
|
|
158
|
+
.description('Revert commit/index safely')
|
|
159
|
+
.action(async (c) => {
|
|
160
|
+
try {
|
|
161
|
+
const sha = await resolveCommit(c);
|
|
162
|
+
await git.revert(sha);
|
|
163
|
+
console.log(`Reverted ${sha}`);
|
|
164
|
+
} catch (e) { console.error(e.message); }
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
program.parse(process.argv);
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "gims",
|
|
3
|
+
"version": "0.4.2",
|
|
4
|
+
"description": "Git Made Simple β AIβpowered git helper using Gemini / OpenAI",
|
|
5
|
+
"author": "S41R4J",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"bin": {
|
|
8
|
+
"gims": "bin/gims.js",
|
|
9
|
+
"g": "bin/gims.js"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"git",
|
|
13
|
+
"cli",
|
|
14
|
+
"ai",
|
|
15
|
+
"commit",
|
|
16
|
+
"gpt",
|
|
17
|
+
"gemini",
|
|
18
|
+
"openai",
|
|
19
|
+
"developer-tools",
|
|
20
|
+
"version-control"
|
|
21
|
+
],
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/s41r4j/gims.git"
|
|
25
|
+
},
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/s41r4j/gims/issues"
|
|
28
|
+
},
|
|
29
|
+
"homepage": "https://github.com/s41r4j/gims#readme",
|
|
30
|
+
"main": "bin/gims.js",
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=20.0.0"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@google/genai": "^1.5.1",
|
|
36
|
+
"commander": "^11.1.0",
|
|
37
|
+
"openai": "^4.0.0",
|
|
38
|
+
"simple-git": "^3.19.1"
|
|
39
|
+
},
|
|
40
|
+
"type": "commonjs",
|
|
41
|
+
"scripts": {
|
|
42
|
+
"test": "echo \"No tests yet\" && exit 0"
|
|
43
|
+
}
|
|
44
|
+
}
|