Programmable JSON. Small arms, big bite.
Rex is a compact expression language for configuration and data-driven logic. It is a superset of JSON with high-level syntax (when, unless, and, or, assignment, loops, comprehensions).
Rex covers two common use-case styles:
- Templated data: generate structured values from JSON-like templates with lightweight logic.
- General-purpose decision logic: write compact policy/router/transform rules as little snippets of logic.
Use Rex when JSON alone is too static, but embedding a full scripting runtime is too heavy.
In practice, Rex works like this:
- Start with normal JSON-shaped data.
- Add template-style dynamics while keeping a structured-data result.
- Add just enough logic for real configs (
when,unless,and,or, loops, comprehensions). - Compile once to compact
rexcbytecode for storage, transport, and fast evaluation.
Rex is a strong fit for:
- HTTP edge routing and middleware policy
- Request/response shaping and header logic
- Feature flags and rollout rules
- Validation and normalization pipelines
- Data-driven rules where full scripting is too much
Rex uses existence, not truthiness. Only undefined means “absent.”
All JSON values (including 0, false, and null) are existing values. Only undefined does not exist.
0 or "fallback" // => 0
false or "fallback" // => false
null or "fallback" // => null
undefined or "fallback" // => "fallback"This drives the language:
- Comparisons return value-or-
undefined when/unlessbranch on defined-vs-undefinedand/or/norshort-circuit on existence
user.name
config.(headers.x-action)
status = 200
headers.content-type = "application/json"
old = count := count + 1when token and token == config.api-token do
headers.x-auth = "ok"
else
status = 401
end// Array comprehension with filtering
[v % 2 == 0 and v for v in 1..10]
// Object comprehension
{(k): v * 10 for k, v in scores}when n = number(input) do
total += n
else when s = string(input) do
log("got string: " + s)
endRex runtimes are gas-bounded: evaluation ends with either a value or a gas-limit failure.
The embedding domain decides how to use Rex (final value, side effects, or both).
For precise semantics and edge-case behavior, see the Language Reference.
Table-driven routing — look up an action in a map and set a header:
actions = {
create-user: "users/create"
delete-user: "users/delete"
update-profile: "users/update-profile"
}
when handler = actions.(headers.x-action) do
headers.x-handler = handler
end// Allow host or CLI to override max, but default to 100
max = max or 100
fibs = []
i = 0
a = 1
b = 1
while a <= max do
fibs.(i) = a
i += 1
c = a + b
a = b
b = c
end
fibsmax = max or 100
composites = {}
n = 2
while n * n <= max do
unless composites.(n) do
m = n * n
while m <= max do
composites.(m) = true
m += n
end
end
n += 1
end
[composites.(self) nor self in 2..max]Rex compiles to rexc — a compact bytecode that serializes as a UTF-8 string. You can store it in JSON, diff it, and transmit it like any other string data. Interpreters execute rexc directly.
For the full bytecode specification, see the Bytecode Format.
Install the CLI:
bun add -g @creationix/rexUse it:
rex fibonacci.rex # evaluate and output JSON result
rex -e 'max = 200' fibonacci.rex # set a variable before running
rex -c --expr "when x do y end" # compile to rexc bytecode
rex --expr "a and b" --ir # show lowered IRZero-install alternatives:
bunx @creationix/rex --expr "when x do y end"
npx -y @creationix/rex -- --expr "when x do y end"import { compile, parseToIR, optimizeIR, encodeIR } from "@creationix/rex";
const source = "when x do y else z end";
const encoded = compile(source);
const optimized = compile(source, { optimize: true });
const ir = parseToIR(source);
const optimizedIR = optimizeIR(ir);
const reEncoded = encodeIR(optimizedIR);The Rex for VS Code extension provides:
- Syntax highlighting for
.rexand.rexcfiles - Parser-backed diagnostics
- Outline, Go to Definition, and Find References
- Domain-aware completion and hover via
.config.rex
- Language Reference — complete syntax and semantics
- Bytecode Format —
rexcencoding specification - Contributing — repo layout, development workflow, architecture