Expression Playground (orchstep eval)
Evaluate template and JavaScript expressions against a real workflow context - without running any steps
Available since v0.8.0.
orchstep eval answers one question instantly: "what value would this
expression have in my workflow, with these exact flags?" It builds the
same variable context orchstep run would - workflow defaults,
environment groups/environments, --vars-file, --var - then evaluates
your expression against it. No steps execute; nothing is touched.
It replaces the debug loop of adding a throwaway echo step and running
the task just to see what a variable resolves to.
Quick examples
All outputs below are real, from the environment-promotion use case:
$ orchstep eval --env production 'vars.db_host'
prod-db.internal:5432
$ orchstep eval --env production --var replicas=99 '{{ vars.replicas }}'
99
$ orchstep eval --env production 'vars.require_approval === "true" && Number(vars.replicas) > 4'
true
$ orchstep eval --env staging --lang template 'deploying {{ vars.app_name }} to {{ vars.env_name }} ({{ vars.replicas }} replicas)'
deploying checkout-service to staging (4 replicas)
$ orchstep eval --env dev '({host: vars.db_host, level: vars.log_level})'
{
"host": "dev-db.internal:5432",
"level": "debug"
}Objects print as JSON; scalars print plainly. Evaluation errors surface exactly as they would in a workflow (and exit non-zero):
$ orchstep eval 'vars.nonexistent.deep'
Error: failed to evaluate JavaScript expression: TypeError: Cannot read property 'deep' of undefinedFlags
| Flag | Description |
|---|---|
-f, --file | Workflow file providing the context (default: orchstep.yml if present) |
--env | Environment to apply, exactly like run |
--var | Runtime variable overrides (repeatable, highest precedence) |
--vars-file | Load variables from a YAML file |
--lang | auto (default), template, or js |
-q, --quiet | Print only the value |
Without a workflow file it still works as a bare calculator
(orchstep eval '1 + 2 * 3' prints 7) - with a note that the context
is empty.
Language selection
auto applies the engine's own condition rule: input fully wrapped in
{{ }} evaluates as a Go template, anything else as JavaScript - the
identical behavior of if: and assert. Two overrides:
--lang templaterenders the input through the template pipeline, so mixed text works ('host={{ vars.db_host }}') - the same renderingdo:andargs:get.--lang jsforces JavaScript.
Interactive REPL
orchstep eval with no expression (in a terminal) starts a REPL:
$ orchstep eval -f orchstep.yml --env staging
orchstep eval - interactive expression playground
eval(auto)> vars.replicas
[javascript] 4 (truthy=true)
eval(auto)> {{ vars.db_host }}
[template] staging-db.internal:5432 (truthy=true)
eval(auto)> :vars # dump the full merged variable map as JSON
eval(auto)> :tpl # switch language (:js, :auto)
eval(auto)> :qWhy results can't lie
eval is not a reimplementation - it calls the engine's own evaluation
paths (the same condition evaluator and template pipeline workflows use).
Whatever it prints is what your if:, assert, until: or {{ }} will
do at run time, byte for byte.
See also
- JavaScript Expressions - the JS-first syntax guide
- Templates & Expressions - the Go-template side
- Environments & Variable Files - what
--envloads