rototo

Runtime configuration, reviewed like code.

rototo keeps your application's runtime configuration in a Git package: validated by lint, changed through pull requests, and resolved at runtime into typed values your services can trust. No config database, no side channel around review — the repository is the control plane.

One package, three guarantees

Declared

Variables, qualifiers, and JSON Schemas live as files under rototo-package.toml. Every change has an author, a diff, and a history.

Validated

Lint understands the package semantically: unknown qualifiers, values that break their schema, and rules that can never match are caught before merge, not in production.

Resolved

Applications load the package by source URI and resolve named variables with runtime context. Long-running services refresh from the same source and keep last-known-good state when a fetch fails.

What it looks like

# variables/checkout-redesign.toml
schema_version = 1
type = "string"

[resolve]
default = "classic"

[[resolve.rule]]
when = 'env.qualifier["premium-users"]'
value = "redesign"
rototo resolve git+https://github.com/acme/config#main \
  --variable checkout-redesign \
  --context user.tier=premium

SDKs that share one engine

The Rust core owns loading, lint, evaluation, and refresh; every SDK is a thin binding over it, so resolution behaves identically in every language.

Rust Python TypeScript Java Go

Operate it from the console

rototo console serves a web console from the same binary as the CLI: browse packages, trace how a variable resolves against saved contexts, edit review branches, and publish pull requests. Run it on your laptop with your own GitHub token, or behind your proxy with GitHub OAuth for the whole team.

Read the concepts →