Skip to content

About

No description, website, or topics provided.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

servo-programmer

Cross-platform replacement for the legacy Axon Robotics Servo Programming Software: a released CLI, a live browser app, and a desktop side experiment built with Electrobun to prove UI/runtime fidelity against the CLI and web app, and to explore a macOS app packaging path, all built from scratch by reverse-engineering a closed HW/SW system with Claude Code, a Saleae Logic 8, and Ghidra.

This started as a research experiment — "how far can a single developer get with a coding agent on a reverse-engineering project against a closed system?" — and ended with a working CLI. The full story is in docs/the-adventure.md.

CI License: MIT

Warning

This is an experimental reverse-engineered project. Use it on your servos at your own risk.

What this is

Axon Robotics sells smart servos (Mini, Max, Micro) used by a lot of FTC robotics teams. The original programmer adapter clips onto the servo's signal wire and exposes the servo's settings through a Windows-only .exe. This repo targets that legacy adapter/servo stack today: bootloader v1.3 hardware and the archived .sfw firmware files published for it.

axon is a cross-platform replacement: a TypeScript CLI on Bun that talks to the same USB HID adapter, reads and writes the same 95-byte config block, and flashes user-supplied vendor .sfw firmware files. Same legacy hardware, no Windows VM.

The current Axon MK2 programmer/servo family uses bootloader v1.4 and is not implemented yet. The HID/protocol layers are intentionally kept separate so this project can be adapted if hardware becomes available.

Use it now

Browser app

Live WebHID app:

Notes:

  • Requires a Chromium-family browser with WebHID support
  • Requires HTTPS or localhost; GitHub Pages satisfies that
  • Best suited to desktops/laptops; this is not intended for phone/tablet use

CLI install

macOS and Linux

Install the latest released CLI with the release-hosted installer:

curl -fsSL https://github.com/caryden/servo-programmer/releases/latest/download/install.sh | bash

For a user-local install without sudo:

curl -fsSL https://github.com/caryden/servo-programmer/releases/latest/download/install.sh | \
  AXON_INSTALL_DIR="$HOME/.local/bin" bash

Windows

Download the latest Windows binary from the latest release:

  • axon-windows-x64.exe

Rename it to axon.exe, put it on %PATH%, then run:

axon --version

Verify the install

On macOS/Linux:

axon --version
axon status

On Windows:

axon --version
axon status

The desktop app was a side experiment with Electrobun. We pushed it far enough to prove fidelity with the CLI/web stack and to explore a macOS packaging path. The CLI remains the primary supported install surface; desktop packaging is still experimental. Tagged releases are intended to publish a macOS DMG alongside the CLI assets.

Experimental desktop app (macOS)

Download the latest experimental desktop app from the latest release:

  • Axon-Servo-Programmer-macos-arm64.dmg

Install path:

  1. download the DMG from the latest release
  2. open it and drag Axon Servo Programmer.app into Applications
  3. launch it from Applications

Notes:

  • this app is still experimental
  • current packaged desktop release is macOS Apple Silicon only
  • because the app is not yet signed/notarized, macOS may require right-click -> Open the first time
  • desktop assets are published by the tagged release workflow; merging to main alone does not create a downloadable DMG

Features

Current source supports:

  • Presence and diagnostics — axon status (one-shot), axon monitor (live 300 ms polling), and axon doctor for a non-destructive runtime/catalog/USB/HID/servo diagnostic report.
  • Config round-trip — axon read (human / --json / --svo / --hex) and axon write --from cfg.svo with diff, confirm, model-id checks, and read-back verify. Vendor .svo files work unmodified.
  • Named parameters with unit conversion — axon get <param> and axon set <param> <value> accept user-facing values such as microseconds, percentages, enum names, steps, and raw bytes, then validate against per-model limits. axon set default resets to catalog defaults.
  • Firmware mode flashing — axon mode set servo, axon mode set cr, or axon mode set --file custom.sfw. Recovery flashing is available with --recover when a servo is stuck in the bootloader and cannot be identified normally.
  • External firmware files — vendor .sfw files are not embedded or redistributed. axon finds user-supplied files in configured search paths, verifies their SHA-256 when known, and decrypts them internally.
  • --json support — command output and top-level errors expose machine-readable fields, including stable error category values for scripting and coding-agent use.
  • Cross-platform, no sudo — Mac (Intel + Apple Silicon), Linux (x64 + ARM64), Windows, via node-hid on top of the OS HID framework.
  • Embedded servo catalog — per-model metadata, known defaults, parameter metadata, firmware filenames, and SHA-256s live in data/servo_catalog.json and ship inside the binary.

Full command surface: docs/CLI_DESIGN.md.

Build from source

# 1. Install Bun if you don't have it
curl -fsSL https://bun.sh/install | bash

# 2. Clone, install dependencies, run from source
git clone https://github.com/caryden/servo-programmer.git
cd servo-programmer
bun install
cd apps/cli
bun run src/cli.ts status

With the dongle plugged in and an Axon Mini connected, axon status prints a compact status bar plus the model docs link. For scripts and agents, use JSON:

cd apps/cli
bun run src/cli.ts --json status
{"adapter":"connected","servo":"present","category":"servo_present","mode_byte":"0x03","mode_label":"Servo Mode","model":{"id":"SA33****","name":"Axon Mini","known":true,"docs_url":"https://docs.axon-robotics.com/servos/mini"}}

