Skip to main content

Features

  • LAGER_GATEWAY_TOKEN authenticates a CI job against an access-gated box. Set the variable to a token that your auth server minted, and every request carries it. The job needs no lager login step and no password in repository secrets. The token outranks any stored session. Lager never refreshes it, and writes nothing to ~/.lager_gateway_auth, so a self-hosted runner keeps no credential and no stale box-to-server mapping between jobs. If the gateway refuses the token, the command stops at once and names the server that refused it. It does not advise a login that cannot help. The Rust crate reads this variable since 0.2.0, and the Python CLI now matches it.
  • The reference docs cover what shipped from v0.40.0 through v0.47.0. Each claim matches the v0.47.0 source rather than the release notes. New or expanded sections:
    • lager nets state, which shipped in 0.34.0 and appeared on no page. The section covers state strings, the shared 8 s budget, reason codes with their remedy lines, and the --json fields.
    • The LabJack U3 across the adc, dac, gpi, gpo, spi, i2c, nets, instruments and supported-instruments pages. These pages cover the pins and the SPI pin order, the 50-byte transfer limit, approximate clock rates, and the 0.04-4.95 V DAC range. They also cover external I2C pull-ups, the refused chip-select options, and the LJM "ANY" limitation.
    • lager box-config: the apply exit codes, every refusal of the host-network pre-flight, network-mode show output, switching back, pip import-legacy, and LAGER_DISABLE_UART_SERVICE.
    • DA1469x flash and erase on both debug backends, DebugNet.connect() errors and backend-specific parameters, and the erase and flash exit codes.
    • lager uart --sessions and --force, lager usb cycle verdicts per hub, lager webcam snapshot, lager exec inside a CI job with LAGER_CI_OVERRIDE, and robot-arm detection with LAGER_ARM_PROBE.
    • /etc/lager/ref, update --check exit codes, the install deploy timeout, and the pre-built image rules. The host CLI, how a command recognizes its own lock, setup_battery(), and where the box services write their logs.

Bug Fixes

  • lager install no longer hangs for two minutes at the end, and no longer garbles the terminal. The step that records the deployed version and ref forced an SSH pseudo-terminal. When its sudo was not passwordless, that step waited on a password that no one can type, until a 120-second timeout. The killed pseudo-terminal then left the local shell in raw mode, and every line after it staircased. The writes now run under BatchMode with a short timeout, so an ungranted sudo fails at once and cleanly. The box’s sudoers grant now also covers /etc/lager/ref, which it never covered before, so on a properly provisioned box the write simply succeeds.
  • lager install and lager update no longer take ownership of the SSH key directory (/etc/lager/authorized_keys.d). The permission repair that makes /etc/lager writable for the box-config renderers used to chown -R the whole tree. That swept the key directory into the container’s ownership. On a box that runs untrusted code, that code can then authorize its own SSH key. The repair now skips that one directory, and leaves its ownership as it found it.
  • lager install and lager update no longer abort on a box whose clone holds a divergent tag. A box cloned before a tag was re-created upstream keeps that tag at the old object. An unforced git fetch then refuses the tag with a non-zero exit, and reports that the fetch clobbers an existing tag. The install’s fetch sits in an && chain under set -e, so the deploy died at [5/8] Deploying Box Code. It stayed dead, because every later attempt fetched the same way. The only way out was a force-fetch on the box by hand. Both fetches now force. Origin is authoritative for a checkout that the very next commands git reset --hard and git clean -fd.
  • lager arm set-acceleration set travel acceleration to the retract value. It sent M204 P T T, and the arm firmware reads retract acceleration from R. The command and Dexarm.set_acceleration() now send M204 P T R.
  • lager arm read-and-save-position asks for confirmation. The command sends M889, which replaces the stored calibration of the arm with its current pose. Pass --yes to skip the prompt.
  • An arm net opens the arm that it names. lager nets add-all records the USB serial number of the arm only in the net address. The box ignored that number and opened the first 0483:5740 serial device. Other STM32 boards use that USB ID.
  • lager arm works again after the USB connection to the arm drops. Before, every command failed until the box hardware service restarted. Now the next command opens the port again, and position retries once.
  • An instrument scan no longer breaks a running lager arm command. The scan sent M105 to an arm that a saved arm net uses, and the arm reply can go to the scan instead. The scan now lists that arm from its USB serial number, without a probe.
  • lager arm move and move-by refuse a timeout longer than 25 seconds. A longer move outlived the 30-second limit on a box hardware call, and the box hardware service restarted.
  • Dexarm.move_to() and move_relative() check the workspace bounds. They raise OutOfBoundsError and send nothing, as lager arm does.
  • lager arm --box lists arm nets without locking the box.
  • lager arm go-home and Dexarm.go_home() wait for the arm to reach home. They returned after half a second, before the arm reached home. Now they return when the arm firmware reports that the move is done.
  • lager arm move and move-by refuse an arm on firmware older than V2.1.4. Rotrics swapped the X and Y axes in V2.1.4, so on older firmware a move turned the arm to the side. The error tells you to update the firmware. position and go-home still work.
  • A move before the arm is homed fails at once. After power-on the firmware ignores motion until go-home runs, and the move timed out after 15 seconds with a message about an obstruction. It now raises NotHomedError.
  • A move that times out no longer blames the workspace bounds. The command checks the bounds before it sends a move. The error now says that the arm did not arrive, and that a long move can need a larger timeout.
  • lager arm position shows the arm error when the arm stops answering. It failed with “hardware service did not respond” after 10 seconds. The box now stops a position read after three attempts of 3 seconds each.

