# LeRobot Quickstart: Record a Dataset, Train an ACT Policy and Run It on an SO-101 Arm

> Source: <https://explainx.ai/blog/lerobot-quickstart-so-101-record-dataset-train-act-policy-rollout-v0-7-0-guide-2026?utm_source=rss&utm_medium=feed&utm_campaign=blog>
> Published: 2026-11-06 00:00:00+00:00

This guide takes you from a fresh machine to a trained policy running on a real robot arm, using the official LeRobot v0.7.0 documentation. LeRobot is the open robotics library from Hugging Face. Version 0.7.0 shipped on November 5, 2026, and our [release breakdown](https://explainx.ai/blog/lerobot-v0-7-0-interactive-rollouts-disk-less-streaming-remote-policy-server-cosmos-3-yam-unitree-g1-2026) covers what is new. This post covers how to use it.

The commands below follow the [LeRobot installation guide](https://huggingface.co/docs/lerobot/v0.7.0/en/installation?ref=explainx) and the [imitation learning tutorial](https://huggingface.co/docs/lerobot/v0.7.0/en/il_robots?ref=explainx). We read both pages while writing. We did not run them on a robot, so treat port names and camera indexes as placeholders to replace.

## TL;DR: the workflow in one table

| Step | Command | What it does | 
|---|---|---|
| 1. Install | `pip install 'lerobot[core_scripts,training]'` | Recording, replay, calibration and training | 
| 2. Teleoperate | `lerobot-teleoperate` | Drive the follower arm with a leader arm | 
| 3. Record | `lerobot-record` | Save episodes in the LeRobotDataset format and upload to the Hub | 
| 4. Check | `lerobot-replay` and the dataset visualizer | Confirm the data is usable | 
| 5. Train | `lerobot-train --policy.type=act` | Train an ACT policy | 
| 6. Deploy | `lerobot-rollout` | Run the policy on the robot | 

## What do you need before you start?

The installation page lists these requirements:

- **Python 3.12 or newer.** The docs recommend conda through miniforge, and say`uv` or`venv` also work.
- **A supported platform.** On Linux, default PyTorch wheels are CUDA 13 builds that need an NVIDIA driver of 580.65 or newer. On Apple Silicon, PyTorch needs macOS 14 or newer, and MPS needs macOS 15 or newer. On macOS 14, LeRobot falls back to CPU.
- **ffmpeg.** LeRobot uses TorchCodec for video decoding, which needs ffmpeg. With conda:`conda install ffmpeg -c conda-forge` . With PyTorch 2.10 or newer you can use a system install such as`sudo apt install ffmpeg` .
- **A robot, or a simulator.** The docs point to SO-101, OpenArm, Koch and LeKiwi pages for hardware, and to LIBERO for simulation.

If your Linux driver is older than 580.65, the docs describe installing PyTorch from a CUDA 12 index first, then LeRobot. That path keeps you on torch 2.14 or older.

## How do you install LeRobot v0.7.0?

Create an environment and install with the extras you need:

```
conda create -y -n lerobot python=3.12
conda activate lerobot
conda install ffmpeg -c conda-forge
pip install 'lerobot[core_scripts,training]'
pip install 'lerobot[feetech]'
```

The base install is deliberately light. Extras add what you use. `core_scripts` covers recording, replay and calibration. `training` adds accelerate and Trackio. `feetech` adds motor support for SO-100, SO-101 and Moss arms, and `dynamixel` is for Koch v1.1. The docs say both talk to the motors through rustypot, which matches the hardware-layer change we described in the release post.

If you hit build errors, the docs suggest installing `cmake`, `build-essential` and the ffmpeg development libraries.

## How do you teleoperate the arm?

Assemble and calibrate your robot first, following its page in the docs. Then run the teleoperate command with your own ports:

```
lerobot-teleoperate \
    --robot.type=so101_follower \
    --robot.port=/dev/tty.usbmodem58760431541 \
    --robot.id=my_awesome_follower_arm \
    --teleop.type=so101_leader \
    --teleop.port=/dev/tty.usbmodem58760431551 \
    --teleop.id=my_awesome_leader_arm
```

Two details matter. First, the `id` is used to store the calibration file, so use the same id in teleoperation, recording and deployment. Second, the command starts calibration automatically if it finds none.

Add cameras with a `--robot.cameras` argument and `--display_data=true` to see feeds and joint positions in rerun. Pick camera names now and keep them. The tutorial says the names become dataset keys such as `observation.images.wrist`, and a policy trained on the data expects the same names and resolution when deployed.

## How do you record a dataset?

Log in to the Hugging Face Hub with a write token, then record. The tutorial's example records five episodes:

```
lerobot-record \
    --robot.type=so101_follower \
    --robot.port=/dev/tty.usbmodem585A0076841 \
    --robot.id=my_awesome_follower_arm \
    --robot.cameras="{ wrist: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}, top: {type: opencv, index_or_path: 1, width: 640, height: 480, fps: 30}}" \
    --teleop.type=so101_leader \
    --teleop.port=/dev/tty.usbmodem58760431551 \
    --teleop.id=my_awesome_leader_arm \
    --display_data=true \
    --dataset.repo_id=${HF_USER}/record-test \
    --dataset.num_episodes=5 \
    --dataset.single_task="Grab the black cube"
```

Facts worth knowing from the docs:

- The command adds a date and time stamp to the end of the repo id, so `record-test` becomes something like`record-test_20260929_143012` . Use the full name later. Add`--dataset.no_stamp=true` to keep your exact name.
- Defaults are 60 seconds per episode, 60 seconds of reset and 50 episodes.
- Keys during recording: right arrow or `n` ends the episode early, left arrow or`r` re-records it, Escape or`q` stops and uploads.
- To resume, re-run with `--resume=true` , pass the full dataset name and set`--dataset.num_episodes` to the number of additional episodes, not the target total.
- To skip the upload, use `--dataset.push_to_hub=False` .

### What makes a good first dataset?

The tutorial gives concrete advice. Record at least 50 episodes for a simple pick-and-place task, with 10 episodes per location. Keep the cameras fixed. Keep the object visible. The rule of thumb is that you should be able to do the task yourself by looking only at the camera images.

Avoid adding too much variation too quickly. Get reliable grasping first, then add new locations, grasp styles or camera positions.

## Why should you read the cadence report?

This is the part many tutorials skip. At the end of each episode, `lerobot-record` prints the frame rate it actually achieved against your target, for example 29.88 Hz against 30 Hz. The docs explain why it matters: a frame's timestamp comes from its index, so a session that ran at 25 Hz still produces a dataset that claims 30 Hz. The recorded motion is then faster than reality.

In the docs' example, the camera `observe` step is 74 percent of the loop's work, and a 40 ms worst case against a 33.3 ms budget pushed some ticks over. Pacing headroom near zero means the loop is saturated. If you see that, lower the resolution or the frame rate before you train.

## How do you check the data before training?

Do both checks. They take minutes and save hours.

1. **Replay an episode** on the robot with`lerobot-replay` , passing the same robot id and`--dataset.episode=0` . The robot should repeat the recorded motion.
2. **Open the dataset in the browser** with the LeRobot dataset visualizer Space. If you pushed to the Hub, open your repo there and step through episode 0.

If replay looks wrong, fix recording before you spend GPU time.

Neural network layers and nodes representing the policy being trained in the LeRobot workflow

## How do you train an ACT policy?

Use `lerobot-train`. The tutorial's example:

```
lerobot-train \
  --dataset.repo_id=${HF_USER}/record-test_YYYYMMDD_HHMMSS \
  --policy.type=act \
  --output_dir=outputs/train/act_so101_test \
  --job_name=act_so101_test \
  --policy.device=cuda \
  --trackio.enable=true \
  --policy.repo_id=${HF_USER}/my_policy
```

What each part does, per the docs:

- `--policy.type=act` loads the ACT configuration and adapts automatically to the number of motor states, actions and cameras saved in your dataset.
- `--policy.device` is`cuda` on an NVIDIA GPU or`mps` on Apple silicon.
- `--trackio.enable=true` logs training curves. Open the dashboard with`trackio show --project lerobot` . In v0.7.0, Trackio replaces Weights and Biases, so old`--wandb.*` flags need translating.
- If you do not set `--steps` , training runs 100,000 steps. The docs say that is usually more than a small dataset needs and that imitation learning typically converges within 5 to 10 epochs.

Training should take several hours, and checkpoints land in `outputs/train/act_so101_test/checkpoints`. Resume with `--config_path=.../train_config.json --resume=true`.

### What if you have no GPU?

Two official options. A Google Colab ACT training notebook is linked from the docs. Or use Hugging Face Jobs by adding `--job.target=a10g-small`. List flavors and prices with `hf jobs hardware`. Jobs are billed per second, the default cap is 48 hours, and a local-only dataset is first pushed to a private Hub repo. The docs warn that a failed run can leave an empty model repo, which you can remove with `hf repos delete`.

## How do you run the policy on the robot?

Use `lerobot-rollout`, with the same robot id, cameras and task text as in recording:

```
lerobot-rollout \
  --strategy.type=base \
  --policy.path=${HF_USER}/my_policy \
  --robot.type=so101_follower \
  --robot.port=/dev/tty.usbmodem5AB90687491 \
  --robot.id=my_follower_arm \
  --robot.cameras="{ wrist: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}, top: {type: opencv, index_or_path: 1, width: 640, height: 480, fps: 30}}" \
  --task="Grab the black cube" \
  --duration=60
```

The `--strategy.type` flag picks the mode: `base` for a quick evaluation with no recording, `sentry` for continuous recording with auto-upload, `highlight` for a ring buffer saved on a keystroke, `dagger` for human-in-the-loop data collection, and `episodic` for episode-based recording with resets. Datasets recorded by rollout must start with `rollout_`.

New in v0.7.0 is the interactive mode, which keeps the model loaded between commands. See our release post for `/subtask`, `/vqa` and `/autosteer`. Those need a text-generating policy, and plain ACT is not one.

## Common mistakes and how to avoid them

| Mistake | Why it hurts | Fix | 
|---|---|---|
| Different robot id between steps | Calibration file not found | Use one id everywhere | 
| Renaming cameras after recording | Policy expects the old keys | Keep names and resolution, or read the docs on rename maps | 
| Ignoring the cadence report | Dataset claims 30 Hz but ran slower | Lower resolution or fps and re-record | 
| Too much variation early | Policy never converges | Start with one task and a few locations | 
| Training the default 100,000 steps | Wasted time on a small set | Convert 5 to 10 epochs to steps | 
| Upgrading mid-project | v0.7.0 changes flags and imports | Pin the version and test in a new environment | 

## What to do next

If you have no robot, the docs point to simulation with LIBERO and to Colab notebooks. For larger open data, see [FineART from Scale AI](https://explainx.ai/blog/fineart-scale-ai-lerobot-dataset-40543-episodes-1718-hours-151-tasks-fineart-vla-pi0-5-2026), the [HIW-500 humanoid dataset](https://explainx.ai/blog/hiw-500-bitrobot-unitree-humanoid-dataset-lerobot-2026) and [RoboValue](https://explainx.ai/blog/robovalue-benchmark-robotic-value-models-15-sim-20-real-tasks-lerobot-2026). For open models you can fine-tune, read about [Ai2 ManiFlow-TB](https://explainx.ai/blog/ai2-maniflow-tb-toyblocks-open-robot-action-model-322m-franka-flow-matching-apache-57-percent-success-2026) and [Verne Robotics v0.5](https://explainx.ai/blog/verne-robotics-v0-5-open-weight-world-action-model-8b-libero-99-3-robotwin-81-gated-license-claim-check-2026), and check licenses first. If you want a hosted alternative to local fine-tuning, see the [Physical Intelligence pi API beta](https://explainx.ai/blog/physical-intelligence-pi-api-beta-robot-fine-tuning-2026). For NVIDIA's simulation tooling, see the [Cosmos interactive simulation guide](https://explainx.ai/blog/nvidia-cosmos-interactive-simulation-guide-sim-auto-transfer-auto-h-dreams-nim-vram-table-2026).

A robot that follows a learned policy can still do something unexpected. Keep a hand near the power switch, test with low speeds first, and treat any network-connected robot like an agent with real-world reach. [AgentBeam](https://agentbeam.com/?ref=explainx), the agent security platform from the explainx.ai team, stops AI agents before they take dangerous actions.

## Related reading

- [LeRobot v0.7.0 release breakdown](https://explainx.ai/blog/lerobot-v0-7-0-interactive-rollouts-disk-less-streaming-remote-policy-server-cosmos-3-yam-unitree-g1-2026)
- [FineART dataset and FineART-VLA](https://explainx.ai/blog/fineart-scale-ai-lerobot-dataset-40543-episodes-1718-hours-151-tasks-fineart-vla-pi0-5-2026)
- [HIW-500 humanoid teleop data](https://explainx.ai/blog/hiw-500-bitrobot-unitree-humanoid-dataset-lerobot-2026)
- [RoboValue benchmark](https://explainx.ai/blog/robovalue-benchmark-robotic-value-models-15-sim-20-real-tasks-lerobot-2026)
- [Loop engineering for coding agents](https://explainx.ai/blog/loop-engineering-coding-agents-claude-code-guide-2026)
- Official docs: [installation](https://huggingface.co/docs/lerobot/v0.7.0/en/installation?ref=explainx) and[imitation learning tutorial](https://huggingface.co/docs/lerobot/v0.7.0/en/il_robots?ref=explainx)

*Commands and versions follow the LeRobot v0.7.0 documentation as of November 6, 2026. Check the docs for later changes.*
