Output formats

RCL can print output in the formats below. The format can be selected with --format on the command line, and with format in build files. The format names are written lowercase.

json

Output pretty-printed JSON. Sets become lists, functions are not supported. Because RCL is a superset of JSON, every JSON value maps to itself. Note that YAML is a superset of JSON, so this format is appropriate for generating configuration for tools that accept YAML, such as Kubernetes and GitHub Actions.

Tip: You can quickly select JSON output on the command line with the je and jq shorthands.

{
  series = "Nexus-6",
  instances = {"Roy Batty", "Leon Kowalski"},
}

Formats as:

{
  "instances": ["Leon Kowalski", "Roy Batty"],
  "series": "Nexus-6"
}

json-lines

If the document is a list, output every element as a JSON value on its own line, consistent with the JSON lines format. Top-level values other than lists are not valid for this format.

[
  { name = "Roy Batty", serial = "N6MAA10816" },
  { name = "Leon Kowalski", serial = "N6MAC41717" },
]

Formats as:

{"name": "Roy Batty", "serial": "N6MAA10816"}
{"name": "Leon Kowalski", "serial": "N6MAC41717"}

raw

If the document is a string, output the string itself. If the document is a list or set of strings, output each string on its own line.

Tip: You can quickly select raw output on the command line with the re and rq shorthands.

["First line", "Second line\nThird line"]

Formats as:

First line
Second line
Third line

rcl

Output pretty-printed RCL.

{
  "where_possible": "Record syntax will be used.",
  "where impossible": "Expression form is used.",
}

Formats as:

{
  "where impossible": "Expression form is used.",
  where_possible = "Record syntax will be used.",
}

systemd

Output as a systemd unit. The format is superficially similar to TOML, but handles nested data differently. The top-level value must always be a dict. Its keys become sections. Its values must be dicts as well, which become the section contents:

{
  Unit = {
    Description = "Example systemd unit.",
    After = "network-online.target",
  },
}
[Unit]
After=network-online.target
Description="Example systemd unit."

Systemd allows repeating keys. To emit those, use a list or set value in RCL:

{
  Service = {
    BindReadOnlyPaths = ["/etc/resolv.conf", "/var/www"],
  },
}
[Service]
BindReadOnlyPaths=/etc/resolv.conf
BindReadOnlyPaths=/var/www

Some settings allow space-separated values. To emit those, use a nested list or set:

{
  Service = {
    ExecStart = [["/usr/bin/nsd", "-P", "", "-c", "/etc/nsd.conf"]],
  },
},
[Service]
ExecStart=/usr/bin/nsd -P "" -c /etc/nsd/nsd.conf

For some settings, systemd accepts the empty string to clear previous assignments. While Value="" and Value= mean the same thing to systemd, the latter is more common, and therefore might communicate the intent more clearly. To emit an empty value from RCL, use null:

{
  Service = {
    Environment = [
      null,
      ["LOG_LEVEL=debug", "PORT=8000"],
      "ENVIRONMENT=prod",
    ],
  },
}
[Service]
Environment=
Environment=LOG_LEVEL=debug PORT=8000
Environment=ENVIRONMENT=prod

Finally, some units support repeated sections. To emit those, wrap the sections in a list or set:

{
  Route = [
    { Gateway = "0.0.0.0", Table = 1 },
    { Gateway = "::", Table = 2 },
  ],
}
[Route]
Gateway=0.0.0.0
Table=1

[Route]
Gateway=::
Table=2

RCL will use escape sequences and quote strings when needed to keep the unit file valid, and to preserve values exactly. For some settings, such as ExecStart=, systemd performs environment variable substitution and specifier substitution, which means that $ and % have special meaning for those settings. RCL does not apply any special handling for these characters.

toml

Alias for toml-1.0.

toml-1.0

Output as TOML 1.0. This version is the most widely supported, but can be less readable because inline tables cannot span multiple lines.

{
  profile = {
    release = {
      lto = "thin",
      panic = "abort",
      strip = "true",
    },
  },
}

Formats as:

[profile]
release = { lto = "thin", panic = "abort", strip = "true" }

toml-1.1

Output TOML 1.1. This version supports multi-line tables, but it was only released in December 2025, so it is less widely supported. The same example as before outputs as follows for a 50-column target line width:

[profile]
release = {
  lto = "thin",
  panic = "abort",
  strip = "true",
}

yaml-stream

If the document is a list, output every element as a JSON document (which is also a valid YAML document), prefixed by the --- YAML document separator. Top-level values other than lists are not valid for this format.

[
  { name = "Roy Batty", serial = "N6MAA10816" },
  { name = "Leon Kowalski", serial = "N6MAC41717" },
]

Formats as:

---
{
  "name": "Roy Batty",
  "serial": "N6MAA10816"
}
---
{
  "name": "Leon Kowalski",
  "serial": "N6MAC41717"
}