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, including task-states, resources, queue-failures and semaphores with actor-ID filters. 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, a stable machine-parseable surface for CI harnesses; --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
doctorEnvironment report: probes per kind, serial ports, directories, target registry, license, caps_in_effect, caps_source (free, license, or none), and effective_caps. 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: required when the CLI programs direct SWO, optional for swo-tcp recorder streams whose CLK: setup supplies the recording clock (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-hostA simulator or debug server's raw-SWO side channel (127.0.0.1) that 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, map_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.1","caps_in_effect":true,"caps_source":"free","effective_caps":{"max_recording_seconds":5,"max_visible_lanes":10,"cooldown_seconds":5,"max_poll_hz":100,"max_poll_symbols":4},"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":"free","caps_in_effect":true,"caps_source":"free","caps":{"max_recording_seconds":5,"max_visible_lanes":10,"cooldown_seconds":5,"max_poll_hz":100,"max_poll_symbols":4}}]}

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

Validate a custom Trace Domain

viewalyzer-cli parse-trace-domain my-domain.vadomain --pretty
viewalyzer --headless --parse-trace-domain my-domain.vadomain --pretty
viewalyzer-cli parse-trace-domain --schema

This offline check uses the same parser as the applications. No SDK, probe or target connection is required. Pass one or more filenames; JSON output includes schema_version, domain_api, valid, and a files array with per-file results. Errors name the precise path, JSON Pointer pointer and message; syntax errors include line and column. Exit status is 0 for valid files, 1 for rejected content, or 2 for unreadable files or invalid arguments. Batch validation checks every file; status 2 takes precedence over 1. The --schema form takes no files and returns the structural schema in the response's schema property. Complete validation also checks semantic constraints and references.

See Creating custom Trace Domains for the full format, steps, examples and the optional Python SDK wrapper.