BKPT LabsDOCS/VIEWALYZER CLI/CLI COMMAND REFERENCE VIEWALYZER · HEADLESS CLI
VIEWALYZER · CLI & AUTOMATION

CLI command reference

viewalyzer-cli <command> [flags], or viewalyzer --headless [flags] for the flag form. viewalyzer-cli help prints this list with every connection key. The binary ships inside the ViewAlyzer app package and next to it in the BKPT Debug extension; the Python SDK finds it through the VIEWALYZER environment variable, then PATH, then the install locations.

Commands

COMMAND WHAT IT DOES
captureRecord a trace to a .vadb (or a .va byte-log). --config, --transport, --output, --duration, --stop-file, --stream, --elf, --keep-va, --no-register, the instrument flags. Capture and stream
snapshotRead the firmware's RAM ring through the probe without a reset, save it as a recording. Same connection flags, --output
pollSample variables over the probe at a fixed rate, no firmware instrumentation: --elf, --symbols a[:u16],0xADDR[:u32][:name], --poll-hz, --duration-s, --stream, --coalesce-gap
resetReset the target behind the configured probe
load <file>Load a .vadb, .va or raw wire dump and print its summary; --output x.vadb converts, --export events|traces|spans|tasks|channels --format json|csv --out file|- exports
query <verb>Pre-shaped JSON views of a recording. Queries
import <rec> --series f.ndjsonMerge an external instrument's samples (a power analyser, a DAQ) into a recording with sync-mark alignment
replay <rec> [--perf]Re-parse a recording and print [metric] category,name,value,unit lines (the HIL bench surface); --perf adds pipeline timings
hwtrace --dry-runThe hardware-trace register image for a core without a target: --arch v7m|v8m|v6m --caps '{...}' --cpu-clock-hz N --swo-freq-hz N --itm-port P --hardware-trace <json|@file>. Capture and stream
probesConnected debug probes with serials
portsSerial ports
targets [--filter s]probe-rs target names (STM32G474RE and 3800 others)
recordingsThe recording index; --delete-recording <id>, --delete-all-recordings
symbols --elf f [--filter s]Pollable data symbols of a firmware image, with address, size and inferred type
memory --elf f [--map f]Flash and RAM usage by section; with the linker map, region capacities and discarded sections
callgraph --elf f [--root fn] [--depth n] [--direction out|in|both] [--entries]Static call graph decoded from the image's code, no toolchain needed
config --config f [flags]Echo the effective connection configuration without touching hardware
domainsInstalled Trace Domain descriptors and their search directories
doctorEnvironment report: probes per kind, serial ports, directories, target registry, license. Always exits 0
license [get|activate <key>|validate|deactivate|install <file>]License state and lifecycle. get is local; the others are the only online calls
version{schema_version, app, version, core, edition, transports[], license{}}

The flag form

VERB FORM FLAG FORM
capture --config b.vacf --output run.vadb --duration 10viewalyzer --headless --config b.vacf --output run.vadb --duration 10
probes--headless --list-probes
snapshot --config b.vacf --output crash.vadb--headless --snapshot --config b.vacf --output crash.vadb
query timeline --recording <id> --tier summary--headless --query timeline --recording <id> --tier summary
poll ...--headless --record-polls ...
replay run.vadb --perf--headless --replay run.vadb --perf
recordings--headless --list-recordings
memory --elf f--headless --analyze-memory --elf f
symbols --elf f--headless --list-symbols --elf f
license get--headless --get-license (and --activate-license KEY, --validate-license, --deactivate-license, --install-license FILE)
version--headless --version

Connection keys

The same names work as flags (--key value) and as keys in a .vacf JSON file (--config); flags win over the file. Unknown keys are errors; comment and _* keys are notes.

KEY MEANING
transportstlink-swo, stlink-rambuf, stlink-rtt, jlink-swo, jlink-rtt, jlink-rambuf, udp, serial, swo-tcp
target-deviceprobe-rs target name (targets --filter lists them); empty lets the probe auto-detect
interfaceSWD (JTAG is accepted and SWD used)
speed-khzSWD clock (a J-Link is capped at 4000 through probe-rs)
stlink-serial, jlink-serialPin a probe when several are attached; with several and no serial the capture refuses rather than guess
no-resettrue attaches without resetting; default false resets after attach and captures from boot
cpu-clock-hzCore clock in Hz: the SWO prescaler and the DWT sample cadence derive from it (trace-clock-hz when the trace clock differs)
swo-freq-hzSWO rate in Hz; 2000000 is the value every probe takes, a STLINK-V3 goes to 24 MHz. It must divide the core clock in whole numbers
itm-portITM stimulus port the recorder stream rides (default 1)
init-swotrue (default): the host programs the ITM and TPIU on connect
rtt-channel, rtt-addressRTT up-channel index (default: the channel named ViewAlyzer, else 0); _SEGGER_RTT address to skip the scan
rambuf-address, rambuf-scan-start, rambuf-scan-size, rambuf-poll-msThe _VA_RAMBUF control block (skips the scan); the RAM scan window (default 0x20000000, 128 KB); the idle poll interval (5 ms)
udp-ip, udp-port, serial-port, baud, cobsThe socket and serial transports; cobs defaults to true for both
swo-tcp-port, swo-tcp-hostThe bkpt_gdbserver --swo-tcp side channel (127.0.0.1) the swo-tcp transport decodes
jlink, jlink-engineSEGGER install directory; auto | segger-dll | probe-rs
dwt, dwt-exc, dwt-pc, dwt-watch, dwt-counters, dwt-path, itm-ports, itm-privilege, itm-timestamps, hardware-traceHardware trace, see Capture and stream

