Skip to content

armnet CLI

armnet-client installs several CLI entrypoints:

armnet --help                 # identity, secrets, volumes
armnet-policy-eval --help     # evaluate a policy backend on a cell
armnet-lerobot-eval --help    # evaluate a LeRobot policy on a cell
armnet-lerobot-train --help   # train locally with background remote evals
armnet-openpi-eval --help     # evaluate an OpenPI (pi0/pi0.5) policy on a cell
armnet-lerobot-teleop --help  # remote-teleoperate a cell from a leader arm
armnet-lerobot-record --help  # record a dataset via remote teleoperation

The policy and teleoperation commands have dedicated guides: Teleoperate and Record Datasets, Train and Deploy a LeRobot Policy, and Evaluate Policies. The sections below are a quick reference for the most common invocations.

Identity

armnet whoami

Prints the username associated with your API key.

Secrets

armnet secret list
armnet secret create huggingface-token hf_...
armnet secret delete huggingface-token

Secret values are not printed by list.

Volumes

armnet volume upload ./checkpoint openpi/checkpoints/my-checkpoint
armnet volume cp openpi/checkpoints/my-checkpoint ./checkpoint
armnet volume ls                            # list the whole volume as a tree
armnet volume ls openpi/checkpoints         # list a sub-tree
armnet volume delete openpi/checkpoints/my-checkpoint

Uploads skip files that already exist in the cloud volume with the same hash, unless --overwrite is provided, and show a progress bar for large transfers. When a job references a volume:// path, the cell mirrors it down from the cloud (source of truth) before running and mirrors job outputs back up afterwards — see Volumes.

LeRobot Evaluation

armnet-policy-eval \
  --policy.path=volume://policies/my-policy \
  --armnet.embodiment=lerobot/so-101 \
  --armnet.task=assemble_block_tower \
  --eval.n_episodes=10

Each eval episode is recorded as a LeRobot dataset using the same streaming video encoding as data collection (software libsvtav1, which keeps episode saves fast and produces training-friendly video). Override with --armnet.vcodec, --armnet.encoder-threads, or disable streaming with --armnet.streaming-encoding=false. The same options apply to armnet-openpi-eval.

If your checkpoint is local, upload it while launching:

armnet-lerobot-eval \
  --policy.path=./outputs/train/my_policy/checkpoints/005000/pretrained_model \
  --armnet.volume_policy_path=policies/my-policy \
  --armnet.embodiment=lerobot/so-101 \
  --armnet.task=assemble_block_tower

OpenPI Evaluation

Evaluate an OpenPI (pi0 / pi0.5) checkpoint on a CUDA-capable cell. See Evaluate Policies:

armnet-policy-eval \
  --policy.type=openpi \
  --policy.path=volume://openpi/checkpoints/5000 \
  --policy.config_name=pi05_so101_stacking_rings \
  --armnet.n_episodes=3 \
  --armnet.task="stack the rings" \
  --armnet.secrets="{HF_TOKEN: huggingface-token}"

GR00T Evaluation

Evaluate a NVIDIA GR00T N1.7 checkpoint by selecting the GR00T backend:

armnet-policy-eval \
  --policy.type=groot \
  --policy.path=https://huggingface.co/pravsels/groot1.7_insert_candle \
  --armnet.embodiment=lerobot/so-101 \
  --armnet.task=insert_candle \
  --armnet.n_episodes=1

LeRobot Training with Remote Evals

armnet-lerobot-train \
  --output_dir=outputs/train/my_policy \
  --save_freq=2000 \
  --armnet.eval.n_episodes=10 \
  --armnet.eval.embodiment=lerobot/so-101 \
  --armnet.eval.task=assemble_block_tower

Remote Teleoperation

Drive a remote cell's follower from locally-attached leader arm(s), streaming the follower back into Rerun — no data recorded (requires pip install 'armnet-client[teleop]'). See Teleoperate and Record Datasets:

armnet-lerobot-teleop \
  --teleop.port=/dev/ttyACM0 \
  --teleop.id=my_leader \
  --armnet.duration_s=300

For a bimanual SO-101 cell, pass both local leader ports instead of --teleop.port:

armnet-lerobot-teleop \
  --teleop.left-port=/dev/ttyACM0 \
  --teleop.right-port=/dev/ttyACM1 \
  --teleop.id=my_bimanual_leader \
  --armnet.task=<bimanual-task-slug> \
  --armnet.duration_s=300

For bimanual jobs, set --armnet.task to the task served by the bimanual cell so the job does not route to a single-arm SO-101 cell.

LeRobot Dataset Recording (Remote Teleop)

Record a LeRobot dataset on a remote cell by driving its follower from a locally-attached leader arm, or a left/right leader pair for bimanual cells (requires pip install 'armnet-client[teleop]'):

armnet-lerobot-record \
  --teleop.port=/dev/ttyACM0 \
  --teleop.id=my_leader \
  --dataset.repo_id=my_user/so101_pick_place \
  --dataset.single_task="Grab the black cube" \
  --dataset.num_episodes=10 \
  --secret HF_TOKEN=huggingface-token

For bimanual recording, use --teleop.left-port and --teleop.right-port, and name the task with --armnet.task; the orchestrator routes it to a cell set up for that task's environment.

--robot-telemetry defaults to full for armnet-lerobot-record and armnet-lerobot-eval (override with off / context / safety).

The bimanual current gate defaults to p99 + 100% for 200 ms on armnet-lerobot-teleop, armnet-lerobot-record, armnet-lerobot-eval, armnet-openpi-eval, and armnet-policy-eval (including GR00T). Joints whose baseline max is ≤15 counts (e.g. wrist_roll) use that max as the trip limit instead of the percentile rule. Override with --current-gate-percentile=95|99, --current-gate-percent-above=<percent> (0 disables), and --current-gate-duration-ms. A trip reports the joint and threshold, returns both arms to rest, and blocks further commands until the next job reset.

Reference wire counts come from armnet_client/current_gate_profile.json. Regenerate that profile offline from Hugging Face dataset repo ids listed in armnet_client/current_gate_datasets.json (default: pravsels/so101_bimanual_telemetry_smoke_long):

uv run armnet-current-gate-derive

Derivation reads each dataset's robot-telemetry sidecar, keeps only valid/fresh current samples, and writes per-arm/joint p95 and p99 wire counts.

The dataset is recorded inside the cell (your machine only streams leader joint positions) and pushed to the HuggingFace Hub when the session ends (--no-push-to-hub to skip). Camera frames are encoded to video in real time on the cell (LeRobot streaming encoding) so saving an episode is near-instant; tune or disable it with --dataset.vcodec (default libsvtav1), --dataset.encoder-threads (default 2), or --dataset.no-streaming-encoding. The default libsvtav1 (software) is used instead of auto because hardware encoders ignore LeRobot's g=2 keyframe interval and emit a large GOP that makes random-access training reads very slow; pass --dataset.vcodec=auto only when training-read speed does not matter. LeRobot's standard recording shortcuts work during the session:

  • Right Arrow: save the episode; the remote arm returns to rest and the next episode starts once a cell operator confirms the workspace reset.
  • Left Arrow: discard the episode and re-record it (same reset flow).
  • Esc: stop the session, finalize and upload the dataset.