Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
run: bash -n gitai

- name: Run ShellCheck
run: shellcheck -e SC1091 gitai
run: shellcheck -S warning -e SC1091 gitai

- name: Validate Homebrew formula Ruby syntax
run: ruby -c Formula/gitai.rb
Expand All @@ -28,4 +28,5 @@ jobs:
test -x gitai
tmp="$(mktemp -d)"
git -C "$tmp" init
(cd "$tmp" && "$GITHUB_WORKSPACE/gitai" --version)
version="$(cd "$tmp" && "$GITHUB_WORKSPACE/gitai" --version)"
test "$version" = "gitai 0.3.0"
4 changes: 3 additions & 1 deletion Formula/gitai.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
class Gitai < Formula
desc "AI-assisted Conventional Commits with a terminal-native workflow"
homepage "https://github.com/jaavid/gitai"
url "https://github.com/jaavid/gitai.git", revision: "f9bd69c4958b3ae10ae83d19cc8d2b490ca4fd0b"
version "0.3.0"
head "https://github.com/jaavid/gitai.git", branch: "main"
license "MIT"

Expand All @@ -13,6 +15,6 @@ def install

test do
system "git", "init", testpath
assert_match "gitai 0.2.0", shell_output("#{bin}/gitai --version")
assert_match "gitai 0.3.0", shell_output("#{bin}/gitai --version")
end
end
205 changes: 89 additions & 116 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,192 +1,165 @@
# GitAI

GitAI is a small terminal-first assistant for generating Conventional Commit messages from staged Git changes, reviewing the result, committing it, and optionally pushing it to one or more remotes.

