Skip to main content

Developer Sessions: admrl dev

A developer session lets you iterate on a workload on a real device without publishing a configuration version for every change. admrl dev holds one device on a dev rootfs, keeps a directory on your machine synced into the workload, and runs commands there. When you end the session, the workload returns to its production image.

Use it for the edit, sync, run loop on a robot you cannot reproduce on a laptop: new navigation parameters, a rebuilt binary, a changed launch file. Use a normal configuration and rollout when a change is ready for the fleet.


Before You Start​

RequirementWhere it is set
Developer sessions switched on for the fleet. Off by default.Fleet > Settings > Developer sessions
Permission to start sessions (workload_dev).See Who can start a session
The device is online and running a workload.Device overview
The admrl CLI, signed in.CLI

Fleet Settings with the Developer sessions card: switch on, Maximum session length 8 hours

The Developer sessions card on Fleet > Settings has a switch and a Maximum session length in hours (0 for no limit). Turning the switch off asks for confirmation and ends the sessions that currently hold devices in the fleet.


The Loop​

# 1. Hold the device and start syncing ./out into /opt/nav-stack in the workload
admrl dev start amr-001 ./out:/opt/nav-stack

# 2. Flush pending changes, then run a command in the workload
admrl dev run amr-001 -- ./nav-stack --selftest

# 3. Release the device when you are done
admrl dev end amr-001

admrl dev start runs a background daemon on your machine. It watches each <local> directory and syncs changes to <dest> in the workload as files change, so after the first sync you only edit and rebuild. admrl dev run first flushes any pending changes, then runs your command in the workload; its exit code is passed through. With no command and a terminal, it opens a shell.

admrl dev start --help in a terminal

Commands​

CommandWhat it does
admrl dev start <device> <local>:<dest>...Hold the device on a dev rootfs and keep syncing each local directory.
admrl dev run <device> [flags] [-- command args...]Flush pending changes, then run a command in the workload. -i, -t, --cwd, --env K=V, --no-sync, --restart, --signal HUP are available.
admrl dev sync <device>Sync once, then exit.
admrl dev watch <device>Stream sync events.
admrl dev status [<device>]Show the developer sessions on this machine.
admrl dev end <device>Release the device.

Add --json to any admrl dev command for one JSON event per line on stdout.

What gets synced​

  • Ignore rules are applied in this order: .git/, .gitignore files, then .admrlignore at the root of each mount. --ignore-file names a different extra ignore file.
  • Empty directories are synced.
  • Files larger than --max-file-size (268435456 bytes by default) are refused.
  • File names are normalised to Unicode NFC. A name that cannot be normalised is refused (the CLI help lists the exact cases).

Running your own image or restarting after a sync​

  • --image <ref> runs the workload from that image for the session instead of the configured one.
  • --restart sets what happens after a sync: never, on-change, or signal=HUP. The default is never when you pass --image and on-change otherwise.
  • admrl dev run --restart or --signal HUP restarts or signals the workload after syncing.
admrl dev start amr-001 ./out:/opt/nav-stack --image registry.example.com/nav-stack:dev --restart signal=HUP

What You See in the Dashboard​

While a session holds a device, its header shows a chip with the user and the time left, for example Dev session: demo.user, expires in 3h 37m (or no expiry). Hover it for when the session started, the mounts, and the image if you set one.

Device header with the Dev session chip

A held device is not counted as stuck or failed by a rollout, and a rollout does not count it toward completion.


Ending a Session​

A session ends in any of these ways:

  • You end it: admrl dev end amr-001. The device stops the workload, restores its production image, and starts the configuration it should now run. By default that is the configuration that arrived during the session; --no-apply restores the configuration that was current before the session instead.
  • It goes idle. The daemon ends the session after --ttl (4 hours by default) without a client request, an open run or watch stream, or a synced change. --keep leaves the session held on the device instead; admrl dev start again rejoins it.
  • It reaches its maximum length. --max-life sets a hard limit on your session. The fleet's Maximum session length also applies, and the shorter limit wins.
  • The fleet switch is turned off. Sessions in the fleet are ended.

Exit codes​

CodeMeaning
3Device busy.
4Session expired. The saved session is forgotten.
125Sync or session failure under admrl dev run.

Who Can Start a Session​

  • Starting a session requires the workload_dev permission on the device. Administrators have it, and so do users whose role includes Root shell (SSH) (remote.shell), which implies it. The role editor has no separate developer-session capability.
  • Turning developer sessions on or off for a fleet, and setting the maximum length, requires Manage SSH access (remote.manage) on the fleet. Without it the card's controls are disabled.
  • Developer sessions are separate from admrl exec and admrl shell, which need Open workload terminal (remote.exec). See Permissions for Shell and Exec.

See Roles & Permissions for how to grant these.


Overriding One Device Without a Session​

For a change that should persist for a while without holding the device, set a sparse override on that device, optionally with an expiry. It changes only the fields you give and inherits everything else from the configuration:

# Run a debug image on one device for two hours
admrl override device amr-001 --set image=registry.example.com/nav-stack:debug --expires 2h

# Return one field to its configuration value
admrl override device amr-001 --reset image

# Remove the override and its expiry
admrl override device amr-001 --clear

--set takes key=value pairs such as env.LOG_LEVEL=debug, options.exposeDBus=true or image=.... --reset returns a field to its configuration value rather than emptying it; use --set env.NAME= for a blank value. --expires 2h drops the override after that long. It is the same per-device override as Edit override in Device Documents.

admrl override device --help in a terminal