gut-cli 0.1.18 → 0.1.19
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 +49 -17
- package/dist/index.js +127 -38
- package/dist/index.js.map +1 -1
- package/dist/lib/index.js +17 -2
- package/dist/lib/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -361,6 +361,15 @@ gut config set lang en --local
|
|
|
361
361
|
|
|
362
362
|
# Get current language
|
|
363
363
|
gut config get lang
|
|
364
|
+
|
|
365
|
+
# Open global config folder
|
|
366
|
+
gut config open
|
|
367
|
+
|
|
368
|
+
# Open global templates folder
|
|
369
|
+
gut config open --templates
|
|
370
|
+
|
|
371
|
+
# Open project's .gut/ folder
|
|
372
|
+
gut config open --local
|
|
364
373
|
```
|
|
365
374
|
|
|
366
375
|
**Available settings:**
|
|
@@ -372,12 +381,19 @@ gut config get lang
|
|
|
372
381
|
|
|
373
382
|
### `gut init`
|
|
374
383
|
|
|
375
|
-
Initialize
|
|
384
|
+
Initialize templates for customization (project-level or global).
|
|
376
385
|
|
|
377
386
|
```bash
|
|
378
387
|
# Copy all templates to .gut/ (translates if language is not English)
|
|
379
388
|
gut init
|
|
380
389
|
|
|
390
|
+
# Initialize global templates (~/.config/gut/templates/)
|
|
391
|
+
gut init --global
|
|
392
|
+
|
|
393
|
+
# Initialize and open folder
|
|
394
|
+
gut init --open
|
|
395
|
+
gut init --global --open
|
|
396
|
+
|
|
381
397
|
# Force overwrite existing templates
|
|
382
398
|
gut init --force
|
|
383
399
|
|
|
@@ -388,8 +404,15 @@ gut init --no-translate
|
|
|
388
404
|
gut init --provider openai
|
|
389
405
|
```
|
|
390
406
|
|
|
407
|
+
To open templates folder without initializing, use `gut config open --templates`.
|
|
408
|
+
|
|
391
409
|
Templates are automatically translated to your configured language (set via `gut lang`).
|
|
392
410
|
|
|
411
|
+
**Template precedence:**
|
|
412
|
+
1. Project templates: `.gut/` (highest priority)
|
|
413
|
+
2. Global templates: `~/.config/gut/templates/`
|
|
414
|
+
3. Built-in templates (lowest priority)
|
|
415
|
+
|
|
393
416
|
### `gut gitignore`
|
|
394
417
|
|
|
395
418
|
Generate a .gitignore file by analyzing your project structure.
|
|
@@ -466,26 +489,35 @@ API keys are stored securely using your operating system's native credential sto
|
|
|
466
489
|
|
|
467
490
|
Keys are never stored in plain text files or configuration files. When you run `gut auth login`, the key is encrypted and managed by your OS.
|
|
468
491
|
|
|
469
|
-
##
|
|
492
|
+
## Template Configuration
|
|
493
|
+
|
|
494
|
+
gut supports customizable templates at two levels:
|
|
495
|
+
|
|
496
|
+
**Project templates** (`.gut/`): Repository-specific customizations that apply only to the current project.
|
|
497
|
+
|
|
498
|
+
**Global templates** (`~/.config/gut/templates/`): User-wide defaults that apply across all projects.
|
|
499
|
+
|
|
500
|
+
**Precedence**: Project > Global > Built-in
|
|
470
501
|
|
|
471
|
-
|
|
502
|
+
Each template uses `{{variable}}` syntax for dynamic content.
|
|
472
503
|
|
|
473
504
|
| File | Purpose |
|
|
474
505
|
|------|---------|
|
|
475
|
-
|
|
|
476
|
-
|
|
|
477
|
-
|
|
|
478
|
-
|
|
|
479
|
-
|
|
|
480
|
-
|
|
|
481
|
-
|
|
|
482
|
-
|
|
|
483
|
-
|
|
|
484
|
-
|
|
|
485
|
-
|
|
|
486
|
-
|
|
|
487
|
-
|
|
|
488
|
-
|
|
506
|
+
| `commit.md` | Commit message prompt |
|
|
507
|
+
| `pr.md` | PR description prompt |
|
|
508
|
+
| `branch.md` | Branch naming rules |
|
|
509
|
+
| `checkout.md` | Checkout branch name prompt |
|
|
510
|
+
| `merge.md` | Merge conflict resolution rules |
|
|
511
|
+
| `review.md` | Code review criteria |
|
|
512
|
+
| `explain.md` | Explanation context |
|
|
513
|
+
| `explain-file.md` | File explanation context |
|
|
514
|
+
| `find.md` | Commit search context |
|
|
515
|
+
| `changelog.md` | Changelog format |
|
|
516
|
+
| `stash.md` | Stash name prompt |
|
|
517
|
+
| `summary.md` | Work summary format |
|
|
518
|
+
| `gitignore.md` | Gitignore generation prompt |
|
|
519
|
+
|
|
520
|
+
**Special case**: `.github/pull_request_template.md` is prioritized over `pr.md` for PR descriptions.
|
|
489
521
|
|
|
490
522
|
## Development
|
|
491
523
|
|
package/dist/index.js
CHANGED
|
@@ -290,6 +290,7 @@ import { createOllama } from "ollama-ai-provider";
|
|
|
290
290
|
import { z } from "zod";
|
|
291
291
|
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
292
292
|
import { join as join2, dirname } from "path";
|
|
293
|
+
import { homedir as homedir2 } from "os";
|
|
293
294
|
import { fileURLToPath } from "url";
|
|
294
295
|
|
|
295
296
|
// src/lib/config.ts
|
|
@@ -414,13 +415,27 @@ function loadTemplate(name) {
|
|
|
414
415
|
}
|
|
415
416
|
throw new Error(`Template not found: ${templatePath}`);
|
|
416
417
|
}
|
|
417
|
-
function
|
|
418
|
-
|
|
418
|
+
function getGlobalTemplatesDir() {
|
|
419
|
+
return join2(homedir2(), ".config", "gut", "templates");
|
|
420
|
+
}
|
|
421
|
+
function findGlobalTemplate(templateName) {
|
|
422
|
+
const templatePath = join2(getGlobalTemplatesDir(), `${templateName}.md`);
|
|
419
423
|
if (existsSync2(templatePath)) {
|
|
420
424
|
return readFileSync2(templatePath, "utf-8");
|
|
421
425
|
}
|
|
422
426
|
return null;
|
|
423
427
|
}
|
|
428
|
+
function findTemplate(repoRoot, templateName) {
|
|
429
|
+
const projectTemplatePath = join2(repoRoot, ".gut", `${templateName}.md`);
|
|
430
|
+
if (existsSync2(projectTemplatePath)) {
|
|
431
|
+
return readFileSync2(projectTemplatePath, "utf-8");
|
|
432
|
+
}
|
|
433
|
+
const globalTemplate = findGlobalTemplate(templateName);
|
|
434
|
+
if (globalTemplate) {
|
|
435
|
+
return globalTemplate;
|
|
436
|
+
}
|
|
437
|
+
return null;
|
|
438
|
+
}
|
|
424
439
|
function applyTemplate(userTemplate, templateName, variables) {
|
|
425
440
|
const langInstruction = getLanguageInstruction(getLanguage());
|
|
426
441
|
let result = userTemplate || loadTemplate(templateName);
|
|
@@ -852,14 +867,14 @@ var commitCommand = new Command3("commit").description("Generate a commit messag
|
|
|
852
867
|
console.log(chalk3.green("\u2713 Committed successfully"));
|
|
853
868
|
} else if (answer.toLowerCase() === "e") {
|
|
854
869
|
console.log(chalk3.gray("Opening editor..."));
|
|
855
|
-
const { execSync:
|
|
870
|
+
const { execSync: execSync9 } = await import("child_process");
|
|
856
871
|
const editor = process.env.EDITOR || process.env.VISUAL || "vi";
|
|
857
872
|
const fs2 = await import("fs");
|
|
858
873
|
const os = await import("os");
|
|
859
874
|
const path2 = await import("path");
|
|
860
875
|
const tmpFile = path2.join(os.tmpdir(), "gut-commit-msg.txt");
|
|
861
876
|
fs2.writeFileSync(tmpFile, message);
|
|
862
|
-
|
|
877
|
+
execSync9(`${editor} "${tmpFile}"`, { stdio: "inherit" });
|
|
863
878
|
const editedMessage = fs2.readFileSync(tmpFile, "utf-8").trim();
|
|
864
879
|
fs2.unlinkSync(tmpFile);
|
|
865
880
|
if (editedMessage) {
|
|
@@ -2197,9 +2212,9 @@ var summaryCommand = new Command14("summary").description("Generate a work summa
|
|
|
2197
2212
|
const output = options.markdown ? formatMarkdown(summary, author, since, options.until) : null;
|
|
2198
2213
|
if (options.copy) {
|
|
2199
2214
|
const textToCopy = output || formatMarkdown(summary, author, since, options.until);
|
|
2200
|
-
const { execSync:
|
|
2215
|
+
const { execSync: execSync9 } = await import("child_process");
|
|
2201
2216
|
try {
|
|
2202
|
-
|
|
2217
|
+
execSync9("pbcopy", { input: textToCopy });
|
|
2203
2218
|
console.log(chalk15.green("Summary copied to clipboard!"));
|
|
2204
2219
|
console.log();
|
|
2205
2220
|
} catch {
|
|
@@ -2315,6 +2330,16 @@ function printSummary(summary, author, since, until) {
|
|
|
2315
2330
|
// src/commands/config.ts
|
|
2316
2331
|
import { Command as Command15 } from "commander";
|
|
2317
2332
|
import chalk16 from "chalk";
|
|
2333
|
+
import { execSync as execSync7 } from "child_process";
|
|
2334
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync2 } from "fs";
|
|
2335
|
+
import { join as join5 } from "path";
|
|
2336
|
+
import { homedir as homedir3 } from "os";
|
|
2337
|
+
import { simpleGit as simpleGit14 } from "simple-git";
|
|
2338
|
+
function openFolder(path2) {
|
|
2339
|
+
const platform = process.platform;
|
|
2340
|
+
const cmd = platform === "darwin" ? "open" : platform === "win32" ? 'start ""' : "xdg-open";
|
|
2341
|
+
execSync7(`${cmd} "${path2}"`);
|
|
2342
|
+
}
|
|
2318
2343
|
var configCommand = new Command15("config").description("Manage gut configuration");
|
|
2319
2344
|
configCommand.command("set <key> <value>").description("Set a configuration value").option("--local", "Set for current repository only").action((key, value, options) => {
|
|
2320
2345
|
if (key === "lang") {
|
|
@@ -2363,6 +2388,39 @@ configCommand.command("list").description("List all configuration values").actio
|
|
|
2363
2388
|
console.log(chalk16.gray("Local config: .gut/config.json"));
|
|
2364
2389
|
}
|
|
2365
2390
|
});
|
|
2391
|
+
configCommand.command("open").description("Open configuration or templates folder").option("-t, --templates", "Open templates folder instead of config").option("-g, --global", "Open global folder (default)").option("-l, --local", "Open local/project folder").action(async (options) => {
|
|
2392
|
+
const git = simpleGit14();
|
|
2393
|
+
const isLocal = options.local === true;
|
|
2394
|
+
let targetPath;
|
|
2395
|
+
if (isLocal) {
|
|
2396
|
+
const isRepo = await git.checkIsRepo();
|
|
2397
|
+
if (!isRepo) {
|
|
2398
|
+
console.error(chalk16.red("Error: Not a git repository"));
|
|
2399
|
+
console.error(chalk16.gray("Use --global to open global config folder"));
|
|
2400
|
+
process.exit(1);
|
|
2401
|
+
}
|
|
2402
|
+
const repoRoot = await git.revparse(["--show-toplevel"]).catch(() => process.cwd());
|
|
2403
|
+
targetPath = join5(repoRoot.trim(), ".gut");
|
|
2404
|
+
} else {
|
|
2405
|
+
if (options.templates) {
|
|
2406
|
+
targetPath = join5(homedir3(), ".config", "gut", "templates");
|
|
2407
|
+
} else {
|
|
2408
|
+
targetPath = join5(homedir3(), ".config", "gut");
|
|
2409
|
+
}
|
|
2410
|
+
}
|
|
2411
|
+
if (!existsSync5(targetPath)) {
|
|
2412
|
+
mkdirSync2(targetPath, { recursive: true });
|
|
2413
|
+
console.log(chalk16.green(`Created ${targetPath}`));
|
|
2414
|
+
}
|
|
2415
|
+
try {
|
|
2416
|
+
openFolder(targetPath);
|
|
2417
|
+
console.log(chalk16.green(`Opened: ${targetPath}`));
|
|
2418
|
+
} catch (error) {
|
|
2419
|
+
console.error(chalk16.red(`Failed to open folder: ${targetPath}`));
|
|
2420
|
+
console.error(chalk16.gray(error.message));
|
|
2421
|
+
process.exit(1);
|
|
2422
|
+
}
|
|
2423
|
+
});
|
|
2366
2424
|
|
|
2367
2425
|
// src/commands/lang.ts
|
|
2368
2426
|
import { Command as Command16 } from "commander";
|
|
@@ -2395,17 +2453,24 @@ var langCommand = new Command16("lang").description("Set or show output language
|
|
|
2395
2453
|
import { Command as Command17 } from "commander";
|
|
2396
2454
|
import chalk18 from "chalk";
|
|
2397
2455
|
import ora14 from "ora";
|
|
2398
|
-
import { simpleGit as
|
|
2399
|
-
import { existsSync as
|
|
2400
|
-
import { join as
|
|
2456
|
+
import { simpleGit as simpleGit15 } from "simple-git";
|
|
2457
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync6, writeFileSync as writeFileSync3 } from "fs";
|
|
2458
|
+
import { join as join6, dirname as dirname2 } from "path";
|
|
2459
|
+
import { homedir as homedir4 } from "os";
|
|
2401
2460
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
2461
|
+
import { execSync as execSync8 } from "child_process";
|
|
2402
2462
|
import { generateText as generateText2 } from "ai";
|
|
2403
2463
|
import { createGoogleGenerativeAI as createGoogleGenerativeAI2 } from "@ai-sdk/google";
|
|
2404
2464
|
import { createOpenAI as createOpenAI2 } from "@ai-sdk/openai";
|
|
2405
2465
|
import { createAnthropic as createAnthropic2 } from "@ai-sdk/anthropic";
|
|
2466
|
+
function openFolder2(path2) {
|
|
2467
|
+
const platform = process.platform;
|
|
2468
|
+
const cmd = platform === "darwin" ? "open" : platform === "win32" ? 'start ""' : "xdg-open";
|
|
2469
|
+
execSync8(`${cmd} "${path2}"`);
|
|
2470
|
+
}
|
|
2406
2471
|
var __filename2 = fileURLToPath2(import.meta.url);
|
|
2407
2472
|
var __dirname2 = dirname2(__filename2);
|
|
2408
|
-
var GUT_ROOT2 =
|
|
2473
|
+
var GUT_ROOT2 = join6(__dirname2, "..");
|
|
2409
2474
|
var TEMPLATE_FILES = [
|
|
2410
2475
|
"branch.md",
|
|
2411
2476
|
"changelog.md",
|
|
@@ -2468,20 +2533,28 @@ Translated template:`
|
|
|
2468
2533
|
});
|
|
2469
2534
|
return text.trim();
|
|
2470
2535
|
}
|
|
2471
|
-
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) => {
|
|
2472
|
-
const
|
|
2473
|
-
const
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2536
|
+
var initCommand = new Command17("init").description("Initialize .gut/ templates in your project or globally").option("-p, --provider <provider>", "AI provider for translation (gemini, openai, anthropic)", "gemini").option("-f, --force", "Overwrite existing templates").option("-g, --global", "Initialize templates globally (~/.config/gut/templates/)").option("-o, --open", "Open the templates folder (can be used alone)").option("--no-translate", "Skip translation even if language is not English").action(async (options) => {
|
|
2537
|
+
const isGlobal = options.global === true;
|
|
2538
|
+
const git = simpleGit15();
|
|
2539
|
+
let targetDir;
|
|
2540
|
+
if (isGlobal) {
|
|
2541
|
+
targetDir = join6(homedir4(), ".config", "gut", "templates");
|
|
2542
|
+
} else {
|
|
2543
|
+
const isRepo = await git.checkIsRepo();
|
|
2544
|
+
if (!isRepo) {
|
|
2545
|
+
console.error(chalk18.red("Error: Not a git repository"));
|
|
2546
|
+
console.error(chalk18.gray("Use --global to initialize templates globally"));
|
|
2547
|
+
process.exit(1);
|
|
2548
|
+
}
|
|
2549
|
+
const repoRoot = await git.revparse(["--show-toplevel"]).catch(() => process.cwd());
|
|
2550
|
+
targetDir = join6(repoRoot.trim(), ".gut");
|
|
2477
2551
|
}
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
const sourceDir = join5(GUT_ROOT2, ".gut");
|
|
2481
|
-
if (!existsSync5(targetDir)) {
|
|
2482
|
-
mkdirSync2(targetDir, { recursive: true });
|
|
2552
|
+
if (!existsSync6(targetDir)) {
|
|
2553
|
+
mkdirSync3(targetDir, { recursive: true });
|
|
2483
2554
|
console.log(chalk18.green(`Created ${targetDir}`));
|
|
2484
2555
|
}
|
|
2556
|
+
console.log(chalk18.blue(isGlobal ? "Initializing global templates...\n" : "Initializing project templates...\n"));
|
|
2557
|
+
const sourceDir = join6(GUT_ROOT2, ".gut");
|
|
2485
2558
|
const lang = getLanguage();
|
|
2486
2559
|
const needsTranslation = options.translate !== false && lang !== "en";
|
|
2487
2560
|
const provider = options.provider.toLowerCase();
|
|
@@ -2493,12 +2566,12 @@ var initCommand = new Command17("init").description("Initialize .gut/ templates
|
|
|
2493
2566
|
let copied = 0;
|
|
2494
2567
|
let skipped = 0;
|
|
2495
2568
|
for (const filename of TEMPLATE_FILES) {
|
|
2496
|
-
const sourcePath =
|
|
2497
|
-
const targetPath =
|
|
2498
|
-
if (!
|
|
2569
|
+
const sourcePath = join6(sourceDir, filename);
|
|
2570
|
+
const targetPath = join6(targetDir, filename);
|
|
2571
|
+
if (!existsSync6(sourcePath)) {
|
|
2499
2572
|
continue;
|
|
2500
2573
|
}
|
|
2501
|
-
if (
|
|
2574
|
+
if (existsSync6(targetPath) && !options.force) {
|
|
2502
2575
|
console.log(chalk18.gray(` Skipped: ${filename} (already exists)`));
|
|
2503
2576
|
skipped++;
|
|
2504
2577
|
continue;
|
|
@@ -2522,21 +2595,37 @@ var initCommand = new Command17("init").description("Initialize .gut/ templates
|
|
|
2522
2595
|
}
|
|
2523
2596
|
console.log();
|
|
2524
2597
|
if (copied > 0) {
|
|
2525
|
-
|
|
2598
|
+
const location = isGlobal ? "~/.config/gut/templates/" : ".gut/";
|
|
2599
|
+
console.log(chalk18.green(`\u2713 ${copied} template(s) initialized in ${location}`));
|
|
2526
2600
|
}
|
|
2527
2601
|
if (skipped > 0) {
|
|
2528
2602
|
console.log(chalk18.gray(` ${skipped} template(s) skipped (use --force to overwrite)`));
|
|
2529
2603
|
}
|
|
2530
|
-
|
|
2604
|
+
if (isGlobal) {
|
|
2605
|
+
console.log(chalk18.gray("\nGlobal templates will be used as fallback for all projects."));
|
|
2606
|
+
console.log(chalk18.gray("Project-level templates (.gut/) take priority over global templates."));
|
|
2607
|
+
} else {
|
|
2608
|
+
console.log(chalk18.gray("\nYou can now customize these templates for your project."));
|
|
2609
|
+
}
|
|
2610
|
+
if (options.open) {
|
|
2611
|
+
try {
|
|
2612
|
+
openFolder2(targetDir);
|
|
2613
|
+
console.log(chalk18.green(`
|
|
2614
|
+
Opened: ${targetDir}`));
|
|
2615
|
+
} catch (error) {
|
|
2616
|
+
console.error(chalk18.red(`
|
|
2617
|
+
Failed to open folder: ${targetDir}`));
|
|
2618
|
+
}
|
|
2619
|
+
}
|
|
2531
2620
|
});
|
|
2532
2621
|
|
|
2533
2622
|
// src/commands/gitignore.ts
|
|
2534
2623
|
import { Command as Command18 } from "commander";
|
|
2535
2624
|
import chalk19 from "chalk";
|
|
2536
2625
|
import ora15 from "ora";
|
|
2537
|
-
import { simpleGit as
|
|
2538
|
-
import { readdirSync as readdirSync2, readFileSync as readFileSync7, existsSync as
|
|
2539
|
-
import { join as
|
|
2626
|
+
import { simpleGit as simpleGit16 } from "simple-git";
|
|
2627
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync7, existsSync as existsSync7, writeFileSync as writeFileSync4 } from "fs";
|
|
2628
|
+
import { join as join7 } from "path";
|
|
2540
2629
|
var CONFIG_FILES = [
|
|
2541
2630
|
// JavaScript/TypeScript
|
|
2542
2631
|
"package.json",
|
|
@@ -2589,7 +2678,7 @@ function getFiles(dir, maxDepth = 3, currentDepth = 0) {
|
|
|
2589
2678
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "vendor" || entry.name === "target" || entry.name === "__pycache__" || entry.name === "venv" || entry.name === ".venv") {
|
|
2590
2679
|
continue;
|
|
2591
2680
|
}
|
|
2592
|
-
const fullPath =
|
|
2681
|
+
const fullPath = join7(dir, entry.name);
|
|
2593
2682
|
if (entry.isDirectory()) {
|
|
2594
2683
|
files.push(entry.name + "/");
|
|
2595
2684
|
const subFiles = getFiles(fullPath, maxDepth, currentDepth + 1);
|
|
@@ -2611,15 +2700,15 @@ function findConfigFiles(repoRoot) {
|
|
|
2611
2700
|
const entries = readdirSync2(repoRoot);
|
|
2612
2701
|
for (const entry of entries) {
|
|
2613
2702
|
if (entry.endsWith(ext)) {
|
|
2614
|
-
const content = readFileSync7(
|
|
2703
|
+
const content = readFileSync7(join7(repoRoot, entry), "utf-8");
|
|
2615
2704
|
found.set(entry, content.slice(0, 2e3));
|
|
2616
2705
|
}
|
|
2617
2706
|
}
|
|
2618
2707
|
} catch {
|
|
2619
2708
|
}
|
|
2620
2709
|
} else {
|
|
2621
|
-
const filePath =
|
|
2622
|
-
if (
|
|
2710
|
+
const filePath = join7(repoRoot, configFile);
|
|
2711
|
+
if (existsSync7(filePath)) {
|
|
2623
2712
|
try {
|
|
2624
2713
|
const content = readFileSync7(filePath, "utf-8");
|
|
2625
2714
|
found.set(configFile, content.slice(0, 2e3));
|
|
@@ -2631,7 +2720,7 @@ function findConfigFiles(repoRoot) {
|
|
|
2631
2720
|
return found;
|
|
2632
2721
|
}
|
|
2633
2722
|
var gitignoreCommand = new Command18("gitignore").description("Generate .gitignore from current codebase").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic)", "gemini").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) => {
|
|
2634
|
-
const git =
|
|
2723
|
+
const git = simpleGit16();
|
|
2635
2724
|
const repoRoot = await git.revparse(["--show-toplevel"]).catch(() => process.cwd());
|
|
2636
2725
|
const root = repoRoot.trim();
|
|
2637
2726
|
const provider = options.provider.toLowerCase();
|
|
@@ -2642,9 +2731,9 @@ var gitignoreCommand = new Command18("gitignore").description("Generate .gitigno
|
|
|
2642
2731
|
const spinner = ora15("Analyzing project structure...").start();
|
|
2643
2732
|
const files = getFiles(root);
|
|
2644
2733
|
const configFiles = findConfigFiles(root);
|
|
2645
|
-
const gitignorePath =
|
|
2734
|
+
const gitignorePath = join7(root, options.output);
|
|
2646
2735
|
let existingGitignore;
|
|
2647
|
-
if (
|
|
2736
|
+
if (existsSync7(gitignorePath)) {
|
|
2648
2737
|
existingGitignore = readFileSync7(gitignorePath, "utf-8");
|
|
2649
2738
|
}
|
|
2650
2739
|
let configFilesStr = "";
|
|
@@ -2679,7 +2768,7 @@ ${content}
|
|
|
2679
2768
|
console.log(gitignoreContent);
|
|
2680
2769
|
console.log(chalk19.gray("\u2500".repeat(50)));
|
|
2681
2770
|
console.log();
|
|
2682
|
-
if (
|
|
2771
|
+
if (existsSync7(gitignorePath) && !options.yes) {
|
|
2683
2772
|
const readline = await import("readline");
|
|
2684
2773
|
const rl = readline.createInterface({
|
|
2685
2774
|
input: process.stdin,
|