gut-cli 0.1.12 → 0.1.14
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/.gut/branch.md +27 -0
- package/.gut/changelog.md +38 -0
- package/.gut/checkout.md +29 -0
- package/.gut/commit.md +22 -0
- package/.gut/config.json +3 -0
- package/.gut/explain-file.md +30 -0
- package/.gut/explain.md +31 -0
- package/.gut/find.md +25 -0
- package/.gut/gitignore.md +42 -0
- package/.gut/merge.md +30 -0
- package/.gut/pr.md +36 -0
- package/.gut/review.md +24 -0
- package/.gut/stash.md +20 -0
- package/.gut/summary.md +38 -0
- package/README.md +28 -0
- package/dist/index.js +190 -2
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/.gut/branch.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
You are an expert at creating git branch names.
|
|
2
|
+
|
|
3
|
+
Generate a clean, descriptive branch name for the following:
|
|
4
|
+
|
|
5
|
+
## Description
|
|
6
|
+
|
|
7
|
+
{{description}}
|
|
8
|
+
|
|
9
|
+
{{#type}}
|
|
10
|
+
Branch type: {{type}}
|
|
11
|
+
{{/type}}
|
|
12
|
+
|
|
13
|
+
{{#issue}}
|
|
14
|
+
Include issue number: {{issue}}
|
|
15
|
+
{{/issue}}
|
|
16
|
+
|
|
17
|
+
## Rules
|
|
18
|
+
|
|
19
|
+
- Use format: `<type>/<short-description>`
|
|
20
|
+
- Types: feature, fix, hotfix, chore, refactor, docs, test
|
|
21
|
+
- Use kebab-case for description
|
|
22
|
+
- Keep it short (under 50 chars total)
|
|
23
|
+
- No special characters except hyphens and slashes
|
|
24
|
+
|
|
25
|
+
## Output
|
|
26
|
+
|
|
27
|
+
Respond with ONLY the branch name, nothing else.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
You are an expert at writing release notes and changelogs.
|
|
2
|
+
|
|
3
|
+
Generate a changelog entry for changes from {{fromRef}} to {{toRef}}.
|
|
4
|
+
|
|
5
|
+
Today's date is {{todayDate}}. Use this date for the release date.
|
|
6
|
+
|
|
7
|
+
## Commits
|
|
8
|
+
|
|
9
|
+
{{commits}}
|
|
10
|
+
|
|
11
|
+
## Diff summary
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
{{diff}}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Format
|
|
18
|
+
|
|
19
|
+
Use Keep a Changelog format (https://keepachangelog.com/):
|
|
20
|
+
- Group changes by: Added, Changed, Deprecated, Removed, Fixed, Security
|
|
21
|
+
- Each item should be a concise description of the change
|
|
22
|
+
- Use past tense
|
|
23
|
+
|
|
24
|
+
## Focus on
|
|
25
|
+
|
|
26
|
+
- User-facing changes and improvements
|
|
27
|
+
- Bug fixes and their impact
|
|
28
|
+
- Breaking changes (highlight these)
|
|
29
|
+
- Group related changes together
|
|
30
|
+
- Write for end users, not developers (unless it's a library)
|
|
31
|
+
|
|
32
|
+
## Output
|
|
33
|
+
|
|
34
|
+
Respond with a JSON object containing:
|
|
35
|
+
- version: Version string if detected (optional)
|
|
36
|
+
- date: Release date in YYYY-MM-DD format
|
|
37
|
+
- sections: Array of { type, items[] }
|
|
38
|
+
- summary: Brief summary of this release (optional)
|
package/.gut/checkout.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Checkout Branch Name Generation
|
|
2
|
+
|
|
3
|
+
You are an expert at creating git branch names.
|
|
4
|
+
|
|
5
|
+
Analyze the following git diff and generate a clean, descriptive branch name that captures the essence of the changes.
|
|
6
|
+
|
|
7
|
+
## Git diff
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
{{diff}}
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Branch Naming Convention
|
|
14
|
+
|
|
15
|
+
- Use format: `<type>/<short-description>`
|
|
16
|
+
- Types: feature, fix, hotfix, chore, refactor, docs, test
|
|
17
|
+
- Use kebab-case for description
|
|
18
|
+
- Keep it short (under 50 chars total)
|
|
19
|
+
- No special characters except hyphens and slashes
|
|
20
|
+
|
|
21
|
+
## Focus on
|
|
22
|
+
|
|
23
|
+
- The main purpose of the changes
|
|
24
|
+
- Whether it's a feature, fix, refactor, etc.
|
|
25
|
+
- Key files or functionality being modified
|
|
26
|
+
|
|
27
|
+
## Output
|
|
28
|
+
|
|
29
|
+
Respond with ONLY the branch name, nothing else.
|
package/.gut/commit.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
You are an expert at writing git commit messages.
|
|
2
|
+
|
|
3
|
+
Analyze the following git diff and generate a concise, meaningful commit message.
|
|
4
|
+
|
|
5
|
+
## Git diff
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
{{diff}}
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Rules
|
|
12
|
+
|
|
13
|
+
- Use format: `<type>(<scope>): <description>`
|
|
14
|
+
- Types: feat, fix, docs, style, refactor, perf, test, chore, build, ci
|
|
15
|
+
- Scope is optional but helpful
|
|
16
|
+
- Description should be lowercase, imperative mood, no period at end
|
|
17
|
+
- Keep the first line under 72 characters
|
|
18
|
+
- If changes are complex, add a blank line and bullet points for details
|
|
19
|
+
|
|
20
|
+
## Output
|
|
21
|
+
|
|
22
|
+
Respond with ONLY the commit message, nothing else.
|
package/.gut/config.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
You are an expert at explaining code in a clear and insightful way.
|
|
2
|
+
|
|
3
|
+
Analyze the following file and explain what it does, its purpose, and its role in a project.
|
|
4
|
+
|
|
5
|
+
## File
|
|
6
|
+
|
|
7
|
+
Path: {{filePath}}
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
{{content}}
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Focus on
|
|
14
|
+
|
|
15
|
+
- What this file does (main functionality)
|
|
16
|
+
- Its purpose and role in the codebase
|
|
17
|
+
- Key functions, classes, or components it defines
|
|
18
|
+
- Dependencies and what it interacts with
|
|
19
|
+
- Any important patterns or architecture decisions
|
|
20
|
+
|
|
21
|
+
## Output
|
|
22
|
+
|
|
23
|
+
Explain in a way that helps someone quickly understand this file's purpose and how it fits into the larger codebase.
|
|
24
|
+
|
|
25
|
+
Respond with a JSON object containing:
|
|
26
|
+
- summary: One-line summary
|
|
27
|
+
- purpose: The purpose and role of this code
|
|
28
|
+
- changes: Array of { file, description }
|
|
29
|
+
- impact: What impact or role this has in the project
|
|
30
|
+
- notes: Important considerations or caveats (optional)
|
package/.gut/explain.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
You are an expert at explaining code changes in a clear and insightful way.
|
|
2
|
+
|
|
3
|
+
Analyze the following {{targetType}} and provide a comprehensive explanation.
|
|
4
|
+
|
|
5
|
+
## Context
|
|
6
|
+
|
|
7
|
+
{{context}}
|
|
8
|
+
|
|
9
|
+
## Diff
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
{{diff}}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Focus on
|
|
16
|
+
|
|
17
|
+
- What the changes accomplish (not just what files changed)
|
|
18
|
+
- WHY these changes were likely made
|
|
19
|
+
- The broader context and purpose
|
|
20
|
+
- Any important implications or side effects
|
|
21
|
+
|
|
22
|
+
## Output
|
|
23
|
+
|
|
24
|
+
Explain in a way that helps someone understand not just the "what" but the "why" behind these changes.
|
|
25
|
+
|
|
26
|
+
Respond with a JSON object containing:
|
|
27
|
+
- summary: One-line summary
|
|
28
|
+
- purpose: The purpose and role of this code
|
|
29
|
+
- changes: Array of { file, description }
|
|
30
|
+
- impact: What impact or role this has in the project
|
|
31
|
+
- notes: Important considerations or caveats (optional)
|
package/.gut/find.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
You are an expert at understanding git history and finding relevant commits.
|
|
2
|
+
|
|
3
|
+
The user is looking for commits related to: "{{query}}"
|
|
4
|
+
|
|
5
|
+
## Commits to search
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
{{commits}}
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Instructions
|
|
12
|
+
|
|
13
|
+
Find the commits that best match the user's query. Consider:
|
|
14
|
+
- Commit messages that mention similar concepts
|
|
15
|
+
- Related features, bug fixes, or changes
|
|
16
|
+
- Semantic similarity (e.g., "login" matches "authentication")
|
|
17
|
+
|
|
18
|
+
Return up to {{maxResults}} matching commits, ordered by relevance (most relevant first).
|
|
19
|
+
Only include commits that actually match the query - if none match well, return an empty array.
|
|
20
|
+
|
|
21
|
+
## Output
|
|
22
|
+
|
|
23
|
+
Respond with a JSON object containing:
|
|
24
|
+
- matches: Array of { hash, reason }
|
|
25
|
+
- summary: Brief summary of the search results (optional)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
You are an expert at creating .gitignore files.
|
|
2
|
+
|
|
3
|
+
Analyze the following project structure and configuration files to generate an appropriate .gitignore file.
|
|
4
|
+
|
|
5
|
+
## Project Structure
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
{{files}}
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
{{#configFiles}}
|
|
12
|
+
## Detected Config Files
|
|
13
|
+
|
|
14
|
+
{{configFiles}}
|
|
15
|
+
{{/configFiles}}
|
|
16
|
+
|
|
17
|
+
{{#existingGitignore}}
|
|
18
|
+
## Existing .gitignore
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
{{existingGitignore}}
|
|
22
|
+
```
|
|
23
|
+
{{/existingGitignore}}
|
|
24
|
+
|
|
25
|
+
## Rules
|
|
26
|
+
|
|
27
|
+
- Detect the language/framework being used (Node.js, Python, Go, Rust, Java, Ruby, PHP, .NET, etc.)
|
|
28
|
+
- Include common ignore patterns for the detected stack
|
|
29
|
+
- Include OS-specific files (.DS_Store, Thumbs.db, etc.)
|
|
30
|
+
- Include IDE/editor files (.vscode/, .idea/, *.swp, etc.)
|
|
31
|
+
- Include environment files (.env, .env.local, etc.)
|
|
32
|
+
- Include build outputs and dependencies based on detected stack
|
|
33
|
+
- Include log files and temporary files
|
|
34
|
+
- Do NOT ignore files that should be tracked (source code, configs, etc.)
|
|
35
|
+
- Keep the file organized with comments for each section
|
|
36
|
+
{{#existingGitignore}}
|
|
37
|
+
- Preserve any project-specific patterns from the existing .gitignore
|
|
38
|
+
{{/existingGitignore}}
|
|
39
|
+
|
|
40
|
+
## Output
|
|
41
|
+
|
|
42
|
+
Respond with ONLY the .gitignore content, nothing else. Include section comments for clarity.
|
package/.gut/merge.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
You are an expert at resolving git merge conflicts intelligently.
|
|
2
|
+
|
|
3
|
+
Analyze the following conflicted file and provide a resolution.
|
|
4
|
+
|
|
5
|
+
## Context
|
|
6
|
+
|
|
7
|
+
- File: {{filename}}
|
|
8
|
+
- Merging: {{theirsRef}} into {{oursRef}}
|
|
9
|
+
|
|
10
|
+
## Conflicted content
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
{{content}}
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Rules
|
|
17
|
+
|
|
18
|
+
- Understand the intent of both changes
|
|
19
|
+
- Combine changes when both are valid additions
|
|
20
|
+
- Choose the more complete/correct version when they conflict
|
|
21
|
+
- Preserve all necessary functionality
|
|
22
|
+
- The resolved content should be valid, working code
|
|
23
|
+
- Do NOT include conflict markers (<<<<<<, =======, >>>>>>)
|
|
24
|
+
|
|
25
|
+
## Output
|
|
26
|
+
|
|
27
|
+
Respond with a JSON object containing:
|
|
28
|
+
- resolvedContent: The resolved file content
|
|
29
|
+
- explanation: Brief explanation of how the conflict was resolved
|
|
30
|
+
- strategy: "ours" | "theirs" | "combined" | "rewritten"
|
package/.gut/pr.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
You are an expert at writing pull request descriptions.
|
|
2
|
+
|
|
3
|
+
Generate a clear and informative PR title and description based on the following information.
|
|
4
|
+
|
|
5
|
+
## Context
|
|
6
|
+
|
|
7
|
+
- Branch: {{currentBranch}} -> {{baseBranch}}
|
|
8
|
+
- Commits:
|
|
9
|
+
{{commits}}
|
|
10
|
+
|
|
11
|
+
## Diff summary
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
{{diff}}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Rules for title
|
|
18
|
+
|
|
19
|
+
- Title should be concise (under 72 chars), start with a verb
|
|
20
|
+
|
|
21
|
+
## Rules for description
|
|
22
|
+
|
|
23
|
+
- Description should have:
|
|
24
|
+
- ## Summary section with 2-3 bullet points
|
|
25
|
+
- ## Changes section listing key modifications
|
|
26
|
+
- ## Test Plan section (suggest what to test)
|
|
27
|
+
|
|
28
|
+
## Output
|
|
29
|
+
|
|
30
|
+
Respond in JSON format:
|
|
31
|
+
```json
|
|
32
|
+
{
|
|
33
|
+
"title": "...",
|
|
34
|
+
"body": "..."
|
|
35
|
+
}
|
|
36
|
+
```
|
package/.gut/review.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
You are an expert code reviewer. Analyze the following git diff and provide a structured review.
|
|
2
|
+
|
|
3
|
+
## Git diff
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
{{diff}}
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Focus on
|
|
10
|
+
|
|
11
|
+
- Bugs and potential issues
|
|
12
|
+
- Security vulnerabilities
|
|
13
|
+
- Performance concerns
|
|
14
|
+
- Code style and best practices
|
|
15
|
+
- Suggestions for improvement
|
|
16
|
+
|
|
17
|
+
## Output
|
|
18
|
+
|
|
19
|
+
Be constructive and specific. Include line numbers when possible.
|
|
20
|
+
|
|
21
|
+
Respond with a JSON object containing:
|
|
22
|
+
- summary: Brief overall assessment
|
|
23
|
+
- issues: Array of { severity: "critical"|"warning"|"suggestion", file, line?, message, suggestion? }
|
|
24
|
+
- positives: Array of good practices observed
|
package/.gut/stash.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
You are an expert at summarizing code changes.
|
|
2
|
+
|
|
3
|
+
Generate a short, descriptive stash name for the following changes.
|
|
4
|
+
|
|
5
|
+
## Diff
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
{{diff}}
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Rules
|
|
12
|
+
|
|
13
|
+
- Start with "WIP: " prefix
|
|
14
|
+
- Keep it under 50 characters total
|
|
15
|
+
- Be specific about what the changes do
|
|
16
|
+
- Use present tense
|
|
17
|
+
|
|
18
|
+
## Output
|
|
19
|
+
|
|
20
|
+
Respond with ONLY the stash name, nothing else.
|
package/.gut/summary.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
You are an expert at writing work summaries and reports.
|
|
2
|
+
|
|
3
|
+
Generate a clear, professional work summary for the following git activity.
|
|
4
|
+
|
|
5
|
+
## Context
|
|
6
|
+
|
|
7
|
+
- Author: {{author}}
|
|
8
|
+
- Period: {{period}}
|
|
9
|
+
- Format: {{format}}
|
|
10
|
+
|
|
11
|
+
## Commits
|
|
12
|
+
|
|
13
|
+
{{commits}}
|
|
14
|
+
|
|
15
|
+
{{#diff}}
|
|
16
|
+
## Diff summary
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
{{diff}}
|
|
20
|
+
```
|
|
21
|
+
{{/diff}}
|
|
22
|
+
|
|
23
|
+
## Focus on
|
|
24
|
+
|
|
25
|
+
- What was accomplished (not just listing commits)
|
|
26
|
+
- Group related work together
|
|
27
|
+
- Highlight important achievements
|
|
28
|
+
- Use clear, non-technical language where possible
|
|
29
|
+
- Make it suitable for sharing with team or manager
|
|
30
|
+
|
|
31
|
+
## Output
|
|
32
|
+
|
|
33
|
+
Respond with a JSON object containing:
|
|
34
|
+
- title: One-line title for the summary
|
|
35
|
+
- overview: Brief overview of what was accomplished
|
|
36
|
+
- highlights: Array of key accomplishments
|
|
37
|
+
- details: Array of { category, items[] }
|
|
38
|
+
- stats: { commits, filesChanged?, additions?, deletions? } (optional)
|
package/README.md
CHANGED
|
@@ -35,6 +35,7 @@ npm install -g gut-cli
|
|
|
35
35
|
| `gut config` | Manage configuration (language, etc.) |
|
|
36
36
|
| `gut lang` | Set or show output language |
|
|
37
37
|
| `gut init` | Initialize .gut/ templates in your project |
|
|
38
|
+
| `gut gitignore` | Generate .gitignore from codebase |
|
|
38
39
|
|
|
39
40
|
### `gut commit`
|
|
40
41
|
|
|
@@ -389,6 +390,32 @@ gut init --provider openai
|
|
|
389
390
|
|
|
390
391
|
Templates are automatically translated to your configured language (set via `gut lang`).
|
|
391
392
|
|
|
393
|
+
### `gut gitignore`
|
|
394
|
+
|
|
395
|
+
Generate a .gitignore file by analyzing your project structure.
|
|
396
|
+
|
|
397
|
+
```bash
|
|
398
|
+
# Generate .gitignore (prompts before overwriting)
|
|
399
|
+
gut gitignore
|
|
400
|
+
|
|
401
|
+
# Auto-overwrite without confirmation
|
|
402
|
+
gut gitignore --yes
|
|
403
|
+
|
|
404
|
+
# Print to stdout instead of file
|
|
405
|
+
gut gitignore --stdout
|
|
406
|
+
|
|
407
|
+
# Use specific provider
|
|
408
|
+
gut gitignore --provider openai
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
**How it works:**
|
|
412
|
+
- Scans your project structure (files and directories)
|
|
413
|
+
- Detects config files (package.json, Cargo.toml, go.mod, pyproject.toml, etc.)
|
|
414
|
+
- Identifies the language/framework stack
|
|
415
|
+
- Generates appropriate ignore patterns
|
|
416
|
+
|
|
417
|
+
**Template Support**: Create `.gut/gitignore.md` to customize the generation prompt.
|
|
418
|
+
|
|
392
419
|
### `gut cleanup`
|
|
393
420
|
|
|
394
421
|
Delete merged branches safely.
|
|
@@ -457,6 +484,7 @@ gut looks for template files in your repository's `.gut/` folder. Each template
|
|
|
457
484
|
| `.gut/changelog.md` | Changelog format |
|
|
458
485
|
| `.gut/stash.md` | Stash name prompt |
|
|
459
486
|
| `.gut/summary.md` | Work summary format |
|
|
487
|
+
| `.gut/gitignore.md` | Gitignore generation prompt |
|
|
460
488
|
| `.github/pull_request_template.md` | GitHub PR template (prioritized over `.gut/pr.md`) |
|
|
461
489
|
|
|
462
490
|
## Development
|
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
|
|
4
|
+
import { Command as Command19 } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/commands/cleanup.ts
|
|
7
7
|
import { Command } from "commander";
|
|
@@ -735,6 +735,20 @@ async function resolveConflict(conflictedContent, context, options, template) {
|
|
|
735
735
|
});
|
|
736
736
|
return result.object;
|
|
737
737
|
}
|
|
738
|
+
async function generateGitignore(context, options, template) {
|
|
739
|
+
const model = await getModel(options);
|
|
740
|
+
const prompt = applyTemplate(template, "gitignore", {
|
|
741
|
+
files: context.files,
|
|
742
|
+
configFiles: context.configFiles,
|
|
743
|
+
existingGitignore: context.existingGitignore
|
|
744
|
+
});
|
|
745
|
+
const result = await generateText({
|
|
746
|
+
model,
|
|
747
|
+
prompt,
|
|
748
|
+
maxTokens: 2e3
|
|
749
|
+
});
|
|
750
|
+
return result.text.trim();
|
|
751
|
+
}
|
|
738
752
|
|
|
739
753
|
// src/commands/commit.ts
|
|
740
754
|
var commitCommand = new Command3("commit").description("Generate a commit message using AI").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic)", "gemini").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) => {
|
|
@@ -2477,8 +2491,181 @@ var initCommand = new Command17("init").description("Initialize .gut/ templates
|
|
|
2477
2491
|
console.log(chalk18.gray("\nYou can now customize these templates for your project."));
|
|
2478
2492
|
});
|
|
2479
2493
|
|
|
2494
|
+
// src/commands/gitignore.ts
|
|
2495
|
+
import { Command as Command18 } from "commander";
|
|
2496
|
+
import chalk19 from "chalk";
|
|
2497
|
+
import ora15 from "ora";
|
|
2498
|
+
import { simpleGit as simpleGit15 } from "simple-git";
|
|
2499
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync7, existsSync as existsSync6, writeFileSync as writeFileSync4 } from "fs";
|
|
2500
|
+
import { join as join6 } from "path";
|
|
2501
|
+
var CONFIG_FILES = [
|
|
2502
|
+
// JavaScript/TypeScript
|
|
2503
|
+
"package.json",
|
|
2504
|
+
"tsconfig.json",
|
|
2505
|
+
"vite.config.ts",
|
|
2506
|
+
"vite.config.js",
|
|
2507
|
+
"next.config.js",
|
|
2508
|
+
"next.config.mjs",
|
|
2509
|
+
"nuxt.config.ts",
|
|
2510
|
+
"astro.config.mjs",
|
|
2511
|
+
// Python
|
|
2512
|
+
"pyproject.toml",
|
|
2513
|
+
"setup.py",
|
|
2514
|
+
"requirements.txt",
|
|
2515
|
+
"Pipfile",
|
|
2516
|
+
"poetry.lock",
|
|
2517
|
+
// Go
|
|
2518
|
+
"go.mod",
|
|
2519
|
+
"go.sum",
|
|
2520
|
+
// Rust
|
|
2521
|
+
"Cargo.toml",
|
|
2522
|
+
"Cargo.lock",
|
|
2523
|
+
// Java/Kotlin
|
|
2524
|
+
"pom.xml",
|
|
2525
|
+
"build.gradle",
|
|
2526
|
+
"build.gradle.kts",
|
|
2527
|
+
// Ruby
|
|
2528
|
+
"Gemfile",
|
|
2529
|
+
"Gemfile.lock",
|
|
2530
|
+
// PHP
|
|
2531
|
+
"composer.json",
|
|
2532
|
+
"composer.lock",
|
|
2533
|
+
// .NET
|
|
2534
|
+
"*.csproj",
|
|
2535
|
+
"*.fsproj",
|
|
2536
|
+
"*.sln",
|
|
2537
|
+
// Elixir
|
|
2538
|
+
"mix.exs",
|
|
2539
|
+
// Dart/Flutter
|
|
2540
|
+
"pubspec.yaml",
|
|
2541
|
+
// Swift
|
|
2542
|
+
"Package.swift"
|
|
2543
|
+
];
|
|
2544
|
+
function getFiles(dir, maxDepth = 3, currentDepth = 0) {
|
|
2545
|
+
if (currentDepth >= maxDepth) return [];
|
|
2546
|
+
const files = [];
|
|
2547
|
+
try {
|
|
2548
|
+
const entries = readdirSync2(dir, { withFileTypes: true });
|
|
2549
|
+
for (const entry of entries) {
|
|
2550
|
+
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "vendor" || entry.name === "target" || entry.name === "__pycache__" || entry.name === "venv" || entry.name === ".venv") {
|
|
2551
|
+
continue;
|
|
2552
|
+
}
|
|
2553
|
+
const fullPath = join6(dir, entry.name);
|
|
2554
|
+
if (entry.isDirectory()) {
|
|
2555
|
+
files.push(entry.name + "/");
|
|
2556
|
+
const subFiles = getFiles(fullPath, maxDepth, currentDepth + 1);
|
|
2557
|
+
files.push(...subFiles.map((f) => entry.name + "/" + f));
|
|
2558
|
+
} else {
|
|
2559
|
+
files.push(entry.name);
|
|
2560
|
+
}
|
|
2561
|
+
}
|
|
2562
|
+
} catch {
|
|
2563
|
+
}
|
|
2564
|
+
return files;
|
|
2565
|
+
}
|
|
2566
|
+
function findConfigFiles(repoRoot) {
|
|
2567
|
+
const found = /* @__PURE__ */ new Map();
|
|
2568
|
+
for (const configFile of CONFIG_FILES) {
|
|
2569
|
+
if (configFile.includes("*")) {
|
|
2570
|
+
const ext = configFile.replace("*", "");
|
|
2571
|
+
try {
|
|
2572
|
+
const entries = readdirSync2(repoRoot);
|
|
2573
|
+
for (const entry of entries) {
|
|
2574
|
+
if (entry.endsWith(ext)) {
|
|
2575
|
+
const content = readFileSync7(join6(repoRoot, entry), "utf-8");
|
|
2576
|
+
found.set(entry, content.slice(0, 2e3));
|
|
2577
|
+
}
|
|
2578
|
+
}
|
|
2579
|
+
} catch {
|
|
2580
|
+
}
|
|
2581
|
+
} else {
|
|
2582
|
+
const filePath = join6(repoRoot, configFile);
|
|
2583
|
+
if (existsSync6(filePath)) {
|
|
2584
|
+
try {
|
|
2585
|
+
const content = readFileSync7(filePath, "utf-8");
|
|
2586
|
+
found.set(configFile, content.slice(0, 2e3));
|
|
2587
|
+
} catch {
|
|
2588
|
+
}
|
|
2589
|
+
}
|
|
2590
|
+
}
|
|
2591
|
+
}
|
|
2592
|
+
return found;
|
|
2593
|
+
}
|
|
2594
|
+
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) => {
|
|
2595
|
+
const git = simpleGit15();
|
|
2596
|
+
const repoRoot = await git.revparse(["--show-toplevel"]).catch(() => process.cwd());
|
|
2597
|
+
const root = repoRoot.trim();
|
|
2598
|
+
const provider = options.provider.toLowerCase();
|
|
2599
|
+
const template = findTemplate(root, "gitignore");
|
|
2600
|
+
if (template) {
|
|
2601
|
+
console.log(chalk19.gray("Using template from project..."));
|
|
2602
|
+
}
|
|
2603
|
+
const spinner = ora15("Analyzing project structure...").start();
|
|
2604
|
+
const files = getFiles(root);
|
|
2605
|
+
const configFiles = findConfigFiles(root);
|
|
2606
|
+
const gitignorePath = join6(root, options.output);
|
|
2607
|
+
let existingGitignore;
|
|
2608
|
+
if (existsSync6(gitignorePath)) {
|
|
2609
|
+
existingGitignore = readFileSync7(gitignorePath, "utf-8");
|
|
2610
|
+
}
|
|
2611
|
+
let configFilesStr = "";
|
|
2612
|
+
if (configFiles.size > 0) {
|
|
2613
|
+
const entries = [];
|
|
2614
|
+
for (const [name, content] of configFiles) {
|
|
2615
|
+
entries.push(`### ${name}
|
|
2616
|
+
\`\`\`
|
|
2617
|
+
${content}
|
|
2618
|
+
\`\`\``);
|
|
2619
|
+
}
|
|
2620
|
+
configFilesStr = entries.join("\n\n");
|
|
2621
|
+
}
|
|
2622
|
+
spinner.text = "Generating .gitignore...";
|
|
2623
|
+
try {
|
|
2624
|
+
const gitignoreContent = await generateGitignore(
|
|
2625
|
+
{
|
|
2626
|
+
files: files.slice(0, 200).join("\n"),
|
|
2627
|
+
configFiles: configFilesStr,
|
|
2628
|
+
existingGitignore
|
|
2629
|
+
},
|
|
2630
|
+
{ provider, model: options.model },
|
|
2631
|
+
template || void 0
|
|
2632
|
+
);
|
|
2633
|
+
spinner.stop();
|
|
2634
|
+
if (options.stdout) {
|
|
2635
|
+
console.log(gitignoreContent);
|
|
2636
|
+
return;
|
|
2637
|
+
}
|
|
2638
|
+
console.log(chalk19.bold("\nGenerated .gitignore:\n"));
|
|
2639
|
+
console.log(chalk19.gray("\u2500".repeat(50)));
|
|
2640
|
+
console.log(gitignoreContent);
|
|
2641
|
+
console.log(chalk19.gray("\u2500".repeat(50)));
|
|
2642
|
+
console.log();
|
|
2643
|
+
if (existsSync6(gitignorePath) && !options.yes) {
|
|
2644
|
+
const readline = await import("readline");
|
|
2645
|
+
const rl = readline.createInterface({
|
|
2646
|
+
input: process.stdin,
|
|
2647
|
+
output: process.stdout
|
|
2648
|
+
});
|
|
2649
|
+
const answer = await new Promise((resolve) => {
|
|
2650
|
+
rl.question(chalk19.cyan(`${options.output} already exists. Overwrite? (y/N) `), resolve);
|
|
2651
|
+
});
|
|
2652
|
+
rl.close();
|
|
2653
|
+
if (answer.toLowerCase() !== "y") {
|
|
2654
|
+
console.log(chalk19.gray("Aborted."));
|
|
2655
|
+
return;
|
|
2656
|
+
}
|
|
2657
|
+
}
|
|
2658
|
+
writeFileSync4(gitignorePath, gitignoreContent);
|
|
2659
|
+
console.log(chalk19.green(`\u2713 Wrote ${options.output}`));
|
|
2660
|
+
} catch (error) {
|
|
2661
|
+
spinner.fail("Failed to generate .gitignore");
|
|
2662
|
+
console.error(chalk19.red(error instanceof Error ? error.message : "Unknown error"));
|
|
2663
|
+
process.exit(1);
|
|
2664
|
+
}
|
|
2665
|
+
});
|
|
2666
|
+
|
|
2480
2667
|
// src/index.ts
|
|
2481
|
-
var program = new
|
|
2668
|
+
var program = new Command19();
|
|
2482
2669
|
program.name("gut").description("Git Utility Tool - AI-powered git commands").version("0.1.0");
|
|
2483
2670
|
program.addCommand(cleanupCommand);
|
|
2484
2671
|
program.addCommand(authCommand);
|
|
@@ -2497,5 +2684,6 @@ program.addCommand(summaryCommand);
|
|
|
2497
2684
|
program.addCommand(configCommand);
|
|
2498
2685
|
program.addCommand(langCommand);
|
|
2499
2686
|
program.addCommand(initCommand);
|
|
2687
|
+
program.addCommand(gitignoreCommand);
|
|
2500
2688
|
program.parse();
|
|
2501
2689
|
//# sourceMappingURL=index.js.map
|