It stays close to normal Git instead of replacing your workflow. The UI uses [Gum](https://github.com/charmbracelet/gum) when available and falls back to plain terminal prompts when it is not.
GitAI is a terminal-first assistant for generating Conventional Commit messages from staged Git changes, reviewing the result, committing it, and optionally pushing it to one or more remotes.

## Features

- Generates Conventional Commit titles and descriptions from staged changes.
- Supports AvalAI, OpenRouter, Cloudflare Workers AI, and Google AI Studio (Gemini API).
- Supports provider fallback chains.
- Terminal UI for staging, reviewing, committing, and choosing a push target.
- Multi-remote aware: push to one remote or all configured remotes.
- Works well in Warp, iTerm2, Terminal.app, and other modern terminals without requiring terminal-specific APIs.
- Falls back to simple text prompts when Gum is unavailable or `GITAI_TUI=0`.
- Warns about changes outside the index and lets you keep the current staged set or stage everything.
- Trims very large diffs before sending them to an AI provider.
- User-wide and repository-specific configuration.

## Requirements

- `bash`
- `git`
- `curl`
- [`jq`](https://jqlang.github.io/jq/)
- [`gum`](https://github.com/charmbracelet/gum) for the richer terminal UI (optional outside Homebrew installs)
- Conventional Commit title + description generated from staged changes.
- Providers: AvalAI, OpenRouter, Cloudflare Workers AI, and Google AI Studio (Gemini).
- First-run credential setup when no usable API key is found.
- `gum`-based terminal UI with plain-shell fallback.
- Multi-remote push selection, including **All remotes**.
- Works cleanly in Warp without using a full-screen alternate buffer.
- Config discovery for old and new installations.
- Versioned Homebrew formula, while keeping `--HEAD` available for development builds.

## Install with Homebrew
## Homebrew

This repository contains a Homebrew formula. Until a dedicated `homebrew-tap` repository exists, add this repository as a custom tap and install the HEAD formula:
Add the tap once:

```bash
brew tap jaavid/gitai https://github.com/jaavid/gitai
brew install --HEAD jaavid/gitai/gitai
```

Upgrade later with:
Install the stable version:

```bash
brew update
brew upgrade --fetch-HEAD gitai
brew install jaavid/gitai/gitai
```

Homebrew installs `jq` and `gum` automatically.

### Manual install
Normal upgrades then work with:

```bash
git clone https://github.com/jaavid/gitai.git
cd gitai
install -m 755 gitai /usr/local/bin/gitai
brew update
brew upgrade gitai
```

## Configuration

GitAI reads configuration in this order, with later files overriding earlier values:

1. Legacy `.gitai` next to the executable, if present.
2. `~/.config/gitai/config` (or `$XDG_CONFIG_HOME/gitai/config`).
3. `.gitai` in the current repository root.
### If you previously installed with `--HEAD`

For API keys, prefer the user-wide config instead of committing credentials into a repository.

Create it with:
Older GitAI instructions used:

```bash
mkdir -p ~/.config/gitai
$EDITOR ~/.config/gitai/config
brew install --HEAD jaavid/gitai/gitai
```

Example:
That produces versions such as `HEAD-e7f82ea`, so Homebrew tracks Git commits rather than semantic releases. Switch once to the stable channel after this release is merged:

```bash
export GITAI_PROVIDER="google,openrouter,cloudflare,avalapis"
export GITAI_GOOGLE_API_KEY="your-google-key"
export GITAI_OPENROUTER_API_KEY="your-openrouter-key"
export GITAI_CLOUDFLARE_API_KEY="your-cloudflare-key"
export GITAI_AVALAPIS_API_KEY="your-avalapis-key"
export GITAI_CLOUDFLARE_ACCOUNT_ID="your-cloudflare-account-id"
brew reinstall jaavid/gitai/gitai
```

### Provider options

Set `GITAI_PROVIDER` to one provider or a comma-separated fallback chain:
Then verify:

- `avalapis` (default)
- `openrouter`
- `cloudflare`
- `google`
```bash
gitai --version
```

Examples:
Expected for this release:

```bash
export GITAI_PROVIDER="google,openrouter,cloudflare,avalapis"
```text
gitai 0.3.0
```

If you intentionally want the newest `main` commit instead of a release, use:

```bash
export GITAI_PROVIDER="openrouter"
brew reinstall --HEAD jaavid/gitai/gitai
brew upgrade --fetch-HEAD gitai
```

Global optional variables:

- `GITAI_API_BASE`: override endpoint URL for advanced/custom setups.
- `GITAI_MAX_DIFF_LENGTH`: maximum staged diff characters sent to a provider (default: `12000`).
- `GITAI_MODEL`: shared model override.
- `GITAI_TUI=0`: disable Gum and use plain terminal prompts.
Homebrew installs `jq` and `gum` automatically.

Per-provider API keys:
## Configuration and API keys

- `GITAI_AVALAPIS_API_KEY`
- `GITAI_OPENROUTER_API_KEY`
- `GITAI_CLOUDFLARE_API_KEY`
- `GITAI_GOOGLE_API_KEY`
GitAI reads config in this order; later files override earlier values:

Per-provider model overrides:
1. `.gitai` next to the executable.
2. `~/.bin/gitai/.gitai` — historical GitAI location.
3. `~/.config/gitai/config` or `$XDG_CONFIG_HOME/gitai/config`.
4. `<repo>/.gitai`.

- `GITAI_AVALAPIS_MODEL`
- `GITAI_OPENROUTER_MODEL`
- `GITAI_CLOUDFLARE_MODEL`
- `GITAI_GOOGLE_MODEL`
So an existing file such as:

Cloudflare additionally needs `GITAI_CLOUDFLARE_ACCOUNT_ID` unless `GITAI_API_BASE` is explicitly set.
```text
/Users/javid/.bin/gitai/.gitai
```

## Usage
continues to work without migration.

From any Git repository:
If no usable key exists for the configured provider(s), GitAI starts an interactive setup wizard. It asks for the provider and API key, masks the key while typing, and stores it in:

```bash
gitai
```text
~/.config/gitai/config
```

A typical flow is:
with mode `600`.

1. GitAI shows the repository, branch, and short status.
2. If needed, choose whether to stage all changes or keep only the current staged set.
3. GitAI sends only the staged diff to the configured AI provider chain.
4. Review the generated Conventional Commit message.
5. Confirm the commit.
6. Choose whether and where to push.
Run setup manually at any time:

If the repository has multiple remotes, GitAI presents all of them together with an **All remotes** option. The current branch is pushed explicitly to each selected remote.
```bash
gitai --setup
```

### Push options
Example config:

```bash
# Commit, then ask where to push
gitai --push
export GITAI_PROVIDER="google,openrouter,cloudflare,avalapis"
export GITAI_GOOGLE_API_KEY="your-google-key"
export GITAI_OPENROUTER_API_KEY="your-openrouter-key"
export GITAI_CLOUDFLARE_API_KEY="your-cloudflare-key"
export GITAI_AVALAPIS_API_KEY="your-avalapis-key"
export GITAI_CLOUDFLARE_ACCOUNT_ID="your-cloudflare-account-id"
```

# Commit and push to every configured remote
gitai --push-all
Supported providers:

# Commit without offering to push
gitai --no-push
```
- `google`
- `openrouter`
- `cloudflare`
- `avalapis`

### Disable the richer TUI
A comma-separated value in `GITAI_PROVIDER` acts as a fallback chain.

```bash
gitai --no-tui
```
## Usage

or:
From any Git repository:

```bash
export GITAI_TUI=0
gitai
```

## Warp compatibility

GitAI deliberately uses normal shell input/output rather than a full-screen alternate-buffer UI. In Warp this means each run remains a normal command block, output stays searchable/copyable, and Git/GitAI subprocess output remains visible in the same block.
Typical flow:

No Warp-specific configuration is required.
1. Load credentials or run setup.
2. Show branch and Git status.
3. Stage changes if needed.
4. Generate a commit message from the staged diff.
5. Review and confirm the commit.
6. Select a remote, all remotes, or skip pushing.

## CLI reference
Useful options:

```text
gitai [options]

--push Push after committing; asks for a remote when necessary
--setup Configure provider and API key
--push Push after committing; choose remote if needed
--push-all Push to every configured remote
--no-push Never ask to push
--no-tui Use plain prompts instead of Gum
-v, --version
-h, --help
```

## Contributing
## Warp

GitAI uses normal terminal input/output rather than a curses-style full-screen interface. In Warp, each run remains a regular command block, and Git/GitAI output stays searchable and copyable.

Issues and pull requests are welcome.
## Manual install

```bash
git clone https://github.com/jaavid/gitai.git
cd gitai
install -m 755 gitai /usr/local/bin/gitai
```

## License

Expand Down
Loading
Loading