The ay-robots CLI
The command line half of the desktop client. It ships the same robot driver, so there is no Python environment to build: install it, pair the machine, and record datasets, move policies around and drive the arm from a terminal or a script.
- 20 commands
- macOS, Windows, Linux
- Robot driver bundled
- Doubles as a local MCP server
Install
One command per platform. It puts the ay-robots binary on your machine with the robot driver already inside, which is the whole reason the CLI exists as a separate thing: a terminal, a USB cable and an arm are enough.
curl -fsSL https://www.ay-robots.com/install.sh | shirm https://www.ay-robots.com/install.ps1 | iexay-robots --version prints the version and exits, which is the quickest confirmation that the install landed. ay-robots commands prints the grouped overview, and so does the bare binary with no arguments.
The installer also puts ayrobots, ay-robot and ayrobot in the same directory, pointing at the one binary rather than copying it. The missing hyphen is the most common typo there is, and it now costs nothing.
The first five minutes
Four commands take you from a fresh install to a recorded episode. Run them in this order, with the arm plugged in and powered.
- 1
Pair this machine with your account
bashay-robots pair <CODE>Exchanges a one-time pairing code from the dashboard for a permanent credential on this machine.
The code comes from the dashboard, on the page where you add a robot. Pairing survives restarts, so this is a step per computer and not something to repeat before every session.
- 2
Check that the driver sees your hardware
bashay-robots devicesLists the arms and cameras the backend can see, with their serial ports.
Nothing below works until the arm shows up here, which makes this the fastest triage step there is: an empty list points at the cable, the port permission or the power supply, not at the software. Note the port it reports, because that is what later log lines refer to.
- 3
Set the zero point
bashay-robots calibrateCaptures the calibration zero point: guide the joints to the neutral pose, press Enter, and it stores the reference.
Once per arm, and again after you re-seat a joint or rebuild the mechanics. A zero that has quietly drifted does not announce itself; it shows up weeks later as a trained policy that reaches consistently beside the object.
- 4
Record your first episodes
bashay-robots record --task "<task>"Records demonstration episodes. It starts and stops the recording; you drive the arm with the desktop client or the web cockpit while it runs.
Write the task as a short instruction in plain language, because the language-conditioned policies are trained on exactly that string and will be given it again at inference time. The episodes land in the LeRobot dataset layout the trainers expect.
SO-100, SO-101 and LeKiwi run Feetech STS3215 servos at 7.4 V. A 12 V supply destroys them in seconds, and no command on this page can warn you before it happens. Koch v1.1 uses Dynamixel servos instead.
What record does and does not do
It does not drive the arm. The command runs the recording, and you teleoperate the arm yourself while it runs, either from the desktop client or from the web cockpit. Press Enter to end an episode. Ctrl-C discards the episode in progress rather than saving a half one. That last part matters more than it sounds: a half episode that ends mid grasp teaches the policy to stop mid grasp, so throwing it away is the correct behavior rather than a lost take.
ay-robots record --task "put the red cube in the bowl" --episodes 20 --cameras wrist,topReset the scene between episodes and vary the object position a little. Twenty demonstrations of the exact same layout teach a policy the layout, not the task.
After the first episodes
Push the dataset to the cloud with ay-robots datasets upload <dataset>, then start training in the dashboard. Training itself has no CLI command, because it runs on a rented GPU rather than on your machine. The training guides walk through the model and arm combination you picked. When a checkpoint exists, bring it back to the hardware with ay-robots run --model <model>.
Every command
All 20 subcommands the parser knows, with the options it really accepts. This list is generated from the same module the rest of the site and the MCP server read, so it cannot quietly drift away from the binary. If a command is not here, it does not exist.
ay-robots serveRuns the robot backend in the foreground, which is what the desktop client starts for you.
- -
--host (default 127.0.0.1) - -
--port (default 8000)
ay-robots startStarts that same backend in the background and returns immediately, which is the form you want on a machine you are also using for something else.
Idempotent: if a backend is already up it says so and starts nothing. The answer names the log file that ay-robots logs reads.
ay-robots restartStops the backend and starts it again. It does not first ask whether the old one still answers, because a backend that has stopped responding is exactly the one you want restarted.
ay-robots stop-backendStops the backend. Named in full rather than stop, because stop has meant "stop the running policy" since the first version and still does.
- -
shutdown (same command under a second name)
It can only stop a backend this CLI started, and says so plainly otherwise. One started by the desktop client belongs to the client: quit that instead.
ay-robots logsPrints what the backend wrote: startup lines, request lines and tracebacks. This is the first place to look when a start times out.
- -
-n, --lines (default 50) - -
-f, --follow (until Ctrl-C)
Only the backend this CLI started writes to this file. One started by the desktop client logs wherever the client sends its output, and the command says that rather than showing an empty file.
ay-robots pair <CODE>Exchanges a one-time pairing code from the dashboard for a permanent credential on this machine.
- -
--base-url
ay-robots unpairRemoves the pairing from this machine.
ay-robots statusShows whether the backend is running and whether this machine is paired.
ay-robots devicesLists the arms and cameras the backend can see, with their serial ports.
ay-robots homeMoves the arm to its home pose.
ay-robots calibrateCaptures the calibration zero point: guide the joints to the neutral pose, press Enter, and it stores the reference.
ay-robots record --task "<task>"Records demonstration episodes. It starts and stops the recording; you drive the arm with the desktop client or the web cockpit while it runs.
- -
--task (required) - -
--dataset (default local) - -
--episodes (default 1) - -
--cameras wrist,top
Press Enter to end an episode. Ctrl-C discards the episode in progress rather than saving a half one.
ay-robots datasets listLists your cloud datasets, or the local ones with --local.
- -
--local
ay-robots datasets upload <dataset>Pushes a local dataset to the cloud.
- -
--name
ay-robots datasets download <dataset>Pulls a cloud dataset to this machine.
ay-robots run --model <model>Runs a policy on the arm. Without a checkpoint it runs the base model, which is a useful smoke test before your own policy exists.
- -
--model (required, for example act or smolvla) - -
--checkpoint (Hugging Face repo id or an s3:// URI) - -
--task (the instruction the policy is given) - -
--mode local or cloud (default local)
ay-robots stopStops a running policy. It leaves the backend running, which is the distinction worth remembering: stop-backend is the one that ends the process.
ay-robots mcpRuns the CLI as an MCP server over stdio, so a local agent can drive the physically connected arm.
This is the local counterpart to the hosted server at /api/mcp, which has no hardware access.
ay-robots commandsPrints the grouped overview of every command. The same overview appears when the binary is run with no arguments at all.
Deliberately not the argparse listing: that is one long unsorted bracket. This one is grouped into backend, setup, arm, datasets and agents.
ay-robots versionPrints the CLI version, the backend it talks to and the platform URL.
ay-robots serve is the one you rarely type by hand: the desktop client starts the same backend on launch, and the other commands talk to it. Run it in the foreground when you want to read the log, or on a machine that has the arm but no desktop session.
Running the backend
Every command above needs the robot backend, and until you say otherwise the CLI starts it for you the first time one of them needs it. These four commands are for when you would rather decide that yourself.
ay-robots startStarts that same backend in the background and returns immediately, which is the form you want on a machine you are also using for something else.
Idempotent: if a backend is already up it says so and starts nothing. The answer names the log file that ay-robots logs reads.
ay-robots restartStops the backend and starts it again. It does not first ask whether the old one still answers, because a backend that has stopped responding is exactly the one you want restarted.
ay-robots stop-backendStops the backend. Named in full rather than stop, because stop has meant "stop the running policy" since the first version and still does.
- -
shutdown (same command under a second name)
It can only stop a backend this CLI started, and says so plainly otherwise. One started by the desktop client belongs to the client: quit that instead.
ay-robots logsPrints what the backend wrote: startup lines, request lines and tracebacks. This is the first place to look when a start times out.
- -
-n, --lines (default 50) - -
-f, --follow (until Ctrl-C)
Only the backend this CLI started writes to this file. One started by the desktop client logs wherever the client sends its output, and the command says that rather than showing an empty file.
ay-robots stop has meant “stop the running policy” since the first version, and it still does: the arm stops, the backend keeps running. ay-robots stop-backend, also spelled shutdown, ends the process itself. Renaming either one would have quietly changed what an existing script does, so both keep their meaning.
Only the backend this CLI started writes to this file. One started by the desktop client logs wherever the client sends its output, and the command says that rather than showing an empty file. So when a start times out, the answer is almost always in ay-robots logs: a port 8000 that is already taken, a camera permission the operating system refused, or a driver that did not come up.
Global flags
2 flags that belong to the binary rather than to a subcommand, so they go directly after the program name.
ay-robots --versionPrints the version and exits.
ay-robots --json <command>Machine-readable output, which is the flag to use from a script.
Use --json in anything automated. The human readable output exists to be read by a person, and its column widths and line breaks are free to change between versions; the JSON form is the one worth parsing in a shell script, a CI job or an agent.
Commands that do not exist
These appear in older write-ups and in answers from models that learned from them. None of them were ever in the binary, so typing one gets you an error and a wasted half hour. Training has no CLI command at all: a run rents a cloud GPU by the hour, and there is nothing on your machine for a local command to start.
ay-robots train startTraining runs on a rented cloud GPU. Start it in the web dashboard under Training, or through the start_training tool on the MCP server.
ay-robots train logsThe run page in the dashboard streams loss, learning rate, gradient norm and GPU telemetry. Agents poll get_training_job. Note that ay-robots logs does exist, but it shows the local backend on this machine, never a cloud training run.
ay-robots train checkpointsCheckpoints are listed on the run page and in the get_training_job response.
The CLI as an MCP server
Runs the CLI as an MCP server over stdio, so a local agent can drive the physically connected arm. That is the part the hosted server cannot do: it lives in a data center and has never seen your USB port. Point a local agent at this one and the arm on your desk becomes something it can actually operate, with the same driver and the same calibration the recording commands use.
ay-robots mcpThe agent runs the command as a child process on the machine that has the hardware. Nothing is exposed to the network, and the reach of the server is exactly the reach of the CLI: the connected arm, the cameras and the local datasets.
The server at /api/mcp is reachable from anywhere and covers documentation, policy facts, your datasets and your training jobs. It has no hardware access, so it can start a cloud run but never a joint movement.
The two are complementary, and an agent can hold both at once: the hosted one to read the guides and launch training, the local one to record and to run the resulting policy. The MCP integration page has the client configuration and the full tool list.
Questions
Is there an ay-robots train command?
No, and there never was. Training runs on a GPU rented by the hour, not on your machine, so there is nothing for a local binary to start. Launch a run in the web dashboard under Training, or let an agent call the start_training tool on the MCP server. The local counterpart is ay-robots run, which takes a finished policy and drives the arm with it.
Does the CLI need Python installed?
No. The robot driver ships inside the binary the install command puts on your machine, the same driver the desktop client bundles. There is no virtualenv to create, no pip install, no ROS and no dependency hunt, and nothing on your system gets a new Python version.
Can I use the CLI without the desktop app?
For everything except driving the arm by hand, yes. ay-robots serve runs the same backend the desktop client would start, and pairing, device discovery, calibration, datasets and policy runs are all terminal commands. Recording is the exception: the CLI starts and stops the recording, but something has to teleoperate the arm while it runs, which is either the desktop client or the web cockpit.
Where does the CLI store the pairing?
On the machine you paired, in the local backend state rather than in a shell variable or a file you pass around. ay-robots status tells you whether this machine is paired, ay-robots unpair removes the credential, and no command prints it back to you. Moving to a new computer means a new pairing code.
What is the difference between ay-robots mcp and the hosted MCP server?
Transport and reach. ay-robots mcp is a local server over stdio that an agent on the same machine talks to, and it can touch the arm that is physically plugged in. The hosted server at /api/mcp is reachable over HTTP from anywhere, serves documentation, policy facts, datasets and training jobs, and has no hardware access at all.
Why does ay-robots stop not stop the backend?
Because it never did. stop ends a running policy and leaves the backend up, which is what you want mid session: the arm stops, and the next run command starts immediately instead of paying the startup cost again. The command that ends the process is stop-backend, also spelled shutdown. Giving stop the other meaning would have silently changed what every existing script does, so both names kept theirs.
Where are the backend logs?
ay-robots logs prints them, with -n for more lines and -f to follow. It reads the log of a backend this CLI started; one started by the desktop client writes wherever the client sends its output, and the command tells you that instead of showing an empty file. This is the first thing to check when a start times out, because the reason is almost always in there.
How do I use the CLI from a script?
Add --json and parse the output instead of scraping the human readable form. It applies to the commands generally, so a script can read the device list, poll the pairing status or list datasets without depending on line breaks and column widths that are free to change.
No arm on the desk yet?
There is a real SO-100 online that anyone can drive from the browser, with no signup and no hardware. It is the same arm the commands on this page were written against.
Command surface verified against the CLI source on 2026-08-29.