Skip to content

AgentGino/gt

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

33 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

gt

AI-powered git commit tool. Uses OpenRouter to generate per-file commit messages from diffs, presented in a rich terminal UI.

Why

Vibe coding with AI generates a high volume of changes — dozens of files touched per prompt. Manually writing commit messages for each file, staging, committing, and pushing becomes the bottleneck. gt removes that friction: it reads your diffs, generates per-file conventional commit messages, and lets you select, commit, and push everything from a single TUI. You stay in flow instead of context-switching to git housekeeping.

How it works

  1. gt reads git status and generates diffs for each changed file.
  2. Diffs are sent to an AI model (via OpenRouter) to produce conventional commit messages (type(scope): description).
  3. A TUI displays all changed files with their AI-generated messages.
  4. You select files, review messages, and commit — each file gets its own atomic commit.
  5. Push to the current branch or create a new branch, all from inside the TUI.

Prerequisites

Dependency Required Notes
Go 1.21+ Yes For building from source
Git Yes Core dependency
OpenRouter API key Yes Sign up and grab a key from the dashboard
GitHub CLI (gh) Optional Required for push (p) and repo creation (gt init -r)

Installation

Using Homebrew

brew update && brew install agentgino/tools/gt

From source

git clone https://github.com/agentgino/gt.git
cd gt
make build

This produces a gt binary in the project root. Move it somewhere on your $PATH:

sudo mv gt /usr/local/bin/

With go install

go install github.com/himakarreddy/gt/cmd/gt@latest

This installs gt to $GOPATH/bin (or $HOME/go/bin if $GOPATH is not set). Make sure that directory is in your $PATH.

Verify installation

gt --version

Getting started

Step 1: Configure API key and model

gt setup

This prompts you for your OpenRouter API key and opens an interactive model picker. Use j/k or arrow keys to navigate, type to filter, and press enter to select.

Enter your OpenRouter API key: sk-or-v1-abc123...
Fetching models from OpenRouter...

  Select a Model

  > type to filter models...

  ▸ openai/gpt-4o
    anthropic/claude-3.5-sonnet
    google/gemini-pro
    ...

  showing 142 models
  j/k or ↑/↓ to move • enter to select • q to quit

Config is saved to ~/.gt.yaml with 0600 permissions (owner read/write only).

Step 2: Initialize a repo (optional)

If you're starting a new project:

# Initialize git in an existing folder and create a GitHub repo with the folder name
gt init -r .

# Create a new folder, initialize git, and create a GitHub repo
gt init -r my-project

# Create under a GitHub organization
gt init -r my-org/my-project

# Create a public repo (default is private)
gt init -r my-project --public

# Use SSH URL instead of HTTPS
gt init -r my-project --ssh

If you just want git init without creating a GitHub repo:

gt init

Step 3: Make changes and commit

cd /path/to/your/repo
# ... edit files ...
gt status

This opens the TUI showing all changed files with AI-generated commit messages:

  gt  main → origin/main in sync  │  model: openai/gpt-4o
  ────────────────────────────────────────────────────────

  SEL  STATUS     FILE                          COMMIT MESSAGE
  ● modified   internal/git/git.go            feat(git): add HTTPS support for remote URLs
  ○ untracked  internal/logger/logger.go      feat(logger): implement structured slog logging
  ○ modified   cmd/gt/main.go                 feat(cli): add version flag and verbose logging

  ────────────────────────────────────────────────────────
  1 selected of 3 files

  space select │ a all │ j/k move │ r regen │ c commit │ p push │ q quit
  1. Use space to select/deselect files (or a to toggle all)
  2. Press c or enter to commit the selected files — each gets its own atomic commit
  3. Press p to push to remote

Commands

gt setup

Configure your OpenRouter API key and select an AI model interactively.

gt setup

What it does:

  • Prompts for your API key (validated: must be 8+ characters)
  • Fetches the full model list from OpenRouter
  • Opens an interactive picker with search/filter
  • Saves everything to ~/.gt.yaml

gt init

Initialize a git repository and optionally create a GitHub repository with remote.

gt init                          # just git init, no remote
gt init -r .                     # use current folder name as repo name
gt init -r my-project            # create folder + repo + remote
gt init -r org/my-project        # create under a GitHub organization
gt init -r my-project --public   # public repo (default: private)
gt init -r my-project --ssh      # use SSH URL (default: HTTPS)

Behavior by flag:

Command Creates folder git init GitHub repo Adds remote
gt init No Yes (cwd) No No
gt init -r . No Yes (cwd) Yes (folder name) Yes
gt init -r name Yes (name/) Yes Yes (name) Yes
gt init -r org/name Yes (name/) Yes Yes (org/name) Yes

Flags:

Flag Short Default Description
--repo -r (none) GitHub repo name. Use . for current folder
--public false Create a public repository
--ssh false Use SSH URL (git@github.com:...) instead of HTTPS

Requirements: The gh CLI must be installed and authenticated (gh auth login) for any -r flag usage.

gt status

The main command. Shows changed files with AI-generated commit messages in an interactive TUI.

gt status             # one-shot: show current changes
gt status -w          # watch mode: auto-refreshes on file changes

Flags:

Flag Short Default Description
--watch -w false Watch filesystem for changes and auto-refresh

Watch mode uses fsnotify to monitor the repo for file changes. When a file is saved, the TUI automatically refreshes the file list and regenerates commit messages only for files whose diffs actually changed (unchanged files keep their existing messages).

TUI keybindings

Key Action
j / k / / Navigate files
space Toggle file selection
a Select all / deselect all
c / enter Commit selected files (one commit per file)
r Regenerate AI message for the current file
p Push to remote (choose current branch or create new)
g Generate .gitignore with AI (shown only when missing)
q / ctrl+c Quit

Committing

When you press c, each selected file gets its own atomic commit with the AI-generated message. After committing, the file list refreshes automatically — committed files disappear, remaining files stay.

Pushing

When you press p, a chooser appears:

  Push to remote

  ▸ Push to current branch (main)
    Push to a new branch

  enter select  │  esc cancel
  • Current branch — runs git push (with -u if no upstream is set)
  • New branch — prompts for a branch name, creates it, and pushes with -u

Gitignore generation

If no .gitignore exists in the repo root, a warning banner appears with a prompt to press g. This scans your project files, sends the file listing to the AI, and generates a language-appropriate .gitignore. The file list refreshes afterward to hide newly-ignored files.

gt models

Switch the AI model after initial setup.

gt models

Opens the same interactive model picker as gt setup, but only changes the model (keeps your API key).

gt --version

Print the current version.

gt --version
# gt version v1.2.0

Version is injected at build time. When building with make build, it uses git describe --tags --always --dirty.


Global flags

These flags work with any command:

Flag Short Default Description
--version Print version and exit
--verbose -v false Enable debug logging to stderr

Verbose mode outputs structured logs (via log/slog) to stderr, useful for debugging API calls, git operations, and watcher events.

gt -v status

Configuration

Config is stored in ~/.gt.yaml with 0600 permissions:

api_key: "sk-or-v1-..."
model: "openai/gpt-4o"
remote_protocol: "https"    # "https" or "ssh" — default for new remotes
max_concurrent: 5            # parallel AI requests (1-20)
debounce_ms: 500             # watcher debounce interval in ms

Configuration options

Key Type Default Description
api_key string (none) Your OpenRouter API key
model string (none) AI model ID (e.g.openai/gpt-4o)
remote_protocol string "https" Default protocol for new remotes
max_concurrent int 5 Max parallel AI requests to OpenRouter
debounce_ms int 500 How long to wait after a file change before refreshing (ms)

max_concurrent controls how many commit messages are generated in parallel. Higher values are faster but may trigger OpenRouter rate limits. Lower values are safer for free-tier keys.

debounce_ms prevents rapid-fire refreshes when editors save multiple files at once (e.g. auto-format on save). The watcher waits this long after the last file change before refreshing.


Typical workflows

New project from scratch

mkdir my-app && cd my-app

# Initialize git + create private GitHub repo + add HTTPS remote
gt init -r .

# Configure AI
gt setup

# Write some code...
echo 'package main' > main.go

# Review AI-generated messages, select, commit, push
gt status

Existing project — batch commit after AI coding session

cd ~/projects/my-app

# See all changes with AI messages
gt status

# In the TUI:
# 1. Press 'a' to select all
# 2. Review messages, press 'r' on any file to regenerate
# 3. Press 'c' to commit all
# 4. Press 'p' to push

Watch mode during development

gt status -w

Leave this running in a terminal pane. Every time you save a file, the TUI refreshes and generates a new commit message. Select and commit when ready.


Commit message format

gt generates conventional commit messages:

type(scope): description
Type When
feat New feature or functionality
fix Bug fix
refactor Code restructuring without behavior change
docs Documentation changes
style Formatting, whitespace, missing semicolons
test Adding or updating tests
chore Maintenance, dependencies, config
perf Performance improvement
ci CI/CD changes
build Build system changes

The AI reads the actual diff line-by-line and generates specific messages describing what changed — not just the filename.


API and rate limits

gt uses OpenRouter as the AI provider. OpenRouter routes to 200+ models (OpenAI, Anthropic, Google, Meta, etc.) with a single API key.

  • Rate limiting: If you hit a 429, gt retries automatically with exponential backoff (up to 3 retries)
  • Server errors: 502/503 errors are also retried automatically
  • Timeouts: Each AI request has a 2-minute timeout
  • Diff truncation: Large diffs are truncated to 4000 characters to stay within token limits

Reduce max_concurrent in config if you're hitting rate limits frequently.


Building and development

Build

make build          # build binary with version from git tags
make install        # install to $GOPATH/bin

Test

make test           # run all tests
make test-race      # run with race detector
make test-cover     # generate coverage report (coverage.html)

Lint

make fmt            # go fmt
make vet            # go vet
make lint           # fmt + vet + golangci-lint

Build with custom version

go build -ldflags "-X main.Version=v2.0.0" -o gt ./cmd/gt

Project structure

gt/
├── cmd/gt/main.go                 # CLI entry point (cobra commands)
├── internal/
│   ├── ai/
│   │   ├── client.go              # OpenRouter API client with retry
│   │   └── client_test.go         # HTTP mock tests
│   ├── config/
│   │   ├── config.go              # YAML config with defaults
│   │   └── config_test.go         # Load/save/validation tests
│   ├── git/
│   │   ├── git.go                 # Git operations (status, diff, commit, push)
│   │   └── git_test.go            # Status parsing, branch, remote tests
│   ├── logger/
│   │   └── logger.go              # slog-based structured logging
│   ├── tui/
│   │   ├── status.go              # Main status TUI
│   │   └── modelselect.go         # Model selection TUI
│   └── watcher/
│       ├── watcher.go             # Filesystem watcher with debounce
│       └── watcher_test.go        # Watch/debounce/filter tests
├── go.mod
├── go.sum
├── Makefile
├── TODO.md
└── README.md

Troubleshooting

"not a git repository"

Run gt init in your project directory first, or make sure you're inside a git repo.

"run 'gt setup' first"

You need to configure an API key and model before using gt status. Run gt setup.

"GitHub CLI (gh) is not installed or not authenticated"

The push feature and gt init -r require the gh CLI:

# Install (macOS)
brew install gh

# Authenticate
gh auth login

Push fails with SSH errors

gt defaults to HTTPS remotes, which work with gh CLI auth. If your existing remote uses SSH and you don't have SSH keys configured:

# Check your remote URL
git remote get-url origin

# Switch to HTTPS
git remote set-url origin https://github.com/user/repo.git

Or configure SSH keys: https://docs.github.com/en/authentication/connecting-to-github-with-ssh

Rate limited by OpenRouter

Reduce parallel requests in ~/.gt.yaml:

max_concurrent: 2

Verbose/debug output

gt -v status

This prints structured logs to stderr showing API calls, git operations, and timing.


License

See LICENSE for details.

About

AI-powered git commit tool

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors