commit-agent-cli 0.1.5 → 0.1.7
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 +2 -7
- package/dist/index.js +64 -26
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# commit-agent-cli
|
|
2
2
|
|
|
3
|
-
> AI-powered git commit message generator using Claude 4.5 and LangGraph
|
|
3
|
+
> AI-powered git commit message generator using Claude Sonnet 4.5 and LangGraph
|
|
4
4
|
|
|
5
5
|
Generate intelligent, context-aware commit messages by simply typing `commit`.
|
|
6
6
|
|
|
@@ -25,12 +25,7 @@ You'll be prompted to:
|
|
|
25
25
|
|
|
26
26
|
## Features
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
- 🕵️ Autonomous codebase exploration
|
|
30
|
-
- 👁️ Transparent agent actions
|
|
31
|
-
- ⚙️ Customizable commit styles
|
|
32
|
-
- 🔒 Secure local storage
|
|
33
|
-
- 🔔 Auto update notifications
|
|
28
|
+
Powered by Claude Sonnet 4.5, this tool autonomously explores your codebase to generate intelligent commit messages with full transparency into its reasoning process. Supports customizable commit styles with secure local configuration storage.
|
|
34
29
|
|
|
35
30
|
## Documentation
|
|
36
31
|
|
package/dist/index.js
CHANGED
|
@@ -100,7 +100,7 @@ var require_picocolors = __commonJS({
|
|
|
100
100
|
|
|
101
101
|
// src/index.ts
|
|
102
102
|
import "dotenv/config";
|
|
103
|
-
import { intro, outro, text, spinner,
|
|
103
|
+
import { intro, outro, text, spinner, isCancel, cancel, note, select } from "@clack/prompts";
|
|
104
104
|
|
|
105
105
|
// src/git.ts
|
|
106
106
|
import { execa } from "execa";
|
|
@@ -349,7 +349,7 @@ function getApp() {
|
|
|
349
349
|
app = workflow.compile();
|
|
350
350
|
return app;
|
|
351
351
|
}
|
|
352
|
-
async function generateCommitMessage(diff, preferences) {
|
|
352
|
+
async function generateCommitMessage(diff, preferences, userFeedback) {
|
|
353
353
|
const conventionalGuide = preferences.useConventionalCommits ? "Use conventional commit format with prefixes like feat:, fix:, chore:, docs:, style:, refactor:, test:, etc." : "Do NOT use conventional commit prefixes. Write natural commit messages.";
|
|
354
354
|
const styleGuide = preferences.commitMessageStyle === "descriptive" ? 'Be descriptive and detailed. Explain the "why" behind changes when relevant. Multi-line messages are encouraged.' : "Be concise and to the point. Keep it short, ideally one line.";
|
|
355
355
|
const systemPrompt = `You are an expert developer. Your task is to generate a commit message for the provided git diff.
|
|
@@ -386,7 +386,10 @@ DEFAULT ACTION: Read the diff, generate the message, done. NO TOOLS.
|
|
|
386
386
|
new SystemMessage(systemPrompt),
|
|
387
387
|
new HumanMessage(`Generate a commit message for this diff:
|
|
388
388
|
|
|
389
|
-
${diff}`
|
|
389
|
+
${diff}${userFeedback ? `
|
|
390
|
+
|
|
391
|
+
User feedback on previous attempt: ${userFeedback}
|
|
392
|
+
Please adjust the commit message based on this feedback.` : ""}`)
|
|
390
393
|
];
|
|
391
394
|
const graph = getApp();
|
|
392
395
|
const result = await graph.invoke({ messages });
|
|
@@ -435,19 +438,25 @@ var notifier = updateNotifier({
|
|
|
435
438
|
updateCheckInterval: 1e3 * 60 * 60
|
|
436
439
|
// Check once per hour (was 24h)
|
|
437
440
|
});
|
|
438
|
-
if (notifier.update) {
|
|
441
|
+
if (notifier.update && notifier.update.current !== notifier.update.latest) {
|
|
439
442
|
const currentVersion = notifier.update.current;
|
|
440
443
|
const latestVersion = notifier.update.latest;
|
|
444
|
+
const boxWidth = 67;
|
|
445
|
+
const padLine = (content, width) => {
|
|
446
|
+
const visibleLength = content.replace(/\u001b\[[0-9;]*m/g, "").length;
|
|
447
|
+
const padding = width - visibleLength;
|
|
448
|
+
return content + " ".repeat(Math.max(0, padding));
|
|
449
|
+
};
|
|
441
450
|
console.log("");
|
|
442
451
|
console.log(import_picocolors.default.yellow("\u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E"));
|
|
443
|
-
console.log(import_picocolors.default.yellow("\u2502") + "
|
|
444
|
-
console.log(import_picocolors.default.yellow("\u2502") + " " + import_picocolors.default.bold("New version of commit-cli is available!")
|
|
445
|
-
console.log(import_picocolors.default.yellow("\u2502") + "
|
|
446
|
-
console.log(import_picocolors.default.yellow("\u2502") + " Current: " + import_picocolors.default.dim(currentVersion) + " \u2192 Latest: " + import_picocolors.default.green(import_picocolors.default.bold(latestVersion))
|
|
447
|
-
console.log(import_picocolors.default.yellow("\u2502") + "
|
|
448
|
-
console.log(import_picocolors.default.yellow("\u2502") + " " + import_picocolors.default.dim("Update after you finish by running:")
|
|
449
|
-
console.log(import_picocolors.default.yellow("\u2502") + " " + import_picocolors.default.cyan(import_picocolors.default.bold(`npm install -g ${packageJson.name}@latest`))
|
|
450
|
-
console.log(import_picocolors.default.yellow("\u2502") + "
|
|
452
|
+
console.log(import_picocolors.default.yellow("\u2502") + padLine("", boxWidth) + import_picocolors.default.yellow("\u2502"));
|
|
453
|
+
console.log(import_picocolors.default.yellow("\u2502") + padLine(" " + import_picocolors.default.bold("New version of commit-cli is available!"), boxWidth) + import_picocolors.default.yellow("\u2502"));
|
|
454
|
+
console.log(import_picocolors.default.yellow("\u2502") + padLine("", boxWidth) + import_picocolors.default.yellow("\u2502"));
|
|
455
|
+
console.log(import_picocolors.default.yellow("\u2502") + padLine(" Current: " + import_picocolors.default.dim(currentVersion) + " \u2192 Latest: " + import_picocolors.default.green(import_picocolors.default.bold(latestVersion)), boxWidth) + import_picocolors.default.yellow("\u2502"));
|
|
456
|
+
console.log(import_picocolors.default.yellow("\u2502") + padLine("", boxWidth) + import_picocolors.default.yellow("\u2502"));
|
|
457
|
+
console.log(import_picocolors.default.yellow("\u2502") + padLine(" " + import_picocolors.default.dim("Update after you finish by running:"), boxWidth) + import_picocolors.default.yellow("\u2502"));
|
|
458
|
+
console.log(import_picocolors.default.yellow("\u2502") + padLine(" " + import_picocolors.default.cyan(import_picocolors.default.bold(`npm install -g ${packageJson.name}@latest`)), boxWidth) + import_picocolors.default.yellow("\u2502"));
|
|
459
|
+
console.log(import_picocolors.default.yellow("\u2502") + padLine("", boxWidth) + import_picocolors.default.yellow("\u2502"));
|
|
451
460
|
console.log(import_picocolors.default.yellow("\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F"));
|
|
452
461
|
console.log("");
|
|
453
462
|
}
|
|
@@ -520,18 +529,24 @@ async function main() {
|
|
|
520
529
|
let preferences = await getStoredPreferences();
|
|
521
530
|
if (!preferences) {
|
|
522
531
|
note("Let's set up your commit message preferences (one-time setup)", "First Time Setup");
|
|
523
|
-
const useConventional = await
|
|
532
|
+
const useConventional = await select({
|
|
524
533
|
message: "Use conventional commit prefixes (feat:, fix:, chore:, etc.)?",
|
|
534
|
+
options: [
|
|
535
|
+
{ value: true, label: "Yes" },
|
|
536
|
+
{ value: false, label: "No" }
|
|
537
|
+
],
|
|
525
538
|
initialValue: true
|
|
526
539
|
});
|
|
527
540
|
if (isCancel(useConventional)) {
|
|
528
541
|
cancel("Operation cancelled.");
|
|
529
542
|
process.exit(0);
|
|
530
543
|
}
|
|
531
|
-
const styleChoice = await
|
|
544
|
+
const styleChoice = await select({
|
|
532
545
|
message: "Prefer descriptive commit messages?",
|
|
533
|
-
|
|
534
|
-
|
|
546
|
+
options: [
|
|
547
|
+
{ value: true, label: "Descriptive (detailed explanations)" },
|
|
548
|
+
{ value: false, label: "Concise (short and to the point)" }
|
|
549
|
+
],
|
|
535
550
|
initialValue: false
|
|
536
551
|
});
|
|
537
552
|
if (isCancel(styleChoice)) {
|
|
@@ -556,16 +571,22 @@ async function main() {
|
|
|
556
571
|
s.stop("Changes detected.");
|
|
557
572
|
let commitMessage = "";
|
|
558
573
|
let confirmed = false;
|
|
574
|
+
let userFeedback = void 0;
|
|
559
575
|
while (!confirmed) {
|
|
560
576
|
s.start("Generating commit message (Agent is exploring)...");
|
|
561
577
|
try {
|
|
562
|
-
commitMessage = await generateCommitMessage(diff, preferences);
|
|
578
|
+
commitMessage = await generateCommitMessage(diff, preferences, userFeedback);
|
|
579
|
+
userFeedback = void 0;
|
|
563
580
|
} catch (error) {
|
|
564
581
|
s.stop("Generation failed.");
|
|
565
582
|
if (error.message?.includes("401") || error.message?.includes("authentication_error") || error.message?.includes("invalid x-api-key") || error.message?.includes("invalid api key")) {
|
|
566
583
|
cancel("Invalid API Key detected.");
|
|
567
|
-
const retryWithNewKey = await
|
|
584
|
+
const retryWithNewKey = await select({
|
|
568
585
|
message: "Would you like to enter a new API key?",
|
|
586
|
+
options: [
|
|
587
|
+
{ value: true, label: "Yes" },
|
|
588
|
+
{ value: false, label: "No" }
|
|
589
|
+
],
|
|
569
590
|
initialValue: true
|
|
570
591
|
});
|
|
571
592
|
if (isCancel(retryWithNewKey) || !retryWithNewKey) {
|
|
@@ -627,10 +648,12 @@ async function main() {
|
|
|
627
648
|
}
|
|
628
649
|
const formattedMessage = wrappedLines.map((line) => import_picocolors.default.cyan(line)).join("\n");
|
|
629
650
|
note(formattedMessage, import_picocolors.default.bold("Proposed Commit Message"));
|
|
630
|
-
const action = await
|
|
651
|
+
const action = await select({
|
|
631
652
|
message: "Do you want to use this message?",
|
|
632
|
-
|
|
633
|
-
|
|
653
|
+
options: [
|
|
654
|
+
{ value: true, label: "Yes, commit" },
|
|
655
|
+
{ value: false, label: "No, regenerate or cancel" }
|
|
656
|
+
]
|
|
634
657
|
});
|
|
635
658
|
if (isCancel(action)) {
|
|
636
659
|
cancel("Operation cancelled.");
|
|
@@ -639,22 +662,37 @@ async function main() {
|
|
|
639
662
|
if (action) {
|
|
640
663
|
confirmed = true;
|
|
641
664
|
} else {
|
|
642
|
-
const nextStep = await
|
|
665
|
+
const nextStep = await select({
|
|
643
666
|
message: "Try again?",
|
|
644
|
-
|
|
645
|
-
|
|
667
|
+
options: [
|
|
668
|
+
{ value: true, label: "Regenerate" },
|
|
669
|
+
{ value: false, label: "Cancel" }
|
|
670
|
+
]
|
|
646
671
|
});
|
|
647
672
|
if (!nextStep || isCancel(nextStep)) {
|
|
648
673
|
cancel("Operation cancelled.");
|
|
649
674
|
process.exit(0);
|
|
650
675
|
}
|
|
676
|
+
const feedback = await text({
|
|
677
|
+
message: "How should I adjust it?",
|
|
678
|
+
placeholder: "e.g., make it shorter, add more detail, or press enter to skip"
|
|
679
|
+
});
|
|
680
|
+
if (isCancel(feedback)) {
|
|
681
|
+
cancel("Operation cancelled.");
|
|
682
|
+
process.exit(0);
|
|
683
|
+
}
|
|
684
|
+
userFeedback = feedback && feedback.trim() !== "" ? feedback : void 0;
|
|
651
685
|
}
|
|
652
686
|
}
|
|
653
687
|
s.start("Committing...");
|
|
654
688
|
await commit(commitMessage);
|
|
655
689
|
s.stop("Committed!");
|
|
656
|
-
const shouldPush = await
|
|
657
|
-
message: "Do you want to push changes now?"
|
|
690
|
+
const shouldPush = await select({
|
|
691
|
+
message: "Do you want to push changes now?",
|
|
692
|
+
options: [
|
|
693
|
+
{ value: true, label: "Yes" },
|
|
694
|
+
{ value: false, label: "No" }
|
|
695
|
+
]
|
|
658
696
|
});
|
|
659
697
|
if (isCancel(shouldPush)) {
|
|
660
698
|
outro(`Changes committed but NOT pushed.`);
|