gut-cli 0.1.32 → 0.1.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -540,6 +540,48 @@ Each template uses `{{variable}}` syntax for dynamic content.
540
540
 
541
541
  **Special case**: `.github/pull_request_template.md` is prioritized over `pr.md` for PR descriptions.
542
542
 
543
+ ## Custom API Endpoints
544
+
545
+ Configure custom base URLs for AI providers (useful for proxies, local instances, or API-compatible services):
546
+
547
+ ### Global Configuration
548
+ ```bash
549
+ # Set base URL for all AI commands
550
+ gut config set baseUrl https://api.example.com/v1
551
+
552
+ # View current config
553
+ gut config list
554
+ ```
555
+
556
+ ### Per-Command Override
557
+ ```bash
558
+ gut commit --base-url https://api.example.com/v1
559
+ gut pr --base-url https://my-proxy.com
560
+ ```
561
+
562
+ ### Local (Project-Specific)
563
+ ```bash
564
+ gut config set baseUrl https://api.example.com/v1 --local
565
+ ```
566
+
567
+ ### Examples
568
+ ```bash
569
+ # OpenAI-compatible API (Groq)
570
+ gut config set provider openai
571
+ gut config set baseUrl https://api.groq.com/openai/v1
572
+
573
+ # Local Ollama on different port
574
+ gut commit --provider ollama --base-url http://192.168.1.100:11434/api
575
+ ```
576
+
577
+ ### Priority Order
578
+ 1. CLI flag `--base-url` (highest)
579
+ 2. Local config (`.gut/config.json`)
580
+ 3. Global config (`~/.config/gut/config.json`)
581
+ 4. Provider defaults (lowest)
582
+
583
+ **Note**: For Ollama, the legacy `ollamaBaseUrl` config takes priority over `baseUrl` for backward compatibility.
584
+
543
585
  ## Development
544
586
 
