Skip to content

metal-arm-harness — Arm-agnostic coding-agent harness for MakerMods Metal (Isaac Sin)

Small, auditable Python harness that lets any shell-driving agent — a person, Claude Code, Codex, anything that can exec a command and read a JPEG — drive a real 6/7-axis arm safely. Shipped alongside the MakerMods Metal arm (Maker Arm — 6-axis 3D-printed robot arm under $1000 with QDD actuators (MakerMods)) but arm-agnostic above the driver layer: the eval loop is a Unix-socket server (serve) plus one-shot op/ops clients that return joint angles, table-clearance, tool-tip pose, and one fresh JPEG per configured camera on every step. The load-bearing design decision is a pre-actuation safety envelope derived from a physical calibration ritual (operator rests the gripper on the table, forward-kinematics records that height as the floor) — every waypoint is envelope-checked before a single CAN frame goes out. Ships a sim backend (--backend sim) so the whole stack, including agent-driven ops, runs in CI without hardware.

  • Session start requires a table-touch ritual: operator physically rests the gripper tip on the table, FK-height at that pose is registered as the floor, two samples must agree within 3 mm or the harness refuses to run [README §The safety model].
  • Hard floor: any waypoint whose lowest monitored point would come within 10 mm of the measured table height rejects the whole move; the arm cannot be commanded to press down [README §The safety model].
  • Recovery-only when inside the margin: if the arm already sits inside 10 mm (gravity sag / ritual pose), only moves that keep or raise the height are allowed — added because a naive floor guard deadlocked on the bench [README §The safety model].
  • Slow zone: within 3 inches (0.0762 m) of the table, speed caps at 5 deg/s; free space runs at the full 20 deg/s; both ends of every step are zone-tested so no fast pose can dive at the table [README §The safety model].
  • Torque is opt-in (--armed), gated by an operator confirmation (--confirm-armed records “operator said go” out of band); unarmed sessions run the full stack with motor writes removed [README §The safety model].
  • Every op call returns a fixed reply schema — joint angles, table clearance, tool-tip pose, one fresh JPEG per camera — so the agent’s next command is grounded in the state after the previous one landed [README top block, §Motion control].
  • Controller.goto (the sole motion primitive) tracks unmentioned joints from their last commanded value (not sagged measured), and settles the final waypoint with integral action (goal + lead) re-planned through the envelope every tick, so a sagging joint lands ~0.2° off target instead of ~1.3° [README §Motion control, learned on the bench].
  • Gripper motion is instrumented: a jaw that stops short while closing is reported as holding something (with the closed goal riding along as a squeeze), while stopping short while opening is reported as blocked [README §Motion control].
  • Latched driver faults (Damiao status nibble, e.g. rotor over-temperature after a gripper stall) are surfaced as vetos with the fix printed; op clear-faults clears them; over-temp vetos also relieve the hot motor [README §Motion control].
  • IK is a damped-least-squares solver over the vendored Pinocchio URDF that runs in under a millisecond and stays in the current configuration family, driving the tip and nudge commands [README §Motion control].
  • The harness core never imports a concrete arm — a new arm is an Arm + Kinematics implementation plus a build_arm(name, ...) factory registration; the envelope, controller, operator session, and CLI are unchanged [README §Architecture].
  • Defense in depth: LeRobot driver layer keeps its own soft-limit clamp and a per-command lead cap over measured position (bench-tuned per joint: shoulder 5°, elbow 3°, gripper 8°, others 2°), enforced independently of the envelope; the lead cap also bounds torque and keeps the gripper motor from stalling itself into a fault [README §The safety model].
  • Ships a --backend sim bench simulator so the entire operator session, IK, controller, and envelope run under CI conditions with no hardware; the operator session is exercised over a real Unix socket in tests [README §Development].

The harness composes four concerns behind a Unix-socket + JPEG-file interface: (a) an Arm abstraction over LeRobot’s DamiaoMotorsBus / MetalFollower (with a sim peer that tracks commands perfectly); (b) Pinocchio-based Kinematics on a vendored + checksummed URDF that exposes FK for the table guard and DLS IK for tip/nudge; (c) a pure-logic safety.py envelope (fully unit-tested off-hardware) that classifies each waypoint against the measured floor, slow zone, joint soft limits, and a 35°-per-move excursion cap; (d) a Controller with a single goto primitive that plans legs, settles with integral action, and inherits lag from the last commanded pose to keep torque continuous across the calls. On top of that sits the operator session — serve opens a socket bound to a robot ID; op/ops clients hit that socket and return a fixed reply schema (joint angles, clearance, tool-tip pose, one fresh JPEG per configured camera). The agent’s control loop is literally a shell loop: op observe → look at the returned JPEGs → decide → op tip 0.34 -0.10 0.10 -80 → repeat, with each command atomic and each rejection returning a readable error rather than tearing the session down.

