Getting Started
Getting Started
This guide walks you through installing Cade, writing your first table configuration, validating and running it, and exploring it in the interactive console.
Prerequisites
- A terminal on Linux or Windows — on Windows, WSL gives the best TUI experience
Cade ships as a single self-contained binary, so there is nothing to compile and
no runtime to install. The Downloads page lists the
current release for every platform, with the install commands for each package
format and the SHA-256 checksums for verifying what you downloaded. Take the
build for your platform and put cade on your PATH.
Releases cover Linux on x86-64 and ARM64, and Windows on x86-64. There is no prebuilt macOS binary — on a Mac, build from source using the instructions on that page.
Verify the install:
cade --version
You can also print the full build details — version, commit, build time, Go version, and platform — with:
cade version
Your First Table
A table configuration is a .cade file written in HCL that describes your machine: its devices, variables, and scoring rules. Cade loads every .cade file it finds in the current directory, or in a directory you point it at with -d.
Create a file named my-first-table.cade:
name = "My First Table"
version = "0.1.0"
# A single standup target switch on the playfield.
device "switch" "standard" "pop_target" {
id = 54
type = "NO"
}
# How many points a target hit is currently worth.
variable "int" "target_value" {
initial = 1000
min = 100
max = 10000
scope = "global"
}
# Award points every time the target is hit.
score "event" "target_hit" {
when = device.pop_target.hit
points = var.target_value
}Three things are happening here. The device block declares a physical switch and gives it the name pop_target. The variable block declares a value the table can read and change while a game runs. The score block ties them together: when the pop_target switch reports a hit, award whatever target_value currently holds.
Two syntax rules are worth internalizing now, because they are the most common source of a table that loads but never scores:
- Event names are written bare. Use
when = device.pop_target.hit. The attribute iswhen;triggeris accepted as a synonym, and if a rule somehow carries both,whenwins. Older tables often usetrigger— those load, but preferwhenin anything you write. - Expressions are written bare, with a
var.prefix. Usepoints = var.target_value. Wrapping an expression in${...}is a parse error inside a.cadefile and will stop the table from loading.
Validate the Configuration
Before running the table, check it for syntax errors, missing references, and structural issues:
cade validate my-first-table.cade
A clean run reports:
Validating Configuration
✓ Configuration loaded successfully
Summary
──────────────────────────────────────────────────────
Files Validated: 1
Valid Files: 1
Files with Issues: 0
Issues by Severity:
Total Issues: 0
✓ Validation PASSED
Cade also prints a few structured log lines around that report; the line that
matters is the final ✓ Validation PASSED, and the exit code is non-zero when
validation fails.
Run validate with no arguments to validate every .cade file in the current directory:
cade validate
Validation reports HCL syntax errors, missing or unresolved references, type mismatches, and circular dependencies. Useful flags:
| Flag | Effect |
|---|---|
--dir <dir> | Validate a specific directory |
-r, --recursive | Recurse into subdirectories of a directory target |
-s, --strict | Enable strict validation, including reserved-word checks |
-f, --format <fmt> | Output as text (default), json, or yaml |
--show-graph | Print the dependency graph between blocks |
See the table configuration reference for the full set of blocks available inside a .cade file.
Run the Table
Launch Cade from the directory containing your table:
cade
By default, Cade loads every .cade file it finds in the current directory. To search subdirectories as well, pass -r:
cade -r
To point at a specific directory of table files, use -d:
cade -d examples/
To bring up the built-in web server for health monitoring and debugging alongside the runtime, add -w:
cade -w
Explore in the Console
The interactive console is the quickest way to experiment with a table. It evaluates expressions, triggers events, and inspects variables in real time, in a multi-panel TUI.
Launch it from the directory containing your table — it discovers .cade files exactly the way cade does:
cade console
At the cade:debug> prompt you can:
- List the events your table can score on —
inspect eventsprintsdevice.pop_target.hit → points: var.target_value, straight from the rule you just wrote - Evaluate expressions —
eval 100 + 50 - Set a value and use it —
set var.target_value 1000, theneval ${var.target_value} * 2 - Trigger events —
trigger device.pop_target.hit - Switch the color scheme —
themelists the built-in themes,theme lightapplies one - List commands with
help, or press Tab for completion
Note: The console’s
evalcommand uses${...}around variable references, and resolves those names from the console session — the values youset, plus built-ins likescore. This is console-only syntax; inside a.cadefile, expressions stay bare (points = var.target_value).
Watch the rule score
trigger pushes the event into the engine, but points are only awarded once a
game is in progress and the console is pointed at an active player. Put the
machine on free play by adding this to cade.conf next to your table:
credits {
free_play = true
}Then, at the prompt:
start
go
player 1
trigger device.pop_target.hit
start adds player 1, go begins the game, and player 1 makes that player the
target of the debug commands. The trigger now reports the points the rule awarded
and the player’s running score.
A few flags worth knowing on first contact:
| Flag | Effect |
|---|---|
--watch=false | Hide the watch panel the TUI shows by default |
--no-audio | Disable the audio subsystem — useful in headless or WSL environments |
--no-tui | Run in pipe mode, reading commands from stdin |
Pipe mode makes the console scriptable:
echo "inspect events" | cade console --no-tui
See the console overview for a full tour of the panels, commands, and keyboard shortcuts.
Optional: Runtime Configuration
Table files describe what your machine is. A separate runtime configuration file, cade.conf, describes how to run it — whether to start the web server, which logging level to use, and which platform driver to bridge to. Cade looks for cade.conf in the current directory first, then at $XDG_CONFIG_HOME/cade/cade.conf (defaulting to ~/.config/cade/cade.conf).
A minimal cade.conf that enables the web server and sets the logging level:
web {
enabled = true
}
logging {
level = "info"
}You only need to specify the settings you want to change; everything else uses sensible defaults. To override the config path explicitly, pass --config:
cade --config ./cade.conf
Note:
--configpoints at acade.confruntime config, never at a.cadetable file. To load tables from a particular place, use-d.
See the Cade config reference for every available setting.
Where to Go Next
- Learn the building blocks — Table Design Basics walks through creating a scoring element and a mode, the two pieces most tables are built from.
- Build out your table — The table configuration reference covers devices, events, variables, scoring rules, fragments, and platforms.
- Wire up hardware — The driver guides cover the FAST Framework, Visual Pinball, and the virtual driver for testing without hardware.
- Write expressions — The expressions guide explains the formula language used inside
when,points, andupdatefields. - Learn the console — The console panels and cascade viewer pages show how to debug live games.