--elf <firmware.elf> on capture, snapshot and poll pins the control block from the image (_VA_RAMBUF, _SEGGER_RTT) instead of scanning RAM, and names the polled symbols.

Older tool-path and server-port keys (jlink, arm-gdb, *-port, stlink) are accepted and reported as "no effect": the native probe drivers spawn no servers.

Output conventions

CHANNEL CONTENTS
stdoutQuery and list commands: exactly one JSON object. capture, snapshot, poll: human progress lines, the contract lines below, then one JSON envelope as the last line
stderr--stream JSON lines during a capture or a poll
exit code0 success, 1 failure (an error envelope is still printed). query compare exits 2 for a regression; hwtrace exits 2 on a configuration error

The two lines hosts parse:

[headless] Recording saved: D:/tmp/run.vadb (2848 KB)
[headless] Recording registered: id=328d49aa4eb6

[headless] ERROR: ... precedes any failure. [headless] State: ..., [headless] t=... events ... and [capture] ... are progress, not contract.

Errors are one envelope:

{ "schema_version": 2, "error": "window_too_wide",
  "message": "634 events in the window exceed the 200 row cap for budget low",
  "suggestion": { "t_end_us": 31545, "or": "filter with --kinds, or raise --budget" },
  "limits": { "max_rows": 200, "would_return_rows": 634 } }

Codes: bad_arguments, bad_config, no_such_recording, bad_recording, window_too_wide, bad_sql, empty_capture, capture_failed, snapshot_failed, empty_snapshot, reset_failed, cooldown_active (with retry_after_s), license_file_rejected, no_hw_trace, etm_not_present, symbol_not_found, internal.

Recordings and the index

A recording is one SQLite file. Any command that takes --recording accepts a path or the 12-hex recording_id; recordings lists {recording_id, path, schema_name, duration_us, size_bytes, created_utc} for every registered file that still exists, and the id is a stable hash of the absolute path and mtime. The index lives at <app dir>/recordings/index.json (%APPDATA%\ViewAlyzer-GPUI, ~/Library/Application Support/ViewAlyzer-GPUI, ~/.config/ViewAlyzer-GPUI); hosts that manage their own files pass paths and --no-register.

Utilities in practice

$ viewalyzer-cli version
{"schema_version":2,"app":"ViewAlyzer","version":"1.1.0","core":"rust","edition":"full","transports":["stlink-swo","stlink-rambuf","stlink-rtt","jlink-swo","jlink-rtt","jlink-rambuf","udp","serial","swo-tcp"],"license":{"type":"key","tier":"solo","licensed":true}}

$ viewalyzer-cli targets --filter STM32G474
{"schema_version":2,"filter":"STM32G474","count":18,"targets":[{"name":"STM32G474CB","architecture":"arm"}, ...]}

$ viewalyzer-cli config --config nucleo_g474_rambuf.vacf --stlink-serial 0033004B3033510735393935
{"schema_version":2,"config":{"transport":"stlink-rambuf","target-device":"STM32G474RE","interface":"SWD","speed-khz":24000,"no-reset":false,"stlink-serial":"0033004B3033510735393935","rambuf-scan-start":536870912,"rambuf-scan-size":131072},"describe":"stlink-rambuf target STM32G474RE cb 0x00000000 scan 0x20000000+0x20000 reset=true","probe_spec":"stlink:0033004B3033510735393935","capture_error":null,"notes":[]}

$ viewalyzer-cli symbols --elf firmware.elf --filter uwTick
{"schema_version":2,"symbol_legend":[{"name":"uwTick","address":"0x20000058","size":4,"type":"i32"}, ...],"data_symbols":3,"text_symbols":0}

$ viewalyzer-cli memory --elf firmware.elf
{"schema_version":2,"text":6816,"data":16,"bss":11016,"total":17848,"flash_used":6832,"ram_used":11032,"sections":[{"name":".text","address":"0x080001D8","size":6056,"category":"flash"}, ...]}

$ viewalyzer-cli doctor
{"schema_version":2,"app_version":"1.1.0","checks":[{"id":"probes_stlink","status":"ok","detail":"0033004B3033510735393935"},{"id":"probes_jlink","status":"none"},{"id":"serial_ports","status":"ok","detail":"COM29"},{"id":"recordings_dir","required":true,"status":"ok","path":"..."},{"id":"probe_rs_targets","status":"ok","detail":"3891 targets"},{"id":"license","status":"ok","detail":"Active"}]}

doctor is the first thing to run on a new machine: it exits 0 whatever it finds and names what is missing.

Tests

cargo test -p va-cli runs hardware-free end-to-end tests on every OS: a synthetic recorder stream through load, every query tier and export, a UDP loopback capture with COBS framing, --stream and --stop-file, the error paths, and a loopback SWO capture through every hardware-trace query plus the hwtrace --dry-run conformance table shared with bkpt_gdbserver.