feat: config file at ~/.aicommits (#51)

Co-authored-by: Yu Le <is.yuler@gmail.com>
This commit is contained in:
hiroki osame
2023-02-16 00:15:07 -05:00
committed by GitHub
parent a282874b7a
commit de38c891f5
5 changed files with 58 additions and 10 deletions

View File

@@ -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.

View File

@@ -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
View File

@@ -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'}

View File

@@ -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) {

View File

@@ -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,