@misaelabanto/commita 1.0.1
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/.claude/settings.local.json +10 -0
- package/.commita.example +22 -0
- package/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc +111 -0
- package/.github/workflows/release.yml +86 -0
- package/README.md +361 -0
- package/index.ts +7 -0
- package/install.sh +113 -0
- package/package.json +40 -0
- package/src/ai/ai.service.ts +124 -0
- package/src/ai/commit-type-analyzer.ts +103 -0
- package/src/ai/emoji-mapper.ts +29 -0
- package/src/cli/commit-handler.ts +185 -0
- package/src/cli/index.ts +58 -0
- package/src/cli/set-handler.ts +134 -0
- package/src/config/config.loader.ts +151 -0
- package/src/config/config.types.ts +22 -0
- package/src/config/config.writer.ts +204 -0
- package/src/config/prompt-templates.ts +55 -0
- package/src/git/file-grouper.ts +142 -0
- package/src/git/git.service.ts +147 -0
- package/src/git/project-detector.ts +89 -0
- package/src/utils/pattern-matcher.ts +39 -0
- package/tsconfig.json +26 -0
package/.commita.example
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Provider: openai or gemini (default: openai)
|
|
2
|
+
PROVIDER=openai
|
|
3
|
+
|
|
4
|
+
# Model name (provider-specific)
|
|
5
|
+
# OpenAI examples: gpt-4o-mini, gpt-4o, gpt-4-turbo
|
|
6
|
+
# Gemini examples: gemini-2.5-flash, gemini-2.5-pro, gemini-1.5-pro
|
|
7
|
+
MODEL=gpt-4o-mini
|
|
8
|
+
|
|
9
|
+
# Prompt style: default, detailed, minimal, or custom
|
|
10
|
+
PROMPT_STYLE=default
|
|
11
|
+
|
|
12
|
+
# Commit style: conventional or emoji
|
|
13
|
+
COMMIT_STYLE=conventional
|
|
14
|
+
|
|
15
|
+
# API Keys (set the one for your chosen provider)
|
|
16
|
+
# For OpenAI:
|
|
17
|
+
OPENAI_API_KEY=your-openai-api-key-here
|
|
18
|
+
|
|
19
|
+
# For Gemini:
|
|
20
|
+
# GEMINI_API_KEY=your-gemini-api-key-here
|
|
21
|
+
# Or use GOOGLE_GENERATIVE_AI_API_KEY environment variable
|
|
22
|
+
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Use Bun instead of Node.js, npm, pnpm, or vite.
|
|
3
|
+
globs: "*.ts, *.tsx, *.html, *.css, *.js, *.jsx, package.json"
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Default to using Bun instead of Node.js.
|
|
8
|
+
|
|
9
|
+
- Use `bun <file>` instead of `node <file>` or `ts-node <file>`
|
|
10
|
+
- Use `bun test` instead of `jest` or `vitest`
|
|
11
|
+
- Use `bun build <file.html|file.ts|file.css>` instead of `webpack` or `esbuild`
|
|
12
|
+
- Use `bun install` instead of `npm install` or `yarn install` or `pnpm install`
|
|
13
|
+
- Use `bun run <script>` instead of `npm run <script>` or `yarn run <script>` or `pnpm run <script>`
|
|
14
|
+
- Bun automatically loads .env, so don't use dotenv.
|
|
15
|
+
|
|
16
|
+
## APIs
|
|
17
|
+
|
|
18
|
+
- `Bun.serve()` supports WebSockets, HTTPS, and routes. Don't use `express`.
|
|
19
|
+
- `bun:sqlite` for SQLite. Don't use `better-sqlite3`.
|
|
20
|
+
- `Bun.redis` for Redis. Don't use `ioredis`.
|
|
21
|
+
- `Bun.sql` for Postgres. Don't use `pg` or `postgres.js`.
|
|
22
|
+
- `WebSocket` is built-in. Don't use `ws`.
|
|
23
|
+
- Prefer `Bun.file` over `node:fs`'s readFile/writeFile
|
|
24
|
+
- Bun.$`ls` instead of execa.
|
|
25
|
+
|
|
26
|
+
## Testing
|
|
27
|
+
|
|
28
|
+
Use `bun test` to run tests.
|
|
29
|
+
|
|
30
|
+
```ts#index.test.ts
|
|
31
|
+
import { test, expect } from "bun:test";
|
|
32
|
+
|
|
33
|
+
test("hello world", () => {
|
|
34
|
+
expect(1).toBe(1);
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Frontend
|
|
39
|
+
|
|
40
|
+
Use HTML imports with `Bun.serve()`. Don't use `vite`. HTML imports fully support React, CSS, Tailwind.
|
|
41
|
+
|
|
42
|
+
Server:
|
|
43
|
+
|
|
44
|
+
```ts#index.ts
|
|
45
|
+
import index from "./index.html"
|
|
46
|
+
|
|
47
|
+
Bun.serve({
|
|
48
|
+
routes: {
|
|
49
|
+
"/": index,
|
|
50
|
+
"/api/users/:id": {
|
|
51
|
+
GET: (req) => {
|
|
52
|
+
return new Response(JSON.stringify({ id: req.params.id }));
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
// optional websocket support
|
|
57
|
+
websocket: {
|
|
58
|
+
open: (ws) => {
|
|
59
|
+
ws.send("Hello, world!");
|
|
60
|
+
},
|
|
61
|
+
message: (ws, message) => {
|
|
62
|
+
ws.send(message);
|
|
63
|
+
},
|
|
64
|
+
close: (ws) => {
|
|
65
|
+
// handle close
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
development: {
|
|
69
|
+
hmr: true,
|
|
70
|
+
console: true,
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
HTML files can import .tsx, .jsx or .js files directly and Bun's bundler will transpile & bundle automatically. `<link>` tags can point to stylesheets and Bun's CSS bundler will bundle.
|
|
76
|
+
|
|
77
|
+
```html#index.html
|
|
78
|
+
<html>
|
|
79
|
+
<body>
|
|
80
|
+
<h1>Hello, world!</h1>
|
|
81
|
+
<script type="module" src="./frontend.tsx"></script>
|
|
82
|
+
</body>
|
|
83
|
+
</html>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
With the following `frontend.tsx`:
|
|
87
|
+
|
|
88
|
+
```tsx#frontend.tsx
|
|
89
|
+
import React from "react";
|
|
90
|
+
|
|
91
|
+
// import .css files directly and it works
|
|
92
|
+
import './index.css';
|
|
93
|
+
|
|
94
|
+
import { createRoot } from "react-dom/client";
|
|
95
|
+
|
|
96
|
+
const root = createRoot(document.body);
|
|
97
|
+
|
|
98
|
+
export default function Frontend() {
|
|
99
|
+
return <h1>Hello, world!</h1>;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
root.render(<Frontend />);
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Then, run index.ts
|
|
106
|
+
|
|
107
|
+
```sh
|
|
108
|
+
bun --hot ./index.ts
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
For more information, read the Bun API docs in `node_modules/bun-types/docs/**.md`.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build:
|
|
11
|
+
name: Build ${{ matrix.output }}
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
strategy:
|
|
14
|
+
matrix:
|
|
15
|
+
include:
|
|
16
|
+
- target: bun-darwin-x64
|
|
17
|
+
output: commita-darwin-amd64
|
|
18
|
+
- target: bun-darwin-arm64
|
|
19
|
+
output: commita-darwin-arm64
|
|
20
|
+
- target: bun-linux-x64
|
|
21
|
+
output: commita-linux-amd64
|
|
22
|
+
- target: bun-linux-arm64
|
|
23
|
+
output: commita-linux-arm64
|
|
24
|
+
- target: bun-windows-x64
|
|
25
|
+
output: commita-windows-amd64.exe
|
|
26
|
+
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v4
|
|
29
|
+
|
|
30
|
+
- uses: oven-sh/setup-bun@v2
|
|
31
|
+
|
|
32
|
+
- run: bun install
|
|
33
|
+
|
|
34
|
+
- name: Build
|
|
35
|
+
run: bun build index.ts --compile --target=${{ matrix.target }} --outfile ${{ matrix.output }}
|
|
36
|
+
|
|
37
|
+
- uses: actions/upload-artifact@v4
|
|
38
|
+
with:
|
|
39
|
+
name: ${{ matrix.output }}
|
|
40
|
+
path: ${{ matrix.output }}
|
|
41
|
+
if-no-files-found: error
|
|
42
|
+
|
|
43
|
+
version:
|
|
44
|
+
name: Create version tag
|
|
45
|
+
needs: build
|
|
46
|
+
if: github.ref == 'refs/heads/main'
|
|
47
|
+
runs-on: ubuntu-latest
|
|
48
|
+
permissions:
|
|
49
|
+
contents: write
|
|
50
|
+
outputs:
|
|
51
|
+
new_tag: ${{ steps.tag.outputs.new_tag }}
|
|
52
|
+
steps:
|
|
53
|
+
- uses: actions/checkout@v4
|
|
54
|
+
with:
|
|
55
|
+
fetch-depth: 0
|
|
56
|
+
|
|
57
|
+
- id: tag
|
|
58
|
+
uses: mathieudutour/github-tag-action@v6.2
|
|
59
|
+
with:
|
|
60
|
+
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
61
|
+
tag_prefix: v
|
|
62
|
+
default_bump: patch
|
|
63
|
+
release_branches: main
|
|
64
|
+
|
|
65
|
+
release:
|
|
66
|
+
name: Release
|
|
67
|
+
needs: [build, version]
|
|
68
|
+
if: github.ref == 'refs/heads/main' && needs.version.outputs.new_tag != ''
|
|
69
|
+
runs-on: ubuntu-latest
|
|
70
|
+
permissions:
|
|
71
|
+
contents: write
|
|
72
|
+
steps:
|
|
73
|
+
- uses: actions/download-artifact@v4
|
|
74
|
+
with:
|
|
75
|
+
merge-multiple: true
|
|
76
|
+
|
|
77
|
+
- uses: softprops/action-gh-release@v2
|
|
78
|
+
with:
|
|
79
|
+
tag_name: ${{ needs.version.outputs.new_tag }}
|
|
80
|
+
generate_release_notes: true
|
|
81
|
+
files: |
|
|
82
|
+
commita-darwin-amd64
|
|
83
|
+
commita-darwin-arm64
|
|
84
|
+
commita-linux-amd64
|
|
85
|
+
commita-linux-arm64
|
|
86
|
+
commita-windows-amd64.exe
|
package/README.md
ADDED
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
# Commita 🤖
|
|
2
|
+
|
|
3
|
+
AI-powered git auto-commit tool that intelligently groups your changes and generates meaningful commit messages.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **AI-Generated Commit Messages**: Uses OpenAI or Google Gemini to analyze diffs and create descriptive commit messages
|
|
8
|
+
- **Multiple AI Providers**: Support for both OpenAI and Google Gemini via the Vercel AI SDK
|
|
9
|
+
- **Intelligent File Grouping**: Automatically groups files by their directory structure for organized commits
|
|
10
|
+
- **Configurable**: Customize prompts, models, and commit styles
|
|
11
|
+
- **Multiple Commit Styles**: Support for conventional commits and emoji commits
|
|
12
|
+
- **Bulk Operations**: Process all changes at once with the `--all` flag
|
|
13
|
+
- **Pattern Filtering**: Exclude files using glob patterns with `--ignore`
|
|
14
|
+
- **Auto-Push**: Automatically pushes commits to remote (can be disabled)
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
Downloads the correct pre-compiled binary for your OS and architecture directly from [GitHub Releases](https://github.com/misaelabanto/commita/releases):
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
curl -fsSL https://raw.githubusercontent.com/misaelabanto/commita/main/install.sh | bash
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Supported platforms:
|
|
25
|
+
|
|
26
|
+
| OS | x86_64 | arm64 |
|
|
27
|
+
|-------|--------|-------|
|
|
28
|
+
| macOS | ✅ | ✅ |
|
|
29
|
+
| Linux | ✅ | ✅ |
|
|
30
|
+
|
|
31
|
+
> Windows users: download the binary manually from the [Releases page](https://github.com/misaelabanto/commita/releases).
|
|
32
|
+
|
|
33
|
+
### Local Development
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
git clone https://github.com/misaelabanto/commita.git
|
|
37
|
+
cd commita
|
|
38
|
+
bun install
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Quick Start
|
|
42
|
+
|
|
43
|
+
1. Clone and install dependencies:
|
|
44
|
+
```bash
|
|
45
|
+
git clone https://github.com/misaelabanto/commita.git
|
|
46
|
+
cd commita
|
|
47
|
+
bun install
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
2. Create a `.commita` file or set environment variables:
|
|
51
|
+
```bash
|
|
52
|
+
cp .commita.example .commita
|
|
53
|
+
# Edit .commita and add your API key (OpenAI or Gemini)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
3. Navigate to your project and run:
|
|
57
|
+
```bash
|
|
58
|
+
commita --all
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Configuration
|
|
62
|
+
|
|
63
|
+
Create a `.commita` file in your project root or use environment variables with the `COMMITA_` prefix.
|
|
64
|
+
|
|
65
|
+
### `.commita` file format (key=value):
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
PROVIDER=openai
|
|
69
|
+
MODEL=gpt-4o-mini
|
|
70
|
+
PROMPT_STYLE=default
|
|
71
|
+
COMMIT_STYLE=conventional
|
|
72
|
+
OPENAI_API_KEY=sk-...
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Or for Gemini:
|
|
76
|
+
```
|
|
77
|
+
PROVIDER=gemini
|
|
78
|
+
MODEL=gemini-2.5-flash
|
|
79
|
+
PROMPT_STYLE=default
|
|
80
|
+
COMMIT_STYLE=conventional
|
|
81
|
+
GEMINI_API_KEY=your-gemini-api-key
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Environment Variables:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
export COMMITA_PROVIDER=openai
|
|
88
|
+
export COMMITA_MODEL=gpt-4o-mini
|
|
89
|
+
export COMMITA_PROMPT_STYLE=default
|
|
90
|
+
export COMMITA_COMMIT_STYLE=emoji
|
|
91
|
+
export OPENAI_API_KEY=sk-...
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Or for Gemini:
|
|
95
|
+
```bash
|
|
96
|
+
export COMMITA_PROVIDER=gemini
|
|
97
|
+
export COMMITA_MODEL=gemini-2.5-flash
|
|
98
|
+
export GEMINI_API_KEY=your-gemini-api-key
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Configuration Options
|
|
102
|
+
|
|
103
|
+
- **PROVIDER**: AI provider to use - `openai` or `gemini` (default: `openai`)
|
|
104
|
+
- **MODEL**: Model name to use (provider-specific)
|
|
105
|
+
- **OpenAI**: `gpt-4o-mini`, `gpt-4o`, `gpt-4-turbo`, etc.
|
|
106
|
+
- **Gemini**: `gemini-2.5-flash`, `gemini-2.5-pro`, `gemini-1.5-pro`, etc.
|
|
107
|
+
- **PROMPT_STYLE**: One of `default`, `detailed`, `minimal`, or `custom`
|
|
108
|
+
- **PROMPT_TEMPLATE**: Custom prompt template (when using custom style)
|
|
109
|
+
- **CUSTOM_PROMPT**: Complete custom prompt (when using custom style)
|
|
110
|
+
- **COMMIT_STYLE**: Either `conventional` or `emoji`
|
|
111
|
+
- **OPENAI_API_KEY**: Your OpenAI API key (required when `PROVIDER=openai`)
|
|
112
|
+
- **GEMINI_API_KEY**: Your Gemini API key (required when `PROVIDER=gemini`)
|
|
113
|
+
|
|
114
|
+
**Note**: You can also use `GOOGLE_GENERATIVE_AI_API_KEY` environment variable instead of `GEMINI_API_KEY`.
|
|
115
|
+
|
|
116
|
+
### Prompt Styles
|
|
117
|
+
|
|
118
|
+
- **default**: Balanced analysis with clear instructions
|
|
119
|
+
- **detailed**: Deep analysis of code changes with context
|
|
120
|
+
- **minimal**: Quick, concise commit messages
|
|
121
|
+
- **custom**: Use your own prompt via `PROMPT_TEMPLATE` or `CUSTOM_PROMPT`
|
|
122
|
+
|
|
123
|
+
#### Using Custom Prompts
|
|
124
|
+
|
|
125
|
+
You can create your own prompt template using the `{diff}` placeholder:
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
PROMPT_STYLE=custom
|
|
129
|
+
CUSTOM_PROMPT=Analyze this diff and create a commit message: {diff}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Or use PROMPT_TEMPLATE for longer prompts:
|
|
133
|
+
```
|
|
134
|
+
PROMPT_STYLE=custom
|
|
135
|
+
PROMPT_TEMPLATE=You are an expert developer. Analyze the following changes and generate a clear commit message in conventional commit format. The diff is: {diff}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Commit Styles
|
|
139
|
+
|
|
140
|
+
**Conventional Commits:**
|
|
141
|
+
```
|
|
142
|
+
feat(components): add new button component
|
|
143
|
+
fix(utils): correct string formatting bug
|
|
144
|
+
refactor(services): restructure API client
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**Emoji Commits:**
|
|
148
|
+
```
|
|
149
|
+
✨(components): add new button component
|
|
150
|
+
🐛(utils): correct string formatting bug
|
|
151
|
+
♻️(services): restructure API client
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Emoji mappings:
|
|
155
|
+
- feat → ✨
|
|
156
|
+
- fix → 🐛
|
|
157
|
+
- refactor → ♻️
|
|
158
|
+
- chore → 🔧
|
|
159
|
+
- docs → 📝
|
|
160
|
+
- style → 💄
|
|
161
|
+
- test → ✅
|
|
162
|
+
- perf → ⚡
|
|
163
|
+
|
|
164
|
+
## Usage
|
|
165
|
+
|
|
166
|
+
**Important**: You must either have staged changes OR use the `--all` flag. The tool requires one of these to proceed.
|
|
167
|
+
|
|
168
|
+
### Basic Usage (with staged changes)
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
git add <files>
|
|
172
|
+
bun run index.ts
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Process All Changes
|
|
176
|
+
|
|
177
|
+
Group all unstaged changes by folder and create multiple commits:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
bun run index.ts --all
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Ignore Patterns
|
|
184
|
+
|
|
185
|
+
Exclude files matching patterns:
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
bun run index.ts --all --ignore "*.log,node_modules/*,dist/*"
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Skip Pushing
|
|
192
|
+
|
|
193
|
+
Don't push commits to remote:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
bun run index.ts --all --no-push
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Custom Config File
|
|
200
|
+
|
|
201
|
+
Use a different config file:
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
bun run index.ts --config .commita.local
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## How It Works
|
|
208
|
+
|
|
209
|
+
### Flow Example
|
|
210
|
+
|
|
211
|
+
Given these changes:
|
|
212
|
+
```
|
|
213
|
+
src/components/button.tsx
|
|
214
|
+
src/components/carousel.tsx
|
|
215
|
+
src/utils/url.ts
|
|
216
|
+
src/utils/strings.ts
|
|
217
|
+
src/services/ai/ai.ts
|
|
218
|
+
src/services/profile/profile.ts
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Running `commita --all` will create commits like:
|
|
222
|
+
|
|
223
|
+
```
|
|
224
|
+
feat(components): add new UI components
|
|
225
|
+
- Implement Button component with variants
|
|
226
|
+
- Add Carousel with auto-play feature
|
|
227
|
+
|
|
228
|
+
feat(utils): enhance utility functions
|
|
229
|
+
- Add URL parsing helper
|
|
230
|
+
- Improve string manipulation utilities
|
|
231
|
+
|
|
232
|
+
fix(ai): correct API integration
|
|
233
|
+
- Fix authentication flow
|
|
234
|
+
- Handle rate limiting
|
|
235
|
+
|
|
236
|
+
refactor(profile): restructure profile service
|
|
237
|
+
- Separate types into dedicated file
|
|
238
|
+
- Improve error handling
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Staged Changes Behavior
|
|
242
|
+
|
|
243
|
+
**Requirements**: You must provide either:
|
|
244
|
+
- Staged changes (via `git add`), OR
|
|
245
|
+
- The `--all` flag
|
|
246
|
+
|
|
247
|
+
**Behavior**:
|
|
248
|
+
- If you have **staged changes** and run without `--all`: processes staged files, grouped by folders, and creates multiple commits
|
|
249
|
+
- If you have **staged changes** and run with `--all`: ignores staged files and processes all unstaged changes grouped by folders
|
|
250
|
+
- If you have **no staged changes** and run without `--all`: exits with error
|
|
251
|
+
- **Note**: Commita temporarily unstages the files you selected so it can create one commit per folder, then restages and commits each group for you.
|
|
252
|
+
- Use this to control exactly which files get committed together
|
|
253
|
+
|
|
254
|
+
## Advanced Usage Examples
|
|
255
|
+
|
|
256
|
+
### Scenario 1: Multiple Feature Commits
|
|
257
|
+
|
|
258
|
+
You've been working on several features and want to commit them separately:
|
|
259
|
+
|
|
260
|
+
```bash
|
|
261
|
+
bun run index.ts --all
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
This will group files by their directories and create separate commits for each group.
|
|
265
|
+
|
|
266
|
+
### Scenario 2: Exclude Generated Files
|
|
267
|
+
|
|
268
|
+
Ignore build artifacts and logs:
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
bun run index.ts --all --ignore "dist/*,*.log,coverage/*"
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Scenario 3: Local Commits Only
|
|
275
|
+
|
|
276
|
+
Commit without pushing to remote:
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
bun run index.ts --all --no-push
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Scenario 4: Using Emoji Style
|
|
283
|
+
|
|
284
|
+
Set in your `.commita`:
|
|
285
|
+
```
|
|
286
|
+
COMMIT_STYLE=emoji
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
Then run:
|
|
290
|
+
```bash
|
|
291
|
+
bun run index.ts --all
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Troubleshooting
|
|
295
|
+
|
|
296
|
+
### "OpenAI API key is required" or "Gemini API key is required"
|
|
297
|
+
|
|
298
|
+
Make sure you have set your API key for the selected provider:
|
|
299
|
+
|
|
300
|
+
**For OpenAI:**
|
|
301
|
+
- `.commita` file: `OPENAI_API_KEY=sk-...`
|
|
302
|
+
- Environment variable: `export OPENAI_API_KEY=sk-...`
|
|
303
|
+
|
|
304
|
+
**For Gemini:**
|
|
305
|
+
- `.commita` file: `GEMINI_API_KEY=your-key`
|
|
306
|
+
- Environment variable: `export GEMINI_API_KEY=your-key`
|
|
307
|
+
- Or use: `export GOOGLE_GENERATIVE_AI_API_KEY=your-key`
|
|
308
|
+
|
|
309
|
+
### "No staged changes found"
|
|
310
|
+
|
|
311
|
+
This error occurs when you run the tool without the `--all` flag and have no staged changes. Either:
|
|
312
|
+
- Stage some changes: `git add <files>`
|
|
313
|
+
- Use the `--all` flag: `bun run index.ts --all`
|
|
314
|
+
|
|
315
|
+
### Provider Selection
|
|
316
|
+
|
|
317
|
+
Make sure you've selected the correct provider and set the corresponding API key:
|
|
318
|
+
- Set `PROVIDER=openai` and provide `OPENAI_API_KEY`
|
|
319
|
+
- Set `PROVIDER=gemini` and provide `GEMINI_API_KEY` (or `GOOGLE_GENERATIVE_AI_API_KEY`)
|
|
320
|
+
|
|
321
|
+
### Permission Denied
|
|
322
|
+
|
|
323
|
+
Make sure the script is executable:
|
|
324
|
+
```bash
|
|
325
|
+
chmod +x index.ts
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### Import Errors
|
|
329
|
+
|
|
330
|
+
The project uses Bun's built-in support for `@/` path aliases. Make sure you're running with Bun, not Node.js:
|
|
331
|
+
```bash
|
|
332
|
+
bun run index.ts # ✓ Correct
|
|
333
|
+
node index.ts # ✗ Won't work
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
## Development
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
bun install
|
|
340
|
+
bun run dev
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### Running Tests
|
|
344
|
+
|
|
345
|
+
```bash
|
|
346
|
+
bun test
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### Build to Binary
|
|
350
|
+
|
|
351
|
+
```bash
|
|
352
|
+
bun build index.ts --compile --outfile commita
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
## Contributing
|
|
356
|
+
|
|
357
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
358
|
+
|
|
359
|
+
## License
|
|
360
|
+
|
|
361
|
+
MIT
|
package/index.ts
ADDED
package/install.sh
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
REPO="misaelabanto/commita"
|
|
6
|
+
BINARY_NAME="commita"
|
|
7
|
+
INSTALL_DIR="/usr/local/bin"
|
|
8
|
+
|
|
9
|
+
# Colors
|
|
10
|
+
RED='\033[0;31m'
|
|
11
|
+
GREEN='\033[0;32m'
|
|
12
|
+
YELLOW='\033[1;33m'
|
|
13
|
+
CYAN='\033[0;36m'
|
|
14
|
+
NC='\033[0m' # No Color
|
|
15
|
+
|
|
16
|
+
info() { echo -e "${CYAN}[commita]${NC} $*"; }
|
|
17
|
+
success() { echo -e "${GREEN}[commita]${NC} $*"; }
|
|
18
|
+
warn() { echo -e "${YELLOW}[commita]${NC} $*"; }
|
|
19
|
+
error() { echo -e "${RED}[commita]${NC} $*" >&2; exit 1; }
|
|
20
|
+
|
|
21
|
+
# Detect OS
|
|
22
|
+
detect_os() {
|
|
23
|
+
local os
|
|
24
|
+
os=$(uname -s | tr '[:upper:]' '[:lower:]')
|
|
25
|
+
case "$os" in
|
|
26
|
+
darwin) echo "darwin" ;;
|
|
27
|
+
linux) echo "linux" ;;
|
|
28
|
+
msys*|mingw*|cygwin*) echo "windows" ;;
|
|
29
|
+
*) error "Unsupported OS: $os" ;;
|
|
30
|
+
esac
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
# Detect architecture
|
|
34
|
+
detect_arch() {
|
|
35
|
+
local arch
|
|
36
|
+
arch=$(uname -m)
|
|
37
|
+
case "$arch" in
|
|
38
|
+
x86_64|amd64) echo "amd64" ;;
|
|
39
|
+
arm64|aarch64) echo "arm64" ;;
|
|
40
|
+
*) error "Unsupported architecture: $arch" ;;
|
|
41
|
+
esac
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
# Check for required tools
|
|
45
|
+
check_deps() {
|
|
46
|
+
for cmd in curl; do
|
|
47
|
+
if ! command -v "$cmd" &>/dev/null; then
|
|
48
|
+
error "'$cmd' is required but not installed."
|
|
49
|
+
fi
|
|
50
|
+
done
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
# Get latest release tag from GitHub API
|
|
54
|
+
get_latest_tag() {
|
|
55
|
+
local tag
|
|
56
|
+
tag=$(curl -fsSL "https://api.github.com/repos/${REPO}/releases/latest" \
|
|
57
|
+
| grep '"tag_name"' \
|
|
58
|
+
| sed -E 's/.*"([^"]+)".*/\1/')
|
|
59
|
+
|
|
60
|
+
if [ -z "$tag" ]; then
|
|
61
|
+
error "Failed to fetch the latest release tag. Check your internet connection or visit https://github.com/${REPO}/releases."
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
echo "$tag"
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
main() {
|
|
68
|
+
check_deps
|
|
69
|
+
|
|
70
|
+
local os arch
|
|
71
|
+
os=$(detect_os)
|
|
72
|
+
arch=$(detect_arch)
|
|
73
|
+
|
|
74
|
+
# Windows is not supported via this script — direct users to releases
|
|
75
|
+
if [ "$os" = "windows" ]; then
|
|
76
|
+
error "Windows is not supported by this install script. Please download the binary manually from: https://github.com/${REPO}/releases"
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
local tag
|
|
80
|
+
tag=$(get_latest_tag)
|
|
81
|
+
|
|
82
|
+
local binary_file="${BINARY_NAME}-${os}-${arch}"
|
|
83
|
+
local download_url="https://github.com/${REPO}/releases/download/${tag}/${binary_file}"
|
|
84
|
+
local tmp_file
|
|
85
|
+
tmp_file=$(mktemp)
|
|
86
|
+
|
|
87
|
+
info "Detected platform: ${os}/${arch}"
|
|
88
|
+
info "Latest version: ${tag}"
|
|
89
|
+
info "Downloading ${binary_file}..."
|
|
90
|
+
|
|
91
|
+
if ! curl -fsSL --progress-bar "$download_url" -o "$tmp_file"; then
|
|
92
|
+
rm -f "$tmp_file"
|
|
93
|
+
error "Download failed. Please check: ${download_url}"
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
chmod +x "$tmp_file"
|
|
97
|
+
|
|
98
|
+
# Install to INSTALL_DIR, using sudo if needed
|
|
99
|
+
if [ -w "$INSTALL_DIR" ]; then
|
|
100
|
+
mv "$tmp_file" "${INSTALL_DIR}/${BINARY_NAME}"
|
|
101
|
+
else
|
|
102
|
+
warn "Installing to ${INSTALL_DIR} requires elevated privileges."
|
|
103
|
+
sudo mv "$tmp_file" "${INSTALL_DIR}/${BINARY_NAME}"
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
success "${BINARY_NAME} ${tag} installed to ${INSTALL_DIR}/${BINARY_NAME}"
|
|
107
|
+
echo ""
|
|
108
|
+
echo " Get started: commita --help"
|
|
109
|
+
echo " Docs: https://github.com/${REPO}#readme"
|
|
110
|
+
echo ""
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
main "$@"
|