Getting Started · Documentation · Changelog · Online Playground
RCL is a domain-specific language for generating configuration files and querying json documents. It is a superset of json that extends it into a simple, gradually typed, functional programming language that resembles Python and Nix. RCL can be used through the [`rcl`][cmd] command-line tool that can export documents to json, yaml, toml, [and more][output]. It can also be used through a native Python module, with an interface similar to the `json` module. ## About RCL solves the following problems: * Copy-pasted yaml blocks that differ by a single value. * Broken configs due to whitespace and escaping footguns in templating engines. * Drift between tools due to lack of a single source of truth. * Struggling to remember `jq` syntax. It does that as follows: * **A real language.** Use variables, loops, imports, and functions to eliminate duplication. * **Familiar syntax.** Have you used Python, TypeScript, or Rust before? Then you will find RCL obvious to read and natural to write. * **Generate rather than template.** Manipulate data structures, not strings. Generate correct json, yaml, and toml. * **Built to integrate.** Generate configs for tools that do not natively talk to each other, all from a single source of truth. Integrate with your existing build tools, use the Python module, or the built-in [`rcl build`][cmd-build] to update generated files. * **Gradual types.** Add type annotations where they help to eliminate bugs and make code self-documenting, omit them in straightforward code. * **Built-in json queries.** A language for manipulating structured data makes a pretty good query tool. Run map and filter pipelines straight from your terminal. [cmd]: https://docs.ruuda.nl/rcl/rcl/ [cmd-build]: https://docs.ruuda.nl/rcl/rcl_build/# [output]: https://docs.ruuda.nl/rcl/rcl_evaluate/#-o-output-format ## Example Given this input: ```rcl { // Generate backup buckets for each database and retention period. backup_buckets = [ let retention_days = { hourly = 4, daily = 30, monthly = 365 }; for database in ["alpha", "bravo"]: for period, days in retention_days: { name = f"{database}-{period}", region = "eu-west", lifecycle_policy = { delete_after_seconds = days * 24 * 3600 }, } ], } ``` RCL generates: ```jsonc { "backup_buckets": [ { "name": "alpha-hourly", "region": "eu-west", "lifecycle_policy": { "delete_after_seconds": 345600 } }, { "name": "alpha-daily", "region": "eu-west", "lifecycle_policy": { "delete_after_seconds": 2592000 } }, // And 4 similar entries, omitted here for brevity. ] } ``` For an interactive demo in your browser, see