@kud/ai-conventional-commit-cli 0.2.0 → 0.3.0

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 CHANGED
@@ -2,8 +2,6 @@
2
2
 
3
3
  Opinionated, style-aware AI assistant for crafting, splitting, and refining git commit messages via the local `opencode` CLI. Uses your installed `opencode` models (default `github-copilot/gpt-5`).
4
4
 
5
- Formerly referenced as `aicc` in examples. The canonical command name is now `ai-conventional-commit`.
6
-
7
5
  ## Why
8
6
 
9
7
  Manual commit messages are noisy, inconsistent, and often miss context. ai-conventional-commit inspects your staged diff, learns your repo's commit style, and produces Conventional Commit messages (single or split) with explanations—optionally decorated with gitmoji.
@@ -33,14 +31,12 @@ ai-conventional-commit --help
33
31
 
34
32
  ### Optional Alias (Short Name)
35
33
 
36
- If you prefer the shorter historical alias, add this to your shell profile:
34
+ If you prefer a shorter alias, add this to your shell profile:
37
35
 
38
36
  ```bash
39
37
  alias aicc='ai-conventional-commit'
40
38
  ```
41
39
 
42
- After that you can type `aicc` instead of the full command. All subsequent examples use the full name for clarity.
43
-
44
40
  ## Publishing
45
41
 
46
42
  A build is automatically produced on `npm publish` via the `prepublishOnly` script so you can simply bump the version and run:
@@ -55,8 +51,6 @@ Only `dist`, `README.md`, and `LICENSE` are included in the published package (s
55
51
  npm publish --dry-run
56
52
  ```
57
53
 
58
- The shorter `aicc` binary has been removed from the package itself; create a local alias if you still prefer it.
59
-
60
54
  ## Quick Start
61
55
 
62
56
  ```bash
package/dist/index.cjs CHANGED
@@ -296,7 +296,7 @@ var OpenCodeProvider = class {
296
296
  Context:
297
297
  ${userAggregate}`;
298
298
  if (mockMode) {
299
- if (debug) console.error("[aicc][mock] Returning deterministic mock response");
299
+ if (debug) console.error("[ai-cc][mock] Returning deterministic mock response");
300
300
  return JSON.stringify({
301
301
  commits: [
302
302
  {
@@ -327,7 +327,7 @@ ${userAggregate}`;
327
327
  const elapsed = Date.now() - start;
328
328
  if (debug) {
329
329
  console.error(
330
- `[aicc][provider] model=${this.model} elapsedMs=${elapsed} promptChars=${fullPrompt.length} bytesOut=${value.length}`
330
+ `[ai-cc][provider] model=${this.model} elapsedMs=${elapsed} promptChars=${fullPrompt.length} bytesOut=${value.length}`
331
331
  );
332
332
  }
333
333
  resolve3(value);
@@ -340,7 +340,7 @@ ${userAggregate}`;
340
340
  const candidate = acc.slice(first, last + 1).trim();
341
341
  try {
342
342
  JSON.parse(candidate);
343
- if (debug) console.error("[aicc][provider] eager JSON detected, terminating process");
343
+ if (debug) console.error("[ai-cc][provider] eager JSON detected, terminating process");
344
344
  subprocess.kill("SIGTERM");
345
345
  finish(candidate);
346
346
  } catch {
@@ -353,7 +353,7 @@ ${userAggregate}`;
353
353
  tryEager();
354
354
  });
355
355
  subprocess.stderr?.on("data", (chunk) => {
356
- if (debug) console.error("[aicc][provider][stderr]", chunk.toString().trim());
356
+ if (debug) console.error("[ai-cc][provider][stderr]", chunk.toString().trim());
357
357
  });
