Skip to content

CLI

The srig CLI lets you interact with SiliconRig boards from your terminal.

Source on GitHub

Installation

bash
# macOS / Linux
curl -fsSL https://siliconrig.dev/install.sh | sh

# or with Go
go install github.com/siliconrig/srig-cli@latest

Authentication

Set your API key as an environment variable:

bash
export SRIG_API_KEY=key_...

Or pass it per-command:

bash
srig --api-key key_... status

Create API keys in the web UI under API Keys.

Commands

srig status

Show available boards and your active sessions.

bash
srig status

srig session

Manage sessions explicitly.

bash
# Create a session on an ESP32-S3 board
srig session create --board esp32-s3

# List your sessions
srig session list

# End a specific session
srig session end sess_xxxxxxxxxxxx

# End your active session (auto-detects)
srig session end

srig flash

Flash firmware to the board in your active session. If --session is not given, auto-detects your active session.

bash
# Flash to the active session
srig flash firmware.bin

# Flash to a specific session
srig flash firmware.bin --session sess_xxxxxxxxxxxx

Accepts a raw .bin (all boards), a .uf2 (RP2350), or — for STM32 boards — an .elf or Intel .hex. SiliconRig converts ELF/HEX to a raw image server-side, so the same formats work from the SDK and the API too. The ELF/HEX must be linked at the board's flash base address; see firmware format per board.

bash
srig flash build/firmware.elf --session sess_xxxxxxxxxxxx

srig run

Collapse the create → flash → watch → end workflow into one command. Point it at a firmware image and a pattern to look for, and it exits with a code your CI pipeline can act on — no scripting required:

bash
srig run firmware.bin --board esp32-s3 --expect "All tests passed"

Under the hood it creates a session on a free board, flashes the firmware, watches serial output until a pass/fail condition is reached or --timeout elapses, then ends the session — always, even on failure or interruption. Firmware can be a raw .bin, a .uf2, or (for STM32) an .elf / Intel .hex — see firmware format per board.

Flags

FlagDefaultDescription
--boardBoard type (required)
--expectRegex that must appear in serial output for the run to pass
--failRegex that fails the run immediately if it appears
--sendString to write to the device's UART after boot (interprets \n, \r, \t)
--logSave the full serial capture to this file
--timeout60sHow long to watch serial output after flashing
--retries0Retry on transient infrastructure failures (e.g. no free board); never retries a test failure
--retry-delay15sDelay between retries
--jsonfalseEmit a machine-readable result on stdout instead of human output

Pass/fail precedence

Only one condition decides the outcome, checked in this order as each serial line arrives:

  1. Sentinel — a line matching ##srig-exit:N## sets the exit code to N directly
  2. --fail — if the pattern matches, the run fails immediately
  3. --expect — the run passes once the pattern matches; if --timeout elapses first, the run fails

If neither --expect nor --fail is given, run watches serial for --timeout and exits 0 once it elapses — useful for smoke-testing that firmware boots without crashing.

Exit codes

CodeMeaning
0Pass
1Test failed, or --expect never matched before --timeout
2Infrastructure error (no free board, connection lost, bad flags, etc.)
130Interrupted (Ctrl-C)

Because each code's meaning is fixed, run is safe as the last step in a CI job — a non-zero exit fails the job like any test runner would.

The exit sentinel

For firmware with real pass/fail logic, have it print a sentinel line with the exact result instead of relying on --expect to infer success from a log message:

c
printf("##srig-exit:%d##\n", tests_failed ? 1 : 0);

srig run picks up the sentinel over any --expect / --fail pattern, so firmware can report any code — not just pass/fail — and the CLI exits with exactly that code.

Driving interactive firmware

If your firmware waits for a command before running its test path, use --send to write it to the device's UART right after boot — the same bidirectional serial connection srig serial uses:

bash
srig run firmware.bin --board <type> --send "test\n" --expect "##srig-exit:0##"

--json output

With --json, serial output goes to stderr and stdout carries a single JSON object once the run concludes:

json
{
  "result": "pass",
  "exit_code": 0,
  "reason": "expect",
  "matched": "All tests passed!",
  "session_id": "sess_xxxxxxxxxxxx"
}

reason is one of sentinel, fail, expect, timeout, or ran.

Examples

bash
# Pass/fail on a log message
srig run firmware.bin --board <type> --expect "All tests passed"

# Firmware reports its own exit code via the sentinel
srig run firmware.bin --board <type> --send "test\n"

# Fail fast on a panic, with a longer watch window
srig run firmware.bin --board <type> --expect "DONE" --fail "PANIC" --timeout 2m

# Save the serial capture and ride out a busy fleet
srig run firmware.bin --board <type> --expect "READY" \
  --log serial.log --retries 5 --retry-delay 30s

In CI, the step's exit code is the run's exit code — a failed on-device test fails the job, no separate grep needed:

yaml
- name: Run on-device tests
  env:
    SRIG_API_KEY: ${{ secrets.SRIG_API_KEY }}
  run: |
    srig run build/firmware.bin --board <type> \
      --expect "All tests passed" --fail "PANIC" --timeout 90s --log serial.log

srig serial

Open an interactive serial console. If --session is not given, auto-detects your active session.

bash
# Connect to the active session
srig serial

# Connect with a timeout (useful in CI)
srig serial --timeout 30s

# Save serial output to a file
srig serial --log output.txt

Press Ctrl+] to disconnect. The session stays alive — reconnect or end it explicitly.

Typical workflow

bash
# 1. Reserve a board
srig session create --board esp32-s3

# 2. Flash your firmware
srig flash firmware.bin

# 3. Interact via serial
srig serial

# 4. Done — release the board
srig session end

Global flags

FlagDescription
--api-keyAPI key (overrides SRIG_API_KEY)
--base-urlAPI base URL (default: https://api.srig.io)
--jsonOutput as JSON (for CI/CD pipelines)