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, catalogs, 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 references, 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 = 'context.user.tier == "premium"'
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

The rototo console is a companion web app that ships separately as rototo-console: browse packages, trace how a variable resolves against saved contexts, edit through curated surfaces, and review changes with their resolution impact before they merge. Run it on your laptop with your own GitHub token, or host it for the team with GitHub OAuth and SSO.

Run the console →