358
358
  subprocess.then(({ stdout }) => {
359
359
  if (!resolved) finish(stdout);
@@ -365,7 +365,7 @@ ${userAggregate}`;
365
365
  new Error(`Model call timed out after ${timeoutMs}ms (elapsed=${elapsed}ms)`)
366
366
  );
367
367
  }
368
- if (debug) console.error("[aicc][provider] failure", e.stderr || e.message);
368
+ if (debug) console.error("[ai-cc][provider] failure", e.stderr || e.message);
369
369
  reject(new Error(e.stderr || e.message || "opencode invocation failed"));
370
370
  });
371
371
  });
@@ -570,6 +570,32 @@ var formatCommitTitle = (raw, opts) => {
570
570
  var import_node_fs = require("fs");
571
571
  var import_node_path2 = require("path");
572
572
  var import_inquirer = __toESM(require("inquirer"), 1);
573
+ async function animateHeader() {
574
+ const text = "ai-conventional-commit";
575
+ if (!process.stdout.isTTY || process.env.AICC_NO_ANIMATION) {
576
+ console.log("\n\u250C " + import_chalk.default.bold(text));
577
+ return;
578
+ }
579
+ const palette = [
580
+ "#3a0d6d",
581
+ "#5a1ea3",
582
+ "#7a32d6",
583
+ "#9a4dff",
584
+ "#b267ff",
585
+ "#c37dff",
586
+ "#b267ff",
587
+ "#9a4dff",
588
+ "#7a32d6",
589
+ "#5a1ea3"
590
+ ];
591
+ process.stdout.write("\n");
592
+ for (const color of palette) {
593
+ const frame = import_chalk.default.bold.hex(color)(text);
594
+ process.stdout.write("\r\u250C " + frame);
595
+ await new Promise((r) => setTimeout(r, 60));
596
+ }
597
+ process.stdout.write("\n");
598
+ }
573
599
  async function runGenerate(config) {
574
600
  if (!await ensureStagedChanges()) {
575
601
  console.log("No staged changes.");
@@ -580,10 +606,12 @@ async function runGenerate(config) {
580
606
  console.log("No diff content detected after staging. Aborting.");
581
607
  return;
582
608
  }
583
- console.log("\n\u250C " + import_chalk.default.bold("ai-conventional-commit"));
609
+ await animateHeader();
584
610
  console.log("\u2502");
585
- console.log(`\u25C6 ${import_chalk.default.bold(`Detected ${files.length} staged files:`)}`);
586
- for (const f of files) console.log(" " + f.file);
611
+ console.log(
612
+ `\u25C6 ${import_chalk.default.bold(`Detected ${files.length} staged ${files.length === 1 ? "file" : "files"}:`)}`
613
+ );
614
+ for (const f of files) console.log(" \u2022 " + f.file);
587
615
  console.log("\u2502");
588
616
  const spinner = (0, import_ora.default)({ text: " Starting", spinner: "dots" }).start();
589
617
  function setPhase(label) {
@@ -633,12 +661,13 @@ async function runGenerate(config) {
633
661
  })
634
662
  }));
635
663
  const chosen = candidates[0];
636
- console.log(" " + import_chalk.default.yellow(chosen.title));
664
+ console.log(" " + import_chalk.default.white(chosen.title));
637
665
  if (chosen.body) {
638
666
  const indent = " ";
667
+ console.log(indent);
639
668
  chosen.body.split("\n").forEach((line) => {
640
669
  if (line.trim().length === 0) console.log(indent);
641
- else console.log(indent + import_chalk.default.gray(line));
670
+ else console.log(indent + import_chalk.default.white(line));
642
671
  });
643
672
  }
644
673
  console.log("\u2502");
@@ -674,8 +703,8 @@ async function selectYesNo() {
674
703
  name: "choice",
675
704
  message: " Use this commit message?",
676
705
  choices: [
677
- { name: "\u25CF Yes", value: true },
678
- { name: "\u25CB No", value: false }
706
+ { name: "Yes", value: true },
707
+ { name: "No", value: false }
679
708
  ],
680
709
  default: 0
681
710
  }
@@ -1015,8 +1044,8 @@ var RefineCommand = class extends import_clipanion.Command {
1015
1044
  }
1016
1045
  };
1017
1046
  var cli = new import_clipanion.Cli({
1018
- binaryLabel: "aicc",
1019
- binaryName: "aicc",
1047
+ binaryLabel: "ai-conventional-commit",
1048
+ binaryName: "ai-conventional-commit",
1020
1049
  binaryVersion: "0.1.0"
1021
1050
  });
1022
1051
  cli.register(GenerateCommand);
package/dist/index.js CHANGED
@@ -273,7 +273,7 @@ var OpenCodeProvider = class {
273
273
  Context:
274
274
  ${userAggregate}`;
275
275
  if (mockMode) {
276
- if (debug) console.error("[aicc][mock] Returning deterministic mock response");
276
+ if (debug) console.error("[ai-cc][mock] Returning deterministic mock response");
277
277
  return JSON.stringify({
278
278
  commits: [
279
279
  {
@@ -304,7 +304,7 @@ ${userAggregate}`;
304
304
  const elapsed = Date.now() - start;
305
305
  if (debug) {
306
306
  console.error(
307
- `[aicc][provider] model=${this.model} elapsedMs=${elapsed} promptChars=${fullPrompt.length} bytesOut=${value.length}`
307
+ `[ai-cc][provider] model=${this.model} elapsedMs=${elapsed} promptChars=${fullPrompt.length} bytesOut=${value.length}`
308
308
  );
309
309
  }
310
310
  resolve3(value);
@@ -317,7 +317,7 @@ ${userAggregate}`;
317
317
  const candidate = acc.slice(first, last + 1).trim();
318
318
  try {
319
319
  JSON.parse(candidate);
320
- if (debug) console.error("[aicc][provider] eager JSON detected, terminating process");
320
+ if (debug) console.error("[ai-cc][provider] eager JSON detected, terminating process");
321
321
  subprocess.kill("SIGTERM");
322
322
  finish(candidate);
323
323
  } catch {
@@ -330,7 +330,7 @@ ${userAggregate}`;
330
330
  tryEager();
331
331
  });
332
332
  subprocess.stderr?.on("data", (chunk) => {
333
- if (debug) console.error("[aicc][provider][stderr]", chunk.toString().trim());
333
+ if (debug) console.error("[ai-cc][provider][stderr]", chunk.toString().trim());
334
334
  });
335
335
  subprocess.then(({ stdout }) => {
336
336
  if (!resolved) finish(stdout);
@@ -342,7 +342,7 @@ ${userAggregate}`;
342
342
  new Error(`Model call timed out after ${timeoutMs}ms (elapsed=${elapsed}ms)`)
343
343
  );
344
344
  }
345
- if (debug) console.error("[aicc][provider] failure", e.stderr || e.message);
345
+ if (debug) console.error("[ai-cc][provider] failure", e.stderr || e.message);
346
346
  reject(new Error(e.stderr || e.message || "opencode invocation failed"));
347
347
  });
348
348
  });
@@ -547,6 +547,32 @@ var formatCommitTitle = (raw, opts) => {
547
547
  import { writeFileSync, mkdirSync, existsSync } from "fs";
548
548
  import { join } from "path";
549
549
  import inquirer from "inquirer";
550
+ async function animateHeader() {
551
+ const text = "ai-conventional-commit";
552
+ if (!process.stdout.isTTY || process.env.AICC_NO_ANIMATION) {
553
+ console.log("\n\u250C " + chalk.bold(text));
554
+ return;
555
+ }
556
+ const palette = [
557
+ "#3a0d6d",
558
+ "#5a1ea3",
559
+ "#7a32d6",
560
+ "#9a4dff",
561
+ "#b267ff",
562
+ "#c37dff",
563
+ "#b267ff",
564
+ "#9a4dff",
565
+ "#7a32d6",
566
+ "#5a1ea3"
567
+ ];
568
+ process.stdout.write("\n");
569
+ for (const color of palette) {
570
+ const frame = chalk.bold.hex(color)(text);
571
+ process.stdout.write("\r\u250C " + frame);
572
+ await new Promise((r) => setTimeout(r, 60));
573
+ }
574
+ process.stdout.write("\n");
575
+ }
550
576
  async function runGenerate(config) {
551
577
  if (!await ensureStagedChanges()) {
552
578
  console.log("No staged changes.");
@@ -557,10 +583,12 @@ async function runGenerate(config) {
557
583
  console.log("No diff content detected after staging. Aborting.");
558
584
  return;
559
585
  }
560
- console.log("\n\u250C " + chalk.bold("ai-conventional-commit"));
586
+ await animateHeader();
561
587
  console.log("\u2502");
562
- console.log(`\u25C6 ${chalk.bold(`Detected ${files.length} staged files:`)}`);
563
- for (const f of files) console.log(" " + f.file);
588
+ console.log(
589
+ `\u25C6 ${chalk.bold(`Detected ${files.length} staged ${files.length === 1 ? "file" : "files"}:`)}`
590
+ );
591
+ for (const f of files) console.log(" \u2022 " + f.file);
564
592
  console.log("\u2502");
565
593
  const spinner = ora({ text: " Starting", spinner: "dots" }).start();
566
594
  function setPhase(label) {
@@ -610,12 +638,13 @@ async function runGenerate(config) {
610
638
  })
611
639
  }));
612
640
  const chosen = candidates[0];
613
- console.log(" " + chalk.yellow(chosen.title));
641
+ console.log(" " + chalk.white(chosen.title));
614
642
  if (chosen.body) {
615
643
  const indent = " ";
644
+ console.log(indent);
616
645
  chosen.body.split("\n").forEach((line) => {
617
646
  if (line.trim().length === 0) console.log(indent);
618
- else console.log(indent + chalk.gray(line));
647
+ else console.log(indent + chalk.white(line));
619
648
  });
620
649
  }
621
650
  console.log("\u2502");
@@ -651,8 +680,8 @@ async function selectYesNo() {
651
680
  name: "choice",
652
681
  message: " Use this commit message?",
653
682
  choices: [
654
- { name: "\u25CF Yes", value: true },
655
- { name: "\u25CB No", value: false }
683
+ { name: "Yes", value: true },
684
+ { name: "No", value: false }
656
685
  ],
657
686
  default: 0
658
687
  }
@@ -992,8 +1021,8 @@ var RefineCommand = class extends Command {
992
1021
  }
993
1022
  };
994
1023
  var cli = new Cli({
995
- binaryLabel: "aicc",
996
- binaryName: "aicc",
1024
+ binaryLabel: "ai-conventional-commit",
1025
+ binaryName: "ai-conventional-commit",
997
1026
  binaryVersion: "0.1.0"
998
1027
  });
999
1028
  cli.register(GenerateCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kud/ai-conventional-commit-cli",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "description": "Opinionated, style-aware AI assistant for crafting and splitting git commits (Copilot + pluggable).",
6
6
  "bin": {