Alpha
Configuration, Specified.
Type-safe, SMT-validated configuration from a single
.dox source. Define it once, validate it at compile time,
emit JSON or YAML.
YAML typos crash production. JSON has no types. Dhall has types but no real validation. Pkl locks you in. CUE validates at runtime. Jsonnet gives you string soup. You deserve a configuration language that catches mistakes before they ship — with output in every format you need.
Write once, output everywhere
import std type DatabaseConfig host: Text port: Port name: Text maxConnections: Natural ssl: Boolean valid DatabaseConfig maxConnections >= 1 && maxConnections <= 1000 | Connection pool must be 1-1000 production: DatabaseConfig host: "db.prod.internal" port: Port 5432 name: "myapp" maxConnections: Natural 100 ssl: true
Generate Config
Unlike other codegen targets, JSON and YAML generation takes a constant name — Paradox evaluates the expression, checks all constraints, and emits the result.
$ paradox generate --json production { "host": "db.prod.internal", "port": 5432, "name": "myapp", "maxConnections": 100, "ssl": true }
$ paradox generate --yaml production host: db.prod.internal port: 5432 name: myapp maxConnections: 100 ssl: true
paradox generate --json production --out prod.json
Why Paradox for Config?
SMT-Verified Constraints
Validation runs at compile time via Z3. Invalid config never makes it to production.
Error: Validation failed port > 0 && port <= 65535 | Port must be between 1 and 65535 port = -1
Simple CLI
Generate JSON or YAML for any constant by name. Paradox evaluates the expression and validates constraints before emitting output.
$ paradox generate \ --json production $ paradox generate \ --yaml production $ paradox generate \ --json production \ --out prod.json
Programmable Config
Functions, pattern matching, conditionals. Template environments without copy-paste.
envConfig: env: Text. DatabaseConfig host: if env == "prod" then "db.prod.internal" else "localhost" port: 5432 name: "myapp" maxConnections: if env == "prod" then 100 else 5 ssl: env == "prod"
How Paradox Compares
| Feature | Paradox | Dhall | Pkl | CUE | Jsonnet |
|---|---|---|---|---|---|
| Type Safety | Refinement types (SMT) | Total types | Schema types | Constraints | None |
| Validation | Compile-time (Z3) | Type-level only | Runtime | Runtime | None |
| Functions | Yes + pattern match | Yes (total) | Yes | Limited | Yes |
| IDE Support | LSP | LSP | LSP + IntelliJ | LSP | None |
Advanced: Unions + Validated Wrappers
Wrap primitive types with validation. Use unions for environment-specific config. Invalid construction is refused at compile time.
import std wrap DbPort: Integer valid DbPort unwrap > 0 && unwrap <= 65535 | Port must be 1-65535 wrap PoolSize: Integer valid PoolSize unwrap >= 1 && unwrap <= 500 | Pool size must be 1-500 union Environment production staging development type ServiceConfig env: Environment dbHost: Text dbPort: DbPort pool: PoolSize debug: Boolean prodConfig: ServiceConfig env: production dbHost: "db.prod.internal" dbPort: DbPort 5432 pool: PoolSize 100 debug: false
dbPort: DbPort 70000 in
prodConfig — Paradox will reject it at compile time
with "Port must be 1-65535". No runtime surprises.