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.
Files changed (3) hide show
  1. package/README.md +2 -7
  2. package/dist/index.js +64 -26
  3. 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
- - 🤖 AI-powered with Claude 4.5
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, confirm, isCancel, cancel, note } from "@clack/prompts";
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") + " " + import_picocolors.default.yellow("\u2502"));
444
- console.log(import_picocolors.default.yellow("\u2502") + " " + import_picocolors.default.bold("New version of commit-cli is available!") + " " + import_picocolors.default.yellow("\u2502"));
445
- console.log(import_picocolors.default.yellow("\u2502") + " " + 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)) + " " + import_picocolors.default.yellow("\u2502"));
447
- console.log(import_picocolors.default.yellow("\u2502") + " " + import_picocolors.default.yellow("\u2502"));
448
- console.log(import_picocolors.default.yellow("\u2502") + " " + import_picocolors.default.dim("Update after you finish by running:") + " " + import_picocolors.default.yellow("\u2502"));
449
- console.log(import_picocolors.default.yellow("\u2502") + " " + import_picocolors.default.cyan(import_picocolors.default.bold(`npm install -g ${packageJson.name}@latest`)) + " " + import_picocolors.default.yellow("\u2502"));
450
- console.log(import_picocolors.default.yellow("\u2502") + " " + 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 confirm({
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 confirm({
544
+ const styleChoice = await select({
532
545
  message: "Prefer descriptive commit messages?",
533
- active: "Descriptive (detailed explanations)",
534
- inactive: "Concise (short and to the point)",
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 confirm({
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 confirm({
651
+ const action = await select({
631
652
  message: "Do you want to use this message?",
632
- active: "Yes, commit",
633
- inactive: "No, regenerate or cancel"
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 confirm({
665
+ const nextStep = await select({
643
666
  message: "Try again?",
644
- active: "Regenerate",
645
- inactive: "Cancel"
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 confirm({
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.`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "commit-agent-cli",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "AI-powered git commit CLI using LangGraph and Claude 4.5",
5
5
  "main": "dist/index.js",
6
6
  "types": "./dist/index.d.ts",