Syntax
Global Options
Commands
Command Reference
List Nets (Default)
List all saved nets on a Lager Box. This is the default behavior when no subcommand is provided.
The
Script, OpenOCD and Purpose columns appear only when at least one net has a value for them. Run lager nets show NAME to see the full purpose text.
Example Output:
add
Create a new net by specifying its name, type, channel, and instrument address.
NAME- Unique name for the net (e.g.,supply1,debug_main)ROLE- Type of net:power-supply,battery,solar,debug,adc,dac,gpio,scope,logic,eload,uart,usb,webcam,arm,watt-meter,energy-analyzer,thermocouple,i2c,spi. The legacy tokenssupplyandbattare accepted as input aliases and normalized topower-supply/battery— saved nets always carry the canonical role.CHANNEL- Channel identifier, aslager instrumentslists it (e.g.,1,AIN0,FIO0,I2C0,STM32F4)ADDRESS- VISA address or device path, aslager instrumentslists it (e.g.,USB0::0x0CD5::0x0007::::INSTR)
--box TEXT- Lager Box name or IP--jlink-script FILE- J-Link script file for debug nets (stored on box)--openocd-config FILE- OpenOCD.cfg/.tclfile for debug nets (stored on box)--sda PIN/--scl PIN- Custom LabJack pins fori2cnets--cs PIN/--sck PIN/--mosi PIN/--miso PIN- Custom LabJack pins forspinets--interface A|B|C|D- FTDI channel for agpio,i2corspinet on an FT2232H or FT4232H. The default isA. See Multi-channel FTDI debug adapters below.
A U3 has no MIO pins. Its
FIO0-FIO3 are fixed analog inputs, so Lager refuses them for gpio, i2c and spi nets. The EIO and CIO lines of a U3 are on its DB15 connector.
When pin options are given, the CHANNEL argument is ignored — pass custom. If a chosen pin overlaps another saved LabJack net, a warning is printed but the net is still created. --cs is optional: omit it for 3-pin SPI with manual chip select.
Examples:
The
--jlink-script option is only applicable for debug nets. If used with other net types, a warning is printed and the option is ignored.- Net names must be globally unique across all types
- The (role, instrument, channel, address) tuple must match a connected instrument
- The channel must be one that the box offers for that role. Run
lager instrumentsto see the list. - The address must identify one device. See Two devices of the same model below.
- Channel binding follows the per-instrument rules described in Channel & Role Constraints below
add prints the valid channels for the role and exits with code 1:
gpio, i2c or spi net on FIO0-FIO3.
The box holds the channel list. A newer CLI against an older Lager Box validates against the older list. Run
lager update to get the current list.Channel & Role Constraints
Different instrument families bind nets to channels differently. Lager classifies every supported instrument into one of three categories and enforces the rules consistently acrossadd, add-all, and the TUI.
1. Multi-channel instruments
Instruments with physically independent outputs / inputs. Each channel is its own circuit and can host its own net.
Rule: at most one net per
(instrument, address, role, channel) tuple. Two nets that share (instrument, address, role) but differ in channel are fine — that’s exactly what multi-channel is for.
2. Single-channel, multi-mode instruments
Instruments with one physical channel that can run in one of several modes but not multiple modes at once. The role tells the box which firmware mode to flip the chip into. Lager treats two groups of these chips differently. Single-output instruments (one net per role, with a notice):
Rule: you can save one net for each role on the same chip. When the chip already has a net,
add prints this notice and saves the second net:
add-all does not pick a role for a chip with no saved net: it skips the chip with a warning. The TUI does not let you select both roles of one chip in one batch.
Mode-exclusive chips (one net in total):
Rule: at most one net per
(instrument, address). Once any role is saved on the chip, every other role disappears from the add list of add-all and the TUI. To switch modes, delete the existing net first.
These chips are tracked in _SINGLE_CHANNEL_INST (Keithley, EA) and _MODE_EXCLUSIVE_INST (FTDI_FT232H) in cli/commands/box/nets.py and cli/commands/box/net_tui.py.
3. Single-role debug probes
Standalone debugger boxes — one probe drives one target MCU.
Rule: at most one
debug net per (instrument, address).
4. Multi-channel FTDI debug adapters
FT2232H (2 channels: A, B) and FT4232H (4 channels: A, B, C, D) physically expose multiple USB interfaces. Channels A and B have an MPSSE engine; on the FT4232H, C and D do not. That matters per net type, not per chip. debug, spi and i2c are MPSSE protocols, so they are limited to A and B. gpio runs as asynchronous bitbang, needs no MPSSE, and works on all four. The user picks an interface per net.
Debug nets encode the channel in the device field:
@A/@0, @B/@1, @C/@2, @D/@3. Devices without an @ suffix default to the interface OpenOCD’s interface config picks (typically channel A).
GPIO, I2C and SPI nets take the channel from --interface when you add the net:
lager nets add stores the channel as params.interface on the net record. A net with no interface uses channel A, the only channel of an FT232H. The Net-Manager TUI does not ask for a channel, so it adds these nets on channel A.
lager nets add refuses a channel that the part does not have for the net type, and it names the channels that work. An i2c or spi net cannot use channel C or D, because those channels have no MPSSE engine. A gpio net can use any channel of the part. The box drivers apply the same rules to a net record that you edit by hand, and they accept A-D or 0-3.
UART nets distinguish channels by their tty path. The USB scanner enumerates every /dev/ttyUSB<N> bound to the chip’s USB serial. Each one shows up as a separate add-list entry, so on an FT4232H you will see up to four UART options.
Rule: the channel is part of a net’s identity. A debug net is unique per (instrument, address, channel-suffix). A gpio, i2c or spi net is unique per (role, instrument, pin, address, interface). So a single FT2232H can host:
- one
debugnet on@A - one
debugnet on@B - one
uartnet on a/dev/ttyUSB<N>belonging to whichever channels you didn’t claim for MPSSE gpio,i2candspinets on each channel that--interfacenames. The same pin number can carry one net on each channel.
debug@A and a spi net on interface A); the box doesn’t validate that today.
Quick decision table
Two devices of the same model
Lager decides whether it can create a net from the device address, not from the model. An address that includes a unique serial number names one device. Two devices of that model on one Lager Box both work. For example, two 8-port Acroname hubs give sixteenusb nets.
A LabJack T7 and a LabJack U3 report no serial number, so their addresses have an empty serial field. Two T7 units, or two U3 units, on one Lager Box report the same address. A net cannot say which device it means, so Lager refuses it:
add exits with code 1. add-all and the TUI skip those devices with the same message. lager instruments hides them and prints the message. One T7 and one U3 on the same Lager Box work, because their addresses differ.
add-all
Automatically create nets for all available channels on all connected instruments. This is useful for quickly setting up a new Lager Box.
--box TEXT- Lager Box name or IP--yes- Skip confirmation prompt
add-all prints a warning for each device that it skips. It skips two devices of one model that report the same address. It also skips a single-output or mode-exclusive chip with no saved net. That chip offers more than one role, and add-all does not choose one for you.
add-batch
Create multiple nets from a JSON file for efficient bulk setup.
JSON_FILE- Path to JSON file containing net definitions
--box TEXT- Lager Box name or IP
name, role, channel and address. An optional instrument key names the instrument. When it is absent, the command looks up the instrument from the address.
An optional params object sets what the lager nets add options set:
sda_pinandscl_pinfor a LabJacki2cnet, orcs_pin,clk_pin,mosi_pinandmiso_pinfor a LabJackspinet. Each value is a pin name or a DIO number. Name theinstrumentin the record, because the pins depend on the model.interface(A-D) for an FTDI FT2232H or FT4232H net.
lager nets add checks its options. It refuses any other key in a record or in params. To give a debug net a script, add the net first, then use set-script.
- A key that the command does not read, or a bad
paramsvalue - A role that the instrument does not support
- An address that more than one present device reports
- A channel that the box does not offer for the role
No nets were saved., and exits with code 1:
- A record whose address is not in the current instrument scan, for example an instrument that is not connected
- A
uartrecord, because its channels are per-device tty paths
instrument whose address is not in the scan also skips the role check.
Example:
assign
Assign a USB-serial cable to a known instrument the box cannot auto-detect.
Some instruments have no USB control port. You reach such an instrument over
RS-232 through a generic USB-serial adapter — a Rigol DP711 power supply
behind a Prolific cable, for example. The box sees only the adapter (a uart
device), not the instrument behind it. assign records “this cable is the
DP711’s serial line” on the box. From then on, the scanner reports the
instrument itself. It appears in lager instruments and in the TUI, and you
can create nets for it with lager nets add like any auto-detected device.
Assign once per cable; the assignment is stored on the box and survives
reboots and replugs. Creating nets stays the normal, repeatable step.
End-to-end example (Rigol DP711):
--as-net, the command prints the exact lager nets add invocation
for the new instrument:
- The cable must be plugged in to assign it — its USB identity (vendor/product ID) is captured from the live device.
- Nets for assigned instruments use a durable
serial://<vid>:<pid>/serial/<s>(or.../port/<p>) address instead of a/dev/ttyUSB*path, so they survive tty renumbering, reboots, and port moves. - While a cable is assigned, it is no longer offered as a generic UART device — the serial line belongs to the instrument.
Some cheap USB-serial clones share one serial number (or have none). If
assign reports multiple matching cables, pin the assignment to a physical
box port with --port instead. The trade-off is that if you move the cable to
a different port, the assignment breaks.serial://
address are deleted automatically and reported in the output. The same cascade
applies when you re-assign a cable to a different instrument, and when you
switch its identity from --serial to --port. Only a baud-only re-assign
keeps the existing nets.
Currently assignable devices: Rigol DP711 (single-channel RS-232 power
supply). Run lager nets assign --list to see the catalog your box supports.
delete
Delete a specific net by its name and type.
NAME- Name of the net to deleteNET_TYPE- Type of the net (supply, debug, adc, i2c, spi, etc.)
--box TEXT- Lager Box name or IP--yes- Skip confirmation prompt
delete-all
Delete all saved nets on a Lager Box. This is a dangerous operation.
--box TEXT- Lager Box name or IP--yes- Skip confirmation prompt
rename
Rename an existing net.
NAME- Current name of the netNEW_NAME- New name for the net (must be unique)
--box TEXT- Lager Box name or IP
tui
Launch an interactive terminal-based UI for managing nets. The TUI provides a visual interface for viewing, creating, and deleting nets.
--box TEXT- Lager Box name or IP
- Browse all connected instruments and their channels
- Create new nets with guided prompts (+ Add Nets)
- Read warnings and notices on the Add screen. They appear together in one block, and the Dismiss button hides the block.
- Pick custom pins for a LabJack T7 or U3
i2corspinet. The pencil button on the row opens one editor for the net name and the pins. The pin dialog also opens when you add the net, unless you already set the pins. The dialog shows the current pins, and offers only the pins that the model can use. You can set CS to none for 3-pin SPI. If you choose the defaults again, the net gets the default channel back. A pin already used by a saved net shows a warning - Rename a new net with the pencil button on its row
- Assign custom serial devices (RS-232 instruments) to their USB cables with Assign Device — the
interactive twin of
assign, including the optional create-the-net step (--as-net) - Select a saved net to Rename, Edit Details or Delete it. Edit Details sets Purpose, Notes and Tags. It changes only those three fields and keeps the rest of the net record.
- Delete every saved net with Delete All Nets
- Keyboard navigation (
qorCtrl+Cquits)
set-script
Attach a debug script — either a JLinkScript or an OpenOCD .cfg/.tcl — to an existing debug net. The file is stored on the box and used automatically during connect, flash, erase, and reset operations.
The backend (J-Link vs. OpenOCD) is auto-detected from two signals:
- The probe’s USB VID on the net’s
addressfield (J-Link →jlink; ST-Link, FTDI, CMSIS-DAP, etc. →openocd). - The file — extension first (
.JLinkScript→ jlink;.cfg/.tcl/.ocd→ openocd), with a content sniff as a tie-breaker for extensionless files or stdin.
set-script refuses with a clear error and asks you to pick one via --backend.
A debug net only carries one script at a time. If the other field is already set, set-script clears it and prints a yellow notice on stderr so nothing disappears silently.
NAME- Name of the debug netSCRIPT_PATH- Path to the script file, or-to read from stdin
--backend [jlink|openocd]- Force a specific backend instead of auto-detecting (required if the probe and file disagree)--box TEXT- Lager Box name or IP
remove-script
Remove the debug script (J-Link or OpenOCD) attached to a debug net.
NAME- Name of the debug net
--backend [jlink|openocd]- Only remove the named backend’s script (default: remove whichever is set)--box TEXT- Lager Box name or IP
show-script
Display the contents of the debug script attached to a debug net. The script content is written to stdout, so > out.cfg works. A one-line summary like # OpenOCD config, 1247 bytes is written to stderr. That tells you which backend’s script you see, and it does not pollute a redirect.
NAME- Name of the debug net
--backend [jlink|openocd]- Only show the named backend’s script (default: show whichever is set)--box TEXT- Lager Box name or IP
show
Display all fields of a saved net, including user-provided metadata (purpose,
notes, tags) set with describe.
NAME- Name of the net
--json- Output as raw JSON--box TEXT- Lager Box name or IP
state
Show the live hardware state of every saved net. The box reads each instrument and returns a short summary for each net. The output is the grouped table of lager nets, with a State column after Channel.
--box TEXT- Lager Box name or IP--json- Output as raw JSON
Net types with no probe, such as
uart, spi, scope and logic, show –.
How the box reads the nets:
- The box groups the nets by instrument and reads up to eight instruments at the same time.
- All instruments share one budget of 8 seconds. When the budget ends, every net that did not answer reports
deadline. - The box reads USB hubs one after another. It does not read a hub that has less than 1 second of budget left, and the nets of that hub report
hub-skipped. - A read takes the same instrument locks as a running test, so the command can wait for a test.
- The box reads an
i2cnet with a full bus scan. - On a LabJack T7, one batch reads all
gpio,adcanddacnets, and agpioread does not change the pin direction. - On a LabJack U3, a
gpiooradcread sets the pin to digital or analog mode. A U3dacnet shows–until the box sets a value.
– that has a reason. It groups the nets by reason. A net type with no probe is normal, so the footnote does not list it.
A
usb net can also carry a code. When all nets in a group have the same code, the footnote adds one remedy line:
JSON output:
--json prints an array with one object for each saved net. Each object holds all stored fields of the net, plus these fields:
A box without this endpoint prints a note to update it. The table still prints, with
– in every State cell.
describe
Set metadata on a saved net so AI agents (and humans) understand what the net does
on the DUT. Introduced in lager 0.24.0; the fields feed agent-assisted testing
via the MCP server. At least one of --purpose,
--notes, --tag, --dut-connection or --test-hint (or one of the --clear-*
flags) must be provided. A Lager Box on 0.46.0 or later serves these fields over
HTTP, so a connected control plane can sync them. dut_connection and
test_hints need a box on 0.50.0 or later.
NAME- Name of the net
-p,--purpose TEXT- One sentence: what this net does on the DUT-n,--notes TEXT- Optional notes (gotchas, jumper positions, scope probe points)-t,--tag TEXT- Tag for categorisation/matching (repeatable)--clear-tags- Remove all existing tags before adding new ones--dut-connection TEXT- Where the net lands on the DUT: connector, pin or test point (e.g."J3 pin 4")--test-hint TEXT- One-line advice for a test author (repeatable)--clear-test-hints- Remove all existing test hints before adding new ones--box TEXT- Lager Box name or IP
Net Types Reference
Debug Script Workflow
Both J-Link and OpenOCD debug probes can carry a custom script for handling reset sequences, clock initialization, board-specific signal pinning, or other device-specific behavior. Lager stores one script per debug net — either a JLinkScript or an OpenOCD.cfg/.tcl, never both. It applies that script automatically during connect, flash, erase, and reset operations.
.lager config file:
set-script) and a project-level script (via .lager config) exist, the project-level script takes priority.
Examples
Notes
- Net names are globally unique regardless of type
- Use
lager instruments --box <lager-box>to see available instruments and channels - The TUI provides the easiest way to set up nets for the first time
- Use
add-allto quickly configure a new Lager Box with sensible defaults - I2C and SPI nets are supported on LabJack T7, LabJack U3, Aardvark, and FTDI FT232H, FT2232H and FT4232H adapters
- Debug scripts (both J-Link and OpenOCD) are base64-encoded for storage and decoded automatically during debug operations
- A debug net carries at most one script (
jlink_scriptoropenocd_config);set-scriptenforces this by clearing the other field when present

