A command-line tool for managing SaaS billing configurations as code. Define your pricing plans, entitlements, and promotions in YAML, then sync them to payment providers.
Managing billing across SaaS applications is painful:
- Scattered configuration — pricing lives in Stripe dashboard, entitlements in code, feature flags elsewhere
- No version control — changes to plans are hard to track, review, or rollback
- Environment drift — sandbox and production get out of sync
- Provider lock-in — switching from Stripe to Paddle means rewriting everything
Raterunner solves this with a single source of truth:
plans:
- id: pro
name: Pro Plan
prices:
monthly: { amount: 2900 }
yearly: { amount: 29000 }
limits:
seats: 10
api_calls: 50000
features:
- "Up to 10 users"
- "Priority support"Benefits:
- Version control — track all billing changes in Git
- Code review — pricing changes go through PR review like any other code
- Environment parity — same config deploys to sandbox and production
- Schema validation — catch errors before they hit production
- CI/CD ready — automate billing deployments
Note: Raterunner currently supports Stripe only. Support for Paddle and Chargebee is planned.
If you need support for other providers, please contact raterunner@akorchak.software.
brew install raterunner/tap/raterunnerDownload the latest release from GitHub Releases.
Available builds:
- macOS:
raterunner_VERSION_darwin_amd64.tar.gz(Intel),raterunner_VERSION_darwin_arm64.tar.gz(Apple Silicon) - Linux:
raterunner_VERSION_linux_amd64.tar.gz,raterunner_VERSION_linux_arm64.tar.gz - Windows:
raterunner_VERSION_windows_amd64.zip,raterunner_VERSION_windows_arm64.zip
# Example: install v0.0.1 on macOS (Apple Silicon)
curl -sL https://github.com/raterunner/cli/releases/download/v0.0.1/raterunner_0.0.1_darwin_arm64.tar.gz | tar xz
sudo mv raterunner /usr/local/bin/Available on GitHub Releases:
.deb— Debian, Ubuntu.rpm— RHEL, Fedora, CentOS.apk— Alpine
# Example: Debian/Ubuntu
curl -sLO https://github.com/raterunner/cli/releases/download/v0.0.1/raterunner_0.0.1_linux_amd64.deb
sudo dpkg -i raterunner_0.0.1_linux_amd64.debgo install github.com/raterunner/cli/cmd/raterunner@latestgit clone https://github.com/raterunner/cli.git
cd cli
make build
sudo mv bin/raterunner /usr/local/bin/- Stripe API keys (for sync operations)
raterunner initThis creates a raterunner/ directory with a sample billing.yaml:
your-project/
└── raterunner/
└── billing.yaml # Your billing configuration
Customize the generated configuration for your needs:
# raterunner/billing.yaml
version: 1
providers:
- stripe
entitlements:
seats:
type: int
unit: seat
api_calls:
type: int
unit: call
plans:
- id: free
name: Free Plan
prices:
monthly: { amount: 0 }
limits:
seats: 1
api_calls: 1000
- id: pro
name: Pro Plan
trial_days: 14
prices:
monthly: { amount: 2900 }
yearly: { amount: 29000 }
limits:
seats: 10
api_calls: 50000raterunner validate raterunner/billing.yamlexport STRIPE_SANDBOX_KEY=sk_test_...
raterunner apply --env sandbox --dry-run raterunner/billing.yamlraterunner apply --env sandbox raterunner/billing.yamlAfter applying, Raterunner creates a provider file with Stripe IDs:
your-project/
└── raterunner/
├── billing.yaml # Your billing configuration (source of truth)
└── stripe_sandbox.yaml # Generated: Stripe IDs for sandbox
The provider file maps your plan IDs to Stripe product/price IDs:
# raterunner/stripe_sandbox.yaml (auto-generated)
provider: stripe
environment: sandbox
synced_at: "2024-01-15T10:30:00Z"
plans:
free:
product_id: prod_ABC123
prices:
monthly: price_XYZ789
pro:
product_id: prod_DEF456
prices:
monthly: price_UVW012
yearly: price_RST345Why provider files?
- ID tracking — know which Stripe objects correspond to your plans
- Environment isolation — separate IDs for sandbox vs production
- Debugging — quickly find Stripe objects when troubleshooting
- Commit to Git — track ID mappings alongside your billing config
Initialize a new billing configuration with example plans.
raterunner init # Creates raterunner/billing.yaml in current directory
raterunner init ./my-app # Creates my-app/raterunner/billing.yaml
raterunner init --force # Overwrite existing filesThe generated billing.yaml includes:
- Free, Pro, and Enterprise plan templates
- Example entitlements (projects, API calls, support)
- Comments with documentation links
Validate a billing or provider configuration against the JSON Schema.
raterunner validate raterunner/billing.yaml
raterunner validate raterunner/stripe_sandbox.yamlSync billing configuration to Stripe. Creates products, prices, coupons, and promotion codes.
# Preview changes (no writes to Stripe)
raterunner apply --env sandbox --dry-run raterunner/billing.yaml
# Apply changes to sandbox
raterunner apply --env sandbox raterunner/billing.yaml
# → Creates raterunner/stripe_sandbox.yaml with Stripe IDs
# Apply to production
raterunner apply --env production raterunner/billing.yaml
# → Creates raterunner/stripe_production.yaml
# Output diff as JSON
raterunner apply --env sandbox --dry-run --json raterunner/billing.yamlStripe API used:
POST /v1/products— create products for plans and addonsPOST /v1/prices— create prices (flat, per-unit, tiered)POST /v1/coupons— create discount couponsPOST /v1/promotion_codes— create promotion codesPOST /v1/prices/{id}— archive old prices when amounts change
Import existing Stripe products/prices to YAML files. Useful for migrating existing Stripe setup to Raterunner.
raterunner import --env sandbox --output raterunner/billing.yaml
# → Creates raterunner/billing.yaml (billing config)
# → Creates raterunner/stripe_sandbox.yaml (provider IDs)Stripe API used:
GET /v1/products— fetch all productsGET /v1/prices— fetch all prices
Archive all products and prices in Stripe sandbox (useful for testing). Sandbox only — refuses to run against production.
raterunner truncate # Interactive confirmation
raterunner truncate --confirm # Skip confirmation (for CI/CD)Stripe API used:
POST /v1/prices/{id}— archive prices (setactive: false)POST /v1/products/{id}— archive products (setactive: false)DELETE /v1/coupons/{id}— delete coupons
Manage CLI settings.
raterunner config set quiet true # Enable quiet mode permanently
raterunner config get quiet # Get current value
raterunner config list # List all settings
raterunner config path # Show config file path| Flag | Description |
|---|---|
--quiet, -q |
Suppress non-essential output (errors still shown) |
--help, -h |
Show help |
--version, -v |
Show version |
| Variable | Description |
|---|---|
STRIPE_SANDBOX_KEY |
Stripe test API key (sk_test_...) |
STRIPE_PRODUCTION_KEY |
Stripe live API key (sk_live_...) |
A typical Raterunner setup in your project:
your-project/
├── raterunner/
│ ├── billing.yaml # Source of truth: plans, prices, entitlements
│ ├── stripe_sandbox.yaml # Auto-generated: Stripe IDs for sandbox
│ └── stripe_production.yaml # Auto-generated: Stripe IDs for production
└── ... your app code
| File | Purpose | Git? |
|---|---|---|
billing.yaml |
Your billing configuration (plans, prices, entitlements) | Yes |
stripe_sandbox.yaml |
Stripe IDs for test environment | Yes |
stripe_production.yaml |
Stripe IDs for live environment | Yes |
All files should be committed to Git — this gives you full history of:
- What plans existed at any point in time
- Which Stripe objects were created for each environment
- When syncs happened (
synced_attimestamp)
The billing configuration schema is maintained in a separate repository:
| Feature | Status |
|---|---|
| Flat pricing | Supported |
| Per-unit pricing | Supported |
| Tiered pricing (graduated/volume) | Supported |
| Trial periods | Supported |
| Addons | Supported |
| Promotions/Coupons | Supported |
| Marketing features | Supported |
| Custom metadata | Supported |
| Multi-currency | Planned |
billing.schema.json— main configuration (plans, entitlements, addons, promotions)provider.schema.json— provider-specific mappings
cmd/raterunner/ # CLI entrypoint
main.go # Commands and flags
main_test.go # Integration tests
testdata/ # Test fixtures
internal/
config/ # Configuration types and loading
stripe/ # Stripe API client
diff/ # Comparison and output
validator/ # JSON Schema validation
schema/ # Embedded JSON schemas
# Build
make build
# Run tests
make test
# Update schemas from submodule
git submodule update --remote schema
make generateContributions are welcome! Please feel free to submit issues and pull requests.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
MIT License — see LICENSE for details.
Andrey Korchak Email: raterunner@akorchak.software