Skip to content

Commit eb5aa4a

Browse files
committed
add belt CLI commit command with AI generation
1 parent d188af0 commit eb5aa4a

File tree

4 files changed

+190
-3
lines changed

4 files changed

+190
-3
lines changed

packages/belt-cli/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,15 @@
4949
"repo:open": {
5050
"script": "commands/repo-open",
5151
"description": "open repo in a browser"
52+
},
53+
"commit": {
54+
"script": "commands/commit",
55+
"description": "commit changes with brief message"
5256
}
5357
}
5458
},
5559
"dependencies": {
60+
"@anthropic-ai/claude-code": "^1.0.108",
5661
"any-shell-escape": "^0.1.1",
5762
"chalk": "^2.4.1",
5863
"execa": "^9.6.0",
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { query } from '@anthropic-ai/claude-code';
2+
import execa from '../modules/execa.js';
3+
4+
export async function run(_: { argv: any }) {
5+
const diff = await getGitDiff();
6+
if (!diff.trim()) {
7+
console.log('No changes to commit');
8+
process.exit(1);
9+
}
10+
11+
const commitMessage = await generateCommitMessage(diff);
12+
13+
console.log(`\nCommit message: ${commitMessage}`);
14+
await execa('git', ['commit', '-m', commitMessage], { stdio: 'inherit' });
15+
console.log('Changes committed successfully');
16+
}
17+
18+
async function generateCommitMessage(diff: string): Promise<string> {
19+
const abortController = new AbortController();
20+
const prompt = `Based on the git status and diff below, generate a brief commit message (max 50 chars):
21+
22+
Git Diff:
23+
${diff.substring(0, 2000)}${diff.length > 2000 ? '...' : ''}
24+
25+
Rules:
26+
- Keep it under 50 characters
27+
- Use present tense (add, update, fix, etc.)
28+
- Be specific but concise
29+
- No periods at the end`;
30+
31+
for await (const message of query({
32+
prompt,
33+
options: {
34+
abortController,
35+
maxTurns: 5,
36+
allowedTools: [],
37+
},
38+
})) {
39+
if (message.type === 'result' && message.subtype === 'success') {
40+
abortController.abort();
41+
return message.result;
42+
}
43+
}
44+
45+
throw new Error('Failed to generate commit message');
46+
}
47+
48+
async function getGitDiff(): Promise<string> {
49+
return await execa('git', ['diff', '--cached'], {});
50+
}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { execa as ogExeca } from 'execa';
1+
import { type Options, execa as ogExeca } from 'execa';
22
import { logShell } from './log.js';
33

44
// seems cleaner without abstractions
5-
export default async function execaProxy(cmd: string, args: string[], opts?: any) {
5+
export default async function execaProxy(cmd: string, args: string[], opts?: Options) {
66
logShell([cmd, ...args]);
77
const { stdout } = await ogExeca(cmd, args, opts);
8-
return stdout;
8+
return stdout as string;
99
}

yarn.lock

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,40 @@ __metadata:
55
version: 8
66
cacheKey: 10c0
77

8+
"@anthropic-ai/claude-code@npm:^1.0.108":
9+
version: 1.0.108
10+
resolution: "@anthropic-ai/claude-code@npm:1.0.108"
11+
dependencies:
12+
"@img/sharp-darwin-arm64": "npm:^0.33.5"
13+
"@img/sharp-darwin-x64": "npm:^0.33.5"
14+
"@img/sharp-linux-arm": "npm:^0.33.5"
15+
"@img/sharp-linux-arm64": "npm:^0.33.5"
16+
"@img/sharp-linux-x64": "npm:^0.33.5"
17+
"@img/sharp-win32-x64": "npm:^0.33.5"
18+
dependenciesMeta:
19+
"@img/sharp-darwin-arm64":
20+
optional: true
21+
"@img/sharp-darwin-x64":
22+
optional: true
23+
"@img/sharp-linux-arm":
24+
optional: true
25+
"@img/sharp-linux-arm64":
26+
optional: true
27+
"@img/sharp-linux-x64":
28+
optional: true
29+
"@img/sharp-win32-x64":
30+
optional: true
31+
bin:
32+
claude: cli.js
33+
checksum: 10c0/d06e265b030fa523f5215bf4292adb4a0af0d0ecc84e5a85a4cf4e9dcda73ede3208c197b23142b9db963ce6989f409016042108c6febb9ab27e3fdc138994f3
34+
languageName: node
35+
linkType: hard
36+
837
"@belt/cli@workspace:packages/belt-cli":
938
version: 0.0.0-use.local
1039
resolution: "@belt/cli@workspace:packages/belt-cli"
1140
dependencies:
41+
"@anthropic-ai/claude-code": "npm:^1.0.108"
1242
"@types/js-yaml": "npm:^4.0.9"
1343
"@types/lodash": "npm:^4.17.20"
1444
"@types/make-dir": "npm:^2.1.0"
@@ -122,6 +152,108 @@ __metadata:
122152
languageName: node
123153
linkType: hard
124154

155+
"@img/sharp-darwin-arm64@npm:^0.33.5":
156+
version: 0.33.5
157+
resolution: "@img/sharp-darwin-arm64@npm:0.33.5"
158+
dependencies:
159+
"@img/sharp-libvips-darwin-arm64": "npm:1.0.4"
160+
dependenciesMeta:
161+
"@img/sharp-libvips-darwin-arm64":
162+
optional: true
163+
conditions: os=darwin & cpu=arm64
164+
languageName: node
165+
linkType: hard
166+
167+
"@img/sharp-darwin-x64@npm:^0.33.5":
168+
version: 0.33.5
169+
resolution: "@img/sharp-darwin-x64@npm:0.33.5"
170+
dependencies:
171+
"@img/sharp-libvips-darwin-x64": "npm:1.0.4"
172+
dependenciesMeta:
173+
"@img/sharp-libvips-darwin-x64":
174+
optional: true
175+
conditions: os=darwin & cpu=x64
176+
languageName: node
177+
linkType: hard
178+
179+
"@img/sharp-libvips-darwin-arm64@npm:1.0.4":
180+
version: 1.0.4
181+
resolution: "@img/sharp-libvips-darwin-arm64@npm:1.0.4"
182+
conditions: os=darwin & cpu=arm64
183+
languageName: node
184+
linkType: hard
185+
186+
"@img/sharp-libvips-darwin-x64@npm:1.0.4":
187+
version: 1.0.4
188+
resolution: "@img/sharp-libvips-darwin-x64@npm:1.0.4"
189+
conditions: os=darwin & cpu=x64
190+
languageName: node
191+
linkType: hard
192+
193+
"@img/sharp-libvips-linux-arm64@npm:1.0.4":
194+
version: 1.0.4
195+
resolution: "@img/sharp-libvips-linux-arm64@npm:1.0.4"
196+
conditions: os=linux & cpu=arm64 & libc=glibc
197+
languageName: node
198+
linkType: hard
199+
200+
"@img/sharp-libvips-linux-arm@npm:1.0.5":
201+
version: 1.0.5
202+
resolution: "@img/sharp-libvips-linux-arm@npm:1.0.5"
203+
conditions: os=linux & cpu=arm & libc=glibc
204+
languageName: node
205+
linkType: hard
206+
207+
"@img/sharp-libvips-linux-x64@npm:1.0.4":
208+
version: 1.0.4
209+
resolution: "@img/sharp-libvips-linux-x64@npm:1.0.4"
210+
conditions: os=linux & cpu=x64 & libc=glibc
211+
languageName: node
212+
linkType: hard
213+
214+
"@img/sharp-linux-arm64@npm:^0.33.5":
215+
version: 0.33.5
216+
resolution: "@img/sharp-linux-arm64@npm:0.33.5"
217+
dependencies:
218+
"@img/sharp-libvips-linux-arm64": "npm:1.0.4"
219+
dependenciesMeta:
220+
"@img/sharp-libvips-linux-arm64":
221+
optional: true
222+
conditions: os=linux & cpu=arm64 & libc=glibc
223+
languageName: node
224+
linkType: hard
225+
226+
"@img/sharp-linux-arm@npm:^0.33.5":
227+
version: 0.33.5
228+
resolution: "@img/sharp-linux-arm@npm:0.33.5"
229+
dependencies:
230+
"@img/sharp-libvips-linux-arm": "npm:1.0.5"
231+
dependenciesMeta:
232+
"@img/sharp-libvips-linux-arm":
233+
optional: true
234+
conditions: os=linux & cpu=arm & libc=glibc
235+
languageName: node
236+
linkType: hard
237+
238+
"@img/sharp-linux-x64@npm:^0.33.5":
239+
version: 0.33.5
240+
resolution: "@img/sharp-linux-x64@npm:0.33.5"
241+
dependencies:
242+
"@img/sharp-libvips-linux-x64": "npm:1.0.4"
243+
dependenciesMeta:
244+
"@img/sharp-libvips-linux-x64":
245+
optional: true
246+
conditions: os=linux & cpu=x64 & libc=glibc
247+
languageName: node
248+
linkType: hard
249+
250+
"@img/sharp-win32-x64@npm:^0.33.5":
251+
version: 0.33.5
252+
resolution: "@img/sharp-win32-x64@npm:0.33.5"
253+
conditions: os=win32 & cpu=x64
254+
languageName: node
255+
linkType: hard
256+
125257
"@nodelib/fs.scandir@npm:2.1.5":
126258
version: 2.1.5
127259
resolution: "@nodelib/fs.scandir@npm:2.1.5"

0 commit comments

Comments
 (0)