AI-powered code review platform that automatically reviews pull requests, detects anti-patterns, security issues, and code quality problems using OpenCode.
OpenDiff is a SaaS platform that integrates with GitHub to provide:
- Automated Code Reviews - AI analyzes pull requests for anti-patterns, security vulnerabilities, performance issues, and bugs
- Intelligent Triage - Automatically fixes detected issues and commits changes back to the PR
- Team Collaboration - Organization-based access with role management and seat-based subscriptions
- Custom Skills - Define custom review instructions that the AI agent follows when reviewing your code
- Custom Review Rules - Configure per-repository review guidelines and coding standards
| Package | Description | Tech Stack |
|---|---|---|
bff |
Backend API with auth, billing, and data management | Hono, Prisma, PostgreSQL, Cloudflare R2 |
app |
Main console dashboard and management UI | React 19, Vite, Tailwind CSS v4 |
website |
Marketing website and landing pages | React 19, Vite, Tailwind CSS v4 |
review-agent |
GitHub webhook handler and AI code reviewer | Hono, OpenCode SDK, Octokit |
prompts |
Shared AI prompt templates with variable substitution | Bun |
components |
Shared UI component library | Radix UI, shadcn, CVA |
shared |
Shared business logic, hooks, and services | React Query, React Router |
github |
GitHub App auth and API utilities | Octokit |
vscode-extension |
VS Code extension for local code review | VS Code API |
assets |
Shared static assets (fonts, icons) | - |
Content sources used by the website:
- Blog articles:
packages/articles/README.md - Changelog entries:
packages/changelog/README.md
- Bun v1.1.29+
- PostgreSQL 15+
- GitHub App credentials
- Anthropic API Key
# Clone the repository
git clone https://github.com/antiptrn/opendiff.git
cd opendiff
# Install dependencies
bun installFor local development, each package requires its own environment configuration. Copy the example files and configure:
# Server
cp packages/bff/.env.example packages/bff/.env
# App (Console)
cp packages/app/.env.example packages/app/.env
# Website
cp packages/website/.env.example packages/website/.env
# Review Agent
cp packages/review-agent/.env.example packages/review-agent/.env# Database
DATABASE_URL=postgresql://user:password@localhost:5432/opendiff
# OAuth Providers
GITHUB_CLIENT_ID=xxx
GITHUB_CLIENT_SECRET=xxx
GOOGLE_CLIENT_ID=xxx
GOOGLE_CLIENT_SECRET=xxx
MICROSOFT_CLIENT_ID=xxx
MICROSOFT_CLIENT_SECRET=xxx
# GitHub App credentials (same values as review agent — used for fetching PR metadata)
GITHUB_APP_ID=xxx
GITHUB_PRIVATE_KEY_PATH=/path/to/private-key.pem
# URLs
FRONTEND_URL=http://localhost:5174
ALLOWED_ORIGINS=http://localhost:5173,http://localhost:5174
PORT=3001
# Redis (recommended for shared rate limiting)
REDIS_URL=redis://localhost:6379
# Optional: in production, keep false unless your proxy headers are trusted
RATE_LIMIT_TRUST_PROXY_HEADERS=false
# Optional: cooldown after Redis failures before retrying Redis (milliseconds)
REDIS_RATE_LIMIT_COOLDOWN_MS=10000
# Payment Provider ("polar" or "stripe")
PAYMENT_PROVIDER=polar
# Polar (when PAYMENT_PROVIDER=polar)
POLAR_ACCESS_TOKEN=polar_oat_xxx
POLAR_WEBHOOK_SECRET=polar_whs_xxx
POLAR_SERVER=sandbox
POLAR_ORGANIZATION_ID=xxx
POLAR_PRO_MONTHLY_PRODUCT_ID=xxx
POLAR_PRO_YEARLY_PRODUCT_ID=xxx
POLAR_ULTRA_MONTHLY_PRODUCT_ID=xxx
POLAR_ULTRA_YEARLY_PRODUCT_ID=xxx
POLAR_SELF_SUFFICIENT_MONTHLY_PRODUCT_ID=xxx
POLAR_SELF_SUFFICIENT_YEARLY_PRODUCT_ID=xxx
# Stripe (when PAYMENT_PROVIDER=stripe)
STRIPE_SECRET_KEY=sk_test_xxx
STRIPE_WEBHOOK_SECRET=whsec_xxx
STRIPE_PRO_MONTHLY_PRICE_ID=price_xxx
STRIPE_PRO_YEARLY_PRICE_ID=price_xxx
STRIPE_ULTRA_MONTHLY_PRICE_ID=price_xxx
STRIPE_ULTRA_YEARLY_PRICE_ID=price_xxx
STRIPE_SELF_SUFFICIENT_MONTHLY_PRICE_ID=price_xxx
STRIPE_SELF_SUFFICIENT_YEARLY_PRICE_ID=price_xxx
# Review Agent Integration
REVIEW_AGENT_API_KEY=xxx
REVIEW_AGENT_WEBHOOK_URL=http://localhost:3000
# Cloudflare R2 Storage
R2_ACCOUNT_ID=xxx
R2_ACCESS_KEY_ID=xxx
R2_SECRET_ACCESS_KEY=xxx
R2_BUCKET_NAME=opendiff
R2_PUBLIC_URL=https://cdn.example.comRate limiting notes:
- Redis-backed rate limits are enabled when
REDIS_URLis configured. - In production, requests should come through Cloudflare (or another trusted proxy) so
CF-Connecting-IPis available. - If you do not fully trust proxy headers, keep
RATE_LIMIT_TRUST_PROXY_HEADERS=false.
VITE_WEBSITE_URL=http://localhost:5173
# Dev server host allowlist (comma-separated)
VITE_ALLOWED_HOSTS=localhost,127.0.0.1,app.opendiff.dev,.opendiff.dev
# Optional: shared cookie domain for cross-subdomain theme sync
# Example: opendiff.dev
VITE_THEME_COOKIE_DOMAIN=
# Product/Price IDs (from Polar or Stripe dashboard)
VITE_PRO_MONTHLY_PRODUCT_ID=xxx
VITE_PRO_YEARLY_PRODUCT_ID=xxx
VITE_ULTRA_MONTHLY_PRODUCT_ID=xxx
VITE_ULTRA_YEARLY_PRODUCT_ID=xxx
VITE_SELF_SUFFICIENT_MONTHLY_PRODUCT_ID=xxx
VITE_SELF_SUFFICIENT_YEARLY_PRODUCT_ID=xxxVITE_API_URL=http://localhost:3001
VITE_APP_URL=http://localhost:5174
# Optional: GitHub repo slug for displaying live star count
# Example: antiptrn/opendiff
VITE_GITHUB_REPO=
# Dev server host allowlist (comma-separated)
VITE_ALLOWED_HOSTS=localhost,127.0.0.1,opendiff.dev,.opendiff.dev
# Product/Price IDs (from Polar or Stripe dashboard)
VITE_SELF_SUFFICIENT_MONTHLY_PRICE_ID=xxx
VITE_SELF_SUFFICIENT_YEARLY_PRICE_ID=xxx
VITE_PRO_MONTHLY_PRICE_ID=xxx
VITE_PRO_YEARLY_PRICE_ID=xxx
VITE_ULTRA_MONTHLY_PRICE_ID=xxx
VITE_ULTRA_YEARLY_PRICE_ID=xxxIf you use the included deploy/preview workflows, configure secrets on GitHub using environments:
-
Repo -> Settings -> Environments -> production -> SecretsDEPLOY_DIR(path to the trusted clone on your runner)GH_APP_PRIVATE_KEY_PATH(absolute path to your GitHub App PEM file on the runner)SLACK_WEBHOOK_URL(optional)
-
Repo -> Settings -> Environments -> preview -> SecretsDEPLOY_DIRPREVIEWS_BASE_DIRINGRESS_DIRPREVIEW_DB_PASSWORDPREVIEW_GITHUB_CLIENT_IDPREVIEW_GITHUB_CLIENT_SECRETSLACK_WEBHOOK_URL(optional)
Preview behavior is controlled by repo-level Actions variables (non-secret):
Repo -> Settings -> Secrets and variables -> Actions -> VariablesPREVIEW_DOMAIN,PREVIEW_*_SUBDOMAIN_PREFIX,PREVIEW_DB_*,PREVIEW_OAUTH_CALLBACK_BASE_URL,PREVIEW_BOT_USERNAME
# GitHub Webhook Secret
GITHUB_WEBHOOK_SECRET=xxx
# GitHub App Authentication (recommended)
GITHUB_APP_ID=xxx
GITHUB_PRIVATE_KEY_PATH=/path/to/private-key.pem
# Or: Personal Access Token (alternative)
# GITHUB_TOKEN=ghp_xxx
# AI provider credentials used by OpenCode
ANTHROPIC_API_KEY=sk-ant-xxx
# Bot configuration
BOT_USERNAME=opendiff-bot
BOT_TEAMS=
# Server Integration
SETTINGS_API_URL=http://localhost:3001
REVIEW_AGENT_API_KEY=xxx
PORT=3000cd packages/bff
# Generate Prisma client
bunx prisma generate
# Run migrations
bunx prisma migrate dev# Start all services concurrently
bun run start:dev
# Or start individually (in separate terminals)
bun run dev:server # Backend API on http://localhost:3001
bun run dev:app # Console dashboard on http://localhost:5174
bun run dev:website # Marketing site on http://localhost:5173
bun run dev:agent # Review agent on http://localhost:3000From the monorepo root:
# Development
bun run dev:server # Start server in watch mode
bun run dev:app # Start console app dev server
bun run dev:website # Start website dev server
bun run dev:agent # Start review agent in watch mode
bun run start:dev # Start all services concurrently
# Building
bun run build # Build website for production
bun run build:app # Build console app for production
bun run build:agent # Build review agent for production
bun run start:prod # Build all and start in production mode
# Code Quality
bun run lint # Lint all packages
bun run lint:fix # Auto-fix linting issues
bun run format # Format all code
bun run check # Run all checks
# Testing
bun run test # Run tests for all packages
# Process Management
bun run start:dev:nohup # Start all services in background (dev)
bun run start:prod:nohup # Start all services in background (prod)
bun run stop # Stop all background servicesThe project uses Biome for linting and formatting:
# Check for issues
bun run lint
# Auto-fix issues
bun run lint:fix
# Format code
bun run format# Run all tests
bun run test
# Run tests for specific package
cd packages/app && bun run test
cd packages/website && bun run test
cd packages/components && bun run test
cd packages/shared && bun run test
The AI reviewer analyzes code for:
| Category | Examples |
|---|---|
| Security | SQL injection, XSS, hardcoded secrets, insecure crypto |
| Anti-patterns | God objects, tight coupling, magic numbers, copy-paste code |
| Performance | N+1 queries, memory leaks, blocking operations |
| Style | Naming conventions, error handling, missing types |
| Bug Risks | Off-by-one errors, null safety, race conditions |
Skills are user-defined instructions that the AI agent follows during code reviews. Each skill includes:
- Name - Unique identifier (e.g.,
security-review,api-standards) - Description - Short description for skill routing
- Content - Detailed instructions for the agent
Skills are automatically applied based on the repository configuration and team membership.
- Critical - Must be fixed before merging
- Warning - Should be addressed
- Suggestion - Optional improvements
| Tier | Token Quota | Features |
|---|---|---|
| Self-sufficient | Unlimited (BYOK) | Bring Your Own Key — use your Anthropic API key |
| Pro | 2.5M tokens/mo | Automated PR reviews, auto-fix, custom rules, skills |
| Ultra | 8M tokens/mo | Everything in Pro with higher token quota |
cd packages/app
bun run build
# Deploy dist/ to your static hostcd packages/website
bun run build
# Deploy dist/ to your static hostDeploy as a standard Node.js/Bun application with PostgreSQL database.
For Docker-based production deploys, set this environment variable on the deploy runner:
export GITHUB_PRIVATE_KEY_PATH=/absolute/path/to/private-key.pemdocker-compose.prod.yml mounts this path into both bff and agent containers.
cd packages/review-agent
# Build image
docker build -t review-agent .
# Run with docker-compose
docker-compose up -dAll authenticated endpoints require:
Authorization: Bearer <token>headerX-Organization-Id: <org-id>header (for org-scoped requests)
GET /api/repos- List available repositoriesGET /api/org/repos- List organization repositoriesPUT /api/settings/:owner/:repo- Update repository settings
GET /api/reviews- List reviews for organizationGET /api/stats- Get review statisticsPOST /api/reviews- Record a completed review (internal)
GET /api/skills- List user's skills (paginated, searchable)POST /api/skills- Create a new skillPUT /api/skills/:id- Update a skillDELETE /api/skills/:id- Delete a skill
GET /api/subscription/status- Check subscription statusPOST /api/subscription/create- Create new subscriptionGET /api/billing- Get billing information
GET /api/organization- Get organization detailsGET /api/organization/members- List organization membersPOST /api/organization/invites- Create inviteDELETE /api/organization/invites/:id- Revoke invite
opendiff/
├── packages/
│ ├── app/ # Console Dashboard
│ │ └── src/
│ │ ├── features/ # Feature modules (admin, billing, dashboard, etc.)
│ │ ├── components/ # App-specific components
│ │ └── main.tsx # App entry point
│ │
│ ├── assets/ # Shared Static Assets
│ │ └── public/
│ │ ├── typefaces/ # Font files (Helvetica Now)
│ │ ├── icons/ # OAuth provider icons
│ │ └── icon.svg # Favicon
│ │
│ ├── bff/ # Backend API
│ │ ├── src/
│ │ │ ├── index.ts # Main server entry
│ │ │ ├── routes/ # API route handlers
│ │ │ ├── auth.ts # OAuth authentication
│ │ │ ├── db.ts # Prisma client
│ │ │ └── payments/ # Polar/Stripe integration
│ │ └── prisma/
│ │ └── schema.prisma # Database schema
│ │
│ ├── components/ # UI Component Library
│ │ └── src/
│ │ ├── components/ui/ # Primitives (Button, Dialog, etc.)
│ │ ├── hooks/ # Shared React hooks
│ │ ├── utils/ # Utility functions
│ │ └── constants/ # Shared constants
│ │
│ ├── prompts/ # Shared AI Prompt Templates
│ │ ├── src/
│ │ │ └── index.ts # loadPrompt() with {var} substitution
│ │ └── templates/
│ │ ├── generate-summary.md
│ │ ├── review.md
│ │ ├── respond-to-comment.md
│ │ └── fix-issue.md
│ │
│ ├── review-agent/ # AI Code Reviewer
│ │ └── src/
│ │ ├── agent/ # OpenCode integration
│ │ │ ├── reviewer.ts # Code review agent
│ │ │ └── triage.ts # Auto-fix agent
│ │ ├── utils/
│ │ │ ├── git.ts # Git operations
│ │ │ └── skill-hydrator.ts # Skill materialization
│ │ └── webhook/ # GitHub webhook handlers
│ │
│ ├── shared/ # Shared Business Logic
│ │ └── src/
│ │ ├── auth/ # Authentication logic
│ │ ├── billing/ # Billing logic
│ │ ├── organizations/ # Organization management
│ │ ├── services/ # API services, query keys
│ │ └── navigation/ # Navigation utilities
│ │
│ ├── github/ # GitHub App Auth & API Utilities
│ │ └── src/
│ │ └── index.ts # JWT auth, installation tokens, types
│ │
│ ├── vscode-extension/ # VS Code Extension
│ │ └── src/
│ │ └── extension.ts
│ │
│ └── website/ # Marketing Website
│ └── src/
│ ├── features/ # Feature modules
│ └── components/ # Website components
│
├── scripts/ # Operations scripts
│ ├── start.sh # Start all services (dev or prod mode)
│ ├── stop.sh # Stop all running services by port
│ └── deploy-webhook.ts # Webhook listener for auto-deploy
├── biome.json # Linting configuration
└── package.json # Workspace configuration
- User - Multi-OAuth user accounts (GitHub, Google, Microsoft)
- Organization - Teams with subscription management
- OrganizationMember - User membership and seat allocation
- OrganizationInvite - Pending team invites
- RepositorySettings - Per-repo review configuration
- Review - Review history tracking
- ReviewComment - Individual review comments
- ReviewFix - Automated fix tracking
- Skill - User-defined review instructions
- SkillResource - Additional resources attached to skills
- Feedback - User feedback submissions
- Notification - In-app notifications
- AuditLog - Security audit trail
See packages/bff/prisma/schema.prisma for the complete schema.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Run linting and tests (
bun run check && bun run test) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the AGPL-3.0 License - see the LICENSE.md file for details.