Improvements

  • Four pages said that the host firewall limits the Lager ports to the VPN. On the default network, Docker publishes those ports ahead of the host firewall, as SECURITY.md states. The install, update, setup and architecture pages now say so, and link the Security Model. update.mdx also documented a firewall step and a script invocation that do not exist.
  • The Logic Analyzer pages said that the feature was not available. The commands run. Both pages, and the scope page, now carry one callout for the MSO5000 triggers and bus decoders that still fail. The pages also list exit codes and valid ranges, and drop the examples that cannot run.
  • Examples that cannot run are corrected. lager debug flash --bin takes FILE,ADDRESS, not ADDRESS FILE. lager python --kill needs the process ID. lager uart takes a net name, not /dev/ttyUSB0. lager exec needs -- before extra arguments that start with a dash. UARTNet.connect() ignores timeout. lager nets add examples used channel 0 where the box lists I2C0, SPI0 or FIO4-FIO5.
  • Stale claims are corrected.
    • pyOCD appeared as a debug backend. J-Link and OpenOCD are the only two.
    • Webcam ports start at 8086, not 8081.
    • lager usb commands are case-sensitive, and the cycle timing and hub hold apply to Plugable docks only.
    • A LabJack U3 supports SPI and I2C.
    • A second role on a Keithley or EA instrument raises a notice, not a block, and two Acroname hubs of one model both work.
    • The .lager defaults are JSON in ~/.lager, not INI in the project.
    • Sample output for lager hello, lager boxes, lager defaults list, lager instruments, lager logs and lager binaries list matches the CLI.
    • The box runs one lager container, not controller.
    • The MCP server is read-only only while both opt-in gates are off.
    • Top-level lager options are --version, --debug and --colorize. --box belongs to each command.
  • The README describes what the software does. The Python example calls psu.set_voltage(3.3), because voltage() only reads the measured value. The MCP section lists the read-only discovery and planning tools that the server exposes by default, and names the two opt-in gates. The Rust section places the lager-net crate in a firmware project, not on the box. The CI section passes --yes to the commands that ask for confirmation. The Supported Hardware table covers the vendor families that the supported-instruments page lists.

Installation

To install this version:
To upgrade from a previous version:
Then update your boxes:

Resources

View Release on PyPI