Getting Started¶
Four ways to run Grippy: as an MCP server for local diff auditing, GitHub Actions with OpenAI, GitHub Actions with a self-hosted LLM, or locally for development.
1. MCP Server (Local Diff Auditing)¶
Grippy runs as an MCP server for local git diff auditing from Claude Code, Cursor, or Claude Desktop --- no GitHub Actions required.
Zero-install¶
Or install globally:
Two tools:
| Tool | What it does | LLM required? |
|---|---|---|
scan_diff |
Deterministic security rules | No |
audit_diff |
Full AI-powered code review | Yes |
Scope options (both tools):
- "staged" --- staged changes (git diff --cached)
- "commit:<ref>" --- a specific commit (e.g. "commit:HEAD")
- "range:<base>..<head>" --- commit range (e.g. "range:main..HEAD")
Install into your MCP client:
grippy install-mcp # registers uvx grippy-mcp in client configs
grippy install-mcp --dev # dev mode: uses uv run --directory
The installer detects Claude Code, Claude Desktop, and Cursor, then writes the server config with your chosen LLM transport and API keys.
2. GitHub Actions + OpenAI¶
The fastest path for CI integration. You need:
- A GitHub repository
- Python 3.12+
- An OpenAI API key
Step 1: Add your API key as a repository secret¶
Go to Settings > Secrets and variables > Actions and add OPENAI_API_KEY with your OpenAI key. The GITHUB_TOKEN is provided automatically by Actions.
Step 2: Add the workflow¶
Create .github/workflows/grippy-review.yml:
name: Grippy Review
on:
pull_request:
types: [opened, synchronize, reopened]
permissions:
contents: read
pull-requests: write
jobs:
review:
name: Grippy Code Review
runs-on: ubuntu-latest
steps:
- uses: step-security/harden-runner@a90bcbc6539c36a85cdfeb73f7e2f433735f215b # v2.15.0
with:
egress-policy: audit
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
with:
python-version: '3.12'
- name: Install Grippy
run: pip install "grippy-mcp"
- name: Run review
id: review
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_EVENT_PATH: ${{ github.event_path }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
GRIPPY_TRANSPORT: openai
GRIPPY_MODEL_ID: gpt-4.1
GRIPPY_EMBEDDING_MODEL: text-embedding-3-large
GRIPPY_DATA_DIR: ./grippy-data
GRIPPY_TIMEOUT: 300
# GRIPPY_PROFILE: security # Default — deterministic rules ON, gate fails on ERROR+
run: python -m grippy
All actions are SHA-pinned (not tag-pinned) for supply chain security.
Step 3: Verify¶
Open a pull request and check the Actions tab. Grippy will post inline findings on the diff and a summary comment with the score and verdict.
3. GitHub Actions + Self-Hosted LLM¶
Run your own model (Ollama, LM Studio, vLLM) and connect it to GitHub Actions via a Cloudflare Tunnel. No API keys to manage, no per-token costs.
See the Self-Hosted LLM Guide for the full tutorial, including tunnel setup, workflow configuration, and model recommendations.
4. Local Development¶
Clone and install¶
Install with uv:
Or with pip:
For other providers:
pip install "grippy-mcp[anthropic]" # Anthropic (Claude)
pip install "grippy-mcp[google]" # Google (Gemini)
pip install "grippy-mcp[groq]" # Groq
pip install "grippy-mcp[mistral]" # Mistral
Set environment variables¶
For OpenAI:
export OPENAI_API_KEY="sk-..." # pragma: allowlist secret
export GITHUB_TOKEN="ghp_..." # pragma: allowlist secret
For a local model (LM Studio, Ollama, etc.):
export GRIPPY_TRANSPORT=local # Valid: openai, anthropic, google, groq, mistral, local
export GRIPPY_BASE_URL="http://localhost:1234/v1"
export GRIPPY_MODEL_ID="devstral-small-2-24b-instruct-2512"
export GITHUB_TOKEN="ghp_..." # pragma: allowlist secret
# Optional: enable security rule engine
export GRIPPY_PROFILE=security
Create a mock event file¶
Grippy reads the PR payload from GITHUB_EVENT_PATH. For local testing, create an event.json:
{
"pull_request": {
"number": 1,
"title": "Test PR",
"user": { "login": "testuser" },
"head": { "ref": "feature-branch", "sha": "abc1234" },
"base": { "ref": "main" },
"body": "Test description"
},
"repository": {
"full_name": "your-org/your-repo"
}
}
Run¶
Caching¶
Add the actions/cache step to persist Grippy's LanceDB vector index and graph database between runs. This avoids re-indexing the codebase on every PR push.
- name: Cache Grippy data
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5
with:
path: ./grippy-data
key: grippy-data-${{ github.event.pull_request.number || 'manual' }}-${{ github.sha }}
restore-keys: |
grippy-data-${{ github.event.pull_request.number || 'manual' }}-
Place this step after checkout and before pip install. The cache is keyed per PR number and commit SHA, with fallback to the latest cache for that PR.
GitHub Actions Outputs¶
Grippy sets seven outputs after a successful review:
| Output | Description | Example |
|---|---|---|
score |
Overall score (0-100) | 72 |
verdict |
PASS, FAIL, or PROVISIONAL | PASS |
findings-count |
Number of findings | 3 |
merge-blocking |
Whether the review blocks merge | false |
rule-findings-count |
Deterministic rule hit count | 2 |
rule-gate-failed |
Whether rule gate caused CI failure | false |
profile |
Active security profile name | security |
Use these in subsequent workflow steps by referencing the step ID:
- name: Run review
id: review
run: python -m grippy
- name: Review summary
if: always()
run: |
echo "### Grippy Review Results" >> "$GITHUB_STEP_SUMMARY"
echo "- Score: ${{ steps.review.outputs.score }}" >> "$GITHUB_STEP_SUMMARY"
echo "- Verdict: ${{ steps.review.outputs.verdict }}" >> "$GITHUB_STEP_SUMMARY"
echo "- Findings: ${{ steps.review.outputs.findings-count }}" >> "$GITHUB_STEP_SUMMARY"
echo "- Merge blocking: ${{ steps.review.outputs.merge-blocking }}" >> "$GITHUB_STEP_SUMMARY"
- name: Block merge on failure
if: steps.review.outputs.merge-blocking == 'true'
run: exit 1