545
587
  ```bash
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
+ import { createRequire as createRequire2 } from "module";
4
5
  import { Command as Command19 } from "commander";
5
6
 
6
7
  // src/commands/auth.ts
@@ -133,6 +134,29 @@ function setProvider(provider, local = false) {
133
134
  setGlobalConfig("provider", provider);
134
135
  }
135
136
  }
137
+ function getBaseUrl() {
138
+ return getConfig().baseUrl;
139
+ }
140
+ function setBaseUrl(url, local = false) {
141
+ if (url === "") {
142
+ const path2 = local ? getLocalConfigPath() : getGlobalConfigPath();
143
+ if (local && !path2) throw new Error("Not in a git repository");
144
+ const config = local ? getLocalConfig() : getGlobalConfig();
145
+ delete config.baseUrl;
146
+ writeFileSync(path2 || getGlobalConfigPath(), JSON.stringify(config, null, 2));
147
+ return;
148
+ }
149
+ try {
150
+ new URL(url);
151
+ } catch {
152
+ throw new Error(`Invalid URL: ${url}`);
153
+ }
154
+ if (local) {
155
+ setLocalConfig("baseUrl", url);
156
+ } else {
157
+ setGlobalConfig("baseUrl", url);
158
+ }
159
+ }
136
160
 
137
161
  // src/lib/credentials.ts
138
162
  var SERVICE_NAME = "gut-cli";
@@ -153,8 +177,8 @@ var FALLBACK_ENV_MAP = {
153
177
  };
154
178
  function getKeytar() {
155
179
  try {
156
- const require2 = createRequire(import.meta.url);
157
- return require2("keytar");
180
+ const require3 = createRequire(import.meta.url);
181
+ return require3("keytar");
158
182
  } catch {
159
183
  return null;
160
184
  }
@@ -498,23 +522,31 @@ async function getModel(options) {
498
522
  switch (options.provider) {
499
523
  case "gemini": {
500
524
  const apiKey = await resolveApiKey();
501
- const google = createGoogleGenerativeAI({ apiKey });
525
+ const google = createGoogleGenerativeAI({
526
+ apiKey,
527
+ ...options.baseUrl && { baseURL: options.baseUrl }
528
+ });
502
529
  return google(modelName);
503
530
  }
504
531
  case "openai": {
505
532
  const apiKey = await resolveApiKey();
506
- const openai = createOpenAI({ apiKey });
533
+ const openai = createOpenAI({
534
+ apiKey,
535
+ ...options.baseUrl && { baseURL: options.baseUrl }
536
+ });
507
537
  return openai(modelName);
508
538
  }
509
539
  case "anthropic": {
510
540
  const apiKey = await resolveApiKey();
511
- const anthropic = createAnthropic({ apiKey });
541
+ const anthropic = createAnthropic({
542
+ apiKey,
543
+ ...options.baseUrl && { baseURL: options.baseUrl }
544
+ });
512
545
  return anthropic(modelName);
513
546
  }
514
547
  case "ollama": {
515
- const ollama = createOllama({
516
- baseURL: options.ollamaBaseUrl || "http://localhost:11434/api"
517
- });
548
+ const baseURL = options.ollamaBaseUrl || options.baseUrl || "http://localhost:11434/api";
549
+ const ollama = createOllama({ baseURL });
518
550
  return ollama(modelName);
519
551
  }
520
552
  }
@@ -983,7 +1015,7 @@ function getIssueInfo(issueNumber) {
983
1015
  return null;
984
1016
  }
985
1017
  }
986
- var branchCommand = new Command2("branch").description("Generate a branch name from issue number or description").argument("[issue]", "Issue number (e.g., 123 or #123)").option("-d, --description <description>", "Use description instead of issue").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("-t, --type <type>", "Branch type (feature, fix, hotfix, chore, refactor)").option("-c, --checkout", "Create and checkout the branch").action(async (issue, options) => {
1018
+ var branchCommand = new Command2("branch").description("Generate a branch name from issue number or description").argument("[issue]", "Issue number (e.g., 123 or #123)").option("-d, --description <description>", "Use description instead of issue").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("--base-url <url>", "Base URL for API provider").option("-t, --type <type>", "Branch type (feature, fix, hotfix, chore, refactor)").option("-c, --checkout", "Create and checkout the branch").action(async (issue, options) => {
987
1019
  const git = simpleGit();
988
1020
  const repoRoot = await git.revparse(["--show-toplevel"]).catch(() => process.cwd());
989
1021
  const isRepo = await git.checkIsRepo();
@@ -1029,7 +1061,12 @@ ${issueInfo.body || ""}`;
1029
1061
  try {
1030
1062
  const branchName = await generateBranchName(
1031
1063
  description,
1032
- { provider, model: options.model, language: getLanguage() },
1064
+ {
1065
+ provider,
1066
+ model: options.model,
1067
+ baseUrl: options.baseUrl || getBaseUrl(),
1068
+ language: getLanguage()
1069
+ },
1033
1070
  { type: options.type, issue: issueNumber },
1034
1071
  template || void 0
1035
1072
  );
@@ -1090,7 +1127,7 @@ function formatChangelog(changelog) {
1090
1127
  }
1091
1128
  return lines.join("\n");
1092
1129
  }
