Set up a robot
CLI reference
Every arc command with its options, the files the command uses, and its environment variables.
arc is the one command on the robot computer. Activate the Python environment first, in every new shell:
source ~/arc_env/bin/activatearc --help starts with the list of commands:
usage: arc run [CONFIG] [--log-dir DIR | --no-log] [relay flags...]
arc doctor [CONFIG] [--identify] [relay flags...]
arc setup [--output PATH] [--force] [--template PATH]
[--answers FILE] [--non-interactive]
arc lagdiag LOG|LOG_DIR
arc enroll [KEY] [--name NAME] [--backend BACKEND] [--yes]
arc config status|sync|pull [CONFIG] [relay flags...]
arc --versionCONFIG is the path of a robot.toml. When it is left out, ./robot.toml is used, so run the commands from the directory that holds the file. A message from a command starts with [arc]. A message from the running client starts with [yam-relay], whatever the arm type.
arc enroll
Registers this robot in your account and stores its identity in ~/.config/arc/identity/. See Enroll.
usage: arc enroll
arc enroll KEY [--name NAME] [--backend BACKEND] [--yes]arc enroll with nothing after it is the usual way: it asks for the key, the robot's name and the arm type, shows a summary and asks before it enrolls. arc enroll KEY is the form for a script.
| Argument | Meaning |
|---|---|
KEY | The account's enrollment key. Asked for when left out. |
--name NAME | The robot's name in the account. Default: the computer's hostname. |
--backend BACKEND | The arm type: yam, trossen, makermods or feather. Default: the one in ./robot.toml when that file exists, otherwise asked. |
--yes | Replace an existing identity, and enroll, without asking. |
Exit code 0 when the robot is enrolled, 1 otherwise. Nothing is written when enrollment fails.
arc setup
Writes robot.toml for this robot, one step at a time. See Configure your robot.
usage: arc setup [-h] [--output PATH] [--force] [--template PATH]
[--backend {yam,makermods}] [--relay-config FILE]
[--answers FILE] [--non-interactive]| Option | Meaning |
|---|---|
--output PATH | The file to write. Default: ./robot.toml. An existing file is resumed from: its values are kept and only the blanks are asked for. |
--force | Start over from the template. The old file is kept as robot.toml.bak. |
--template PATH | Start from this file. |
--backend {yam,makermods} | The template to start from when there is no file to resume: makermods for MakerMods Metal arms, otherwise YAM. |
--relay-config FILE | For a robot that is not enrolled: a file from Northstar with the relay values. Not needed on an enrolled robot. |
--answers FILE | A TOML or JSON file of answers, with keys such as arms.can_left or cameras.wristL.index. A key that is not in it is asked for. |
--non-interactive | Never ask. A value with no answer stays blank, the file is written anyway, and one WARNING line names every blank. |
-h, --help | Show the options and the steps. |
The steps, as arc setup --help lists them:
steps, in order:
cameras find the cameras, save a snapshot of each, assign roles
arms list the CAN buses that are up, ask which is the left arm
relay nothing to ask on an enrolled robot (arc enroll); otherwise relay host, CA cert path and robot id, and the robot's identity cert
review every value and where it came from, then confirm
write write the file, blanks included and named; an existing file is kept as .bakarc doctor
Checks what arc run with the same arguments would use, and starts nothing. It prints one line per check and a summary, and exits with code 1 if any check failed.
| Argument | Meaning |
|---|---|
CONFIG | The robot.toml to check. Default: ./robot.toml. |
--identify | After the checks, save one frame per camera to doctor-snapshots/ next to CONFIG, and for each YAM arm read its joint positions for two seconds while you move it by hand. Enables no motor and commands no motion. |
| relay flags | Any option of arc run. Doctor then checks the run with that option. |
Each line is PASS, WARN, FAIL or SKIP, the name of the check, and a detail. SKIP means the check does not apply here, for example the arm address check on a robot with CAN arms. A FAIL line says what is missing and, where there is one, the command that fixes it.
| Check | What it looks at |
|---|---|
config | The file exists, loads, and has no blank value. |
identity | The enrollment: robot id, account, certificate, and whether it is in use. SKIP on a robot that is not enrolled. |
relay cert, client cert | The certificates the run would use, and the expiry date. |
relay address, check-in | The relay address resolves. Nothing is contacted. |
config sync | The same state as arc config status. WARN when out of sync. Only on an enrolled robot. |
can <link> | The CAN link of each arm is up. |
can buses | The two arms are not on the same CAN link. |
can adapters | Each CAN link is still on the USB adapter it was on when arc setup wrote the file. |
arm right, arm left | Trossen arms: each arm's address answers a ping. |
camera exo, camera wristL, camera wristR | A USB camera's device exists. A RealSense camera is not checked here. Use --identify. |
camera slots | No two roles name the same camera. |
arm backend | The arm software for your arm type is installed. |
client lock | No other arc run is running. |
wifi bssid, wifi retries, wifi profiles, wifi powersave, net watchdog | Wi-Fi settings that can keep a robot offline after a drop. See Run as a service. |
The config sync line on a robot whose file matches the console's copy:
[arc] PASS config sync: in syncOn an enrolled robot doctor asks Northstar for that one state and changes nothing. It makes no other connection.
Do not run --identify while arc run is running. It refuses when another client holds the lock. See Troubleshooting for what to do about a failed check.
arc run
Checks that the robot can start, then starts the client: it opens the arms and the cameras, connects to the relay and waits for an operator. It runs until it is stopped. Ctrl+C stops it.
Before it starts anything, run stops with a one-line error if the file is missing or has a blank value, if the robot is not enrolled, or if another arc run is already running on this computer. A CAN link that is down is a warning with the command that brings it up. The client then keeps trying that arm until it opens.
On an enrolled robot run syncs robot.toml with the console first. See how settings sync.
| Argument | Meaning |
|---|---|
CONFIG | The robot.toml to run from. Default: ./robot.toml. |
--log-dir DIR | Write the session log to DIR instead of logs/ next to CONFIG. |
--no-log | Do not write a session log. |
--local-config-only | Skip the settings sync for this start: do not upload the file and do not apply a change from the console. |
Every other option overrides one value of robot.toml for this run. The file is not changed. The ones you may need:
| Option | Overrides | Meaning |
|---|---|---|
--can-right NAME, --can-left NAME | [arms] can_right, can_left | The CAN link of each arm. |
--arm-right-address IP, --arm-left-address IP | [arms] right_address, left_address | Trossen arm addresses, or none. |
--gripper NAME | [arms] gripper | The YAM gripper type. |
--gravity-comp | [arms] gravity_comp | Start in gravity compensation: the arms are moved by hand and ignore the operator. |
--startup-fault-reset | [arms] startup_fault_reset | Clear one latched 0xD fault per motor at start. |
--arm-isolation {process,thread} | [arms] isolation | Where the arm drivers run. |
--camera-exo N, --camera-wristl N, --camera-wristr N | [[cameras]] index | A USB camera's device number or path. |
--camera-exo-realsense SERIAL, --camera-wristl-realsense SERIAL, --camera-wristr-realsense SERIAL | [[cameras]] serial | A RealSense camera's serial number. |
--camera-isolation {process,thread} | [[cameras]] isolation | For all cameras at once. |
--camera-color-format {bgr8,yuyv} | [[cameras]] color_format | For all RealSense cameras at once. |
--camera-backend {auto,gst,cv2} | (no key) | How USB camera video is decoded. auto tries hardware decoding and falls back to the CPU. cv2 uses the CPU only. |
--no-hwaccel | (no key) | The same as --camera-backend cv2. |
--sim | (no key) | Mock arms on both sides. Nothing moves. Cameras and the connection run as usual. |
--policy-port PORT | [relay] policy_port | See Configure your robot. |
arc run --help prints every option, including the connection options (--relay-host, --relay-cert and others). An enrolled robot gets those values from its identity, so leave them out.
Every run writes a session log, one file per start, to logs/ next to CONFIG. Its path is the first line printed:
[arc] Session log: ~/robot/logs/arc-20261007-214853-98807.logThe log holds everything the terminal shows and is readable only by your user. Old logs are not deleted.
arc config status
Shows whether robot.toml and the console's copy match, and whether a change from the console is waiting. Changes nothing.
arc config --help describes the three config commands:
usage: arc config status [CONFIG] [relay flags...]
arc config sync [CONFIG] [relay flags...]
arc config pull [CONFIG] [relay flags...]
The console keeps a copy of this robot's robot.toml. Only a robot that
uses its enrolled identity (arc enroll, [relay] cert blank) syncs.
CONFIG is a robot.toml (default: ./robot.toml), as for arc run.
status the local hash, the hash and time of the synced copy, and whether
a change made in the console is waiting. Changes nothing.
sync upload the local file now. It becomes the copy the console shows.
pull what arc run does at each start, without starting: upload
when the file changed, or write a waiting change into robot.toml
(the old file is kept as robot.toml.<date>-<time>.bak).arc config status[arc] config: ~/robot/robot.toml
[arc] local hash: 9c3534ec...
[arc] baseline hash: 9c3534ec..., synced 2026-10-08T02:47:58.254604+00:00
[arc] pending change: none
[arc] state: in syncThe hashes are shortened here. With a change waiting, the fourth line names it:
[arc] pending change: 8e2dc98d-c310-4e0e-9cee-ca1e304f597b, 2 setting(s), made 2026-10-08T02:48:19.754299+00:00
[arc] state: a change is waiting for the next startConfigure your robot lists the four states. Exit code 0, or 1 when the state could not be read.
The three config commands work on a robot that uses its enrolled identity. On a robot that was set up before enrollment they print one line saying that its settings are not synced.
arc config sync
Uploads robot.toml now. It becomes the copy the console shows.
arc config sync[arc] config sync: settings uploaded (9c3534ec...), synced 2026-10-08T02:47:58.254604+00:00If a change from the console was waiting and no longer fits the file, a second line says that it now needs review in the console. Exit code 0 when the file was uploaded, 1 otherwise.
arc config pull
Does what arc run does at each start, without starting: uploads the file if it changed, or writes a waiting change from the console into robot.toml. The old file is kept as robot.toml.<date>-<time>.bak.
arc config pullWith nothing to do:
[arc] config sync: in sync (9c3534ec7970)With a change waiting:
[arc] config sync: applied 2 changes from the console to ~/robot/robot.toml (relay.record_fps = 20, relay.record_stream = true); the old file is kept as ~/robot/robot.toml.20261007-214820.bakExit code 1 when Northstar could not be asked, 0 otherwise. A change that was refused or that no longer fits the file is reported in one line and the exit code is still 0. Use arc config status to read the state in a script.
Run it while arc run is stopped. A running client read the file when it started and does not read it again.
arc lagdiag
Summarizes the timing lines of a session log. While it runs, the client prints one line per second that starts with [diag:loop]. lagdiag reads them and prints one row per measurement.
usage: arc lagdiag RELAY_LOG|LOG_DIR| Argument | Meaning |
|---|---|
RELAY_LOG | A session log file. |
LOG_DIR | A directory of logs, such as logs/. The newest .log file in it is used. |
arc lagdiag logs/The first rows, from a ten second log with nobody driving:
log: logs/arc-20261007-214853-98807.log
10 [diag:loop] lines (one per second). worst is min for ctrl_pps and *_hz; for the rest it is max.
field median min max n worst
lag_p50_ms 0.5 0.4 0.6 10 0.6
lag_p99_ms 3.1 2.6 22.5 10 22.5
lag_max_ms 3.1 2.6 22.5 10 22.5More rows follow, one per field. na means there was no sample, for example no commands while nobody is driving.
| Field | Meaning |
|---|---|
lag_p50_ms, lag_p99_ms, lag_max_ms | How late the client's main loop wakes up. High values mean something is holding it up. |
getpos_<side>_*, faults_<side>_*, cmd_<side>_* | Time spent reading an arm's position, reading its faults, and sending it a command. |
cmd_age_p50_ms, cmd_age_p99_ms | From a command arriving at the robot to the arm command that follows it. |
ctrl_pps | Commands received per second. |
server_hz_<side>, dm_hz_<side>, overruns_<side> | Loop rates of the arm's own process, and how many of its loop turns ran late. |
<side> is right or left. Northstar may ask for this output when a session feels slow.
arc --version
Prints arc and the installed version. -V does the same.
Files
Paths that start with ./ are next to robot.toml.
| Path | Written by | What it is |
|---|---|---|
./robot.toml | setup, config pull, run at start | The robot's settings. See Configure your robot. |
./robot.toml.bak | setup | The file before the last arc setup. |
./robot.toml.<date>-<time>.bak | config pull, run at start | The file before a change from the console was applied. One per applied change. Not deleted for you. |
./robot.toml.sync-applied | config pull, run at start | A short note that exists only while an applied change has not been reported to the console yet. Leave it. |
./logs/ | run | Session logs, arc-<date>-<time>-<pid>.log. |
./setup-snapshots/ | setup | One picture per camera found. |
./doctor-snapshots/ | doctor --identify | One picture per camera role. |
~/.config/arc/identity/ | enroll | The robot's certificate, its private key, the relay's certificate and identity.json. See Enroll. Do not copy it to another robot. |
~/.cache/larp/record-spool/ | run | Recording frames that wait to be sent, with record_stream = true. Emptied at every start. |
~/.cache/larp/depth-spool/ | run | Depth frames that wait to be sent. Kept across restarts. |
/etc/arc/net-watchdog.conf | the installer | Settings of the network watchdog. See Run as a service. |
arc run also holds a lock file, arc-robot.lock, in $XDG_RUNTIME_DIR (or in an arc-<uid> directory under the system's temporary directory) while it runs. The lock is released when the process ends, also after a crash.
Environment variables
| Variable | Used by | Meaning |
|---|---|---|
ARC_ENROLL_URL | enroll | The address of the enrollment server. It is built into the command. Set it only when Northstar gives you another address. |
XDG_CACHE_HOME | run | When set, the two spool directories are under $XDG_CACHE_HOME/larp/ instead of ~/.cache/larp/. |
XDG_RUNTIME_DIR | run, doctor | Where the lock file is kept. |
HOME | all | The identity is read from ~/.config/arc/identity/ of the user that runs the command. Run every command, and the service, as the user that enrolled. |
NORTHSTAR