Getting Started

install onboarding first-table cli

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, macOS, or Windows (on Windows, WSL gives the best TUI experience)
  • A Go toolchain, to build the binary from source

Cade is currently distributed as source. Clone the repository and build it:

git clone https://cade.run/cade.git
cd cade
go build .

If you have task installed, task build does the same thing with the project’s standard build flags.

Put the resulting cade binary somewhere on your PATH, then verify the install:

cade --version

You can also print the full build details — version, commit, build time, 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 is when; trigger is accepted as a synonym, and if a rule somehow carries both, when wins. Older tables often use trigger — those load, but prefer when in anything you write.
  • Expressions are written bare, with a var. prefix. Use points = var.target_value. Wrapping an expression in ${...} is a parse error inside a .cade file 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:

✓ Configuration loaded successfully

Summary
──────────────────────────────────────────────────────
Files Validated:     1
Valid Files:         1
Files with Issues:   0

✓ Validation PASSED

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:

FlagEffect
--dir <dir>Validate a specific directory
-r, --recursiveRecurse into subdirectories of a directory target
-s, --strictEnable strict validation, including reserved-word checks
-f, --format <fmt>Output as text (default), json, or yaml
--show-graphPrint 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:

  • Evaluate expressions — eval ${var.target_value} * 2
  • Trigger events — trigger device.pop_target.hit
  • Inspect state — inspect target_value
  • List commands with help, or press Tab for completion

Note: The console’s eval command uses ${...} around variable references. This is console-only syntax — inside a .cade file, expressions stay bare (points = var.target_value).

A few flags worth knowing on first contact:

FlagEffect
--startStart the engine automatically on launch
--theme <name>Choose the color theme: dark (default), light, or nord
--no-audioDisable the audio subsystem — useful in headless or WSL environments
--no-tuiRun in pipe mode, reading commands from stdin

Pipe mode makes the console scriptable:

echo "trigger device.pop_target.hit" | 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: --config points at a cade.conf runtime config, never at a .cade table file. To load tables from a particular place, use -d.

See the Cade config reference for every available setting.

Where to Go Next