gut-cli 0.1.10 → 0.1.12

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/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import { Command as Command17 } from "commander";
4
+ import { Command as Command18 } from "commander";
5
5
 
6
6
  // src/commands/cleanup.ts
7
7
  import { Command } from "commander";
@@ -395,7 +395,6 @@ function findTemplate(repoRoot, templateName) {
395
395
  }
396
396
  function applyTemplate(userTemplate, templateName, variables) {
397
397
  const langInstruction = getLanguageInstruction(getLanguage());
398
- const isUserTemplate = !!userTemplate;
399
398
  let result = userTemplate || loadTemplate(templateName);
400
399
  result = result.replace(/\{\{#(\w+)\}\}([\s\S]*?)\{\{\/\1\}\}/g, (_, key, content) => {
401
400
  return variables[key] ? content : "";
@@ -403,7 +402,7 @@ function applyTemplate(userTemplate, templateName, variables) {
403
402
  for (const [key, value] of Object.entries(variables)) {
404
403
  result = result.replace(new RegExp(`\\{\\{${key}\\}\\}`, "g"), value || "");
405
404
  }
406
- if (!isUserTemplate) {
405
+ if (langInstruction) {
407
406
  result += langInstruction;
408
407
  }
409
408
  return result;
@@ -514,7 +513,8 @@ async function generateChangelog(context, options, template) {
514
513
  fromRef: context.fromRef,
515
514
  toRef: context.toRef,
516
515
  commits: commitList,
517
- diff: context.diff.slice(0, 8e3)
516
+ diff: context.diff.slice(0, 8e3),
517
+ todayDate: (/* @__PURE__ */ new Date()).toISOString().split("T")[0]
518
518
  });
519
519
  const result = await generateObject({
520
520
  model,
@@ -799,14 +799,14 @@ var commitCommand = new Command3("commit").description("Generate a commit messag
799
799
  console.log(chalk3.green("\u2713 Committed successfully"));
800
800
  } else if (answer.toLowerCase() === "e") {
801
801
  console.log(chalk3.gray("Opening editor..."));
802
- const { execSync: execSync5 } = await import("child_process");
802
+ const { execSync: execSync7 } = await import("child_process");
803
803
  const editor = process.env.EDITOR || process.env.VISUAL || "vi";
804
804
  const fs2 = await import("fs");
805
805
  const os = await import("os");
806
806
  const path2 = await import("path");
807
807
  const tmpFile = path2.join(os.tmpdir(), "gut-commit-msg.txt");
808
808
  fs2.writeFileSync(tmpFile, message);
809
- execSync5(`${editor} "${tmpFile}"`, { stdio: "inherit" });
809
+ execSync7(`${editor} "${tmpFile}"`, { stdio: "inherit" });
810
810
  const editedMessage = fs2.readFileSync(tmpFile, "utf-8").trim();
811
811
  fs2.unlinkSync(tmpFile);
812
812
  if (editedMessage) {
@@ -830,11 +830,45 @@ var commitCommand = new Command3("commit").description("Generate a commit messag
830
830
 
831
831
  // src/commands/pr.ts
832
832
  import { Command as Command4 } from "commander";
833
- import chalk4 from "chalk";
833
+ import chalk5 from "chalk";
834
834
  import ora3 from "ora";
835
835
  import { simpleGit as simpleGit3 } from "simple-git";
836
836
  import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
837
837
  import { join as join3 } from "path";
838
+ import { execSync as execSync3 } from "child_process";
839
+
840
+ // src/lib/gh.ts
841
+ import { execSync as execSync2 } from "child_process";
842
+ import chalk4 from "chalk";
843
+ var ghInstalledCache = null;
844
+ function isGhCliInstalled() {
845
+ if (ghInstalledCache !== null) {
846
+ return ghInstalledCache;
847
+ }
848
+ try {
849
+ execSync2("gh --version", { stdio: "pipe" });
850
+ ghInstalledCache = true;
851
+ return true;
852
+ } catch {
853
+ ghInstalledCache = false;
854
+ return false;
855
+ }
856
+ }
857
+ function printGhNotInstalledMessage() {
858
+ console.log(chalk4.yellow("\n\u26A0 GitHub CLI (gh) is not installed"));
859
+ console.log(chalk4.gray(" This command requires gh CLI. Install it:"));
860
+ console.log(chalk4.gray(" brew install gh (macOS)"));
861
+ console.log(chalk4.gray(" https://cli.github.com/"));
862
+ }
863
+ function requireGhCli() {
864
+ if (!isGhCliInstalled()) {
865
+ printGhNotInstalledMessage();
866
+ return false;
867
+ }
868
+ return true;
869
+ }
870
+
871
+ // src/commands/pr.ts
838
872
  var GITHUB_PR_TEMPLATE_PATHS = [
839
873
  ".github/pull_request_template.md",
840
874
  ".github/PULL_REQUEST_TEMPLATE.md",
@@ -855,7 +889,7 @@ var prCommand = new Command4("pr").description("Generate a pull request title an
855
889
  const git = simpleGit3();
856
890
  const isRepo = await git.checkIsRepo();
857
891
  if (!isRepo) {
858
- console.error(chalk4.red("Error: Not a git repository"));
892
+ console.error(chalk5.red("Error: Not a git repository"));
859
893
  process.exit(1);
860
894
  }
861
895
  const provider = options.provider.toLowerCase();
@@ -903,73 +937,78 @@ var prCommand = new Command4("pr").description("Generate a pull request title an
903
937
  template || void 0
904
938
  );
905
939
  spinner.stop();
906
- console.log(chalk4.bold("\n\u{1F4DD} Generated PR:\n"));
907
- console.log(chalk4.cyan("Title:"), chalk4.white(title));
908
- console.log(chalk4.cyan("\nDescription:"));
909
- console.log(chalk4.gray("\u2500".repeat(50)));
940
+ console.log(chalk5.bold("\n\u{1F4DD} Generated PR:\n"));
941
+ console.log(chalk5.cyan("Title:"), chalk5.white(title));
942
+ console.log(chalk5.cyan("\nDescription:"));
943
+ console.log(chalk5.gray("\u2500".repeat(50)));
910
944
  console.log(body);
911
- console.log(chalk4.gray("\u2500".repeat(50)));
945
+ console.log(chalk5.gray("\u2500".repeat(50)));
912
946
  if (options.copy) {
913
947
  try {
914
- const { execSync: execSync5 } = await import("child_process");
915
948
  const fullText = `${title}
916
949
 
917
950
  ${body}`;
918
- execSync5("pbcopy", { input: fullText });
919
- console.log(chalk4.green("\n\u2713 Copied to clipboard"));
951
+ execSync3("pbcopy", { input: fullText });
952
+ console.log(chalk5.green("\n\u2713 Copied to clipboard"));
920
953
  } catch {
921
- console.log(chalk4.yellow("\n\u26A0 Could not copy to clipboard"));
954
+ console.log(chalk5.yellow("\n\u26A0 Could not copy to clipboard"));
922
955
  }
923
956
  }
924
- if (options.create) {
957
+ const ghInstalled = isGhCliInstalled();
958
+ if (!ghInstalled) {
959
+ console.log(chalk5.yellow("\n\u26A0 GitHub CLI (gh) is not installed"));
960
+ console.log(chalk5.gray(" To create PRs directly from gut, install gh CLI:"));
961
+ console.log(chalk5.gray(" brew install gh (macOS)"));
962
+ console.log(chalk5.gray(" https://cli.github.com/"));
963
+ if (!options.copy) {
964
+ console.log(chalk5.gray("\nTip: Use --copy to copy to clipboard"));
965
+ }
966
+ } else {
925
967
  const readline = await import("readline");
926
968
  const rl = readline.createInterface({
927
969
  input: process.stdin,
928
970
  output: process.stdout
929
971
  });
972
+ const promptMessage = options.create ? chalk5.cyan("\nCreate PR with this description? (y/N) ") : chalk5.cyan("\nCreate PR with gh CLI? (y/N) ");
930
973
  const answer = await new Promise((resolve) => {
931
- rl.question(chalk4.cyan("\nCreate PR with this description? (y/N) "), resolve);
974
+ rl.question(promptMessage, resolve);
932
975
  });
933
976
  rl.close();
934
977
  if (answer.toLowerCase() === "y") {
935
978
  const createSpinner = ora3("Creating PR...").start();
936
979
  try {
937
- const { execSync: execSync5 } = await import("child_process");
938
980
  const escapedTitle = title.replace(/"/g, '\\"');
939
981
  const escapedBody = body.replace(/"/g, '\\"');
940
- execSync5(
982
+ execSync3(
941
983
  `gh pr create --title "${escapedTitle}" --body "${escapedBody}" --base ${baseBranch}`,
942
984
  { stdio: "pipe" }
943
985
  );
944
986
  createSpinner.succeed("PR created successfully!");
945
987
  } catch (error) {
946
988
  createSpinner.fail("Failed to create PR");
947
- console.error(chalk4.gray("Make sure gh CLI is installed and authenticated"));
989
+ console.error(chalk5.gray("Make sure gh CLI is authenticated: gh auth login"));
948
990
  }
991
+ } else if (!options.copy) {
992
+ console.log(chalk5.gray("\nTip: Use --copy to copy to clipboard"));
949
993
  }
950
994
  }
951
- if (!options.copy && !options.create) {
952
- console.log(chalk4.gray("\nOptions:"));
953
- console.log(chalk4.gray(" --copy Copy to clipboard"));
954
- console.log(chalk4.gray(" --create Create PR with gh CLI"));
955
- }
956
995
  } catch (error) {
957
996
  spinner.fail("Failed to generate PR description");
958
- console.error(chalk4.red(error instanceof Error ? error.message : "Unknown error"));
997
+ console.error(chalk5.red(error instanceof Error ? error.message : "Unknown error"));
959
998
  process.exit(1);
960
999
  }
961
1000
  });
962
1001
 
963
1002
  // src/commands/review.ts
964
1003
  import { Command as Command5 } from "commander";
965
- import chalk5 from "chalk";
1004
+ import chalk6 from "chalk";
966
1005
  import ora4 from "ora";
967
1006
  import { simpleGit as simpleGit4 } from "simple-git";
968
- import { execSync as execSync2 } from "child_process";
1007
+ import { execSync as execSync4 } from "child_process";
969
1008
  async function getPRDiff(prNumber) {
970
1009
  try {
971
- const diff = execSync2(`gh pr diff ${prNumber}`, { encoding: "utf-8", maxBuffer: 10 * 1024 * 1024 });
972
- const prJsonStr = execSync2(`gh pr view ${prNumber} --json number,title,author,url`, { encoding: "utf-8" });
1010
+ const diff = execSync4(`gh pr diff ${prNumber}`, { encoding: "utf-8", maxBuffer: 10 * 1024 * 1024 });
1011
+ const prJsonStr = execSync4(`gh pr view ${prNumber} --json number,title,author,url`, { encoding: "utf-8" });
973
1012
  const prJson = JSON.parse(prJsonStr);
974
1013
  return {
975
1014
  diff,
@@ -991,7 +1030,7 @@ var reviewCommand = new Command5("review").description("Get an AI code review of
991
1030
  const git = simpleGit4();
992
1031
  const isRepo = await git.checkIsRepo();
993
1032
  if (!isRepo) {
994
- console.error(chalk5.red("Error: Not a git repository"));
1033
+ console.error(chalk6.red("Error: Not a git repository"));
995
1034
  process.exit(1);
996
1035
  }
997
1036
  const provider = options.provider.toLowerCase();
@@ -1000,7 +1039,11 @@ var reviewCommand = new Command5("review").description("Get an AI code review of
1000
1039
  let diff;
1001
1040
  let prInfo = null;
1002
1041
  if (prNumber) {
1003
- spinner.text = `Fetching PR #${prNumber}...`;
1042
+ spinner.stop();
1043
+ if (!requireGhCli()) {
1044
+ process.exit(1);
1045
+ }
1046
+ spinner.start(`Fetching PR #${prNumber}...`);
1004
1047
  const result = await getPRDiff(prNumber);
1005
1048
  diff = result.diff;
1006
1049
  prInfo = result.prInfo;
@@ -1035,29 +1078,29 @@ var reviewCommand = new Command5("review").description("Get an AI code review of
1035
1078
  return;
1036
1079
  }
1037
1080
  if (prInfo) {
1038
- console.log(chalk5.bold(`
1081
+ console.log(chalk6.bold(`
1039
1082
  \u{1F517} PR #${prInfo.number}: ${prInfo.title}`));
1040
- console.log(chalk5.gray(` by ${prInfo.author} - ${prInfo.url}`));
1083
+ console.log(chalk6.gray(` by ${prInfo.author} - ${prInfo.url}`));
1041
1084
  }
1042
1085
  printReview(review);
1043
1086
  } catch (error) {
1044
1087
  spinner.fail("Failed to generate review");
1045
- console.error(chalk5.red(error instanceof Error ? error.message : "Unknown error"));
1088
+ console.error(chalk6.red(error instanceof Error ? error.message : "Unknown error"));
1046
1089
  process.exit(1);
1047
1090
  }
1048
1091
  });
1049
1092
  function printReview(review) {
1050
- console.log(chalk5.bold("\n\u{1F50D} AI Code Review\n"));
1051
- console.log(chalk5.cyan("Summary:"));
1093
+ console.log(chalk6.bold("\n\u{1F50D} AI Code Review\n"));
1094
+ console.log(chalk6.cyan("Summary:"));
1052
1095
  console.log(` ${review.summary}
1053
1096
  `);
1054
1097
  if (review.issues.length > 0) {
1055
- console.log(chalk5.cyan("Issues Found:"));
1098
+ console.log(chalk6.cyan("Issues Found:"));
1056
1099
  for (const issue of review.issues) {
1057
1100
  const severityColors = {
1058
- critical: chalk5.red,
1059
- warning: chalk5.yellow,
1060
- suggestion: chalk5.blue
1101
+ critical: chalk6.red,
1102
+ warning: chalk6.yellow,
1103
+ suggestion: chalk6.blue
1061
1104
  };
1062
1105
  const severityIcons = {
1063
1106
  critical: "\u{1F534}",
@@ -1068,34 +1111,34 @@ function printReview(review) {
1068
1111
  const icon = severityIcons[issue.severity];
1069
1112
  console.log(`
1070
1113
  ${icon} ${color(issue.severity.toUpperCase())}`);
1071
- console.log(` ${chalk5.gray("File:")} ${issue.file}${issue.line ? `:${issue.line}` : ""}`);
1114
+ console.log(` ${chalk6.gray("File:")} ${issue.file}${issue.line ? `:${issue.line}` : ""}`);
1072
1115
  console.log(` ${issue.message}`);
1073
1116
  if (issue.suggestion) {
1074
- console.log(` ${chalk5.green("\u2192")} ${issue.suggestion}`);
1117
+ console.log(` ${chalk6.green("\u2192")} ${issue.suggestion}`);
1075
1118
  }
1076
1119
  }
1077
1120
  } else {
1078
- console.log(chalk5.green(" \u2713 No issues found!\n"));
1121
+ console.log(chalk6.green(" \u2713 No issues found!\n"));
1079
1122
  }
1080
1123
  if (review.positives.length > 0) {
1081
- console.log(chalk5.cyan("\nGood Practices:"));
1124
+ console.log(chalk6.cyan("\nGood Practices:"));
1082
1125
  for (const positive of review.positives) {
1083
- console.log(` ${chalk5.green("\u2713")} ${positive}`);
1126
+ console.log(` ${chalk6.green("\u2713")} ${positive}`);
1084
1127
  }
1085
1128
  }
1086
1129
  const criticalCount = review.issues.filter((i) => i.severity === "critical").length;
1087
1130
  const warningCount = review.issues.filter((i) => i.severity === "warning").length;
1088
1131
  const suggestionCount = review.issues.filter((i) => i.severity === "suggestion").length;
1089
- console.log(chalk5.gray("\n\u2500".repeat(40)));
1132
+ console.log(chalk6.gray("\n\u2500".repeat(40)));
1090
1133
  console.log(
1091
- ` ${chalk5.red(criticalCount)} critical ${chalk5.yellow(warningCount)} warnings ${chalk5.blue(suggestionCount)} suggestions`
1134
+ ` ${chalk6.red(criticalCount)} critical ${chalk6.yellow(warningCount)} warnings ${chalk6.blue(suggestionCount)} suggestions`
1092
1135
  );
1093
1136
  console.log();
1094
1137
  }
1095
1138
 
1096
1139
  // src/commands/merge.ts
1097
1140
  import { Command as Command6 } from "commander";
1098
- import chalk6 from "chalk";
1141
+ import chalk7 from "chalk";
1099
1142
  import ora5 from "ora";
1100
1143
  import { simpleGit as simpleGit5 } from "simple-git";
1101
1144
  import * as fs from "fs";
@@ -1104,53 +1147,53 @@ var mergeCommand = new Command6("merge").description("Merge a branch with AI-pow
1104
1147
  const git = simpleGit5();
1105
1148
  const isRepo = await git.checkIsRepo();
1106
1149
  if (!isRepo) {
1107
- console.error(chalk6.red("Error: Not a git repository"));
1150
+ console.error(chalk7.red("Error: Not a git repository"));
1108
1151
  process.exit(1);
1109
1152
  }
1110
1153
  const provider = options.provider.toLowerCase();
1111
1154
  const status = await git.status();
1112
1155
  if (status.modified.length > 0 || status.staged.length > 0) {
1113
- console.error(chalk6.red("Error: Working directory has uncommitted changes"));
1114
- console.log(chalk6.gray("Please commit or stash your changes first"));
1156
+ console.error(chalk7.red("Error: Working directory has uncommitted changes"));
1157
+ console.log(chalk7.gray("Please commit or stash your changes first"));
1115
1158
  process.exit(1);
1116
1159
  }
1117
1160
  const branchInfo = await git.branch();
1118
1161
  const currentBranch = branchInfo.current;
1119
- console.log(chalk6.bold(`
1120
- Merging ${chalk6.cyan(branch)} into ${chalk6.cyan(currentBranch)}...
1162
+ console.log(chalk7.bold(`
1163
+ Merging ${chalk7.cyan(branch)} into ${chalk7.cyan(currentBranch)}...
1121
1164
  `));
1122
1165
  try {
1123
1166
  await git.merge([branch]);
1124
- console.log(chalk6.green("\u2713 Merged successfully (no conflicts)"));
1167
+ console.log(chalk7.green("\u2713 Merged successfully (no conflicts)"));
1125
1168
  return;
1126
1169
  } catch (error) {
1127
1170
  }
1128
1171
  const conflictStatus = await git.status();
1129
1172
  const conflictedFiles = conflictStatus.conflicted;
1130
1173
  if (conflictedFiles.length === 0) {
1131
- console.error(chalk6.red("Merge failed for unknown reason"));
1174
+ console.error(chalk7.red("Merge failed for unknown reason"));
1132
1175
  await git.merge(["--abort"]);
1133
1176
  process.exit(1);
1134
1177
  }
1135
- console.log(chalk6.yellow(`\u26A0 ${conflictedFiles.length} conflict(s) detected
1178
+ console.log(chalk7.yellow(`\u26A0 ${conflictedFiles.length} conflict(s) detected
1136
1179
  `));
1137
1180
  const spinner = ora5();
1138
1181
  const rootDir = await git.revparse(["--show-toplevel"]);
1139
1182
  const template = findTemplate(rootDir.trim(), "merge");
1140
1183
  if (template) {
1141
- console.log(chalk6.gray("Using merge template from project...\n"));
1184
+ console.log(chalk7.gray("Using merge template from project...\n"));
1142
1185
  }
1143
1186
  for (const file of conflictedFiles) {
1144
1187
  const filePath = path.join(rootDir.trim(), file);
1145
1188
  const content = fs.readFileSync(filePath, "utf-8");
1146
- console.log(chalk6.bold(`
1189
+ console.log(chalk7.bold(`
1147
1190
  \u{1F4C4} ${file}`));
1148
1191
  const conflictMatch = content.match(/<<<<<<< HEAD[\s\S]*?>>>>>>>.+/g);
1149
1192
  if (conflictMatch) {
1150
- console.log(chalk6.gray("\u2500".repeat(50)));
1151
- console.log(chalk6.gray(conflictMatch[0].slice(0, 500)));
1152
- if (conflictMatch[0].length > 500) console.log(chalk6.gray("..."));
1153
- console.log(chalk6.gray("\u2500".repeat(50)));
1193
+ console.log(chalk7.gray("\u2500".repeat(50)));
1194
+ console.log(chalk7.gray(conflictMatch[0].slice(0, 500)));
1195
+ if (conflictMatch[0].length > 500) console.log(chalk7.gray("..."));
1196
+ console.log(chalk7.gray("\u2500".repeat(50)));
1154
1197
  }
1155
1198
  spinner.start("AI is analyzing conflict...");
1156
1199
  try {
@@ -1160,55 +1203,55 @@ Merging ${chalk6.cyan(branch)} into ${chalk6.cyan(currentBranch)}...
1160
1203
  theirsRef: branch
1161
1204
  }, { provider, model: options.model }, template || void 0);
1162
1205
  spinner.stop();
1163
- console.log(chalk6.cyan("\n\u{1F916} AI suggests:"));
1164
- console.log(chalk6.gray("\u2500".repeat(50)));
1206
+ console.log(chalk7.cyan("\n\u{1F916} AI suggests:"));
1207
+ console.log(chalk7.gray("\u2500".repeat(50)));
1165
1208
  const preview = resolution.resolvedContent.slice(0, 800);
1166
1209
  console.log(preview);
1167
- if (resolution.resolvedContent.length > 800) console.log(chalk6.gray("..."));
1168
- console.log(chalk6.gray("\u2500".repeat(50)));
1169
- console.log(chalk6.gray(`Strategy: ${resolution.strategy}`));
1170
- console.log(chalk6.gray(`Reason: ${resolution.explanation}`));
1210
+ if (resolution.resolvedContent.length > 800) console.log(chalk7.gray("..."));
1211
+ console.log(chalk7.gray("\u2500".repeat(50)));
1212
+ console.log(chalk7.gray(`Strategy: ${resolution.strategy}`));
1213
+ console.log(chalk7.gray(`Reason: ${resolution.explanation}`));
1171
1214
  const readline = await import("readline");
1172
1215
  const rl = readline.createInterface({
1173
1216
  input: process.stdin,
1174
1217
  output: process.stdout
1175
1218
  });
1176
1219
  const answer = await new Promise((resolve) => {
1177
- rl.question(chalk6.cyan("\nAccept this resolution? (y/n/s to skip) "), resolve);
1220
+ rl.question(chalk7.cyan("\nAccept this resolution? (y/n/s to skip) "), resolve);
1178
1221
  });
1179
1222
  rl.close();
1180
1223
  if (answer.toLowerCase() === "y") {
1181
1224
  fs.writeFileSync(filePath, resolution.resolvedContent);
1182
1225
  await git.add(file);
1183
- console.log(chalk6.green(`\u2713 Resolved ${file}`));
1226
+ console.log(chalk7.green(`\u2713 Resolved ${file}`));
1184
1227
  } else if (answer.toLowerCase() === "s") {
1185
- console.log(chalk6.yellow(`\u23ED Skipped ${file}`));
1228
+ console.log(chalk7.yellow(`\u23ED Skipped ${file}`));
1186
1229
  } else {
1187
- console.log(chalk6.yellow(`\u2717 Rejected - resolve manually: ${file}`));
1230
+ console.log(chalk7.yellow(`\u2717 Rejected - resolve manually: ${file}`));
1188
1231
  }
1189
1232
  } catch (error) {
1190
1233
  spinner.fail("AI resolution failed");
1191
- console.error(chalk6.red(error instanceof Error ? error.message : "Unknown error"));
1192
- console.log(chalk6.yellow(`Please resolve manually: ${file}`));
1234
+ console.error(chalk7.red(error instanceof Error ? error.message : "Unknown error"));
1235
+ console.log(chalk7.yellow(`Please resolve manually: ${file}`));
1193
1236
  }
1194
1237
  }
1195
1238
  const finalStatus = await git.status();
1196
1239
  if (finalStatus.conflicted.length > 0) {
1197
- console.log(chalk6.yellow(`
1240
+ console.log(chalk7.yellow(`
1198
1241
  \u26A0 ${finalStatus.conflicted.length} conflict(s) remaining`));
1199
- console.log(chalk6.gray("Resolve manually and run: git add <files> && git commit"));
1242
+ console.log(chalk7.gray("Resolve manually and run: git add <files> && git commit"));
1200
1243
  } else if (options.commit !== false) {
1201
1244
  await git.commit(`Merge branch '${branch}' into ${currentBranch}`);
1202
- console.log(chalk6.green("\n\u2713 All conflicts resolved and committed"));
1245
+ console.log(chalk7.green("\n\u2713 All conflicts resolved and committed"));
1203
1246
  } else {
1204
- console.log(chalk6.green("\n\u2713 All conflicts resolved"));
1205
- console.log(chalk6.gray("Run: git commit"));
1247
+ console.log(chalk7.green("\n\u2713 All conflicts resolved"));
1248
+ console.log(chalk7.gray("Run: git commit"));
1206
1249
  }
1207
1250
  });
1208
1251
 
1209
1252
  // src/commands/changelog.ts
1210
1253
  import { Command as Command7 } from "commander";
1211
- import chalk7 from "chalk";
1254
+ import chalk8 from "chalk";
1212
1255
  import ora6 from "ora";
1213
1256
  import { simpleGit as simpleGit6 } from "simple-git";
1214
1257
  function formatChangelog(changelog) {
@@ -1235,7 +1278,7 @@ var changelogCommand = new Command7("changelog").description("Generate a changel
1235
1278
  const git = simpleGit6();
1236
1279
  const isRepo = await git.checkIsRepo();
1237
1280
  if (!isRepo) {
1238
- console.error(chalk7.red("Error: Not a git repository"));
1281
+ console.error(chalk8.red("Error: Not a git repository"));
1239
1282
  process.exit(1);
1240
1283
  }
1241
1284
  const provider = options.provider.toLowerCase();
@@ -1275,34 +1318,34 @@ var changelogCommand = new Command7("changelog").description("Generate a changel
1275
1318
  console.log(JSON.stringify(changelog, null, 2));
1276
1319
  return;
1277
1320
  }
1278
- console.log(chalk7.bold("\n\u{1F4CB} Generated Changelog\n"));
1279
- console.log(chalk7.gray("\u2500".repeat(50)));
1321
+ console.log(chalk8.bold("\n\u{1F4CB} Generated Changelog\n"));
1322
+ console.log(chalk8.gray("\u2500".repeat(50)));
1280
1323
  console.log(formatChangelog(changelog));
1281
- console.log(chalk7.gray("\u2500".repeat(50)));
1282
- console.log(chalk7.gray(`
1324
+ console.log(chalk8.gray("\u2500".repeat(50)));
1325
+ console.log(chalk8.gray(`
1283
1326
  Range: ${fromRef}..${toRef} (${commits.length} commits)`));
1284
1327
  if (template) {
1285
- console.log(chalk7.gray("Style matched from existing CHANGELOG.md"));
1328
+ console.log(chalk8.gray("Style matched from existing CHANGELOG.md"));
1286
1329
  }
1287
1330
  } catch (error) {
1288
1331
  spinner.fail("Failed to generate changelog");
1289
- console.error(chalk7.red(error instanceof Error ? error.message : "Unknown error"));
1332
+ console.error(chalk8.red(error instanceof Error ? error.message : "Unknown error"));
1290
1333
  process.exit(1);
1291
1334
  }
1292
1335
  });
1293
1336
 
1294
1337
  // src/commands/explain.ts
1295
1338
  import { Command as Command8 } from "commander";
1296
- import chalk8 from "chalk";
1339
+ import chalk9 from "chalk";
1297
1340
  import ora7 from "ora";
1298
1341
  import { simpleGit as simpleGit7 } from "simple-git";
1299
- import { execSync as execSync3 } from "child_process";
1342
+ import { execSync as execSync5 } from "child_process";
1300
1343
  import { existsSync as existsSync4, readFileSync as readFileSync5 } from "fs";
1301
1344
  var explainCommand = new Command8("explain").description("Get an AI-powered explanation of changes, commits, PRs, or files").argument("[target]", "Commit hash, PR number, PR URL, or file path (default: uncommitted changes)").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic)", "gemini").option("-m, --model <model>", "Model to use (provider-specific)").option("-s, --staged", "Explain only staged changes").option("-n, --commits <n>", "Number of commits to analyze for file history (default: 1)", "1").option("--history", "Explain file change history instead of content").option("--json", "Output as JSON").action(async (target, options) => {
1302
1345
  const git = simpleGit7();
1303
1346
  const isRepo = await git.checkIsRepo();
1304
1347
  if (!isRepo) {
1305
- console.error(chalk8.red("Error: Not a git repository"));
1348
+ console.error(chalk9.red("Error: Not a git repository"));
1306
1349
  process.exit(1);
1307
1350
  }
1308
1351
  const provider = options.provider.toLowerCase();
@@ -1320,6 +1363,11 @@ var explainCommand = new Command8("explain").description("Get an AI-powered expl
1320
1363
  const isPR = target.match(/^#?\d+$/) || target.includes("/pull/");
1321
1364
  const isFile = existsSync4(target);
1322
1365
  if (isPR) {
1366
+ spinner.stop();
1367
+ if (!requireGhCli()) {
1368
+ process.exit(1);
1369
+ }
1370
+ spinner.start();
1323
1371
  context = await getPRContext(target, spinner);
1324
1372
  } else if (isFile) {
1325
1373
  if (options.history) {
@@ -1335,7 +1383,7 @@ var explainCommand = new Command8("explain").description("Get an AI-powered expl
1335
1383
  const templateName = isFileContent ? "explain-file" : "explain";
1336
1384
  const template = findTemplate(repoRoot.trim(), templateName);
1337
1385
  if (template) {
1338
- console.log(chalk8.gray("Using template from project..."));
1386
+ console.log(chalk9.gray("Using template from project..."));
1339
1387
  }
1340
1388
  spinner.text = "AI is generating explanation...";
1341
1389
  const explanation = await generateExplanation(
@@ -1351,7 +1399,7 @@ var explainCommand = new Command8("explain").description("Get an AI-powered expl
1351
1399
  printExplanation(explanation, context.type);
1352
1400
  } catch (error) {
1353
1401
  spinner.fail("Failed to generate explanation");
1354
- console.error(chalk8.red(error instanceof Error ? error.message : "Unknown error"));
1402
+ console.error(chalk9.red(error instanceof Error ? error.message : "Unknown error"));
1355
1403
  process.exit(1);
1356
1404
  }
1357
1405
  });
@@ -1455,7 +1503,7 @@ async function getPRContext(target, spinner) {
1455
1503
  spinner.text = `Fetching PR #${prNumber}...`;
1456
1504
  let prInfo;
1457
1505
  try {
1458
- const prJson = execSync3(
1506
+ const prJson = execSync5(
1459
1507
  `gh pr view ${prNumber} --json title,url,baseRefName,headRefName,commits`,
1460
1508
  { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
1461
1509
  );
@@ -1466,7 +1514,7 @@ async function getPRContext(target, spinner) {
1466
1514
  spinner.text = `Getting diff for PR #${prNumber}...`;
1467
1515
  let diff;
1468
1516
  try {
1469
- diff = execSync3(`gh pr diff ${prNumber}`, {
1517
+ diff = execSync5(`gh pr diff ${prNumber}`, {
1470
1518
  encoding: "utf-8",
1471
1519
  stdio: ["pipe", "pipe", "pipe"],
1472
1520
  maxBuffer: 10 * 1024 * 1024
@@ -1498,31 +1546,31 @@ function printExplanation(explanation, type) {
1498
1546
  staged: "\u{1F4CB}"
1499
1547
  };
1500
1548
  const icon = icons[type] || "\u{1F4DD}";
1501
- console.log(chalk8.bold(`
1549
+ console.log(chalk9.bold(`
1502
1550
  ${icon} Explanation
1503
1551
  `));
1504
- console.log(chalk8.cyan("Summary:"));
1552
+ console.log(chalk9.cyan("Summary:"));
1505
1553
  console.log(` ${explanation.summary}
1506
1554
  `);
1507
- console.log(chalk8.cyan("Purpose:"));
1555
+ console.log(chalk9.cyan("Purpose:"));
1508
1556
  console.log(` ${explanation.purpose}
1509
1557
  `);
1510
1558
  if (explanation.changes.length > 0) {
1511
1559
  const header = type === "file-content" ? "Components:" : "Key Changes:";
1512
- console.log(chalk8.cyan(header));
1560
+ console.log(chalk9.cyan(header));
1513
1561
  for (const change of explanation.changes) {
1514
- console.log(` ${chalk8.yellow(change.file)}`);
1515
- console.log(` ${chalk8.gray(change.description)}`);
1562
+ console.log(` ${chalk9.yellow(change.file)}`);
1563
+ console.log(` ${chalk9.gray(change.description)}`);
1516
1564
  }
1517
1565
  console.log();
1518
1566
  }
1519
- console.log(chalk8.cyan("Impact:"));
1567
+ console.log(chalk9.cyan("Impact:"));
1520
1568
  console.log(` ${explanation.impact}
1521
1569
  `);
1522
1570
  if (explanation.notes && explanation.notes.length > 0) {
1523
- console.log(chalk8.cyan("Notes:"));
1571
+ console.log(chalk9.cyan("Notes:"));
1524
1572
  for (const note of explanation.notes) {
1525
- console.log(` ${chalk8.gray("\u2022")} ${note}`);
1573
+ console.log(` ${chalk9.gray("\u2022")} ${note}`);
1526
1574
  }
1527
1575
  console.log();
1528
1576
  }
@@ -1530,14 +1578,14 @@ ${icon} Explanation
1530
1578
 
1531
1579
  // src/commands/find.ts
1532
1580
  import { Command as Command9 } from "commander";
1533
- import chalk9 from "chalk";
1581
+ import chalk10 from "chalk";
1534
1582
  import ora8 from "ora";
1535
1583
  import { simpleGit as simpleGit8 } from "simple-git";
1536
1584
  var findCommand = new Command9("find").description("Find commits matching a vague description using AI").argument("<query>", 'Description of the change you are looking for (e.g., "login feature added")').option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic)", "gemini").option("-m, --model <model>", "Model to use (provider-specific)").option("-n, --num <n>", "Number of commits to search through", "100").option("--path <path>", "Limit search to commits affecting this path").option("--author <author>", "Limit search to commits by this author").option("--since <date>", "Limit search to commits after this date").option("--until <date>", "Limit search to commits before this date").option("--max-results <n>", "Maximum number of matching commits to return", "5").option("--json", "Output as JSON").action(async (query, options) => {
1537
1585
  const git = simpleGit8();
1538
1586
  const isRepo = await git.checkIsRepo();
1539
1587
  if (!isRepo) {
1540
- console.error(chalk9.red("Error: Not a git repository"));
1588
+ console.error(chalk10.red("Error: Not a git repository"));
1541
1589
  process.exit(1);
1542
1590
  }
1543
1591
  const provider = options.provider.toLowerCase();
@@ -1581,8 +1629,8 @@ var findCommand = new Command9("find").description("Find commits matching a vagu
1581
1629
  );
1582
1630
  spinner.stop();
1583
1631
  if (results.matches.length === 0) {
1584
- console.log(chalk9.yellow("\nNo matching commits found for your query."));
1585
- console.log(chalk9.gray(`Searched ${commits.length} commits.`));
1632
+ console.log(chalk10.yellow("\nNo matching commits found for your query."));
1633
+ console.log(chalk10.gray(`Searched ${commits.length} commits.`));
1586
1634
  process.exit(0);
1587
1635
  }
1588
1636
  if (options.json) {
@@ -1592,46 +1640,46 @@ var findCommand = new Command9("find").description("Find commits matching a vagu
1592
1640
  printResults(results, query);
1593
1641
  } catch (error) {
1594
1642
  spinner.fail("Failed to search commits");
1595
- console.error(chalk9.red(error instanceof Error ? error.message : "Unknown error"));
1643
+ console.error(chalk10.red(error instanceof Error ? error.message : "Unknown error"));
1596
1644
  process.exit(1);
1597
1645
  }
1598
1646
  });
1599
1647
  function printResults(results, query) {
1600
- console.log(chalk9.bold(`
1648
+ console.log(chalk10.bold(`
1601
1649
  \u{1F50D} Found ${results.matches.length} matching commit(s)
1602
1650
  `));
1603
- console.log(chalk9.gray(`Query: "${query}"
1651
+ console.log(chalk10.gray(`Query: "${query}"
1604
1652
  `));
1605
1653
  for (let i = 0; i < results.matches.length; i++) {
1606
1654
  const match = results.matches[i];
1607
1655
  const num = i + 1;
1608
- console.log(chalk9.cyan(`\u{1F4DD} Commit ${num}`));
1609
- console.log(` ${chalk9.gray("Hash:")} ${chalk9.yellow(match.hash.slice(0, 7))}`);
1610
- console.log(` ${chalk9.gray("Message:")} ${match.message.split("\n")[0]}`);
1611
- console.log(` ${chalk9.gray("Author:")} ${match.author} <${match.email}>`);
1612
- console.log(` ${chalk9.gray("Date:")} ${match.date}`);
1613
- console.log(` ${chalk9.gray("Reason:")} ${chalk9.green(match.reason)}`);
1656
+ console.log(chalk10.cyan(`\u{1F4DD} Commit ${num}`));
1657
+ console.log(` ${chalk10.gray("Hash:")} ${chalk10.yellow(match.hash.slice(0, 7))}`);
1658
+ console.log(` ${chalk10.gray("Message:")} ${match.message.split("\n")[0]}`);
1659
+ console.log(` ${chalk10.gray("Author:")} ${match.author} <${match.email}>`);
1660
+ console.log(` ${chalk10.gray("Date:")} ${match.date}`);
1661
+ console.log(` ${chalk10.gray("Reason:")} ${chalk10.green(match.reason)}`);
1614
1662
  if (match.relevance) {
1615
- const relevanceColor = match.relevance === "high" ? chalk9.green : match.relevance === "medium" ? chalk9.yellow : chalk9.gray;
1616
- console.log(` ${chalk9.gray("Match:")} ${relevanceColor(match.relevance)}`);
1663
+ const relevanceColor = match.relevance === "high" ? chalk10.green : match.relevance === "medium" ? chalk10.yellow : chalk10.gray;
1664
+ console.log(` ${chalk10.gray("Match:")} ${relevanceColor(match.relevance)}`);
1617
1665
  }
1618
1666
  console.log();
1619
1667
  }
1620
1668
  if (results.summary) {
1621
- console.log(chalk9.gray("---"));
1622
- console.log(chalk9.gray(`Summary: ${results.summary}`));
1669
+ console.log(chalk10.gray("---"));
1670
+ console.log(chalk10.gray(`Summary: ${results.summary}`));
1623
1671
  }
1624
1672
  }
1625
1673
 
1626
1674
  // src/commands/branch.ts
1627
1675
  import { Command as Command10 } from "commander";
1628
- import chalk10 from "chalk";
1676
+ import chalk11 from "chalk";
1629
1677
  import ora9 from "ora";
1630
1678
  import { simpleGit as simpleGit9 } from "simple-git";
1631
- import { execSync as execSync4 } from "child_process";
1679
+ import { execSync as execSync6 } from "child_process";
1632
1680
  function getIssueInfo(issueNumber) {
1633
1681
  try {
1634
- const result = execSync4(`gh issue view ${issueNumber} --json title,body`, {
1682
+ const result = execSync6(`gh issue view ${issueNumber} --json title,body`, {
1635
1683
  encoding: "utf-8",
1636
1684
  stdio: ["pipe", "pipe", "pipe"]
1637
1685
  });
@@ -1645,7 +1693,7 @@ var branchCommand = new Command10("branch").description("Generate a branch name
1645
1693
  const repoRoot = await git.revparse(["--show-toplevel"]).catch(() => process.cwd());
1646
1694
  const isRepo = await git.checkIsRepo();
1647
1695
  if (!isRepo) {
1648
- console.error(chalk10.red("Error: Not a git repository"));
1696
+ console.error(chalk11.red("Error: Not a git repository"));
1649
1697
  process.exit(1);
1650
1698
  }
1651
1699
  let description;
@@ -1653,30 +1701,33 @@ var branchCommand = new Command10("branch").description("Generate a branch name
1653
1701
  if (options.description) {
1654
1702
  description = options.description;
1655
1703
  } else if (issue) {
1704
+ if (!requireGhCli()) {
1705
+ process.exit(1);
1706
+ }
1656
1707
  issueNumber = issue.replace(/^#/, "");
1657
1708
  const spinner2 = ora9(`Fetching issue #${issueNumber}...`).start();
1658
1709
  const issueInfo = getIssueInfo(issueNumber);
1659
1710
  if (!issueInfo) {
1660
1711
  spinner2.fail(`Could not fetch issue #${issueNumber}`);
1661
- console.log(chalk10.gray("Make sure gh CLI is installed and you are authenticated"));
1712
+ console.log(chalk11.gray("Make sure you are authenticated: gh auth login"));
1662
1713
  process.exit(1);
1663
1714
  }
1664
1715
  spinner2.stop();
1665
- console.log(chalk10.gray(`Issue: ${issueInfo.title}`));
1716
+ console.log(chalk11.gray(`Issue: ${issueInfo.title}`));
1666
1717
  description = `${issueInfo.title}
1667
1718
 
1668
1719
  ${issueInfo.body || ""}`;
1669
1720
  } else {
1670
- console.error(chalk10.red("Error: Please provide an issue number or use -d for description"));
1671
- console.log(chalk10.gray("Usage:"));
1672
- console.log(chalk10.gray(" gut branch 123"));
1673
- console.log(chalk10.gray(' gut branch -d "add user authentication"'));
1721
+ console.error(chalk11.red("Error: Please provide an issue number or use -d for description"));
1722
+ console.log(chalk11.gray("Usage:"));
1723
+ console.log(chalk11.gray(" gut branch 123"));
1724
+ console.log(chalk11.gray(' gut branch -d "add user authentication"'));
1674
1725
  process.exit(1);
1675
1726
  }
1676
1727
  const provider = options.provider.toLowerCase();
1677
1728
  const template = findTemplate(repoRoot.trim(), "branch");
1678
1729
  if (template) {
1679
- console.log(chalk10.gray("Using template from project..."));
1730
+ console.log(chalk11.gray("Using template from project..."));
1680
1731
  }
1681
1732
  const spinner = ora9("Generating branch name...").start();
1682
1733
  try {
@@ -1687,12 +1738,12 @@ ${issueInfo.body || ""}`;
1687
1738
  template || void 0
1688
1739
  );
1689
1740
  spinner.stop();
1690
- console.log(chalk10.bold("\nGenerated branch name:\n"));
1691
- console.log(chalk10.green(` ${branchName}`));
1741
+ console.log(chalk11.bold("\nGenerated branch name:\n"));
1742
+ console.log(chalk11.green(` ${branchName}`));
1692
1743
  console.log();
1693
1744
  if (options.checkout) {
1694
1745
  await git.checkoutLocalBranch(branchName);
1695
- console.log(chalk10.green(`\u2713 Created and checked out branch: ${branchName}`));
1746
+ console.log(chalk11.green(`\u2713 Created and checked out branch: ${branchName}`));
1696
1747
  } else {
1697
1748
  const readline = await import("readline");
1698
1749
  const rl = readline.createInterface({
@@ -1700,34 +1751,34 @@ ${issueInfo.body || ""}`;
1700
1751
  output: process.stdout
1701
1752
  });
1702
1753
  const answer = await new Promise((resolve) => {
1703
- rl.question(chalk10.cyan("Create and checkout this branch? (y/N) "), resolve);
1754
+ rl.question(chalk11.cyan("Create and checkout this branch? (y/N) "), resolve);
1704
1755
  });
1705
1756
  rl.close();
1706
1757
  if (answer.toLowerCase() === "y") {
1707
1758
  await git.checkoutLocalBranch(branchName);
1708
- console.log(chalk10.green(`\u2713 Created and checked out branch: ${branchName}`));
1759
+ console.log(chalk11.green(`\u2713 Created and checked out branch: ${branchName}`));
1709
1760
  } else {
1710
- console.log(chalk10.gray("\nTo create manually:"));
1711
- console.log(chalk10.gray(` git checkout -b ${branchName}`));
1761
+ console.log(chalk11.gray("\nTo create manually:"));
1762
+ console.log(chalk11.gray(` git checkout -b ${branchName}`));
1712
1763
  }
1713
1764
  }
1714
1765
  } catch (error) {
1715
1766
  spinner.fail("Failed to generate branch name");
1716
- console.error(chalk10.red(error instanceof Error ? error.message : "Unknown error"));
1767
+ console.error(chalk11.red(error instanceof Error ? error.message : "Unknown error"));
1717
1768
  process.exit(1);
1718
1769
  }
1719
1770
  });
1720
1771
 
1721
1772
  // src/commands/checkout.ts
1722
1773
  import { Command as Command11 } from "commander";
1723
- import chalk11 from "chalk";
1774
+ import chalk12 from "chalk";
1724
1775
  import ora10 from "ora";
1725
1776
  import { simpleGit as simpleGit10 } from "simple-git";
1726
1777
  var checkoutCommand = new Command11("checkout").description("Generate a branch name from current diff and checkout").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic)", "gemini").option("-m, --model <model>", "Model to use (provider-specific)").option("-y, --yes", "Skip confirmation and checkout directly").option("-s, --staged", "Use staged changes only instead of all changes").action(async (options) => {
1727
1778
  const git = simpleGit10();
1728
1779
  const isRepo = await git.checkIsRepo();
1729
1780
  if (!isRepo) {
1730
- console.error(chalk11.red("Error: Not a git repository"));
1781
+ console.error(chalk12.red("Error: Not a git repository"));
1731
1782
  process.exit(1);
1732
1783
  }
1733
1784
  const repoRoot = await git.revparse(["--show-toplevel"]).catch(() => process.cwd());
@@ -1744,7 +1795,7 @@ var checkoutCommand = new Command11("checkout").description("Generate a branch n
1744
1795
  const hasChanges = diff.trim() || status.not_added.length > 0 || status.created.length > 0;
1745
1796
  if (!hasChanges) {
1746
1797
  spinner.fail("No changes found");
1747
- console.log(chalk11.gray("Make some changes first, then run gut checkout"));
1798
+ console.log(chalk12.gray("Make some changes first, then run gut checkout"));
1748
1799
  process.exit(1);
1749
1800
  }
1750
1801
  if (!diff.trim() && (status.not_added.length > 0 || status.created.length > 0)) {
@@ -1756,7 +1807,7 @@ ${untrackedFiles.map((f) => `+ ${f}`).join("\n")}`;
1756
1807
  const provider = options.provider.toLowerCase();
1757
1808
  const template = findTemplate(repoRoot.trim(), "checkout");
1758
1809
  if (template) {
1759
- console.log(chalk11.gray("\nUsing template from project..."));
1810
+ console.log(chalk12.gray("\nUsing template from project..."));
1760
1811
  }
1761
1812
  try {
1762
1813
  const branchName = await generateBranchNameFromDiff(
@@ -1765,12 +1816,12 @@ ${untrackedFiles.map((f) => `+ ${f}`).join("\n")}`;
1765
1816
  template
1766
1817
  );
1767
1818
  spinner.stop();
1768
- console.log(chalk11.bold("\nGenerated branch name:\n"));
1769
- console.log(chalk11.green(` ${branchName}`));
1819
+ console.log(chalk12.bold("\nGenerated branch name:\n"));
1820
+ console.log(chalk12.green(` ${branchName}`));
1770
1821
  console.log();
1771
1822
  if (options.yes) {
1772
1823
  await git.checkoutLocalBranch(branchName);
1773
- console.log(chalk11.green(`\u2713 Created and checked out branch: ${branchName}`));
1824
+ console.log(chalk12.green(`\u2713 Created and checked out branch: ${branchName}`));
1774
1825
  } else {
1775
1826
  const readline = await import("readline");
1776
1827
  const rl = readline.createInterface({
@@ -1778,34 +1829,34 @@ ${untrackedFiles.map((f) => `+ ${f}`).join("\n")}`;
1778
1829
  output: process.stdout
1779
1830
  });
1780
1831
  const answer = await new Promise((resolve) => {
1781
- rl.question(chalk11.cyan("Create and checkout this branch? (y/N) "), resolve);
1832
+ rl.question(chalk12.cyan("Create and checkout this branch? (y/N) "), resolve);
1782
1833
  });
1783
1834
  rl.close();
1784
1835
  if (answer.toLowerCase() === "y") {
1785
1836
  await git.checkoutLocalBranch(branchName);
1786
- console.log(chalk11.green(`\u2713 Created and checked out branch: ${branchName}`));
1837
+ console.log(chalk12.green(`\u2713 Created and checked out branch: ${branchName}`));
1787
1838
  } else {
1788
- console.log(chalk11.gray("\nTo create manually:"));
1789
- console.log(chalk11.gray(` git checkout -b ${branchName}`));
1839
+ console.log(chalk12.gray("\nTo create manually:"));
1840
+ console.log(chalk12.gray(` git checkout -b ${branchName}`));
1790
1841
  }
1791
1842
  }
1792
1843
  } catch (error) {
1793
1844
  spinner.fail("Failed to generate branch name");
1794
- console.error(chalk11.red(error instanceof Error ? error.message : "Unknown error"));
1845
+ console.error(chalk12.red(error instanceof Error ? error.message : "Unknown error"));
1795
1846
  process.exit(1);
1796
1847
  }
1797
1848
  });
1798
1849
 
1799
1850
  // src/commands/sync.ts
1800
1851
  import { Command as Command12 } from "commander";
1801
- import chalk12 from "chalk";
1852
+ import chalk13 from "chalk";
1802
1853
  import ora11 from "ora";
1803
1854
  import { simpleGit as simpleGit11 } from "simple-git";
1804
1855
  var syncCommand = new Command12("sync").description("Sync current branch with remote (fetch + rebase/merge)").option("-m, --merge", "Use merge instead of rebase").option("--no-push", "Skip push after syncing").option("--stash", "Auto-stash changes before sync").option("-f, --force", "Force sync even with uncommitted changes").action(async (options) => {
1805
1856
  const git = simpleGit11();
1806
1857
  const isRepo = await git.checkIsRepo();
1807
1858
  if (!isRepo) {
1808
- console.error(chalk12.red("Error: Not a git repository"));
1859
+ console.error(chalk13.red("Error: Not a git repository"));
1809
1860
  process.exit(1);
1810
1861
  }
1811
1862
  const spinner = ora11("Checking repository status...").start();
@@ -1814,15 +1865,15 @@ var syncCommand = new Command12("sync").description("Sync current branch with re
1814
1865
  const hasChanges = !status.isClean();
1815
1866
  if (hasChanges && !options.stash && !options.force) {
1816
1867
  spinner.stop();
1817
- console.log(chalk12.yellow("You have uncommitted changes:"));
1868
+ console.log(chalk13.yellow("You have uncommitted changes:"));
1818
1869
  if (status.modified.length > 0) {
1819
- console.log(chalk12.gray(` Modified: ${status.modified.length} file(s)`));
1870
+ console.log(chalk13.gray(` Modified: ${status.modified.length} file(s)`));
1820
1871
  }
1821
1872
  if (status.not_added.length > 0) {
1822
- console.log(chalk12.gray(` Untracked: ${status.not_added.length} file(s)`));
1873
+ console.log(chalk13.gray(` Untracked: ${status.not_added.length} file(s)`));
1823
1874
  }
1824
1875
  console.log();
1825
- console.log(chalk12.gray("Use --stash to auto-stash, or --force to sync anyway"));
1876
+ console.log(chalk13.gray("Use --stash to auto-stash, or --force to sync anyway"));
1826
1877
  process.exit(1);
1827
1878
  }
1828
1879
  let stashed = false;
@@ -1841,11 +1892,11 @@ var syncCommand = new Command12("sync").description("Sync current branch with re
1841
1892
  const trackingBranch = status.tracking;
1842
1893
  if (!trackingBranch) {
1843
1894
  spinner.warn(`Branch ${currentBranch} has no upstream tracking branch`);
1844
- console.log(chalk12.gray(`
1895
+ console.log(chalk13.gray(`
1845
1896
  To set upstream: git push -u origin ${currentBranch}`));
1846
1897
  if (stashed) {
1847
1898
  await git.stash(["pop"]);
1848
- console.log(chalk12.gray("Restored stashed changes"));
1899
+ console.log(chalk13.gray("Restored stashed changes"));
1849
1900
  }
1850
1901
  return;
1851
1902
  }
@@ -1859,36 +1910,36 @@ To set upstream: git push -u origin ${currentBranch}`));
1859
1910
  }
1860
1911
  } catch (error) {
1861
1912
  spinner.fail(`${strategy} failed - you may have conflicts`);
1862
- console.log(chalk12.yellow("\nResolve conflicts and then:"));
1913
+ console.log(chalk13.yellow("\nResolve conflicts and then:"));
1863
1914
  if (options.merge) {
1864
- console.log(chalk12.gray(" git add . && git commit"));
1915
+ console.log(chalk13.gray(" git add . && git commit"));
1865
1916
  } else {
1866
- console.log(chalk12.gray(" git add . && git rebase --continue"));
1917
+ console.log(chalk13.gray(" git add . && git rebase --continue"));
1867
1918
  }
1868
1919
  if (stashed) {
1869
- console.log(chalk12.yellow("\nNote: You have stashed changes. Run `git stash pop` after resolving."));
1920
+ console.log(chalk13.yellow("\nNote: You have stashed changes. Run `git stash pop` after resolving."));
1870
1921
  }
1871
1922
  process.exit(1);
1872
1923
  }
1873
1924
  const newStatus = await git.status();
1874
1925
  const ahead = newStatus.ahead || 0;
1875
1926
  const behind = newStatus.behind || 0;
1876
- spinner.succeed(chalk12.green("Synced successfully"));
1927
+ spinner.succeed(chalk13.green("Synced successfully"));
1877
1928
  if (behind > 0) {
1878
- console.log(chalk12.yellow(` \u2193 ${behind} commit(s) behind`));
1929
+ console.log(chalk13.yellow(` \u2193 ${behind} commit(s) behind`));
1879
1930
  }
1880
1931
  if (ahead > 0) {
1881
1932
  if (options.push !== false) {
1882
1933
  const pushSpinner = ora11("Pushing to remote...").start();
1883
1934
  try {
1884
1935
  await git.push();
1885
- pushSpinner.succeed(chalk12.green(`Pushed ${ahead} commit(s)`));
1936
+ pushSpinner.succeed(chalk13.green(`Pushed ${ahead} commit(s)`));
1886
1937
  } catch (error) {
1887
1938
  pushSpinner.fail("Push failed");
1888
- console.error(chalk12.red(error instanceof Error ? error.message : "Unknown error"));
1939
+ console.error(chalk13.red(error instanceof Error ? error.message : "Unknown error"));
1889
1940
  }
1890
1941
  } else {
1891
- console.log(chalk12.cyan(` \u2191 ${ahead} commit(s) ahead`));
1942
+ console.log(chalk13.cyan(` \u2191 ${ahead} commit(s) ahead`));
1892
1943
  }
1893
1944
  }
1894
1945
  if (stashed) {
@@ -1898,37 +1949,37 @@ To set upstream: git push -u origin ${currentBranch}`));
1898
1949
  spinner.succeed("Restored stashed changes");
1899
1950
  } catch {
1900
1951
  spinner.warn("Could not auto-restore stash (may have conflicts)");
1901
- console.log(chalk12.gray(" Run `git stash pop` manually"));
1952
+ console.log(chalk13.gray(" Run `git stash pop` manually"));
1902
1953
  }
1903
1954
  }
1904
1955
  } catch (error) {
1905
1956
  spinner.fail("Sync failed");
1906
- console.error(chalk12.red(error instanceof Error ? error.message : "Unknown error"));
1957
+ console.error(chalk13.red(error instanceof Error ? error.message : "Unknown error"));
1907
1958
  process.exit(1);
1908
1959
  }
1909
1960
  });
1910
1961
 
1911
1962
  // src/commands/stash.ts
1912
1963
  import { Command as Command13 } from "commander";
1913
- import chalk13 from "chalk";
1964
+ import chalk14 from "chalk";
1914
1965
  import ora12 from "ora";
1915
1966
  import { simpleGit as simpleGit12 } from "simple-git";
1916
1967
  var stashCommand = new Command13("stash").description("Stash changes with AI-generated name").argument("[name]", "Custom stash name (skips AI generation)").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic)", "gemini").option("-m, --model <model>", "Model to use (provider-specific)").option("-l, --list", "List all stashes").option("-a, --apply [index]", "Apply stash (default: latest)").option("--pop [index]", "Pop stash (default: latest)").option("-d, --drop [index]", "Drop stash").option("--clear", "Clear all stashes").action(async (name, options) => {
1917
1968
  const git = simpleGit12();
1918
1969
  const isRepo = await git.checkIsRepo();
1919
1970
  if (!isRepo) {
1920
- console.error(chalk13.red("Error: Not a git repository"));
1971
+ console.error(chalk14.red("Error: Not a git repository"));
1921
1972
  process.exit(1);
1922
1973
  }
1923
1974
  if (options.list) {
1924
1975
  const stashList = await git.stashList();
1925
1976
  if (stashList.all.length === 0) {
1926
- console.log(chalk13.gray("No stashes found"));
1977
+ console.log(chalk14.gray("No stashes found"));
1927
1978
  return;
1928
1979
  }
1929
- console.log(chalk13.bold("\nStashes:\n"));
1980
+ console.log(chalk14.bold("\nStashes:\n"));
1930
1981
  stashList.all.forEach((stash, index) => {
1931
- console.log(` ${chalk13.cyan(index.toString())} ${stash.message}`);
1982
+ console.log(` ${chalk14.cyan(index.toString())} ${stash.message}`);
1932
1983
  });
1933
1984
  console.log();
1934
1985
  return;
@@ -1937,9 +1988,9 @@ var stashCommand = new Command13("stash").description("Stash changes with AI-gen
1937
1988
  const index = typeof options.apply === "string" ? options.apply : "0";
1938
1989
  try {
1939
1990
  await git.stash(["apply", `stash@{${index}}`]);
1940
- console.log(chalk13.green(`\u2713 Applied stash@{${index}}`));
1991
+ console.log(chalk14.green(`\u2713 Applied stash@{${index}}`));
1941
1992
  } catch (error) {
1942
- console.error(chalk13.red(`Failed to apply stash: ${error instanceof Error ? error.message : "Unknown error"}`));
1993
+ console.error(chalk14.red(`Failed to apply stash: ${error instanceof Error ? error.message : "Unknown error"}`));
1943
1994
  process.exit(1);
1944
1995
  }
1945
1996
  return;
@@ -1948,9 +1999,9 @@ var stashCommand = new Command13("stash").description("Stash changes with AI-gen
1948
1999
  const index = typeof options.pop === "string" ? options.pop : "0";
1949
2000
  try {
1950
2001
  await git.stash(["pop", `stash@{${index}}`]);
1951
- console.log(chalk13.green(`\u2713 Popped stash@{${index}}`));
2002
+ console.log(chalk14.green(`\u2713 Popped stash@{${index}}`));
1952
2003
  } catch (error) {
1953
- console.error(chalk13.red(`Failed to pop stash: ${error instanceof Error ? error.message : "Unknown error"}`));
2004
+ console.error(chalk14.red(`Failed to pop stash: ${error instanceof Error ? error.message : "Unknown error"}`));
1954
2005
  process.exit(1);
1955
2006
  }
1956
2007
  return;
@@ -1959,9 +2010,9 @@ var stashCommand = new Command13("stash").description("Stash changes with AI-gen
1959
2010
  const index = typeof options.drop === "string" ? options.drop : "0";
1960
2011
  try {
1961
2012
  await git.stash(["drop", `stash@{${index}}`]);
1962
- console.log(chalk13.green(`\u2713 Dropped stash@{${index}}`));
2013
+ console.log(chalk14.green(`\u2713 Dropped stash@{${index}}`));
1963
2014
  } catch (error) {
1964
- console.error(chalk13.red(`Failed to drop stash: ${error instanceof Error ? error.message : "Unknown error"}`));
2015
+ console.error(chalk14.red(`Failed to drop stash: ${error instanceof Error ? error.message : "Unknown error"}`));
1965
2016
  process.exit(1);
1966
2017
  }
1967
2018
  return;
@@ -1973,20 +2024,20 @@ var stashCommand = new Command13("stash").description("Stash changes with AI-gen
1973
2024
  output: process.stdout
1974
2025
  });
1975
2026
  const answer = await new Promise((resolve) => {
1976
- rl.question(chalk13.yellow("Clear all stashes? This cannot be undone. (y/N) "), resolve);
2027
+ rl.question(chalk14.yellow("Clear all stashes? This cannot be undone. (y/N) "), resolve);
1977
2028
  });
1978
2029
  rl.close();
1979
2030
  if (answer.toLowerCase() === "y") {
1980
2031
  await git.stash(["clear"]);
1981
- console.log(chalk13.green("\u2713 Cleared all stashes"));
2032
+ console.log(chalk14.green("\u2713 Cleared all stashes"));
1982
2033
  } else {
1983
- console.log(chalk13.gray("Cancelled"));
2034
+ console.log(chalk14.gray("Cancelled"));
1984
2035
  }
1985
2036
  return;
1986
2037
  }
1987
2038
  const status = await git.status();
1988
2039
  if (status.isClean()) {
1989
- console.log(chalk13.yellow("No changes to stash"));
2040
+ console.log(chalk14.yellow("No changes to stash"));
1990
2041
  return;
1991
2042
  }
1992
2043
  let stashName;
@@ -2013,19 +2064,19 @@ var stashCommand = new Command13("stash").description("Stash changes with AI-gen
2013
2064
  }
2014
2065
  }
2015
2066
  await git.stash(["push", "-u", "-m", stashName]);
2016
- console.log(chalk13.green(`\u2713 Stashed: ${stashName}`));
2067
+ console.log(chalk14.green(`\u2713 Stashed: ${stashName}`));
2017
2068
  });
2018
2069
 
2019
2070
  // src/commands/summary.ts
2020
2071
  import { Command as Command14 } from "commander";
2021
- import chalk14 from "chalk";
2072
+ import chalk15 from "chalk";
2022
2073
  import ora13 from "ora";
2023
2074
  import { simpleGit as simpleGit13 } from "simple-git";
2024
2075
  var summaryCommand = new Command14("summary").description("Generate a work summary from your commits (for daily/weekly reports)").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic)", "gemini").option("-m, --model <model>", "Model to use (provider-specific)").option("--since <date>", "Start date (default: today)", "today").option("--until <date>", "End date").option("--author <author>", "Filter by author (default: current user)").option("--daily", "Generate daily report (alias for --since today)").option("--weekly", 'Generate weekly report (alias for --since "1 week ago")').option("--with-diff", "Include diff analysis for more detail").option("--markdown", "Output as markdown").option("--json", "Output as JSON").option("--copy", "Copy to clipboard").action(async (options) => {
2025
2076
  const git = simpleGit13();
2026
2077
  const isRepo = await git.checkIsRepo();
2027
2078
  if (!isRepo) {
2028
- console.error(chalk14.red("Error: Not a git repository"));
2079
+ console.error(chalk15.red("Error: Not a git repository"));
2029
2080
  process.exit(1);
2030
2081
  }
2031
2082
  const provider = options.provider.toLowerCase();
@@ -2093,13 +2144,13 @@ var summaryCommand = new Command14("summary").description("Generate a work summa
2093
2144
  const output = options.markdown ? formatMarkdown(summary, author, since, options.until) : null;
2094
2145
  if (options.copy) {
2095
2146
  const textToCopy = output || formatMarkdown(summary, author, since, options.until);
2096
- const { execSync: execSync5 } = await import("child_process");
2147
+ const { execSync: execSync7 } = await import("child_process");
2097
2148
  try {
2098
- execSync5("pbcopy", { input: textToCopy });
2099
- console.log(chalk14.green("Summary copied to clipboard!"));
2149
+ execSync7("pbcopy", { input: textToCopy });
2150
+ console.log(chalk15.green("Summary copied to clipboard!"));
2100
2151
  console.log();
2101
2152
  } catch {
2102
- console.log(chalk14.yellow("Could not copy to clipboard"));
2153
+ console.log(chalk15.yellow("Could not copy to clipboard"));
2103
2154
  }
2104
2155
  }
2105
2156
  if (options.markdown) {
@@ -2109,7 +2160,7 @@ var summaryCommand = new Command14("summary").description("Generate a work summa
2109
2160
  }
2110
2161
  } catch (error) {
2111
2162
  spinner.fail("Failed to generate summary");
2112
- console.error(chalk14.red(error instanceof Error ? error.message : "Unknown error"));
2163
+ console.error(chalk15.red(error instanceof Error ? error.message : "Unknown error"));
2113
2164
  process.exit(1);
2114
2165
  }
2115
2166
  });
@@ -2177,29 +2228,29 @@ function formatDate(d) {
2177
2228
  }
2178
2229
  function printSummary(summary, author, since, until) {
2179
2230
  const period = until ? `${since} - ${until}` : `${since} - now`;
2180
- console.log(chalk14.bold(`
2231
+ console.log(chalk15.bold(`
2181
2232
  \u{1F4CA} ${summary.title}
2182
2233
  `));
2183
- console.log(chalk14.gray(`Author: ${author}`));
2184
- console.log(chalk14.gray(`Period: ${period}`));
2234
+ console.log(chalk15.gray(`Author: ${author}`));
2235
+ console.log(chalk15.gray(`Period: ${period}`));
2185
2236
  if (summary.stats) {
2186
- console.log(chalk14.gray(`Commits: ${summary.stats.commits}`));
2237
+ console.log(chalk15.gray(`Commits: ${summary.stats.commits}`));
2187
2238
  }
2188
2239
  console.log();
2189
- console.log(chalk14.cyan("Overview:"));
2240
+ console.log(chalk15.cyan("Overview:"));
2190
2241
  console.log(` ${summary.overview}`);
2191
2242
  console.log();
2192
2243
  if (summary.highlights.length > 0) {
2193
- console.log(chalk14.cyan("Highlights:"));
2244
+ console.log(chalk15.cyan("Highlights:"));
2194
2245
  for (const highlight of summary.highlights) {
2195
- console.log(` ${chalk14.green("\u2605")} ${highlight}`);
2246
+ console.log(` ${chalk15.green("\u2605")} ${highlight}`);
2196
2247
  }
2197
2248
  console.log();
2198
2249
  }
2199
2250
  if (summary.details.length > 0) {
2200
- console.log(chalk14.cyan("Details:"));
2251
+ console.log(chalk15.cyan("Details:"));
2201
2252
  for (const section of summary.details) {
2202
- console.log(` ${chalk14.yellow(section.category)}`);
2253
+ console.log(` ${chalk15.yellow(section.category)}`);
2203
2254
  for (const item of section.items) {
2204
2255
  console.log(` \u2022 ${item}`);
2205
2256
  }
@@ -2210,26 +2261,26 @@ function printSummary(summary, author, since, until) {
2210
2261
 
2211
2262
  // src/commands/config.ts
2212
2263
  import { Command as Command15 } from "commander";
2213
- import chalk15 from "chalk";
2264
+ import chalk16 from "chalk";
2214
2265
  var configCommand = new Command15("config").description("Manage gut configuration");
2215
2266
  configCommand.command("set <key> <value>").description("Set a configuration value").option("--local", "Set for current repository only").action((key, value, options) => {
2216
2267
  if (key === "lang") {
2217
2268
  if (!isValidLanguage(value)) {
2218
- console.error(chalk15.red(`Invalid language: ${value}`));
2219
- console.error(chalk15.gray(`Valid languages: ${VALID_LANGUAGES.join(", ")}`));
2269
+ console.error(chalk16.red(`Invalid language: ${value}`));
2270
+ console.error(chalk16.gray(`Valid languages: ${VALID_LANGUAGES.join(", ")}`));
2220
2271
  process.exit(1);
2221
2272
  }
2222
2273
  try {
2223
2274
  setLanguage(value, options.local ?? false);
2224
2275
  const scope = options.local ? "(local)" : "(global)";
2225
- console.log(chalk15.green(`\u2713 Language set to: ${value} ${scope}`));
2276
+ console.log(chalk16.green(`\u2713 Language set to: ${value} ${scope}`));
2226
2277
  } catch (err) {
2227
- console.error(chalk15.red(err.message));
2278
+ console.error(chalk16.red(err.message));
2228
2279
  process.exit(1);
2229
2280
  }
2230
2281
  } else {
2231
- console.error(chalk15.red(`Unknown config key: ${key}`));
2232
- console.error(chalk15.gray("Available keys: lang"));
2282
+ console.error(chalk16.red(`Unknown config key: ${key}`));
2283
+ console.error(chalk16.gray("Available keys: lang"));
2233
2284
  process.exit(1);
2234
2285
  }
2235
2286
  });
@@ -2238,7 +2289,7 @@ configCommand.command("get <key>").description("Get a configuration value").acti
2238
2289
  if (key in config) {
2239
2290
  console.log(config[key]);
2240
2291
  } else {
2241
- console.error(chalk15.red(`Unknown config key: ${key}`));
2292
+ console.error(chalk16.red(`Unknown config key: ${key}`));
2242
2293
  process.exit(1);
2243
2294
  }
2244
2295
  });
@@ -2246,49 +2297,188 @@ configCommand.command("list").description("List all configuration values").actio
2246
2297
  const globalConfig = getGlobalConfig();
2247
2298
  const localConfig = getLocalConfig();
2248
2299
  const effectiveConfig = getConfig();
2249
- console.log(chalk15.bold("Configuration:"));
2300
+ console.log(chalk16.bold("Configuration:"));
2250
2301
  console.log();
2251
2302
  for (const key of Object.keys(effectiveConfig)) {
2252
2303
  const value = effectiveConfig[key];
2253
2304
  const isLocal = key in localConfig;
2254
- const scope = isLocal ? chalk15.cyan(" (local)") : chalk15.gray(" (global)");
2255
- console.log(` ${chalk15.cyan(key)}: ${value}${scope}`);
2305
+ const scope = isLocal ? chalk16.cyan(" (local)") : chalk16.gray(" (global)");
2306
+ console.log(` ${chalk16.cyan(key)}: ${value}${scope}`);
2256
2307
  }
2257
2308
  if (Object.keys(localConfig).length > 0) {
2258
2309
  console.log();
2259
- console.log(chalk15.gray("Local config: .gut/config.json"));
2310
+ console.log(chalk16.gray("Local config: .gut/config.json"));
2260
2311
  }
2261
2312
  });
2262
2313
 
2263
2314
  // src/commands/lang.ts
2264
2315
  import { Command as Command16 } from "commander";
2265
- import chalk16 from "chalk";
2316
+ import chalk17 from "chalk";
2266
2317
  var langCommand = new Command16("lang").description("Set or show output language").argument("[language]", `Language to set (${VALID_LANGUAGES.join(", ")})`).option("--local", "Set for current repository only").action((language, options) => {
2267
2318
  if (!language) {
2268
2319
  const lang = getLanguage();
2269
2320
  const localConfig = getLocalConfig();
2270
2321
  const isLocal = "lang" in localConfig;
2271
- const scope = isLocal ? chalk16.cyan("(local)") : chalk16.gray("(global)");
2322
+ const scope = isLocal ? chalk17.cyan("(local)") : chalk17.gray("(global)");
2272
2323
  console.log(`${lang} ${scope}`);
2273
2324
  return;
2274
2325
  }
2275
2326
  if (!isValidLanguage(language)) {
2276
- console.error(chalk16.red(`Invalid language: ${language}`));
2277
- console.error(chalk16.gray(`Valid languages: ${VALID_LANGUAGES.join(", ")}`));
2327
+ console.error(chalk17.red(`Invalid language: ${language}`));
2328
+ console.error(chalk17.gray(`Valid languages: ${VALID_LANGUAGES.join(", ")}`));
2278
2329
  process.exit(1);
2279
2330
  }
2280
2331
  try {
2281
2332
  setLanguage(language, options.local ?? false);
2282
2333
  const scope = options.local ? "(local)" : "(global)";
2283
- console.log(chalk16.green(`\u2713 Language set to: ${language} ${scope}`));
2334
+ console.log(chalk17.green(`\u2713 Language set to: ${language} ${scope}`));
2284
2335
  } catch (err) {
2285
- console.error(chalk16.red(err.message));
2336
+ console.error(chalk17.red(err.message));
2286
2337
  process.exit(1);
2287
2338
  }
2288
2339
  });
2289
2340
 
2341
+ // src/commands/init.ts
2342
+ import { Command as Command17 } from "commander";
2343
+ import chalk18 from "chalk";
2344
+ import ora14 from "ora";
2345
+ import { simpleGit as simpleGit14 } from "simple-git";
2346
+ import { existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync6, writeFileSync as writeFileSync3 } from "fs";
2347
+ import { join as join5, dirname as dirname2 } from "path";
2348
+ import { fileURLToPath as fileURLToPath2 } from "url";
2349
+ import { generateText as generateText2 } from "ai";
2350
+ import { createGoogleGenerativeAI as createGoogleGenerativeAI2 } from "@ai-sdk/google";
2351
+ import { createOpenAI as createOpenAI2 } from "@ai-sdk/openai";
2352
+ import { createAnthropic as createAnthropic2 } from "@ai-sdk/anthropic";
2353
+ var __filename2 = fileURLToPath2(import.meta.url);
2354
+ var __dirname2 = dirname2(__filename2);
2355
+ var GUT_ROOT2 = join5(__dirname2, "..");
2356
+ var TEMPLATE_FILES = [
2357
+ "branch.md",
2358
+ "changelog.md",
2359
+ "checkout.md",
2360
+ "commit.md",
2361
+ "explain.md",
2362
+ "explain-file.md",
2363
+ "find.md",
2364
+ "merge.md",
2365
+ "pr.md",
2366
+ "review.md",
2367
+ "stash.md",
2368
+ "summary.md"
2369
+ ];
2370
+ async function translateTemplate(content, targetLang, provider) {
2371
+ const apiKey = await getApiKey(provider);
2372
+ if (!apiKey) {
2373
+ throw new Error(`No API key found for ${provider}`);
2374
+ }
2375
+ const modelName = provider === "gemini" ? "gemini-2.0-flash" : provider === "openai" ? "gpt-4o-mini" : "claude-sonnet-4-20250514";
2376
+ let model;
2377
+ switch (provider) {
2378
+ case "gemini": {
2379
+ const google = createGoogleGenerativeAI2({ apiKey });
2380
+ model = google(modelName);
2381
+ break;
2382
+ }
2383
+ case "openai": {
2384
+ const openai = createOpenAI2({ apiKey });
2385
+ model = openai(modelName);
2386
+ break;
2387
+ }
2388
+ case "anthropic": {
2389
+ const anthropic = createAnthropic2({ apiKey });
2390
+ model = anthropic(modelName);
2391
+ break;
2392
+ }
2393
+ }
2394
+ const langNames = {
2395
+ ja: "Japanese",
2396
+ en: "English",
2397
+ zh: "Chinese",
2398
+ ko: "Korean",
2399
+ es: "Spanish",
2400
+ fr: "French",
2401
+ de: "German"
2402
+ };
2403
+ const targetLangName = langNames[targetLang] || targetLang;
2404
+ const { text } = await generateText2({
2405
+ model,
2406
+ prompt: `Translate the following prompt template to ${targetLangName}.
2407
+ Keep all {{variable}} placeholders exactly as they are - do not translate them.
2408
+ Keep the markdown formatting intact.
2409
+ Only translate the instructional text.
2410
+
2411
+ Template to translate:
2412
+ ${content}
2413
+
2414
+ Translated template:`
2415
+ });
2416
+ return text.trim();
2417
+ }
2418
+ var initCommand = new Command17("init").description("Initialize .gut/ templates in your project").option("-p, --provider <provider>", "AI provider for translation (gemini, openai, anthropic)", "gemini").option("-f, --force", "Overwrite existing templates").option("--no-translate", "Skip translation even if language is not English").action(async (options) => {
2419
+ const git = simpleGit14();
2420
+ const isRepo = await git.checkIsRepo();
2421
+ if (!isRepo) {
2422
+ console.error(chalk18.red("Error: Not a git repository"));
2423
+ process.exit(1);
2424
+ }
2425
+ const repoRoot = await git.revparse(["--show-toplevel"]).catch(() => process.cwd());
2426
+ const targetDir = join5(repoRoot.trim(), ".gut");
2427
+ const sourceDir = join5(GUT_ROOT2, ".gut");
2428
+ if (!existsSync5(targetDir)) {
2429
+ mkdirSync2(targetDir, { recursive: true });
2430
+ console.log(chalk18.green(`Created ${targetDir}`));
2431
+ }
2432
+ const lang = getLanguage();
2433
+ const needsTranslation = options.translate !== false && lang !== "en";
2434
+ const provider = options.provider.toLowerCase();
2435
+ if (needsTranslation) {
2436
+ console.log(chalk18.gray(`Language: ${lang} - templates will be translated
2437
+ `));
2438
+ }
2439
+ const spinner = ora14();
2440
+ let copied = 0;
2441
+ let skipped = 0;
2442
+ for (const filename of TEMPLATE_FILES) {
2443
+ const sourcePath = join5(sourceDir, filename);
2444
+ const targetPath = join5(targetDir, filename);
2445
+ if (!existsSync5(sourcePath)) {
2446
+ continue;
2447
+ }
2448
+ if (existsSync5(targetPath) && !options.force) {
2449
+ console.log(chalk18.gray(` Skipped: ${filename} (already exists)`));
2450
+ skipped++;
2451
+ continue;
2452
+ }
2453
+ let content = readFileSync6(sourcePath, "utf-8");
2454
+ if (needsTranslation) {
2455
+ spinner.start(`Translating ${filename}...`);
2456
+ try {
2457
+ content = await translateTemplate(content, lang, provider);
2458
+ spinner.succeed(`Translated: ${filename}`);
2459
+ } catch (error) {
2460
+ spinner.fail(`Failed to translate ${filename}`);
2461
+ console.error(chalk18.red(` ${error instanceof Error ? error.message : "Unknown error"}`));
2462
+ console.log(chalk18.gray(` Using original English template`));
2463
+ }
2464
+ } else {
2465
+ console.log(chalk18.green(` Copied: ${filename}`));
2466
+ }
2467
+ writeFileSync3(targetPath, content);
2468
+ copied++;
2469
+ }
2470
+ console.log();
2471
+ if (copied > 0) {
2472
+ console.log(chalk18.green(`\u2713 ${copied} template(s) initialized in .gut/`));
2473
+ }
2474
+ if (skipped > 0) {
2475
+ console.log(chalk18.gray(` ${skipped} template(s) skipped (use --force to overwrite)`));
2476
+ }
2477
+ console.log(chalk18.gray("\nYou can now customize these templates for your project."));
2478
+ });
2479
+
2290
2480
  // src/index.ts
2291
- var program = new Command17();
2481
+ var program = new Command18();
2292
2482
  program.name("gut").description("Git Utility Tool - AI-powered git commands").version("0.1.0");
2293
2483
  program.addCommand(cleanupCommand);
2294
2484
  program.addCommand(authCommand);
@@ -2306,5 +2496,6 @@ program.addCommand(stashCommand);
2306
2496
  program.addCommand(summaryCommand);
2307
2497
  program.addCommand(configCommand);
2308
2498
  program.addCommand(langCommand);
2499
+ program.addCommand(initCommand);
2309
2500
  program.parse();
2310
2501
  //# sourceMappingURL=index.js.map