feat: config file at ~/.aicommits (#51)
Co-authored-by: Yu Le <is.yuler@gmail.com>
This commit is contained in:
22
README.md
22
README.md
@@ -14,20 +14,28 @@
|
|||||||
|
|
||||||
## Installation and Usage
|
## Installation and Usage
|
||||||
|
|
||||||
Install the CLI then grab your [OpenAI key](https://openai.com/api/) and add it as an env variable with the two commands below.
|
1. Install the CLI:
|
||||||
|
|
||||||
1. `npm install -g aicommits`
|
```sh
|
||||||
2. `export OPENAI_KEY=sk-xxxxxxxxxxxxxxxx`
|
npm install -g aicommits
|
||||||
|
```
|
||||||
|
|
||||||
It's recommended to add the line in #2 to your `.zshrc` or `.bashrc` so it persists instead of having to define it in each terminal session.
|
2. Retrieve your API key from [OpenAI](https://platform.openai.com/account/api-keys)
|
||||||
|
> Note: If you haven't already, you'll have to create an account and set up billing.
|
||||||
|
|
||||||
After doing the two steps above, generate your commit by running `aicommits`.
|
3. Set the key so aicommits can use it:
|
||||||
|
|
||||||
> Note: If you get a EACCESS error on mac/linux when running the first command, try running it with `sudo npm install -g aicommits`.
|
```sh
|
||||||
|
echo "OPENAI_KEY=<your token>" >> ~/.aicommits
|
||||||
|
```
|
||||||
|
|
||||||
|
4. You're ready to go!
|
||||||
|
|
||||||
|
Run `aicommits` in any Git repo and it will generate a commit message for you.
|
||||||
|
|
||||||
## How it works
|
## How it works
|
||||||
|
|
||||||
This CLI tool runs a `git diff` command to grab all the latest changes, sends this to OpenAI's GPT-3, then returns the AI generated commit message. I also want to note that it does cost money since GPT-3 generations aren't free. However, OpenAI gives folks $18 of free credits and commit message generations are cheap so it should be free for a long time.
|
This CLI tool runs `git diff` to grab all the latest changes, sends them to OpenAI's GPT-3, then returns the AI generated commit message.
|
||||||
|
|
||||||
Video coming soon where I rebuild it from scratch to show you how to easily build your own CLI tools powered by AI.
|
Video coming soon where I rebuild it from scratch to show you how to easily build your own CLI tools powered by AI.
|
||||||
|
|
||||||
|
|||||||
@@ -20,11 +20,13 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chalk": "^4.1.2",
|
"chalk": "^4.1.2",
|
||||||
|
"ini": "^3.0.1",
|
||||||
"inquirer": "^8.0.0",
|
"inquirer": "^8.0.0",
|
||||||
"openai": "^3.1.0"
|
"openai": "^3.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@pvtnbr/eslint-config": "^0.33.0",
|
"@pvtnbr/eslint-config": "^0.33.0",
|
||||||
|
"@types/ini": "^1.3.31",
|
||||||
"@types/node": "^18.13.0",
|
"@types/node": "^18.13.0",
|
||||||
"eslint": "^8.34.0",
|
"eslint": "^8.34.0",
|
||||||
"typescript": "^4.9.5"
|
"typescript": "^4.9.5"
|
||||||
|
|||||||
13
pnpm-lock.yaml
generated
13
pnpm-lock.yaml
generated
@@ -2,20 +2,24 @@ lockfileVersion: 5.4
|
|||||||
|
|
||||||
specifiers:
|
specifiers:
|
||||||
'@pvtnbr/eslint-config': ^0.33.0
|
'@pvtnbr/eslint-config': ^0.33.0
|
||||||
|
'@types/ini': ^1.3.31
|
||||||
'@types/node': ^18.13.0
|
'@types/node': ^18.13.0
|
||||||
chalk: ^4.1.2
|
chalk: ^4.1.2
|
||||||
eslint: ^8.34.0
|
eslint: ^8.34.0
|
||||||
|
ini: ^3.0.1
|
||||||
inquirer: ^8.0.0
|
inquirer: ^8.0.0
|
||||||
openai: ^3.1.0
|
openai: ^3.1.0
|
||||||
typescript: ^4.9.5
|
typescript: ^4.9.5
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
|
ini: 3.0.1
|
||||||
inquirer: 8.2.5
|
inquirer: 8.2.5
|
||||||
openai: 3.1.0
|
openai: 3.1.0
|
||||||
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@pvtnbr/eslint-config': 0.33.0_7kw3g6rralp5ps6mg3uyzz6azm
|
'@pvtnbr/eslint-config': 0.33.0_7kw3g6rralp5ps6mg3uyzz6azm
|
||||||
|
'@types/ini': 1.3.31
|
||||||
'@types/node': 18.13.0
|
'@types/node': 18.13.0
|
||||||
eslint: 8.34.0
|
eslint: 8.34.0
|
||||||
typescript: 4.9.5
|
typescript: 4.9.5
|
||||||
@@ -141,6 +145,10 @@ packages:
|
|||||||
- typescript
|
- typescript
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@types/ini/1.3.31:
|
||||||
|
resolution: {integrity: sha512-8ecxxaG4AlVEM1k9+BsziMw8UsX0qy3jYI1ad/71RrDZ+rdL6aZB0wLfAuflQiDhkD5o4yJ0uPK3OSUic3fG0w==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/json-schema/7.0.11:
|
/@types/json-schema/7.0.11:
|
||||||
resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==}
|
resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==}
|
||||||
dev: true
|
dev: true
|
||||||
@@ -1487,6 +1495,11 @@ packages:
|
|||||||
/inherits/2.0.4:
|
/inherits/2.0.4:
|
||||||
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
||||||
|
|
||||||
|
/ini/3.0.1:
|
||||||
|
resolution: {integrity: sha512-it4HyVAUTKBc6m8e1iXWvXSTdndF7HbdN713+kvLrymxTaU4AUBWrJ4vEooP+V7fexnVD3LKcBshjGGPefSMUQ==}
|
||||||
|
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/inquirer/8.2.5:
|
/inquirer/8.2.5:
|
||||||
resolution: {integrity: sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==}
|
resolution: {integrity: sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==}
|
||||||
engines: {node: '>=12.0.0'}
|
engines: {node: '>=12.0.0'}
|
||||||
|
|||||||
10
src/cli.ts
10
src/cli.ts
@@ -3,11 +3,15 @@
|
|||||||
import { execSync } from 'child_process';
|
import { execSync } from 'child_process';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import inquirer from 'inquirer';
|
import inquirer from 'inquirer';
|
||||||
import { generateCommitMessage } from './utils';
|
import {
|
||||||
|
getConfig,
|
||||||
const OPENAI_KEY = process.env.OPENAI_KEY ?? process.env.OPENAI_API_KEY;
|
generateCommitMessage,
|
||||||
|
} from './utils';
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
|
const config = await getConfig();
|
||||||
|
const OPENAI_KEY = process.env.OPENAI_KEY ?? process.env.OPENAI_API_KEY ?? config.OPENAI_KEY;
|
||||||
|
|
||||||
console.log(chalk.white('▲ ') + chalk.green('Welcome to AICommits!'));
|
console.log(chalk.white('▲ ') + chalk.green('Welcome to AICommits!'));
|
||||||
|
|
||||||
if (!OPENAI_KEY) {
|
if (!OPENAI_KEY) {
|
||||||
|
|||||||
21
src/utils.ts
21
src/utils.ts
@@ -1,5 +1,26 @@
|
|||||||
|
import fs from 'fs/promises';
|
||||||
|
import path from 'path';
|
||||||
|
import os from 'os';
|
||||||
|
import ini from 'ini';
|
||||||
import { Configuration, OpenAIApi } from 'openai';
|
import { Configuration, OpenAIApi } from 'openai';
|
||||||
|
|
||||||
|
const fileExists = (filePath: string) => fs.access(filePath).then(() => true, () => false);
|
||||||
|
|
||||||
|
type ConfigType = {
|
||||||
|
OPENAI_KEY?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getConfig = async (): Promise<ConfigType> => {
|
||||||
|
const configPath = path.join(os.homedir(), '.aicommits');
|
||||||
|
const configExists = await fileExists(configPath);
|
||||||
|
if (!configExists) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const configString = await fs.readFile(configPath, 'utf8');
|
||||||
|
return ini.parse(configString);
|
||||||
|
};
|
||||||
|
|
||||||
export const generateCommitMessage = async (
|
export const generateCommitMessage = async (
|
||||||
apiKey: string,
|
apiKey: string,
|
||||||
prompt: string,
|
prompt: string,
|
||||||
|
|||||||
Reference in New Issue
Block a user