.lager file is a JSON configuration file that stores settings for the Lager CLI. There are two distinct versions of this file that serve different purposes: a global file shared across all projects, and a project-local file specific to a single project directory.
Two Files, Two Purposes
Global .lager | Project-Local .lager | |
|---|---|---|
| Location | ~/.lager | Any directory in your project (found by searching upward from cwd) |
| Created by | lager boxes add, lager defaults add, lager nets add | lager devenv create, or manually |
| Purpose | Machine-wide box registry, net definitions, command defaults | Project-specific Docker dev environment, debug scripts, file includes |
| Sections | DEFAULTS, BOXES, NETS | DEVENV, DEBUG, includes |
| Shared | One file for all projects | One per project (committed to version control) |
lager boxes and lager defaults read and write the global file. Commands like lager devenv and lager exec search upward from your current directory for a project-local file. The two files never conflict — they contain entirely different sections.
When lager devenv terminal or lager exec starts a Docker container, the global ~/.lager file is automatically mounted inside the container at /lager/.lager (with LAGER_CONFIG_FILE_DIR=/lager), so that box and net definitions are available inside the container.
Global File (~/.lager)
The global file lives in your home directory and is shared across all projects. It stores your box registry, hardware net configurations, and command defaults.
DEFAULTS
Stores default values so you can omit common options from CLI commands. When you run a command without specifying--box or a net name, the CLI checks this section.
Managed with lager defaults.
Fields:
| Config Key | CLI Option | Description |
|---|---|---|
gateway_id | --box | Default box name |
serial_device | --serial-port | Default serial port path |
net_power_supply | --supply-net | Default power supply net |
net_battery | --battery-net | Default battery net |
net_solar | --solar-net | Default solar net |
net_scope | --scope-net | Default oscilloscope net |
net_logic | --logic-net | Default logic analyzer net |
net_adc | --adc-net | Default ADC net |
net_dac | --dac-net | Default DAC net |
net_gpio | --gpio-net | Default GPIO net |
net_debug | --debug-net | Default debug net |
net_eload | --eload-net | Default electronic load net |
net_usb | --usb-net | Default USB hub net |
net_webcam | --webcam-net | Default webcam net |
net_watt_meter | --watt-meter-net | Default watt meter net |
net_thermocouple | --thermocouple-net | Default thermocouple net |
net_uart | --uart-net | Default UART net |
net_arm | --arm-net | Default robotic arm net |
- Command-line option (
--box, net argument) — highest priority LAGER_BOXenvironment variable (for box only)DEFAULTSsection in global~/.lager- Error if required and not found
BOXES
Maps human-readable box names to their IP addresses. This is the box registry that all other commands use to resolve box names to IPs. Managed withlager boxes.
Each entry can be either a simple IP string (legacy format) or an object with additional metadata.
Fields (object format):
| Field | Required | Description |
|---|---|---|
ip | Yes | IP address of the box (typically a Tailscale IP) |
user | No | Username for SSH access |
version | No | Branch or version the box is running (e.g., "main", "staging") |
NETS
Stores hardware net configurations organized by box name. Each net maps a human-readable name to a physical hardware connection (channel on an instrument). Nets are stored in the global file but the actual net data lives on the box — this section serves as a local cache managed bylager nets.
Structure: A dictionary keyed by box name, where each value is an array of net objects.
Net object fields:
| Field | Required | Description |
|---|---|---|
name | Yes | Unique name for the net (e.g., "VDD_MAIN", "SWD") |
role | Yes | Net type: supply, battery, solar, eload, adc, dac, gpio, debug, scope, logic, uart, i2c, spi, usb, watt, thermocouple, webcam, arm |
instrument | Yes | Instrument model name (e.g., "Rigol_DP831", "LabJack_T7") |
address | Yes | Instrument address (USB or network path) |
pin | Yes | Channel or pin number on the instrument |
jlink_script | No | Base64-encoded J-Link script (debug nets only) |
device_path | No | Direct device path (UART nets with USB serial, e.g., "/dev/ttyUSB0") |
channel | No | Port number (UART nets) |
Project-Local File (./.lager)
The project-local file lives in your project directory (or any parent directory). The CLI finds it by searching upward from your current working directory. It is typically committed to version control so that all developers on a project share the same development environment configuration.
This file is completely separate from the global ~/.lager — it contains different sections and is read by different commands.
How the local file is found
When you runlager devenv terminal, lager exec, or lager debug, the CLI starts in your current directory and walks up the directory tree until it finds a .lager file (that is not the global ~/.lager). The first one found is used.
DEVENV
Configures a Docker-based development environment for your project. Managed withlager devenv.
When you run lager devenv terminal, the CLI reads this section to determine which Docker image to launch, where to mount your source code, and how to configure the container. When you run lager exec <name>, it reads the saved commands from this section.
Fields:
| Field | Required | Description |
|---|---|---|
image | Yes | Docker image name (e.g., "lagerdata/devenv-cortexm") |
mount_dir | Yes | Directory inside the container where your source code is mounted (e.g., "/app") |
shell | Yes | Shell executable path inside the container (e.g., "/bin/bash") |
user | No | User to run as inside the container |
group | No | Group to run as inside the container |
macaddr | No | MAC address to assign to the container |
hostname | No | Hostname to assign to the container |
repo_root_relative_path | No | Relative path from the .lager file to the repo root. Used when the .lager file is in a subdirectory — the CLI mounts the repo root and sets the working directory to the correct subdirectory. |
cmd.<name> | No | Custom named commands that can be executed with lager exec <name> |
DEBUG
Maps debug net names to local J-Link script file paths. Paths can be relative (resolved relative to the.lager file location) or absolute.
This is separate from the jlink_script field on net objects in the NETS section of the global file. The DEBUG section provides project-local script overrides — lager debug commands check this section first before using the script stored on the box. This lets you keep J-Link scripts in your project repo and have them used automatically.
Example:
includes
Maps destination names to source directories that should be uploaded alongside Python scripts run withlager python. This lets your test scripts import from external directories outside the project.
Paths are resolved relative to the .lager file location.
Example:
lager python test_script.py, the CLI checks the local .lager for an includes section and uploads the referenced directories to the box so they are available as imports.
Environment Variables
These environment variables override the default file location and behavior:| Variable | Description |
|---|---|
LAGER_CONFIG_FILE_DIR | Override the directory where the global .lager file is located (default: ~) |
LAGER_CONFIG_FILE_NAME | Override the filename (default: .lager) |
LAGER_BOX | Override the default box for all commands (takes priority over DEFAULTS.gateway_id) |
Legacy Format Migration
Older.lager files may use lowercase section names. The CLI automatically upgrades these when writing:
| Legacy Key | Current Key |
|---|---|
duts | BOXES |
DUTS | BOXES |
LAGER | DEFAULTS |
nets | NETS |
devenv | DEVENV |
debug | DEBUG |