The serve command reuses the calibration file at ~/.cache/huggingface/lerobot/calibration/robots/metal_follower/<id>.json when --armed is set (--armed requires the confirm gate; unarmed sessions omit the motor writes but keep everything else). Camera configuration is a comma-separated name=index list. The --backend sim switch replaces the LeRobot driver with a perfect tracker so the same operator loop, controller, IK, and envelope run in CI (and, per the README, the operator session is exercised over a real Unix socket in the test suite).

Not a paper. The Isaac Sin tweet accompanying the release reports Fable 5.1 zero-shotting a pick-and-place task on the MakerMods Metal arm through this harness in ~15 minutes; the run missed the grip on a plug a few times and self-corrected. The tweet also mentions the author is working on a robotic-task benchmark on top of the harness, with attribution to @benchflow_ai / @xdotli / @bingran_bry.

This is the second filed “coding-agent-drives-real-arm” harness on the wiki, next to Inspect Robots — An Open-Source Evaluation Framework for Physical AI (Robocurve), and Ben’s Slack note lays out the precise contrast: metal-arm-harness is deliberately narrow (one arm family via the LeRobot Damiao bus, one bench-tuned safety envelope, one motion primitive, one reply schema — save an image, agent looks, agent outputs joint angles), while Inspect Robots is deliberately broad (Policy × Embodiment two-slot decomposition, six real-robot plugins, XPolicyLab / CaP-X / frontier-LLM policy adapters, immutable EvalLog per run). “More opinionated, more info per step” vs “easier to run” is not just a taste split — it is the same split that repeatedly shows up under RL Environment Platforms between hand-tuned single-vendor stacks (e.g. Cyclo — ROBOTIS Open-Source Modular Physical AI Framework for ROBOTIS, Microduck RL — RL training environments for a ~800 g open-source bipedal robot for the microduck) and platform-level frameworks that abstract over embodiments (Inspect Robots, RoboLab — Task-Based Evaluation Benchmark for Robot Manipulation Policies on Isaac Lab (NVLabs) RoboLab).

Two things stand out. First, the pre-actuation envelope earns its complexity: a hard floor derived from a real measurement, a recovery-only rule for the case where the arm starts inside the margin (added because the naive rule deadlocked), and a slow zone that is checked at both ends of every step so no fast pose can dive at the table. This is the same pattern Inspect Robots — An Open-Source Evaluation Framework for Physical AI (Robocurve) ships as a global bounds-clamp + per-step delta limit, but here it is tuned specifically to the class of failure Claude/Codex-style agents actually produce (issue a big tip step, then discover the previous step didn’t land where they expected). Second, the reply schema — joint angles, clearance, tool-tip pose, one fresh JPEG per camera per step — is the tool-use interface: it turns “drive a robot arm” into “shell tool with a well-typed return”, which is exactly the Tool-Use Agents recipe that made SO-ARM101 via MHS (LeRobot demos Claude Code operating SO-ARM101 zero-shot via Anthropic MHS — self-calibration to 4.1mm accuracy) work zero-shot for Claude Code. The metal-arm-harness is the substrate that lets that recipe run against a 999/999 / 1199 tabletop arm (Maker Arm — 6-axis 3D-printed robot arm under $1000 with QDD actuators (MakerMods)) rather than a specialty rig.

Third, this filing sharpens the “what changes when the arm gets cheap” story on the wiki. The VLA Models evaluation literature has been converging on SO-100/SO-101-tier hardware at the ~3kpoint;MakerModsMetalat3k point; MakerMods Metal at 999 DIY / $1199 assembled with QDD actuators (per Maker Arm — 6-axis 3D-printed robot arm under $1000 with QDD actuators (MakerMods)) plus this harness pushes the LLM-as-controller loop below the price of most researcher laptops, and does it with an envelope explicit enough that a first-year lab intern (or the coding agent itself) can run the calibration ritual and hit serve --armed --confirm-armed without a supervisor next to the arm.