OM Script Language Reference¶
This page is the formal reference for the OM Core scripting language (.openm files). It covers syntax grammar, all commands, types, control flow, and error codes. For a tutorial-style introduction, see Scripting.
File format¶
OM Core scripts use the .openm extension. Each line is a statement. Lines are executed sequentially by the REPL/TUI command interpreter.
Lexical rules¶
| Element | Rule |
|---|---|
| Comments | Lines starting with # are comments and ignored. |
| Whitespace | Spaces and tabs separate tokens. Leading/trailing whitespace is stripped. |
| Strings | Double-quoted "..." or single-quoted '...' literals. |
| Numbers | Integer (42) or float (3.14). |
| Booleans | true/yes and false/no (case-insensitive). |
| Tuples | (item1, item2) or (item1,) — used for key parameters. |
| Identifiers | [a-zA-Z_][a-zA-Z0-9_]* — dimension, cube, view, variable, and item names. |
| Semantic address | Cube::Dim.Item:Dim.Item — see Semantic addresses. |
Variables¶
Assignment¶
Three forms are accepted. The canonical form is var (or set):
var count = 42
set name = "test"
var message = "hello world"
Bash-style assignment also works when there are no spaces around =:
count=42
name="test"
Use var -g (or set -g) to create a global variable that persists across macro playback:
var -g theme_color = "#3B82F6"
Expansion¶
The canonical expansion syntax is {{name}}:
selected="PL::Account.Revenue:Year.2026"
echo Selected: {{selected}}
rule {{selected}} = 100000
Command capture¶
The canonical command capture syntax is exec {{cmd}}:
cmd = "timestamp %Y%m%d_%H%M%S"
ts = exec {{cmd}}
You can also capture directly in an assignment:
ts = exec timestamp %Y%m%d_%H%M%S
Legacy syntax (deprecated)¶
The $name, ${name}, and $(command) syntax still works but emits a warning. Use {{name}} and exec {{cmd}} instead.
Variable commands¶
| Command | Syntax | Description |
|---|---|---|
var |
var <name> = <value> |
Create a variable. Use var -g for global. |
set |
set <name> = <value> |
Alias for var. Use set -g for global. |
vars |
vars [name] / vars -g |
List all variables, or show one by name, or list globals. |
unset |
unset <name> |
Delete a variable. |
Control flow¶
if / then / else / elseif / end¶
Conditional execution with comparison operators and boolean logic.
if Revenue > 1000 then echo "High revenue" end
if Quarter == "Q1" then set Target 100 else set Target 200 end
if A > B then echo "A wins" elseif A == B then echo "Tie" else echo "B wins" end
Comparison operators: ==, !=, <, >, <=, >=
Boolean operators: and, or, not
run¶
Execute an OpenM script file with control flow support.
run myscript.openm
Script files support all REPL commands, if/then/else/elseif/end blocks, variables, and conditions.
Commands¶
Model definition¶
dim — define a dimension¶
dim Region North South East West # unordered by default
dim Region --set North South East West # explicit unordered
dim Year --seq 2026 2027 2028 2029 2030 # ordered sequence
dimension — dimension sub-commands¶
dimension create <name> [--set|--seq] [item1 item2 ...]
dimension rename <old_name> <new_name>
dimension delete <name>
cube — define or manage a cube¶
cube PL Year # create (backward-compatible)
cube create <name> [dim1 dim2 ...]
cube delete <name>
cube attach <cube_name> <dim_name>
cube detach <cube_name> <dim_name>
view — define or activate a view¶
view PnL # activate existing view
view PnL = Financials::Account:Year # create simple 2D view
view PnL = Sales rows: Account cols: Month page: Scenario Version
view create V = Sales::Region:Product
view rename <old_name> <new_name>
view delete <name>
Supported axes: rows (vertical), cols (horizontal), page (higher-level).
use — set the active cube context¶
use Sales
rule Revenue = Cost * 1.15 # resolves to Sales::Revenue
use sets the default cube for subsequent rule commands that omit a Cube:: prefix.
Rule definition¶
rule — define a calculation rule¶
rule Cube::@.channel:Dim.Item:Dim.Item = expression
rule set <target> = <expression>
rule delete <rule_id>
rule set-anchored <view_id> <cell_ref> = <expression>
rule delete-anchored <view_id> <cell_ref>
Cube::— the target cube.@.channel— the channel the rule writes to. If omitted,@.valueis implied. Use@.fill,@.font_color, etc. for style/format rules.Dim.Item:Dim.Item— the semantic address.*— slice wildcard.$prefix — anchored rule (attached to a specific cell).
Examples:
rule Drivers::Driver.PriceGadgets:* = 120
rule PnL::Account.TotalRevenue:* = PnL::[Account.RevenueGadgets] + PnL::[Account.RevenueWidgets]
rule $Sales::Years.2023:Products.A = 100 # anchored rule
delete_rule — delete a rule by ID¶
delete_rule rule_abc123
set_rule_order — set rule execution order¶
set_rule_order rule_a rule_b rule_c
rules — list rules for a cube¶
rules <cube_name>
Cell values¶
hval / hardvalue — set a cell hardvalue¶
Set a user hardvalue that overrides rule computation. This is the preferred way to input data without creating per-cell rules.
hval view_id=<id> row=<n> col=<n> value=<value>
hval view_id=<id> row_key=(<id>,) col_key=(<id>,) value=<value>
hardvalue is an alias for hval. Both delegate to the canonical set_cell_hardvalue command.
Examples:
hval view_id=view_1 row=0 col=0 value=42
hval view_id=view_1 row_key=(item1,) col_key=(item2,) value=3.14
hardvalue view_id=view_1 row=0 col=0 value="hello"
set_cell — set a cell value by indices¶
set_cell view_id=<id> row=<n> col=<n> value=<value>
Alias for hval with row/col index addressing.
set_cell_by_keys — set a cell value by dimension keys¶
set_cell_by_keys view_id=<id> row_key=(<id>,) col_key=(<id>,) value=<value>
Alias for hval with dimension item key addressing.
clear_cell — clear a cell hardvalue¶
clear_cell view_id=<id> row=<n> col=<n>
Removes the direct stored value/override. Does NOT delete anchored rules.
clear_cell_by_keys — clear a cell hardvalue by keys¶
clear_cell_by_keys view_id=<id> row_key=(<id>,) col_key=(<id>,)
Calculation¶
calc — recalculate the model¶
calc
calc all
recalc — force full recalculation¶
recalc
Groups and outlines¶
group — group/outline operations¶
group create <dim> <label> [parent=<group>] [item1 item2 ...]
group add <dim> <group> <item1 item2 ...>
group detach <dim> <item1 item2 ...>
group delete <dim> <group>
group rename <dim> <group> <new_label>
group list <dim>
Persistence¶
save — save the workspace¶
save model.json
save model ~/models/finance.openm
save macro format_blue ~/format_blue.json
load — load data, macros, or models¶
load model ~/models/finance.openm
load macro my_macro.json
load macro ~/macros/format.json --play
load data ~/data/sales.xlsx
source — execute another script¶
source scripts/depreciation_schedule.openm
Commands executed via source are not saved to command history. Nested source paths resolve relative to the containing script. Circular sources are detected and rejected.
Style channels¶
Visual styling is applied through rule channels, not a separate formatting command.
| Channel | Description |
|---|---|
@.value |
Default value channel (implied when no channel is given) |
@.format_number |
Number or currency display format |
@.fill |
Background fill color |
@.font_color |
Font color |
@.font_weight |
Font weight (e.g. 700 for bold) |
rule C::@.fill:PL.Revenue:Year.2026 = #3B82F6
rule C::@.font_color:PL.Revenue:Year.2026 = #FFFFFF
rule C::@.font_weight:PL.Revenue:Year.2026 = 700
rule C::@.format_number:PL.Revenue:Year.2026 = 'preset:number(decimals=2; group=true)'
See Formatting for number format patterns.
Debugging¶
echo — print a message¶
echo Model built successfully
echo Total is: {{total}}
assert — verify a condition¶
assert <condition> [message]
Halts script execution on failure. Supports numeric comparisons and OpenM rule references.
assert 5 > 3
assert count == 10 "Count should be 10"
assert Inputs::Asset.Vehicle:Metric.Cost == 50000 "Vehicle cost"
Comparison operators: ==, !=, <, >, <=, >=
timestamp — print a timestamp¶
timestamp # 2026-05-03T11:42:00+12:00
timestamp %Y%m%d_%H%M%S # 20260503_114200
Selection and navigation¶
| Command | Syntax | Description |
|---|---|---|
selection |
selection |
Show current cursor position as (row, col). |
select |
select <row> <col> or select <r1> <c1> <r2> <c2> |
Select a cell or range. |
up |
up [steps] |
Move selection up. |
down |
down [steps] |
Move selection down. |
left |
left [steps] |
Move selection left. |
right |
right [steps] |
Move selection right. |
Introspection¶
| Command | Syntax | Description |
|---|---|---|
info |
info or info <command_id> |
Workspace summary or detailed command info. |
views |
views |
List all views. |
cubes |
cubes |
List all cubes. |
dimensions |
dimensions |
List all dimensions. |
engine |
engine [version] |
Show engine backend type and version. |
list |
list [category] [search] |
List available commands. |
categories |
categories |
List all command categories. |
search |
search <pattern> |
Search for commands. |
exec |
exec <command_id> [key=value ...] |
Execute a registered command. |
Macros¶
| Command | Syntax | Description |
|---|---|---|
record |
record start [--expand] <name> [description] |
Start recording a macro. |
record |
record stop |
Stop recording. |
play |
play <name> [--preserve-vars] |
Play back a recorded macro. |
Engine settings¶
| Command | Syntax | Description |
| --- | --- |
| set_dependency_tracking | set_dependency_tracking on\|off | Toggle dependency tracking. |
| set_multithread_recompute | set_multithread_recompute on\|off | Toggle multithreaded recalculation. |
Session¶
| Command | Syntax | Description |
|---|---|---|
clear |
clear |
Clear the screen. |
quit / exit |
quit |
Exit the REPL. |
restart |
restart |
Quit and relaunch OpenM. |
Aliases¶
| Alias | Canonical |
|---|---|
cat |
categories |
ls |
list |
run |
exec (in command context) or run <filename> (script execution) |
recalc |
calc |
hval |
set_cell_hardvalue |
hardvalue |
set_cell_hardvalue |
set_cell |
set_cell_hardvalue |
set_cell_by_keys |
set_cell_hardvalue |
exit |
quit |
Semantic addresses¶
Semantic addresses identify cells or slices without referring to grid coordinates.
Cube::Dim1.Item1:Dim2.Item2
Components:
Cube— the cube name.Dim1.Item1— a dimension item selector.Dim2.Item2— another dimension item selector.@.channel— optional channel specifier (before the selectors). Implied@.valueif omitted.:— separates multiple selectors.*— slice wildcard (matches all items in that dimension).
Sequential accessors¶
Sequential keywords are valid only in bracket notation on the right-hand side of rules:
Dim[FIRST] # first item in ordered dimension
Dim[LAST] # last item
Dim[PREV] # previous item (RHS only)
Dim[NEXT] # next item (RHS only)
Dim[THIS] # current item during rule evaluation
Regular item references use dot notation: DimensionName.ItemName, not DimensionName[ItemName].
Reference resolution¶
OM Core resolves a shorthand reference in this order:
- Explicit selectors in the RHS reference are applied first.
- For any remaining dimensions in the referenced cube, OM Core carries over matching dimensions from the current target-cell context, provided the binding is unambiguous.
- Dimensions that exist in the target cube but not in the referenced cube are ignored.
- Any dimension that exists in the referenced cube but is neither explicitly selected nor available from the current context is ambiguous and should be written explicitly.
Script structure¶
A .openm script typically follows this order:
- Define dimensions
- Define cubes
- Define views
- Define rules (or set hardvalues)
- Calculate
- Assert or save
For model bundles, use the numbered structure:
00_variables
01_dimensions
02_cubes
03_inputs
04_rules
05_checks
06_views
07_formatting
08_groups
build.openm
build.openm sources the other files in order and then runs calc.
Error codes¶
OM Core uses cell-level error codes consistent with spreadsheet conventions:
| Code | Meaning |
|---|---|
#DIV/0! |
Division by zero |
#NAME? |
Unrecognized or deleted name |
#N/A |
Value not available (reserved) |
#NULL! |
Intersection of ranges produced zero cells (reserved) |
#NUM! |
Failed to meet domain constraints |
#REF! |
Reference to an invalid cell |
#VALUE! |
Parameter is wrong type |
#CIRC! |
Circular dependency detected |
#EXPRESSION! |
Expression evaluation failure |
#SYNTAX! |
Syntax or reload parse error (reserved) |
Error propagation rules:
- Arithmetic operators propagate errors from any operand.
- Functions propagate errors from arguments (unless
IFERRORis used). - Aggregates (
SUM,AVERAGE, etc.) skip error cells by default. IFERROR(expr, fallback)returns the fallback when the expression errors.
See also¶
- Scripting — tutorial-style introduction
- Rule syntax — detailed rule syntax reference
- Formatting — number format patterns
- Rule engine semantics — evaluation order and dependency tracking
- Functions — built-in function reference