1093
- var changelogCommand = new Command3("changelog").description("Generate a changelog from commits between refs").argument("[from]", "Starting ref (tag, branch, commit)", "HEAD~10").argument("[to]", "Ending ref", "HEAD").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("-t, --tag <tag>", "Generate changelog since this tag").option("--json", "Output as JSON").action(async (from, to, options) => {
1130
+ var changelogCommand = new Command3("changelog").description("Generate a changelog from commits between refs").argument("[from]", "Starting ref (tag, branch, commit)", "HEAD~10").argument("[to]", "Ending ref", "HEAD").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("--base-url <url>", "Base URL for API provider").option("-t, --tag <tag>", "Generate changelog since this tag").option("--json", "Output as JSON").action(async (from, to, options) => {
1094
1131
  const git = simpleGit2();
1095
1132
  const isRepo = await git.checkIsRepo();
1096
1133
  if (!isRepo) {
@@ -1126,7 +1163,12 @@ var changelogCommand = new Command3("changelog").description("Generate a changel
1126
1163
  }
1127
1164
  const changelog = await generateChangelog(
1128
1165
  { commits, diff, fromRef, toRef },
1129
- { provider, model: options.model, language: getLanguage() },
1166
+ {
1167
+ provider,
1168
+ model: options.model,
1169
+ baseUrl: options.baseUrl || getBaseUrl(),
1170
+ language: getLanguage()
1171
+ },
1130
1172
  template || void 0
1131
1173
  );
1132
1174
  spinner.stop();
@@ -1155,7 +1197,7 @@ import chalk5 from "chalk";
1155
1197
  import { Command as Command4 } from "commander";
1156
1198
  import ora3 from "ora";
1157
1199
  import { simpleGit as simpleGit3 } from "simple-git";
1158
- var checkoutCommand = new Command4("checkout").description("Generate a branch name from current diff and checkout").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").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) => {
1200
+ var checkoutCommand = new Command4("checkout").description("Generate a branch name from current diff and checkout").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("--base-url <url>", "Base URL for API provider").option("-y, --yes", "Skip confirmation and checkout directly").option("-s, --staged", "Use staged changes only instead of all changes").action(async (options) => {
1159
1201
  const git = simpleGit3();
1160
1202
  const isRepo = await git.checkIsRepo();
1161
1203
  if (!isRepo) {
@@ -1194,7 +1236,12 @@ ${untrackedFiles.map((f) => `+ ${f}`).join("\n")}`;
1194
1236
  try {
1195
1237
  const branchName = await generateBranchNameFromDiff(
1196
1238
  diff,
1197
- { provider, model: options.model, language: getLanguage() },
1239
+ {
1240
+ provider,
1241
+ model: options.model,
1242
+ baseUrl: options.baseUrl || getBaseUrl(),
1243
+ language: getLanguage()
1244
+ },
1198
1245
  template
1199
1246
  );
1200
1247
  spinner.stop();
@@ -1316,7 +1363,7 @@ import chalk7 from "chalk";
1316
1363
  import { Command as Command6 } from "commander";
1317
1364
  import ora5 from "ora";
1318
1365
  import { simpleGit as simpleGit5 } from "simple-git";
1319
- var commitCommand = new Command6("commit").description("Generate a commit message using AI").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("-c, --commit", "Automatically commit with the generated message").option("-a, --all", "Force stage all changes (default: auto-stage if nothing staged)").action(async (options) => {
1366
+ var commitCommand = new Command6("commit").description("Generate a commit message using AI").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("--base-url <url>", "Base URL for API provider").option("-c, --commit", "Automatically commit with the generated message").option("-a, --all", "Force stage all changes (default: auto-stage if nothing staged)").action(async (options) => {
1320
1367
  const git = simpleGit5();
1321
1368
  const repoRoot = await git.revparse(["--show-toplevel"]).catch(() => process.cwd());
1322
1369
  const isRepo = await git.checkIsRepo();
@@ -1349,7 +1396,12 @@ var commitCommand = new Command6("commit").description("Generate a commit messag
1349
1396
  try {
1350
1397
  const message = await generateCommitMessage(
1351
1398
  diff,
1352
- { provider, model: options.model, language: getLanguage() },
1399
+ {
1400
+ provider,
1401
+ model: options.model,
1402
+ baseUrl: options.baseUrl || getBaseUrl(),
1403
+ language: getLanguage()
1404
+ },
1353
1405
  template || void 0
1354
1406
  );
1355
1407
  spinner.stop();
@@ -1468,9 +1520,19 @@ configCommand.command("set <key> <value>").description("Set a configuration valu
1468
1520
  console.error(chalk8.red(err.message));
1469
1521
  process.exit(1);
1470
1522
  }
1523
+ } else if (key === "baseUrl") {
1524
+ try {
1525
+ setBaseUrl(value, options.local ?? false);
1526
+ const scope = options.local ? "(local)" : "(global)";
1527
+ console.log(chalk8.green(`\u2713 Base URL set to: ${value} ${scope}`));
1528
+ console.log(chalk8.gray("Applies to all AI providers (OpenAI, Anthropic, Gemini, Ollama)"));
1529
+ } catch (err) {
1530
+ console.error(chalk8.red(err.message));
1531
+ process.exit(1);
1532
+ }
1471
1533
  } else {
1472
1534
  console.error(chalk8.red(`Unknown config key: ${key}`));
1473
- console.error(chalk8.gray("Available keys: lang, model, provider"));
1535
+ console.error(chalk8.gray("Available keys: lang, model, provider, baseUrl"));
1474
1536
  process.exit(1);
1475
1537
  }
1476
1538
  });
@@ -1543,7 +1605,7 @@ import { simpleGit as simpleGit7 } from "simple-git";
1543
1605
  var explainCommand = new Command8("explain").description("Get an AI-powered explanation of changes, commits, PRs, or files").argument(
1544
1606
  "[target]",
1545
1607
  "Commit hash, PR number, PR URL, or file path (default: uncommitted changes)"
1546
- ).option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").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) => {
1608
+ ).option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("--base-url <url>", "Base URL for API provider").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) => {
1547
1609
  const git = simpleGit7();
1548
1610
  const isRepo = await git.checkIsRepo();
1549
1611
  if (!isRepo) {
@@ -1595,7 +1657,12 @@ var explainCommand = new Command8("explain").description("Get an AI-powered expl
1595
1657
  spinner.text = "AI is generating explanation...";
1596
1658
  const explanation = await generateExplanation(
1597
1659
  context,
1598
- { provider, model: options.model, language: getLanguage() },
1660
+ {
1661
+ provider,
1662
+ model: options.model,
1663
+ baseUrl: options.baseUrl || getBaseUrl(),
1664
+ language: getLanguage()
1665
+ },
1599
1666
  template || void 0
1600
1667
  );
1601
1668
  spinner.stop();
@@ -1794,7 +1861,7 @@ import { simpleGit as simpleGit8 } from "simple-git";
1794
1861
  var findCommand = new Command9("find").description("Find commits matching a vague description using AI").argument(
1795
1862
  "<query>",
1796
1863
  'Description of the change you are looking for (e.g., "login feature added")'
1797
- ).option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").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) => {
1864
+ ).option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("--base-url <url>", "Base URL for API provider").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) => {
1798
1865
  const git = simpleGit8();
1799
1866
  const isRepo = await git.checkIsRepo();
1800
1867
  if (!isRepo) {
@@ -1836,7 +1903,12 @@ var findCommand = new Command9("find").description("Find commits matching a vagu
1836
1903
  const results = await searchCommits(
1837
1904
  query,
1838
1905
  commits,
1839
- { provider, model: options.model, language: getLanguage() },
1906
+ {
1907
+ provider,
1908
+ model: options.model,
1909
+ baseUrl: options.baseUrl || getBaseUrl(),
1910
+ language: getLanguage()
1911
+ },
1840
1912
  parseInt(options.maxResults, 10),
1841
1913
  template || void 0
1842
1914
  );
@@ -1984,7 +2056,7 @@ function findConfigFiles(repoRoot) {
1984
2056
  }
1985
2057
  return found;
1986
2058
  }
1987
- var gitignoreCommand = new Command10("gitignore").description("Generate .gitignore from current codebase").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("-o, --output <file>", "Output file (default: .gitignore)", ".gitignore").option("--stdout", "Print to stdout instead of file").option("-y, --yes", "Overwrite existing .gitignore without confirmation").action(async (options) => {
2059
+ var gitignoreCommand = new Command10("gitignore").description("Generate .gitignore from current codebase").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("--base-url <url>", "Base URL for API provider").option("-o, --output <file>", "Output file (default: .gitignore)", ".gitignore").option("--stdout", "Print to stdout instead of file").option("-y, --yes", "Overwrite existing .gitignore without confirmation").action(async (options) => {
1988
2060
  const git = simpleGit9();
1989
2061
  const repoRoot = await git.revparse(["--show-toplevel"]).catch(() => process.cwd());
1990
2062
  const root = repoRoot.trim();
@@ -2020,7 +2092,12 @@ ${content}
2020
2092
  configFiles: configFilesStr,
2021
2093
  existingGitignore
2022
2094
  },
2023
- { provider, model: options.model, language: getLanguage() },
2095
+ {
2096
+ provider,
2097
+ model: options.model,
2098
+ baseUrl: options.baseUrl || getBaseUrl(),
2099
+ language: getLanguage()
2100
+ },
2024
2101
  template || void 0
2025
2102
  );
2026
2103
  spinner.stop();
@@ -2279,7 +2356,7 @@ import chalk14 from "chalk";
2279
2356
  import { Command as Command13 } from "commander";
2280
2357
  import ora10 from "ora";
2281
2358
  import { simpleGit as simpleGit11 } from "simple-git";
2282
- var mergeCommand = new Command13("merge").description("Merge a branch with AI-powered conflict resolution").argument("<branch>", "Branch to merge").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("--no-commit", "Do not auto-commit after resolving").action(async (branch, options) => {
2359
+ var mergeCommand = new Command13("merge").description("Merge a branch with AI-powered conflict resolution").argument("<branch>", "Branch to merge").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("--base-url <url>", "Base URL for API provider").option("--no-commit", "Do not auto-commit after resolving").action(async (branch, options) => {
2283
2360
  const git = simpleGit11();
2284
2361
  const isRepo = await git.checkIsRepo();
2285
2362
  if (!isRepo) {
@@ -2342,7 +2419,12 @@ Merging ${chalk14.cyan(branch)} into ${chalk14.cyan(currentBranch)}...
2342
2419
  oursRef: currentBranch,
2343
2420
  theirsRef: branch
2344
2421
  },
2345
- { provider, model: options.model, language: getLanguage() },
2422
+ {
2423
+ provider,
2424
+ model: options.model,
2425
+ baseUrl: options.baseUrl || getBaseUrl(),
2426
+ language: getLanguage()
2427
+ },
2346
2428
  template || void 0
2347
2429
  );
2348
2430
  spinner.stop();
@@ -2416,7 +2498,7 @@ function findPRTemplate(repoRoot) {
2416
2498
  }
2417
2499
  return findTemplate(repoRoot, "pr");
2418
2500
  }
2419
- var prCommand = new Command14("pr").description("Generate a pull request title and description using AI").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("-b, --base <branch>", "Base branch to compare against (default: main or master)").option("--create", "Create the PR using gh CLI").option("--copy", "Copy the description to clipboard").action(async (options) => {
2501
+ var prCommand = new Command14("pr").description("Generate a pull request title and description using AI").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("--base-url <url>", "Base URL for API provider").option("-b, --base <branch>", "Base branch to compare against (default: main or master)").option("--create", "Create the PR using gh CLI").option("--copy", "Copy the description to clipboard").action(async (options) => {
2420
2502
  const git = simpleGit12();
2421
2503
  const isRepo = await git.checkIsRepo();
2422
2504
  if (!isRepo) {
@@ -2467,7 +2549,12 @@ var prCommand = new Command14("pr").description("Generate a pull request title a
2467
2549
  commits,
2468
2550
  diff
2469
2551
  },
2470
- { provider, model: options.model, language: getLanguage() },
2552
+ {
2553
+ provider,
2554
+ model: options.model,
2555
+ baseUrl: options.baseUrl || getBaseUrl(),
2556
+ language: getLanguage()
2557
+ },
2471
2558
  template || void 0
2472
2559
  );
2473
2560
  spinner.stop();
@@ -2633,7 +2720,7 @@ async function getPRDiff(prNumber) {
2633
2720
  throw err;
2634
2721
  }
2635
2722
  }
2636
- var reviewCommand = new Command15("review").description("Get an AI code review of your changes or a GitHub PR").argument("[pr-number]", "GitHub PR number to review").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("-s, --staged", "Review only staged changes").option("-c, --commit <hash>", "Review a specific commit").option("--json", "Output as JSON").action(async (prNumber, options) => {
2723
+ var reviewCommand = new Command15("review").description("Get an AI code review of your changes or a GitHub PR").argument("[pr-number]", "GitHub PR number to review").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("--base-url <url>", "Base URL for API provider").option("-s, --staged", "Review only staged changes").option("-c, --commit <hash>", "Review a specific commit").option("--json", "Output as JSON").action(async (prNumber, options) => {
2637
2724
  const git = simpleGit13();
2638
2725
  const isRepo = await git.checkIsRepo();
2639
2726
  if (!isRepo) {
@@ -2677,7 +2764,12 @@ ${diff}`;
2677
2764
  const template = findTemplate(repoRoot.trim(), "review");
2678
2765
  const review = await generateCodeReview(
2679
2766
  diff,
2680
- { provider, model: options.model, language: getLanguage() },
2767
+ {
2768
+ provider,
2769
+ model: options.model,
2770
+ baseUrl: options.baseUrl || getBaseUrl(),
2771
+ language: getLanguage()
2772
+ },
2681
2773
  template || void 0
2682
2774
  );
2683
2775
  spinner.stop();
@@ -2749,7 +2841,7 @@ import chalk17 from "chalk";
2749
2841
  import { Command as Command16 } from "commander";
2750
2842
  import ora13 from "ora";
2751
2843
  import { simpleGit as simpleGit14 } from "simple-git";
2752
- var stashCommand = new Command16("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, ollama)").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) => {
2844
+ var stashCommand = new Command16("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, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("--base-url <url>", "Base URL for API provider").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) => {
2753
2845
  const git = simpleGit14();
2754
2846
  const isRepo = await git.checkIsRepo();
2755
2847
  if (!isRepo) {
@@ -2851,7 +2943,12 @@ ${stagedDiff}`;
2851
2943
  const template = findTemplate(repoRoot.trim(), "stash");
2852
2944
  stashName = await generateStashName(
2853
2945
  fullDiff,
2854
- { provider, model: options.model, language: getLanguage() },
2946
+ {
2947
+ provider,
2948
+ model: options.model,
2949
+ baseUrl: options.baseUrl || getBaseUrl(),
2950
+ language: getLanguage()
2951
+ },
2855
2952
  template || void 0
2856
2953
  );
2857
2954
  spinner.stop();
@@ -2870,7 +2967,7 @@ import chalk18 from "chalk";
2870
2967
  import { Command as Command17 } from "commander";
2871
2968
  import ora14 from "ora";
2872
2969
  import { simpleGit as simpleGit15 } from "simple-git";
2873
- var summaryCommand = new Command17("summary").description("Generate a work summary from your commits (for daily/weekly reports)").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").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) => {
2970
+ var summaryCommand = new Command17("summary").description("Generate a work summary from your commits (for daily/weekly reports)").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("--base-url <url>", "Base URL for API provider").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) => {
2874
2971
  const git = simpleGit15();
2875
2972
  const isRepo = await git.checkIsRepo();
2876
2973
  if (!isRepo) {
@@ -2930,7 +3027,12 @@ var summaryCommand = new Command17("summary").description("Generate a work summa
2930
3027
  const template = findTemplate(repoRoot.trim(), "summary");
2931
3028
  const summary = await generateWorkSummary(
2932
3029
  { commits, author, since, until: options.until, diff },
2933
- { provider, model: options.model, language: getLanguage() },
3030
+ {
3031
+ provider,
3032
+ model: options.model,
3033
+ baseUrl: options.baseUrl || getBaseUrl(),
3034
+ language: getLanguage()
3035
+ },
2934
3036
  format,
2935
3037
  template || void 0
2936
3038
  );
@@ -3172,8 +3274,10 @@ To set upstream: git push -u origin ${currentBranch}`));
3172
3274
  });
3173
3275
 
3174
3276
  // src/index.ts
3277
+ var require2 = createRequire2(import.meta.url);
3278
+ var pkg = require2("../package.json");
3175
3279
  var program = new Command19();
3176
- program.name("gut").description("Git Utility Tool - AI-powered git commands").version("0.1.0");
3280
+ program.name("gut").description("Git Utility Tool - AI-powered git commands").version(pkg.version, "-v, --version");
3177
3281
  program.addCommand(cleanupCommand);
3178
3282
  program.addCommand(authCommand);
3179
3283
  program.addCommand(commitCommand);