gitpt 1.0.0
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/LICENSE +21 -0
- package/README.md +103 -0
- package/dist/commands/add.d.ts +1 -0
- package/dist/commands/add.js +16 -0
- package/dist/commands/commit.d.ts +7 -0
- package/dist/commands/commit.js +74 -0
- package/dist/commands/setup.d.ts +1 -0
- package/dist/commands/setup.js +60 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +48 -0
- package/dist/utils/api.d.ts +1 -0
- package/dist/utils/api.js +55 -0
- package/dist/utils/config.d.ts +7 -0
- package/dist/utils/config.js +24 -0
- package/dist/utils/git.d.ts +6 -0
- package/dist/utils/git.js +62 -0
- package/package.json +52 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 @bartaxyz
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# GitPT
|
|
2
|
+
|
|
3
|
+
Git Prompt Tool is a CLI tool that helps you write commit messages using AI through [OpenRouter](https://openrouter.ai/).
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Generate commit messages with AI based on your code changes
|
|
8
|
+
- Compatible with all regular git commit options (you can treat it as an alias)
|
|
9
|
+
- Edit suggested messages before committing
|
|
10
|
+
- Works with various AI models via OpenRouter
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# Install globally
|
|
16
|
+
npm install -g gitpt
|
|
17
|
+
|
|
18
|
+
# Or use npx
|
|
19
|
+
npx gitpt
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Set up
|
|
23
|
+
|
|
24
|
+
To configure GitPT with your OpenRouter API key and select a model:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
gitpt setup
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
This will guide you through:
|
|
31
|
+
1. Entering your OpenRouter API key
|
|
32
|
+
2. Selecting an AI model from popular options or specifying a custom one
|
|
33
|
+
|
|
34
|
+
You'll need an [OpenRouter](https://openrouter.ai/) account to get an API key.
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
### Adding Files
|
|
39
|
+
|
|
40
|
+
Add files to the staging area using either git directly or the GitPT wrapper:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Standard git command
|
|
44
|
+
git add .
|
|
45
|
+
|
|
46
|
+
# Or using GitPT wrapper
|
|
47
|
+
gitpt add .
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Creating Commits
|
|
51
|
+
|
|
52
|
+
Generate an AI-powered commit message based on your staged changes:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
gitpt commit
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The tool will:
|
|
59
|
+
1. Analyze your staged changes
|
|
60
|
+
2. Generate a commit message using the configured AI model
|
|
61
|
+
3. Show you the suggested message
|
|
62
|
+
4. Let you edit the message before committing
|
|
63
|
+
5. Create the commit with your approved message
|
|
64
|
+
|
|
65
|
+
### Options
|
|
66
|
+
|
|
67
|
+
You can use any standard git commit options with the `gitpt commit` command:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# Skip editing the message
|
|
71
|
+
gitpt commit --no-edit
|
|
72
|
+
|
|
73
|
+
# Provide your own message instead of generating one
|
|
74
|
+
gitpt commit -m "Your message here"
|
|
75
|
+
|
|
76
|
+
# Pass any other git commit options
|
|
77
|
+
gitpt commit --amend
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## How It Works
|
|
81
|
+
|
|
82
|
+
GitPT sends a diff of your staged changes to the configured AI model via OpenRouter, which generates a contextual commit message following best practices.
|
|
83
|
+
|
|
84
|
+
## Development
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# Clone the repository
|
|
88
|
+
git clone https://github.com/bartaxyz/GitPT.git
|
|
89
|
+
cd GitPT
|
|
90
|
+
|
|
91
|
+
# Install dependencies
|
|
92
|
+
npm install
|
|
93
|
+
|
|
94
|
+
# Build the project
|
|
95
|
+
npm run build
|
|
96
|
+
|
|
97
|
+
# Link for local development
|
|
98
|
+
npm link
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## License
|
|
102
|
+
|
|
103
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function addCommand(files: string[]): void;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { isGitRepository, executeGitAdd } from '../utils/git.js';
|
|
3
|
+
export function addCommand(files) {
|
|
4
|
+
if (!isGitRepository()) {
|
|
5
|
+
console.error(chalk.red('Error: Not a git repository'));
|
|
6
|
+
process.exit(1);
|
|
7
|
+
}
|
|
8
|
+
try {
|
|
9
|
+
executeGitAdd(files);
|
|
10
|
+
console.log(chalk.green('Files added to staging area'));
|
|
11
|
+
}
|
|
12
|
+
catch (error) {
|
|
13
|
+
console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import inquirer from 'inquirer';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { isGitRepository, hasStagedChanges, getStagedChanges, executeGitCommit } from '../utils/git.js';
|
|
4
|
+
import { generateCommitMessage } from '../utils/api.js';
|
|
5
|
+
import { getConfig } from '../utils/config.js';
|
|
6
|
+
export async function commitCommand(options) {
|
|
7
|
+
if (!isGitRepository()) {
|
|
8
|
+
console.error(chalk.red('Error: Not a git repository'));
|
|
9
|
+
process.exit(1);
|
|
10
|
+
}
|
|
11
|
+
// Check if config exists
|
|
12
|
+
const config = getConfig();
|
|
13
|
+
if (!config) {
|
|
14
|
+
console.error(chalk.red('GitPT is not configured. Please run "gitpt setup" first.'));
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
// Check if there are staged changes
|
|
18
|
+
if (!hasStagedChanges()) {
|
|
19
|
+
console.error(chalk.yellow('No staged changes. Use "git add" or "gitpt add" to stage changes first.'));
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
let commitMessage;
|
|
23
|
+
// If message is provided, use that
|
|
24
|
+
if (options.message) {
|
|
25
|
+
commitMessage = options.message;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
try {
|
|
29
|
+
// Get staged changes
|
|
30
|
+
const diff = getStagedChanges();
|
|
31
|
+
console.log(chalk.blue('Generating commit message...'));
|
|
32
|
+
// Generate commit message
|
|
33
|
+
commitMessage = await generateCommitMessage(diff);
|
|
34
|
+
console.log(chalk.green('✓ Commit message generated'));
|
|
35
|
+
console.log('');
|
|
36
|
+
console.log(chalk.cyan('Generated message:'));
|
|
37
|
+
console.log(commitMessage);
|
|
38
|
+
console.log('');
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// If edit is true or not specified, prompt user to edit the message
|
|
46
|
+
if (options.edit !== false) {
|
|
47
|
+
const answer = await inquirer.prompt([
|
|
48
|
+
{
|
|
49
|
+
type: 'editor',
|
|
50
|
+
name: 'message',
|
|
51
|
+
message: 'Edit commit message:',
|
|
52
|
+
default: commitMessage
|
|
53
|
+
}
|
|
54
|
+
]);
|
|
55
|
+
commitMessage = answer.message;
|
|
56
|
+
}
|
|
57
|
+
// Extract other git options to pass through
|
|
58
|
+
const gitOptions = Object.keys(options)
|
|
59
|
+
.filter(key => !['message', 'edit'].includes(key))
|
|
60
|
+
.map(key => {
|
|
61
|
+
if (typeof options[key] === 'boolean') {
|
|
62
|
+
return options[key] ? `--${key}` : `--no-${key}`;
|
|
63
|
+
}
|
|
64
|
+
return `--${key}=${options[key]}`;
|
|
65
|
+
});
|
|
66
|
+
try {
|
|
67
|
+
executeGitCommit(commitMessage, gitOptions);
|
|
68
|
+
console.log(chalk.green('✓ Changes committed successfully'));
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function setupCommand(): Promise<void>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import inquirer from 'inquirer';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { saveConfig, clearConfig } from '../utils/config.js';
|
|
4
|
+
// List of popular models available on OpenRouter
|
|
5
|
+
const POPULAR_MODELS = [
|
|
6
|
+
{ name: 'Claude 3 Opus - Anthropic', value: 'anthropic/claude-3-opus:beta' },
|
|
7
|
+
{ name: 'Claude 3 Sonnet - Anthropic', value: 'anthropic/claude-3-sonnet:beta' },
|
|
8
|
+
{ name: 'Claude 3 Haiku - Anthropic', value: 'anthropic/claude-3-haiku:beta' },
|
|
9
|
+
{ name: 'GPT-4o - OpenAI', value: 'openai/gpt-4o' },
|
|
10
|
+
{ name: 'GPT-4 Turbo - OpenAI', value: 'openai/gpt-4-turbo' },
|
|
11
|
+
{ name: 'GPT-3.5 Turbo - OpenAI', value: 'openai/gpt-3.5-turbo' },
|
|
12
|
+
{ name: 'Other (specify model identifier)', value: 'custom' }
|
|
13
|
+
];
|
|
14
|
+
export async function setupCommand() {
|
|
15
|
+
console.log(chalk.blue('GitPT Setup'));
|
|
16
|
+
console.log('This will configure GitPT to use OpenRouter for generating commit messages.');
|
|
17
|
+
console.log('If you don\'t have an OpenRouter account yet, sign up at https://openrouter.ai');
|
|
18
|
+
console.log('');
|
|
19
|
+
const answers = await inquirer.prompt([
|
|
20
|
+
{
|
|
21
|
+
type: 'input',
|
|
22
|
+
name: 'apiKey',
|
|
23
|
+
message: 'Enter your OpenRouter API key:',
|
|
24
|
+
validate: (input) => {
|
|
25
|
+
if (!input)
|
|
26
|
+
return 'API key is required';
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
type: 'list',
|
|
32
|
+
name: 'modelChoice',
|
|
33
|
+
message: 'Select an AI model:',
|
|
34
|
+
choices: POPULAR_MODELS
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
type: 'input',
|
|
38
|
+
name: 'customModel',
|
|
39
|
+
message: 'Enter model identifier:',
|
|
40
|
+
when: (answers) => answers.modelChoice === 'custom',
|
|
41
|
+
validate: (input) => {
|
|
42
|
+
if (!input)
|
|
43
|
+
return 'Model identifier is required';
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
]);
|
|
48
|
+
// Clear existing config before saving new one
|
|
49
|
+
clearConfig();
|
|
50
|
+
// Save the new configuration
|
|
51
|
+
const model = answers.modelChoice === 'custom' ? answers.customModel : answers.modelChoice;
|
|
52
|
+
saveConfig({
|
|
53
|
+
apiKey: answers.apiKey,
|
|
54
|
+
model: model
|
|
55
|
+
});
|
|
56
|
+
console.log(chalk.green('✓ GitPT configuration saved successfully'));
|
|
57
|
+
console.log(`Model set to: ${chalk.yellow(model)}`);
|
|
58
|
+
console.log('');
|
|
59
|
+
console.log(`Use ${chalk.cyan('gitpt commit')} to create commits with AI-generated messages.`);
|
|
60
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { setupCommand } from './commands/setup.js';
|
|
5
|
+
import { commitCommand } from './commands/commit.js';
|
|
6
|
+
import { addCommand } from './commands/add.js';
|
|
7
|
+
import fs from 'fs';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import { fileURLToPath } from 'url';
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
+
const __dirname = path.dirname(__filename);
|
|
12
|
+
const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, '../package.json'), 'utf8'));
|
|
13
|
+
const version = packageJson.version;
|
|
14
|
+
const program = new Command();
|
|
15
|
+
program
|
|
16
|
+
.name('gitpt')
|
|
17
|
+
.description('Git Prompt Tool helps you write commit messages using AI')
|
|
18
|
+
.version(version);
|
|
19
|
+
// Setup command
|
|
20
|
+
program
|
|
21
|
+
.command('setup')
|
|
22
|
+
.description('Configure GitPT with your OpenRouter API key and model selection')
|
|
23
|
+
.action(setupCommand);
|
|
24
|
+
// Add command (pass-through to git add)
|
|
25
|
+
program
|
|
26
|
+
.command('add [files...]')
|
|
27
|
+
.description('Add files to git staging area (pass-through to git add)')
|
|
28
|
+
.action(addCommand);
|
|
29
|
+
// Commit command
|
|
30
|
+
program
|
|
31
|
+
.command('commit')
|
|
32
|
+
.description('Generate AI-powered commit message based on staged changes')
|
|
33
|
+
.option('-m, --message <message>', 'use provided message instead of generating one')
|
|
34
|
+
.option('-e, --edit', 'edit the message after generation')
|
|
35
|
+
.option('--no-edit', 'do not edit the message after generation')
|
|
36
|
+
.allowUnknownOption(true) // Pass through other git commit options
|
|
37
|
+
.action(commitCommand);
|
|
38
|
+
// Main logic
|
|
39
|
+
async function main() {
|
|
40
|
+
try {
|
|
41
|
+
await program.parseAsync();
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
main();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function generateCommitMessage(diff: string): Promise<string>;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import fetch from 'node-fetch';
|
|
2
|
+
import { getConfig } from './config.js';
|
|
3
|
+
const OPENROUTER_API_URL = 'https://openrouter.ai/api/v1/chat/completions';
|
|
4
|
+
export async function generateCommitMessage(diff) {
|
|
5
|
+
const config = getConfig();
|
|
6
|
+
if (!config) {
|
|
7
|
+
throw new Error('GitPT is not configured. Please run "gitpt setup" first.');
|
|
8
|
+
}
|
|
9
|
+
const { apiKey, model } = config;
|
|
10
|
+
const messages = [
|
|
11
|
+
{
|
|
12
|
+
role: 'system',
|
|
13
|
+
content: `You are a helpful assistant that generates concise, informative Git commit messages.
|
|
14
|
+
Follow conventional commit style. Be brief but descriptive.
|
|
15
|
+
Focus on WHAT changes were made, WHY they were made, and their IMPACT.
|
|
16
|
+
Use present tense (e.g., "add feature" not "added feature").
|
|
17
|
+
Split the message like this if needed:
|
|
18
|
+
|
|
19
|
+
feat(scope): short description
|
|
20
|
+
|
|
21
|
+
More detailed explanation if necessary
|
|
22
|
+
|
|
23
|
+
Only include a detailed explanation for complex changes.`
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
role: 'user',
|
|
27
|
+
content: `Generate a commit message for the following git diff:\n\n${diff}`
|
|
28
|
+
}
|
|
29
|
+
];
|
|
30
|
+
try {
|
|
31
|
+
const response = await fetch(OPENROUTER_API_URL, {
|
|
32
|
+
method: 'POST',
|
|
33
|
+
headers: {
|
|
34
|
+
'Content-Type': 'application/json',
|
|
35
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
36
|
+
'HTTP-Referer': 'https://github.com/bartaxyz/GitPT',
|
|
37
|
+
},
|
|
38
|
+
body: JSON.stringify({
|
|
39
|
+
model: model,
|
|
40
|
+
messages: messages,
|
|
41
|
+
max_tokens: 300,
|
|
42
|
+
}),
|
|
43
|
+
});
|
|
44
|
+
if (!response.ok) {
|
|
45
|
+
const errorText = await response.text();
|
|
46
|
+
throw new Error(`API request failed: ${response.status} ${response.statusText}\n${errorText}`);
|
|
47
|
+
}
|
|
48
|
+
const data = await response.json();
|
|
49
|
+
return data.choices[0].message.content.trim();
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
console.error('Error generating commit message:', error);
|
|
53
|
+
throw new Error('Failed to generate commit message');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import Configstore from 'configstore';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
const config = new Configstore('gitpt');
|
|
4
|
+
export function getConfig() {
|
|
5
|
+
try {
|
|
6
|
+
const apiKey = config.get('apiKey');
|
|
7
|
+
const model = config.get('model');
|
|
8
|
+
if (!apiKey || !model) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
return { apiKey, model };
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
console.error(chalk.red('Error reading configuration:'), error);
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function saveConfig(newConfig) {
|
|
19
|
+
config.set('apiKey', newConfig.apiKey);
|
|
20
|
+
config.set('model', newConfig.model);
|
|
21
|
+
}
|
|
22
|
+
export function clearConfig() {
|
|
23
|
+
config.clear();
|
|
24
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function isGitRepository(): boolean;
|
|
2
|
+
export declare function getStagedChanges(): string;
|
|
3
|
+
export declare function getStagedFiles(): string[];
|
|
4
|
+
export declare function hasStagedChanges(): boolean;
|
|
5
|
+
export declare function executeGitAdd(files: string[]): void;
|
|
6
|
+
export declare function executeGitCommit(message: string, additionalArgs?: string[]): void;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
export function isGitRepository() {
|
|
4
|
+
try {
|
|
5
|
+
execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' });
|
|
6
|
+
return true;
|
|
7
|
+
}
|
|
8
|
+
catch (error) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export function getStagedChanges() {
|
|
13
|
+
try {
|
|
14
|
+
return execSync('git diff --staged').toString();
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
console.error(chalk.red('Error getting staged changes:'), error);
|
|
18
|
+
throw new Error('Failed to get staged changes');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export function getStagedFiles() {
|
|
22
|
+
try {
|
|
23
|
+
const result = execSync('git diff --staged --name-only').toString();
|
|
24
|
+
return result.split('\n').filter(Boolean);
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
console.error(chalk.red('Error getting staged files:'), error);
|
|
28
|
+
throw new Error('Failed to get staged files');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export function hasStagedChanges() {
|
|
32
|
+
try {
|
|
33
|
+
const output = execSync('git diff --staged --quiet || echo "has-changes"').toString();
|
|
34
|
+
return output.includes('has-changes');
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
return true; // Assume there are changes if we can't check
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export function executeGitAdd(files) {
|
|
41
|
+
try {
|
|
42
|
+
if (files.length === 0) {
|
|
43
|
+
throw new Error('No files specified');
|
|
44
|
+
}
|
|
45
|
+
const fileArgs = files.join(' ');
|
|
46
|
+
execSync(`git add ${fileArgs}`, { stdio: 'inherit' });
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
console.error(chalk.red('Error adding files:'), error);
|
|
50
|
+
throw new Error('Failed to add files to git');
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export function executeGitCommit(message, additionalArgs = []) {
|
|
54
|
+
try {
|
|
55
|
+
const args = additionalArgs.join(' ');
|
|
56
|
+
execSync(`git commit -m "${message}" ${args}`, { stdio: 'inherit' });
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
console.error(chalk.red('Error committing changes:'), error);
|
|
60
|
+
throw new Error('Failed to commit changes');
|
|
61
|
+
}
|
|
62
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "gitpt",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CLI tool that helps you write commit messages & pull request descriptions using AI",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"gitpt": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist/**/*",
|
|
12
|
+
"README.md",
|
|
13
|
+
"LICENSE"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc",
|
|
17
|
+
"dev": "ts-node --esm src/index.ts",
|
|
18
|
+
"start": "node dist/index.js",
|
|
19
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
20
|
+
"prepublishOnly": "npm run build"
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/bartaxyz/GitPT.git"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"git",
|
|
28
|
+
"ai",
|
|
29
|
+
"prompt"
|
|
30
|
+
],
|
|
31
|
+
"author": "@bartaxyz",
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/bartaxyz/GitPT/issues"
|
|
35
|
+
},
|
|
36
|
+
"homepage": "https://github.com/bartaxyz/GitPT#readme",
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/configstore": "^6.0.2",
|
|
39
|
+
"@types/inquirer": "^9.0.7",
|
|
40
|
+
"@types/node": "^22.14.1",
|
|
41
|
+
"@types/node-fetch": "^2.6.12",
|
|
42
|
+
"ts-node": "^10.9.2",
|
|
43
|
+
"typescript": "^5.8.3"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"chalk": "^5.4.1",
|
|
47
|
+
"commander": "^13.1.0",
|
|
48
|
+
"configstore": "^7.0.0",
|
|
49
|
+
"inquirer": "^12.5.2",
|
|
50
|
+
"node-fetch": "^3.3.2"
|
|
51
|
+
}
|
|
52
|
+
}
|