When you change an API, Ripple finds every consumer and opens PRs to fix them. Automatically.
You change POST /users to require a new field. Three teams find out when their code breaks in production on Friday night.
Ripple detects breaking API changes, finds every consumer, generates the fix, and opens a PR — in seconds, not days.
🌊 RIPPLE — API Change Propagation
⚠️ 1 breaking change detected:
POST /payments — added required field 'idempotency_key' (string)
🔍 Found 3 consumers (Python SDK, Node SDK, Java SDK)
🔧 Generated 3 fixes (validated ✓)
📤 Opened 3 PRs
✅ Done in 15 seconds.
Option 1: GitHub App (recommended)
Install on your org — Ripple auto-triggers on every push:
That's it. Push a breaking change to any API spec and fix PRs appear in consumer repos.
Option 2: Run from source
git clone https://github.com/Aakash2408/ripple.git
cd ripple
pip install -r requirements.txt
# Detect breaking changes
python -m app.cli diff old.yaml new.yaml
# Find consumers + generate fixes
python -m app.cli run old.yaml new.yaml --repos ./consumer1 ./consumer2
# Deploy as webhook (auto-triggers on push)
uvicorn app.webhook:app --port 8000- Detect — Parses API contracts (OpenAPI, Protobuf, GraphQL, database schemas) and finds breaking changes
- Find — Scans your org's repos for code that calls the changed endpoint
- Fix — Generates the minimal code fix for each consumer (TypeScript, Python, Java)
- Validate — Syntax-checks every fix before opening a PR
- PR — Opens a pull request with the fix + clear explanation
Ripple gets smarter the more you use it:
- Co-change learning — Scans git history on install. If two files always changed together, Ripple knows they're related.
- Consumer graph — Builds a persistent map of which services depend on which APIs. Updates on every push.
- Multi-invoker detection — Warns when a shared config/schema has multiple consumers (prevents the "I deleted a block and broke an unrelated service" problem).
- Pattern playbooks — Knows that proto changes also affect
*_pb2.py,*.pb.go, and test files. - Custom playbooks — Define your own patterns in
.ripple.yaml(see below).
Result: 3x better consumer detection than grep alone.
Add a .ripple.yaml to your repo root to teach Ripple about YOUR codebase:
playbooks:
- name: "Our API gateway"
trigger:
files: ["api/openapi.yaml"]
change_types: ["added_required_field", "removed_field"]
consumers:
- pattern: "sdk/python/**/*.py"
confidence: 0.95
reason: "Python SDK wraps this API"
- pattern: "sdk/node/**/*.ts"
confidence: 0.95
reason: "Node SDK wraps this API"
- pattern: "tests/integration/**/*"
confidence: 0.85
reason: "Integration tests call this API"
- name: "Database migrations"
trigger:
files: ["db/migrations/*.sql", "prisma/schema.prisma"]
change_types: ["*"]
consumers:
- pattern: "src/models/**/*"
confidence: 0.90
reason: "ORM models mirror DB schema"
ignore:
- "*.lock"
- "node_modules/**"
- "dist/**"
settings:
min_confidence: 0.6
auto_learn: true
max_prs_per_push: 10Get the template: GET /config/template
- OpenAPI / Swagger
- Protobuf (gRPC)
- GraphQL
- Database schemas (SQL DDL + Prisma)
OpenAPI:
- Added required field
- Removed field
- Field type changed (string → integer breaks consumers)
- Endpoint removed (consumers get 404)
- Response field removed (consumers reading it get null)
- Required header added (requests rejected without it)
Protobuf:
- Field removed
- Field type changed
- Field number changed (wire incompatibility)
- Required field added
- Message removed
- Message renamed (detected via field overlap)
GraphQL:
- Field removed from type
- Field made non-nullable (String → String!)
- Type removed
- Required argument added
- Enum value removed
- Union member removed
Database:
- Column removed
- Column type changed
- NOT NULL column added (existing rows fail)
- Column made NOT NULL
- Table removed
- Table renamed
- TypeScript / JavaScript
- Python
- Java
- Go (coming soon)
- Rust (coming soon)
# Docker
docker build -t ripple .
docker run -p 8000:8000 -e GITHUB_TOKEN=ghp_xxx ripple
# Railway (one-click deploy)
# Live: https://ripple-production-be7f.up.railway.appRipple works with GitLab too. Setup:
-
Set environment variables:
GITLAB_TOKEN=glpat-xxxxxxxxxxxx # Personal/Project access token (api scope) GITLAB_WEBHOOK_SECRET=your-secret # Optional
-
Add webhook to your GitLab project:
- Go to Settings → Webhooks
- URL:
https://your-ripple-server.com/webhook/gitlab - Secret token: (same as GITLAB_WEBHOOK_SECRET)
- Trigger: ✅ Push events
- Click "Add webhook"
-
Push a breaking change — Ripple creates a Merge Request automatically.
Works with all 4 contract types (OpenAPI, Proto, GraphQL, Database) on GitLab.
POST /webhook — GitHub push events (auto-triggered by GitHub App)
POST /webhook/gitlab — GitLab push events
POST /webhook/install — GitHub App installation (triggers learning)
POST /learn — Manually trigger co-change learning
GET /dashboard — Web UI (monitored repos, activity, stats)
GET /status/{org} — What Ripple knows about your codebase (JSON)
GET /rate-limit/{org} — Rate limit status for an org
GET /config/template — Default .ripple.yaml template
GET /health — Server health
GET /docs — Swagger UI (auto-generated)
See what Ripple has learned about your org:
GET /dashboard — web UI (monitored repos, activity, stats)
GET /status/{org} — what Ripple knows about your codebase (JSON)
GET /health — server health
- Not Dependabot — Dependabot bumps library versions. Ripple fixes YOUR code when YOUR APIs change.
- Not a linter — Linters find style issues. Ripple finds breaking contract violations across repos.
- Not AI code review — Code review finds bugs in what you wrote. Ripple fixes what you forgot to update.
- Not SDK generation — SDK generators rebuild from scratch. Ripple patches your EXISTING code.
MIT