No sudo required on any platform.

Full end-user CLI install notes are in docs/INSTALL.md.

Supported servos

Model ID Name Catalog status
SA33**** Axon Mini Baseline supported model; defaults and firmware hashes are cataloged, fresh GUI/runtime validation is still tracked separately
SA20BHS* Axon Micro Primary development hardware; same-mode apply, mode switching, discard, and recovery are confirmed in CLI/web/desktop, with servo-mode catalog completion still pending
SA81BHMW Axon Max Model ID and firmware hashes are known from .sfw headers; physical config/default capture still needed

Got an Axon Max, another Micro capture, or an unknown model? Please help fill out the catalog. Plug it in, run cd apps/cli && bun run src/cli.ts read --svo > my-model.svo, and open an issue with the file attached and the model ID string from axon status. I'll add the model/defaults to data/servo_catalog.json.

Repo layout

The repo is now organized as a Bun workspace:

Firmware files

This repo does not redistribute Axon .sfw firmware files. Download the legacy programmer files from Axon's archive page and either pass them explicitly:

axon mode set --file ~/Downloads/Axon_Mini_Servo_Mode.sfw

or place them in a firmware search directory:

  1. $AXON_FIRMWARE_PATH
  2. User firmware cache:
    • macOS: ~/Library/Application Support/axon/firmware
    • Linux: $XDG_DATA_HOME/axon/firmware or ~/.local/share/axon/firmware
    • Windows: %LOCALAPPDATA%\Axon\firmware
  3. Repo-root downloads/ when running from source

Then catalog mode changes can find and hash-check the files:

axon mode set servo
axon mode set cr

If a failed flash leaves a servo in bootloader mode, recovery flashing skips normal identity/config reads and uses either the .sfw header or an explicit catalog target:

axon mode set --file "$HOME/Downloads/Axon Micro Servo Mode.sfw" --recover
axon mode set servo --recover micro

How it was built

The whole thing is a research experiment: a single developer plus coding agents, pointed at a closed vendor stack, to see how far that pairing could get. The tools that actually mattered were Ghidra, Saleae wire capture, hidapi/node-hid, WebHID, and some ETW captures in a Parallels Windows VM. libusb was part of the investigation, but it turned out to be a dead end rather than part of the final system.

The path:

  1. Static analysis in Ghidra recovered the .sfw firmware format: a Brian Gladman AES-128 reference implementation with a hardcoded 16-byte key of "TTTTTTTTTTTTTTTT", found by walking backwards from the Error 1030: Firmware is incorrect. string.
  2. A Saleae Logic 8 on the servo signal wire recovered the on-wire framing: 9600-baud 8N1 Dynamixel v1, with the standard FF FF <id> <len> ... header and a one-byte checksum.
  3. Dual capture (libusb and the Saleae sampling simultaneously) proved the dongle is a transparent HID-to-wire proxy — every byte written to HID interface 1 shows up unchanged on the serial line.
  4. A libusb detour chasing what looked like a transport bug turned out to be a misdiagnosed protocol bug. The final shipping clients use hidapi/node-hid and WebHID instead.
  5. A clean CLI on Bun + node-hid, with the catalog embedded at build time and externally supplied .sfw files decrypted internally.

Most of the hands-on work — Ghidra scripting, protocol decoding, TypeScript scaffolding, tests — was driven by the agent. The full first-person write-up, including every dead end, is in docs/the-adventure.md.

Documentation

Using this with a coding agent

axon commands expose JSON output where useful, and top-level AxonError failures include a stable category field in --json mode. Agents and scripts should branch on that category rather than screen-scraping human text. Start with docs/CLI_DESIGN.md for the command surface and exit codes, and docs/wire-protocol.md if you need transport details. When setup or USB ownership is unclear, start with axon --json doctor; it reports stable per-check IDs and categories. The current direction is to keep the CLI self-explanatory enough for both humans and agents: good --help, stable JSON, and direct error messages with concrete suggestions rather than a repo-specific skill.

Contributing

See CONTRIBUTING.md. The most useful contribution right now is physical hardware testing on Axon Max and additional Micro/unknown servos to fill in catalog gaps (see above). Bug reports and protocol-edge-case .sal captures are also welcome.

Acknowledgments

  • Axon Robotics for making genuinely cool hardware. This project is a workaround for a Windows-only exe, not a complaint about the servos.
  • The FTC robotics community for the use case.
  • Saleae for a logic analyzer with an automation API that made the dual-capture experiment cheap enough to try.
  • Ghidra for making the static-analysis phase possible at all.
  • The libusb, hidapi, node-hid, and Bun maintainers for the open infrastructure this sits on top of.
  • Anthropic and Claude Code for the early reverse-engineering push that got the project off the ground.
  • OpenAI and Codex for the later hardening, shared UI, browser/desktop integration, recovery flows, releases, and overall productization push that turned the research repo into a usable tool.

License

MIT.

The Axon Robotics vendor binaries (.sfw firmware files, the Windows .exe) are not redistributed with this project. They're downloadable from docs.axon-robotics.com — you obtain them yourself and place them where the CLI searches, or pass them with --file. See vendor/README.md for licensing notes.

About

No description, website, or topics provided.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages