Provider-agnostic code review using AI
Use Claude, Gemini, Codex, OpenCode, Ollama, LM Studio, GitHub Models, or any AI to enforce your coding standards.
Zero dependencies. Pure Bash. Works everywhere.
Installation β’ Quick Start β’ Providers β’ Commands β’ Configuration β’ Caching β’ Development
You have coding standards. Your team ignores them. Code reviews catch issues too late.
Gentleman Guardian Angel runs on every commit, validating your staged files against your project's AGENTS.md (or any rules file). It's like having a senior developer review every line before it hits the repo.
βββββββββββββββββββ ββββββββββββββββ βββββββββββββββββββ
β git commit β βββΆ β AI Review β βββΆ β β
Pass/Fail β
β (staged files) β β (any LLM) β β (with details) β
βββββββββββββββββββ ββββββββββββββββ βββββββββββββββββββ
Key features:
- π Provider agnostic - Use whatever AI you have installed
- π¦ Zero dependencies - Pure Bash, no Node/Python/Go required
- πͺ Git native - Installs as a standard pre-commit hook
- βοΈ Highly configurable - File patterns, exclusions, custom rules
- π¨ Strict mode - Fail CI on ambiguous responses
- β‘ Smart caching - Skip unchanged files for faster reviews
- β±οΈ Timeout & progress - Configurable timeout with visual spinner
- π PR review mode - Review full PRs, not just last commit
- πΊ Homebrew ready - One command install
brew tap gentleman-programming/tap
brew install ggaOr in a single command:
brew install gentleman-programming/tap/ggagit clone https://github.com/Gentleman-Programming/gentleman-guardian-angel.git
cd gga
./install.shgga version
# Output: gga v2.7.0# 1. Go to your project
cd ~/your-project
# 2. Initialize config
gga init
# 3. Create your rules file
touch AGENTS.md # Add your coding standards
# 4. Install the git hook
gga install
# 5. Done! Now every commit gets reviewed πLet's walk through a complete example from setup to commit:
$ cd ~/projects/my-react-app
$ gga init
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Gentleman Guardian Angel v2.2.0
Provider-agnostic code review using AI
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
Created config file: .gga
βΉοΈ Next steps:
1. Edit .gga to set your preferred provider
2. Create AGENTS.md with your coding standards
3. Run: gga install$ cat .gga
# AI Provider (required)
PROVIDER="claude"
# File patterns to include in review (comma-separated)
FILE_PATTERNS="*.ts,*.tsx,*.js,*.jsx"
# File patterns to exclude from review (comma-separated)
EXCLUDE_PATTERNS="*.test.ts,*.spec.ts,*.test.tsx,*.spec.tsx,*.d.ts"
# File containing code review rules
RULES_FILE="AGENTS.md"
# Strict mode: fail if AI response is ambiguous
STRICT_MODE="true"$ cat > AGENTS.md << 'EOF'
# Code Review Rules
## TypeScript
- No `any` types - use proper typing
- Use `const` over `let` when possible
- Prefer interfaces over type aliases for objects
## React
- Use functional components with hooks
- No `import * as React` - use named imports like `import { useState }`
- All images must have alt text for accessibility
## Styling
- Use Tailwind CSS utilities only
- No inline styles or CSS-in-JS
- No hardcoded colors - use design system tokens
EOF$ gga install
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Gentleman Guardian Angel v2.2.0
Provider-agnostic code review using AI
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
Installed pre-commit hook: /Users/dev/projects/my-react-app/.git/hooks/pre-commit$ git add src/components/Button.tsx
$ git commit -m "feat: add new button component"
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Gentleman Guardian Angel v2.2.0
Provider-agnostic code review using AI
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βΉοΈ Provider: claude
βΉοΈ Rules file: AGENTS.md
βΉοΈ File patterns: *.ts,*.tsx,*.js,*.jsx
βΉοΈ Cache: enabled
Files to review:
- src/components/Button.tsx
βΉοΈ Sending to claude for review...
STATUS: FAILED
Violations found:
1. **src/components/Button.tsx:3** - TypeScript Rule
- Issue: Using `any` type for props
- Fix: Define proper interface for ButtonProps
2. **src/components/Button.tsx:15** - React Rule
- Issue: Using `import * as React`
- Fix: Use `import { useState, useCallback } from 'react'`
3. **src/components/Button.tsx:22** - Styling Rule
- Issue: Hardcoded color `#3b82f6`
- Fix: Use Tailwind class `bg-blue-500` instead
β CODE REVIEW FAILED
Fix the violations listed above before committing.$ git add src/components/Button.tsx
$ git commit -m "feat: add new button component"
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Gentleman Guardian Angel v2.2.0
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βΉοΈ Provider: claude
βΉοΈ Cache: enabled
Files to review:
- src/components/Button.tsx
βΉοΈ Sending to claude for review...
STATUS: PASSED
All files comply with the coding standards defined in AGENTS.md.
β
CODE REVIEW PASSED
[main 4a2b3c1] feat: add new button component
1 file changed, 45 insertions(+)
create mode 100644 src/components/Button.tsx| Command | Description | Example |
|---|---|---|
init |
Create sample .gga config file |
gga init |
install |
Install git pre-commit hook (default) | gga install |
install --commit-msg |
Install git commit-msg hook (for commit message validation) | gga install --commit-msg |
uninstall |
Remove git hooks from current repo | gga uninstall |
run |
Run code review on staged files | gga run |
run --ci |
Run code review on last commit (for CI/CD) | gga run --ci |
run --pr-mode |
Review all files changed in the full PR | gga run --pr-mode |
run --pr-mode --diff-only |
PR review with diffs only (faster, cheaper) | gga run --pr-mode --diff-only |
run --no-cache |
Run review ignoring cache | gga run --no-cache |
config |
Display current configuration and status | gga config |
cache status |
Show cache status for current project | gga cache status |
cache clear |
Clear cache for current project | gga cache clear |
cache clear-all |
Clear all cached data | gga cache clear-all |
help |
Show help message with all commands | gga help |
version |
Show installed version | gga version |
Creates a sample .gga configuration file in your project root with sensible defaults.
$ gga init
β
Created config file: .ggaInstalls a git hook that automatically runs code review on every commit.
Default (pre-commit hook):
$ gga install
β
Installed pre-commit hook: .git/hooks/pre-commitWith commit message validation (commit-msg hook):
$ gga install --commit-msg
β
Installed commit-msg hook: .git/hooks/commit-msgThe --commit-msg flag installs a commit-msg hook instead of pre-commit. This allows GGA to also validate your commit message (e.g., conventional commits format, issue references, etc.). The commit message is automatically included in the AI review.
If a hook already exists, GGA will append to it rather than replacing it.
Removes the git pre-commit hook from your repository.
$ gga uninstall
β
Removed pre-commit hookRuns code review on currently staged files. Uses intelligent caching by default to skip unchanged files.
$ git add src/components/Button.tsx
$ gga run
# Reviews the staged file (uses cache)
$ gga run --no-cache
# Forces review of all files, ignoring cacheShows the current configuration, including where config files are loaded from and all settings.
$ gga config
Current Configuration:
Config Files:
Global: Not found
Project: .gga
Values:
PROVIDER: claude
FILE_PATTERNS: *.ts,*.tsx,*.js,*.jsx
EXCLUDE_PATTERNS: *.test.ts,*.spec.ts
RULES_FILE: AGENTS.md
STRICT_MODE: true
TIMEOUT: 300s
PR_BASE_BRANCH: auto-detect
Rules File: FoundGGA includes intelligent caching to speed up reviews by skipping files that haven't changed.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Cache Logic β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 1. Hash AGENTS.md + .gga config β
β βββΊ If changed β Invalidate ALL cache β
β β
β 2. For each staged file: β
β βββΊ Hash file content β
β βββΊ If hash exists in cache with PASSED β Skip β
β βββΊ If not cached β Send to AI for review β
β β
β 3. After PASSED review: β
β βββΊ Store file hash in cache β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
The cache automatically invalidates when:
| Change | Effect |
|---|---|
| File content changes | Only that file is re-reviewed |
AGENTS.md changes |
All files are re-reviewed |
.gga config changes |
All files are re-reviewed |
# Check cache status
$ gga cache status
Cache Status:
Cache directory: ~/.cache/gga/a1b2c3d4...
Cache validity: Valid
Cached files: 12
Cache size: 4.0K
# Clear project cache
$ gga cache clear
β
Cleared cache for current project
# Clear all cache (all projects)
$ gga cache clear-all
β
Cleared all cache data# Force review all files, ignoring cache
gga run --no-cache~/.cache/gga/
βββ <project-hash-1>/
β βββ metadata # Hash of AGENTS.md + .gga
β βββ files/
β βββ <file-hash-a> # "PASSED"
β βββ <file-hash-b> # "PASSED"
βββ <project-hash-2>/
βββ ...
Use whichever AI CLI you have installed:
| Provider | Config Value | CLI Command Used | Installation |
|---|---|---|---|
| Claude | claude |
echo "prompt" | claude --print |
claude.ai/code |
| Gemini | gemini |
echo "prompt" | gemini |
github.com/google-gemini/gemini-cli |
| Codex | codex |
codex exec "prompt" |
npm i -g @openai/codex |
| OpenCode | opencode |
echo "prompt" | opencode run |
opencode.ai |
| Ollama | ollama:<model> |
ollama run <model> "prompt" |
ollama.ai |
| LM Studio | lmstudio[:model] |
HTTP API call to local server | lmstudio.ai |
| GitHub Models | github:<model> |
HTTP API via gh auth token |
github.com/marketplace/models |
# Use Claude (recommended - most reliable)
PROVIDER="claude"
# Use Google Gemini
PROVIDER="gemini"
# Use OpenAI Codex
PROVIDER="codex"
# Use OpenCode (uses default model)
PROVIDER="opencode"
# Use OpenCode with specific model
PROVIDER="opencode:anthropic/claude-opus-4-5"
# Use Ollama with Llama 3.2
PROVIDER="ollama:llama3.2"
# Use Ollama with CodeLlama (optimized for code)
PROVIDER="ollama:codellama"
# Use Ollama with Qwen Coder
PROVIDER="ollama:qwen2.5-coder"
# Use Ollama with DeepSeek Coder
PROVIDER="ollama:deepseek-coder"
# Use LM Studio with default model
PROVIDER="lmstudio"
# Use LM Studio with specific model
PROVIDER="lmstudio:llama-3.2-3b-instruct"
# Use LM Studio with custom host
LMSTUDIO_HOST="http://localhost:8080/v1"
PROVIDER="lmstudio"
# Use GitHub Models (requires: gh auth login)
PROVIDER="github:gpt-4o"
PROVIDER="github:gpt-4.1"
PROVIDER="github:deepseek-r1"
PROVIDER="github:grok-3"Create this file in your project root:
# AI Provider (required)
# Options: claude, gemini, codex, opencode, ollama:<model>, lmstudio[:model], github:<model>
PROVIDER="claude"
# File patterns to review (comma-separated globs)
# Default: * (all files)
FILE_PATTERNS="*.ts,*.tsx,*.js,*.jsx"
# Patterns to exclude from review (comma-separated globs)
# Default: none
EXCLUDE_PATTERNS="*.test.ts,*.spec.ts,*.d.ts"
# File containing your coding standards
# Default: AGENTS.md
RULES_FILE="AGENTS.md"
# Fail if AI response is ambiguous (recommended for CI)
# Default: true
STRICT_MODE="true"
# Timeout in seconds for AI provider response
# Default: 300 (5 minutes)
TIMEOUT="300"
# Base branch for --pr-mode (auto-detects main/master/develop if empty)
# PR_BASE_BRANCH="main"| Option | Required | Default | Description |
|---|---|---|---|
PROVIDER |
β Yes | - | AI provider to use |
FILE_PATTERNS |
No | * |
Comma-separated file patterns to include |
EXCLUDE_PATTERNS |
No | - | Comma-separated file patterns to exclude |
RULES_FILE |
No | AGENTS.md |
Path to your coding standards file |
STRICT_MODE |
No | true |
Fail on ambiguous AI responses |
TIMEOUT |
No | 300 |
Max seconds to wait for AI response |
PR_BASE_BRANCH |
No | auto-detect | Base branch for --pr-mode |
- Environment variable
GGA_PROVIDER,GGA_TIMEOUT(highest priority) - Project config
.gga(in project root) - Global config
~/.config/gga/config(lowest priority)
# Override provider for a single run
GGA_PROVIDER="gemini" gga run
# Or export for the session
export GGA_PROVIDER="ollama:llama3.2"
# Override timeout for a single run
GGA_TIMEOUT=600 gga runThe AI needs to know your standards. Create an AGENTS.md file.
Your rules file should be optimized for LLM parsing, not for human documentation. Here's why and how:
Large files dilute the AI's focus. A focused, concise file produces better reviews.
# β Bad: Verbose explanations
## TypeScript Guidelines
When writing TypeScript code, it's important to consider type safety.
The `any` type should be avoided because it defeats the purpose of
using TypeScript in the first place. Instead, you should always...
(continues for 50 more lines)
# β
Good: Direct and actionable
## TypeScript
REJECT if:
- `any` type used
- Missing return types on public functions
- Type assertions without justificationUse REJECT, REQUIRE, PREFER to give the AI clear signals:
| Keyword | Meaning | AI Action |
|---|---|---|
REJECT if |
Hard rule, must fail | Returns STATUS: FAILED |
REQUIRE |
Mandatory pattern | Returns STATUS: FAILED if missing |
PREFER |
Soft recommendation | May note but won't fail |
For large projects or monorepos, use references instead of concatenating multiple files:
# Code Review Rules
## References
- UI guidelines: `ui/AGENTS.md`
- API guidelines: `api/AGENTS.md`
- Shared rules: `docs/CODE-STYLE.md`
---
## Critical Rules (ALL files)
REJECT if:
- Hardcoded secrets/credentials
- `console.log` in production code
- Missing error handlingWhy references work: Claude, Gemini, and Codex have built-in tools to read files. When they see a reference like "ui/AGENTS.md", they can go read it if they need more context. This keeps your main file focused while allowing deep dives when needed.
β οΈ Note for Ollama users: Ollama is a pure LLM without file-reading tools. If you use Ollama and need multiple rules files, you'll need to manually consolidate them into one file.
Use bullet points, not paragraphs. The AI scans faster:
# β
Good: Scannable structure
## TypeScript/React
REJECT if:
- `import * as React` β use `import { useState }`
- Union types `type X = "a" | "b"` β use `const X = {...} as const`
- `any` type without `// @ts-expect-error` justification
PREFER:
- Named exports over default exports
- Composition over inheritanceHere's a battle-tested example from a production monorepo:
# Code Review Rules
## References
- UI details: `ui/AGENTS.md`
- SDK details: `sdk/AGENTS.md`
---
## ALL FILES
REJECT if:
- Hardcoded secrets/credentials
- `any` type (TypeScript) or missing type hints (Python)
- Code duplication (violates DRY)
- Silent error handling (empty catch blocks)
---
## TypeScript/React
REJECT if:
- `import React` β use `import { useState }`
- `var()` or hex colors in className β use Tailwind
- `useMemo`/`useCallback` without justification (React 19 Compiler handles this)
- Missing `"use client"` in client components
PREFER:
- `cn()` for conditional class merging
- Semantic HTML over divs
- Colocated files (component + test + styles)
---
## Python
REJECT if:
- Missing type hints on public functions
- Bare `except:` without specific exception
- `print()` instead of `logger`
REQUIRE:
- Docstrings on all public classes/methods
---
## Response Format
FIRST LINE must be exactly:
STATUS: PASSED
or
STATUS: FAILED
If FAILED, list: `file:line - rule violated - issue`This file is 89 lines, uses clear keywords, and has references for component-specific rules.
π‘ Pro tip: Your
AGENTS.mdcan also serve as documentation for human reviewers!
# .gga
PROVIDER="claude"
FILE_PATTERNS="*.ts,*.tsx"
EXCLUDE_PATTERNS="*.test.ts,*.test.tsx,*.spec.ts,*.d.ts,*.stories.tsx"
RULES_FILE="AGENTS.md"# .gga
PROVIDER="lmstudio:codellama"
FILE_PATTERNS="*.py"
EXCLUDE_PATTERNS="*_test.py,test_*.py,conftest.py,__pycache__/*"
RULES_FILE=".coding-standards.md"# .gga
PROVIDER="gemini"
FILE_PATTERNS="*.go"
EXCLUDE_PATTERNS="*_test.go,mock_*.go,*_mock.go"# .gga
PROVIDER="claude"
FILE_PATTERNS="*.ts,*.tsx,*.py,*.go"
EXCLUDE_PATTERNS="*.test.*,*_test.*,*.mock.*,*.d.ts,dist/*,build/*"git commit -m "feat: add feature"
β
βΌ
βββββββββββββββββββββββββββββββββββββββββ
β Pre-commit Hook (gga run) β
βββββββββββββββββββββββββββββββββββββββββ
β
ββββΆ 1. Load config from .gga
β
ββββΆ 2. Validate provider is installed
β
ββββΆ 3. Check AGENTS.md exists
β
ββββΆ 4. Get staged files matching FILE_PATTERNS
β (excluding EXCLUDE_PATTERNS)
β
ββββΆ 5. Read coding rules from AGENTS.md
β
ββββΆ 6. Build prompt: rules + file contents
β
ββββΆ 7. Send to AI provider (with timeout + progress)
β (claude/gemini/codex/opencode/ollama/lmstudio/github)
β
ββββΆ 8. Parse response
β
βββ "STATUS: PASSED" βββΆ β
Commit proceeds
β
βββ "STATUS: FAILED" βββΆ β Commit blocked
(shows violation details)
Sometimes you need to commit without review:
# Skip pre-commit hook entirely
git commit --no-verify -m "wip: work in progress"
# Short form
git commit -n -m "hotfix: urgent fix"Gentleman Guardian Angel works standalone with native git hooks, but you can also integrate it with popular hook managers.
This is what gga install does automatically:
# .git/hooks/pre-commit
#!/usr/bin/env bash
gga run || exit 1Husky is popular in JavaScript/TypeScript projects.
# Install husky
npm install -D husky
# Initialize husky
npx husky initEdit .husky/pre-commit:
#!/usr/bin/env bash
# Run Gentleman Guardian Angel
gga run || exit 1
# Your other checks (optional)
npm run lint
npm run typecheck# Install dependencies
npm install -D husky lint-stagedpackage.json:
{
"scripts": {
"prepare": "husky"
},
"lint-staged": {
"*.{ts,tsx,js,jsx}": ["eslint --fix", "prettier --write"]
}
}.husky/pre-commit:
#!/usr/bin/env bash
# AI Review first (uses git staged files internally)
gga run || exit 1
# Then lint-staged for formatting
npx lint-stagedpre-commit is the standard for Python projects.
# Install pre-commit
pip install pre-commit
# Or with brew
brew install pre-commitCreate .pre-commit-config.yaml:
repos:
# Gentleman Guardian Angel (runs first)
- repo: local
hooks:
- id: gga
name: Gentleman Guardian Angel
entry: gga run
language: system
pass_filenames: false
stages: [pre-commit]
# Your other hooks
- repo: https://github.com/psf/black
rev: 24.4.2
hooks:
- id: black
- repo: https://github.com/pycqa/flake8
rev: 7.0.0
hooks:
- id: flake8
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.10.0
hooks:
- id: mypyInstall the hooks:
pre-commit install# Run all hooks
pre-commit run --all-files
# Run only AI review
pre-commit run ggaLefthook is a fast Git hooks manager written in Go.
# Install
brew install lefthook
# Or with npm
npm install -D lefthookCreate lefthook.yml:
pre-commit:
parallel: false
commands:
ai-review:
run: gga run
fail_text: "Gentleman Guardian Angel failed. Fix violations before committing."
lint:
glob: "*.{ts,tsx,js,jsx}"
run: npm run lint
typecheck:
run: npm run typecheckInstall hooks:
lefthook installYou can also run Gentleman Guardian Angel in your CI pipeline:
# .github/workflows/ai-review.yml
name: Gentleman Guardian Angel
on:
pull_request:
types: [opened, synchronize]
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Gentleman Guardian Angel
run: |
git clone https://github.com/Gentleman-Programming/gentleman-guardian-angel.git /tmp/gga
chmod +x /tmp/gga/bin/gga
echo "/tmp/gga/bin" >> $GITHUB_PATH
- name: Install Claude CLI
run: |
# Install your preferred provider CLI
npm install -g @anthropic-ai/claude-code
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
- name: Run AI Review
run: |
# Review all files changed in the PR
gga run --pr-mode
# Or with diffs only (faster, cheaper)
# gga run --pr-mode --diff-only# .gitlab-ci.yml
gga:
stage: test
image: ubuntu:latest
before_script:
- apt-get update && apt-get install -y git curl
- git clone https://github.com/Gentleman-Programming/gentleman-guardian-angel.git /opt/gga
- export PATH="/opt/gga/bin:$PATH"
# Install your provider CLI here
script:
- git diff --name-only $CI_MERGE_REQUEST_DIFF_BASE_SHA | xargs git add
- gga run
only:
- merge_requests# Check if your provider CLI is installed and in PATH
which claude # Should show: /usr/local/bin/claude or similar
which gemini
which codex
which ollama
# Test if the provider works
echo "Say hello" | claude --print
# For LM Studio, check if the API is accessible
curl http://localhost:1234/v1/modelsThe tool requires a rules file to know what to check:
# Create your rules file
touch AGENTS.md
# Add your coding standards
echo "# My Coding Standards" > AGENTS.md
echo "- No console.log in production" >> AGENTS.mdThe AI must respond with STATUS: PASSED or STATUS: FAILED as the first line. If it doesn't:
- Try Claude (most reliable at following instructions)
- Check your rules file isn't confusing the AI
- Temporarily disable strict mode:
STRICT_MODE="false"
The tool sends full file contents. For better performance:
# Add large/generated files to exclude
EXCLUDE_PATTERNS="*.min.js,*.bundle.js,dist/*,build/*,*.generated.ts"# 1. Install GitHub CLI
brew install gh
# 2. Authenticate
gh auth login
# 3. Configure GGA
echo 'PROVIDER="github:gpt-4o"' > .gga
# Available models: https://github.com/marketplace/modelsIf reviews are timing out (exit code 124):
# Increase timeout (default: 300s)
TIMEOUT="600" # In .gga config
GGA_TIMEOUT=600 gga run # Or via environment variable
# Review fewer files at once
EXCLUDE_PATTERNS="*.min.js,*.bundle.js,dist/*"If you get "Failed to connect to LM Studio" errors:
- Ensure LM Studio is running and the API server is enabled
- Check the API port in LM Studio settings (default: 1234)
- Verify the host setting:
# Default LMSTUDIO_HOST="http://localhost:1234/v1" # Custom port LMSTUDIO_HOST="http://localhost:8080/v1"
- Test the connection:
curl http://localhost:1234/v1/models
gentleman-guardian-angel/
βββ bin/
β βββ gga # Main CLI script
βββ lib/
β βββ providers.sh # AI provider implementations
β βββ cache.sh # Smart caching logic
β βββ pr_mode.sh # PR review mode functions
βββ spec/ # ShellSpec test suite
β βββ spec_helper.sh # Test setup and helpers
β βββ unit/
β β βββ cache_spec.sh # Cache unit tests
β β βββ providers_spec.sh # Provider unit tests
β β βββ github_models_spec.sh # GitHub Models tests
β β βββ pr_mode_spec.sh # PR mode tests
β β βββ timeout_spec.sh # Timeout/spinner tests
β β βββ status_parsing_spec.sh # STATUS parsing tests
β βββ integration/
β βββ commands_spec.sh # CLI integration tests
β βββ ollama_spec.sh # Ollama integration (local)
β βββ github_models_spec.sh # GitHub Models integration (local)
βββ Makefile # Development commands
βββ .shellspec # Test runner config
βββ install.sh # Manual installer
βββ uninstall.sh # Uninstaller
βββ README.md
GGA uses ShellSpec for testing - a BDD-style testing framework for shell scripts.
# Install dependencies (once)
brew install shellspec shellcheck
# Run all tests
make test
# Run specific test suites
make test-unit # Unit tests only
make test-integration # Integration tests only
# Lint shell scripts with shellcheck
make lint
# Run all checks before commit (lint + tests)
make check| Module | Tests | Description |
|---|---|---|
cache.sh |
26 | Hash functions, cache validation, file caching |
providers.sh |
98 | All providers, routing, validation, security |
github_models |
16 | GitHub Models provider, API, auth, error handling |
pr_mode |
26 | Base branch detection, PR files, diff, prompt building |
timeout |
19 | Timeout wrapper, spinner, provider routing |
status_parsing |
14 | STATUS: PASSED/FAILED parsing edge cases |
| Integration | 34+ | CLI commands, Ollama, GitHub Models (local) |
| Total | 174 | Full coverage of core functionality |
# Create a new spec file
touch spec/unit/my_feature_spec.sh
# Run only your new tests
shellspec spec/unit/my_feature_spec.sh- β
feat: Timeout & progress feedback for AI provider calls (#35, based on PR #20 by @ramarivera)
- Configurable
TIMEOUT(default: 300s) withGGA_TIMEOUTenv override - Visual spinner in TTY mode, periodic text updates in CI/pipes
- Exit code 124 on timeout with troubleshooting suggestions
- Generic fallback for unknown/future providers
- 19 new tests
- Configurable
- β
feat: GitHub Models provider (#36, based on PR #3 by @Kyonax)
PROVIDER="github:<model>"β access GPT-4o, DeepSeek R1, Grok 3, Phi-4, LLaMA, etc.- Auth via
gh auth tokenβ no extra API keys needed - Uses python3 for safe JSON (no jq dependency)
- 16 new tests
- β
feat: PR review mode (#37, based on PR #30 by @Jose-cd)
--pr-mode: review all files changed in the full PR range--diff-only: with--pr-mode, send only diffs (faster, cheaper)- Auto-detects base branch (main/master/develop) with
PR_BASE_BRANCHconfig override - 26 new tests
- β 174 tests total, 0 failures
- β
fix: Relaxed STATUS parsing to handle AI preamble text (#18, PR #19)
- Search for STATUS in first 15 lines instead of requiring line 1
- Accept markdown formatting (
**STATUS: PASSED**) - Works with AI agents that have system-wide instruction files (AGENTS.md, CLAUDE.md)
- β 14 new tests for STATUS parsing edge cases
- β 161 tests total
- β
feat: Commit message validation support (PR #17, based on #11 by @ramarivera)
gga install --commit-msginstalls commit-msg hook instead of pre-commit- Commit message is automatically included in AI review when available
- No config needed - behavior is automatic based on context
- β
fix: Read from staging area (
git show :file) to prevent index corruption (#15, #16)- Fixes race conditions when files are modified after staging
- Works correctly with lint-staged, prettier, and other tools
- β feat: Signal handling for graceful cleanup on interruption
- β
gga uninstallnow handles both pre-commit and commit-msg hooks - β 147 tests (17 new for commit-msg and staging area fixes)
- β
fix(gemini): Use
-pflag for non-interactive prompt passing - fixes exit code 41 in CI - β fix(opencode): Use positional argument instead of stdin pipe per documentation
- β Both providers now work correctly in CI/non-interactive environments
- β
feat: OpenCode provider support (PR #4 by @ramarivera)
PROVIDER="opencode"for default modelPROVIDER="opencode:model_name"for specific models
- β
Added
CONTRIBUTING.mdwith development guide - β 130 tests (12 new for OpenCode)
- β
feat: CI mode (
--ciflag) for GitHub Actions/GitLab CI- Reviews files from last commit (
HEAD~1..HEAD) instead of staged files - Cache automatically disabled in CI mode
- Reviews files from last commit (
- β 118 tests (6 new for CI mode)
- β Fixed Ollama ANSI escape codes breaking STATUS parsing (#6)
- β
New
execute_ollama_api()using curl for clean JSON responses - β
Fallback
execute_ollama_cli()with ANSI stripping - β
Security validation for
OLLAMA_HOST - β Worktree support and improved hook install/uninstall (PR #10 by @ramarivera)
- β Best practices docs for AGENTS.md rules file
- β GitHub Actions CI pipeline (lint, unit tests, integration tests)
- β Expanded test suite to 104 tests
- β Added comprehensive test suite with 68 tests
- β
Unit tests for
cache.shandproviders.sh - β Integration tests for all CLI commands
- β
Added
Makefilewithtest,lint,checktargets - β Fixed shellcheck warnings
- β Smart caching system - skip unchanged files
- β Auto-invalidation when AGENTS.md or .gga changes
- β
Cache commands:
status,clear,clear-all - β
--no-cacheflag to bypass caching
- β Renamed to Gentleman Guardian Angel (gga)
- β
Auto-migration from legacy
ai-code-reviewhooks - β Homebrew tap distribution
- β Initial release with Claude, Gemini, Codex, Ollama support
- β File patterns and exclusions
- β Strict mode for CI/CD
Contributions are welcome! Some ideas:
- Add more providers (Copilot, Codeium, etc.)
- Support for
.gga.yamlformat -
Caching to avoid re-reviewing unchanged filesβ Done in v2.1.0 -
Add test suiteβ Done in v2.2.0 -
CI mode for GitHub Actions/GitLabβ Done in v2.4.0 -
OpenCode providerβ Done in v2.5.0 (by @ramarivera) -
Timeout & progress feedbackβ Done in v2.7.0 (based on @ramarivera) -
GitHub Models providerβ Done in v2.7.0 (based on @Kyonax) -
PR review modeβ Done in v2.7.0 (based on @Jose-cd) - Configurable temperature per provider
- GitHub Action version
- Output formats (JSON, SARIF for IDE integration)
# Fork, clone, and submit PRs!
git clone https://github.com/Gentleman-Programming/gentleman-guardian-angel.git
cd gentleman-guardian-angel
# Run tests before submitting
make checkMIT Β© 2024
Built with π§ by developers who got tired of repeating the same code review comments
