prATC (PR Air Traffic Control) is a self-hostable system for large-scale pull request triage and merge planning.
- CLI Analysis: Analyze, cluster, graph, and plan merges for GitHub repositories
- Web Dashboard: ATC overview, triage inbox, dependency graphs, and merge planning
- ML Clustering: Python service for PR clustering and duplicate detection
- SQLite Cache: Incremental GitHub sync with persisted state
- Rate-Limit Aware: Built-in retry and budget management
# Build everything
make verify-env
make build
make test
# Run with Docker Compose
docker-compose --profile local-ml up
docker-compose --profile minimax-light upAnalyze pull requests for a repository.
pratc analyze --repo=owner/repo --format=jsonOutput includes: repo, generatedAt, counts, clusters, duplicates, overlaps, conflicts, stalenessSignals.
Cluster pull requests by similarity.
pratc cluster --repo=owner/repo --format=jsonOutput includes: repo, generatedAt, model, thresholds, clusters.
Generate dependency/conflict graphs.
pratc graph --repo=owner/repo --format=dot # Default DOT output
pratc graph --repo=owner/repo --format=json # JSON outputGenerate a ranked merge plan. Dry-run by default (no changes executed).
pratc plan --repo=owner/repo --target=20
pratc plan --repo=owner/repo --target=20 --mode=combination
pratc plan --repo=owner/repo --target=20 --include-bots
pratc plan --repo=owner/repo --target=20 --dry-run=false # Execute modeFlags:
--target: Number of PRs to include (default: 20)--mode: Formula mode -combination(default),permutation,with_replacement--dry-run: Plan only, do not execute (default:true, always true if not explicitly set)--include-bots: Include bot PRs in merge plan (default:false)
Start the API server.
pratc serve --port=8080
pratc serve --port=8080 --repo=owner/repo # Default repo for APISync repository metadata and refs.
pratc sync --repo=owner/repo
pratc sync --repo=owner/repo --watch --interval=5mQuery the audit log.
pratc audit --limit=20 --format=jsonGET /healthz- Health checkGET /api/health- Health check (alias)
GET /api/settings?repo=- Get settingsPOST /api/settings- Set settingDELETE /api/settings?scope=&repo=&key=- Delete settingGET /api/settings/export?scope=&repo=- Export as YAMLPOST /api/settings/import?scope=&repo=- Import YAML
Legacy routes (query string repo):
GET /analyze?repo=- Analyze PRsGET /cluster?repo=- Cluster PRsGET /graph?repo=&format=- Graph PRs (add&format=dotfor DOT output)GET /plan?repo=&target=&mode=- Plan PRs
RESTful routes (/api/repos/:owner/:repo/...):
GET /api/repos/:owner/:repo/analyzeGET /api/repos/:owner/:repo/clusterGET /api/repos/:owner/:repo/graphGET /api/repos/:owner/:repo/planor/api/repos/:owner/:repo/plans
POST /api/repos/:owner/:repo/sync- Trigger syncGET /api/repos/:owner/:repo/sync/stream- Stream sync progress
When calling plan endpoints, these query parameters are supported:
| Parameter | Type | Default | Description |
|---|---|---|---|
target |
int | 20 | Number of PRs to include |
mode |
string | combination |
Formula mode: combination, permutation, with_replacement |
cluster_id |
string | - | Filter to specific cluster |
exclude_conflicts |
bool | false | Exclude conflicting PRs |
stale_score_threshold |
float | 0.0 | Staleness threshold (0-1) |
candidate_pool_cap |
int | 100 | Max candidate pool size (1-500) |
score_min |
float | 0.0 | Minimum PR score (0-100) |
dry_run |
bool | true | Plan only, do not execute |
The web dashboard runs at http://localhost:3000.
| Route | Description |
|---|---|
/ |
ATC overview dashboard |
/inbox |
PR inbox view |
/triage |
Sequential triage workflow |
/plan |
Merge plan panel |
/graph |
Interactive dependency graph |
/settings |
Configuration settings |
Two profiles are available for different deployment scenarios:
Full local ML stack with Python clustering service.
docker-compose --profile local-ml upLightweight profile without local ML (uses external APIs).
docker-compose --profile minimax-light upNote: The minimax-light profile replaces the previous openrouter-light naming.
cmd/pratc/ # CLI entrypoints
internal/ # Go packages
cmd/ # CLI command implementations
app/ # Service layer
cache/ # SQLite persistence
github/ # GitHub client
filter/ # Pre-filter pipeline
formula/ # Combinatorial formula engine
graph/ # Dependency graph engine
planner/ # Merge planning
settings/ # Settings management
sync/ # Background sync
types/ # Shared types
ml-service/ # Python ML service
web/ # TypeScript Next.js dashboard
fixtures/ # Test fixtures
Environment variables:
| Variable | Description |
|---|---|
PRATC_PORT |
API server port (default: 8080) |
PRATC_DB_PATH |
SQLite database path |
PRATC_SETTINGS_DB |
Settings database path |
PRATC_ANALYSIS_BACKEND |
Analysis backend: local or remote |
GITHUB_TOKEN |
GitHub API token |
# Go tests
go test -race -v ./...
# Python tests
uv run pytest -v
# Web tests
bun run test
# All tests
make test0- Success1- Runtime failure2- Invalid arguments
- Similarity > 0.90: duplicate
- Similarity 0.70-0.90: overlapping
MIT