gut-cli 0.1.10 → 0.1.11

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