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
|
||||
|
||||
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`
|
||||
2. `export OPENAI_KEY=sk-xxxxxxxxxxxxxxxx`
|
||||
```sh
|
||||
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
|
||||
|
||||
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.
|
||||
|
||||
|
||||
@@ -20,11 +20,13 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"chalk": "^4.1.2",
|
||||
"ini": "^3.0.1",
|
||||
"inquirer": "^8.0.0",
|
||||
"openai": "^3.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@pvtnbr/eslint-config": "^0.33.0",
|
||||
"@types/ini": "^1.3.31",
|
||||
"@types/node": "^18.13.0",
|
||||
"eslint": "^8.34.0",
|
||||
"typescript": "^4.9.5"
|
||||
|
||||
13
pnpm-lock.yaml
generated
13
pnpm-lock.yaml
generated
@@ -2,20 +2,24 @@ lockfileVersion: 5.4
|
||||
|
||||
specifiers:
|
||||
'@pvtnbr/eslint-config': ^0.33.0
|
||||
'@types/ini': ^1.3.31
|
||||
'@types/node': ^18.13.0
|
||||
chalk: ^4.1.2
|
||||
eslint: ^8.34.0
|
||||
ini: ^3.0.1
|
||||
inquirer: ^8.0.0
|
||||
openai: ^3.1.0
|
||||
typescript: ^4.9.5
|
||||
|
||||
dependencies:
|
||||
chalk: 4.1.2
|
||||
ini: 3.0.1
|
||||
inquirer: 8.2.5
|
||||
openai: 3.1.0
|
||||
|
||||
devDependencies:
|
||||
'@pvtnbr/eslint-config': 0.33.0_7kw3g6rralp5ps6mg3uyzz6azm
|
||||
'@types/ini': 1.3.31
|
||||
'@types/node': 18.13.0
|
||||
eslint: 8.34.0
|
||||
typescript: 4.9.5
|
||||
@@ -141,6 +145,10 @@ packages:
|
||||
- typescript
|
||||
dev: true
|
||||
|
||||
/@types/ini/1.3.31:
|
||||
resolution: {integrity: sha512-8ecxxaG4AlVEM1k9+BsziMw8UsX0qy3jYI1ad/71RrDZ+rdL6aZB0wLfAuflQiDhkD5o4yJ0uPK3OSUic3fG0w==}
|
||||
dev: true
|
||||
|
||||
/@types/json-schema/7.0.11:
|
||||
resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==}
|
||||
dev: true
|
||||
@@ -1487,6 +1495,11 @@ packages:
|
||||
/inherits/2.0.4:
|
||||
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:
|
||||
resolution: {integrity: sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
||||
10
src/cli.ts
10
src/cli.ts
@@ -3,11 +3,15 @@
|
||||
import { execSync } from 'child_process';
|
||||
import chalk from 'chalk';
|
||||
import inquirer from 'inquirer';
|
||||
import { generateCommitMessage } from './utils';
|
||||
|
||||
const OPENAI_KEY = process.env.OPENAI_KEY ?? process.env.OPENAI_API_KEY;
|
||||
import {
|
||||
getConfig,
|
||||
generateCommitMessage,
|
||||
} from './utils';
|
||||
|
||||
(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!'));
|
||||
|
||||
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';
|
||||
|
||||
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 (
|
||||
apiKey: string,
|
||||
prompt: string,
|
||||
|
||||
Reference in New Issue
Block a user