Microduck RL
Close the loop: spec → sim → package → Hub → localhost control → robot. You are training a 61→14 PPO policy, not an LLM. Hub publish is not the end — deploy is in scope. A published repo is a deliverable for whoever owns a duck, not a baked-in official weight.
Canonical playbook: AGENTS.md in pollen-robotics/microduck_rl. This skill is the job ticket; that file wins if they disagree.
$SKILL = directory that contains this SKILL.md. Always invoke scripts with that absolute path. The skill id is microduck-skill.
Preconditions
- Run
$SKILL/scripts/doctor.sh (add --clone --sync if there is no checkout). It must print doctor ok.
- Default compute is Hugging Face Jobs. Require
HF_TOKEN (or hf auth login) and MICRODUCK_HF_NAMESPACE (user or org). No namespace → Jobs prompts and the agent hangs.
- Local train only if
MICRODUCK_TRAIN_LOCAL=1 and CUDA is present. Smoke uses the same switch.
- Stop if doctor fails. Do not invent another trainer (Isaac Sim, AutoTrain, Colab-only hacks).
Hard rules
- Never skip the 64-env × 5-iter smoke test (
$SKILL/scripts/smoke.sh).
- Never hand-convert a
.pt to ONNX. Only upstream scripts/export.py.
- Observation stays 61D; action stays 14D. Unused command slots are zero-padded, never deleted.
- Do not hardcode joint indices. Servo helpers in
mdp.py only.
- Community publish is constant-command episodic/perpetual only. Phase / posture-flag stay official.
- Do not run
robotctl / SSH unless the user explicitly says to install on a real robot. Print the commands.
Workflow (do not skip stages)
- Spec — one-line behavior,
kind (episodic | perpetual), closest template. references/TRAIN.md.
- Sim — edit env → CPU
pytest tests/ → $SKILL/scripts/smoke.sh → $SKILL/scripts/train.sh. If wandb is logged in, watch the run page (curves; Jobs cannot record --video — no GL in the image). Keep penalty Episode_Reward/* ≤ 0. If not, tensorboard + --no-wandb so Jobs do not hang. Replay a checkpoint with $SKILL/scripts/play.sh (Viser + local mp4).
- Package —
$SKILL/scripts/export_publish.sh. references/PUBLISH.md. After a tensorboard run, export from --checkpoint-file (or an already-gated --onnx), not a wandb path. Then try $SKILL/scripts/preview.sh --repo <this-run-repo> --task … (or --mp4 if a clip already exists). That is a sim checkpoint replay on this Hub card (preview.mp4), not ONNX control, not a robot, not a ranking. play.sh is a viewer and does not exit; preview starts it, waits for the clip, then stops it. Play/upload failure is not a failed publish — say preview skipped and continue. Do not put mp4 in the plugin git.
- Sim control — you run
$SKILL/scripts/control.sh yourself (localhost HTTP). Do not paste these commands for the human to type. search lists Hub policy.onnx (not a store). You pick a repo by name/README match, then start --repo / pull --as. Worked Hub examples (not bundled, not official Pollen): neil-jo/microduck-walk (perpetual; start --repo) and neil-jo/microduck-polite-bow (pull --as then do). Read status.command_notes before twisting — walk speed caps are not universal. Read status.body_state to say what the body did (tilt_deg, feet, joints vs HOME) — same card for every policy. Do not call it fallen. Episodic Hub graphs: pull --as name then do name (same swap as kick). Do not start --repo them. Exercise twist/head/do, and report from that card. references/CONTROL.md. status.skills is loaded or untrained. --record + dataset.sh is datacollect only. Bind stays localhost. Do not start a train from a search hit.
- Deploy — always this stage after publish. Print the install lines from references/DEPLOY.md for this run's
--repo (never a hardcoded test repo). If the user explicitly says to install on a Microduck they own, run those robotctl lines. If they have no robot or did not ask, stop after printing. Do not claim hardware success until they report it.
Scripts
| Script |
Does |
scripts/doctor.sh [--clone] [--sync] |
Tools, checkout, Jobs env. |
scripts/smoke.sh <TASK_ID> |
64×5. Jobs unless MICRODUCK_TRAIN_LOCAL=1. wandb → curves; --video only on local CUDA. |
scripts/train.sh <TASK_ID> [args…] |
Same compute switch. Default 4096 envs. Same wandb/video rules. |
scripts/play.sh <TASK_ID> --checkpoint-file|--wandb-run-path … |
Local Viser webpage + mp4. Checkpoint watch. Not Jobs. |
scripts/preview.sh --repo USER/NAME … |
Optional. play.sh (or --mp4) → Hub preview.mp4 + README embed. Failure exits 0. Not a store. |
scripts/control.sh start|search|pull|twist|head|body|sit|stand|do|stop|status|shutdown |
Agent runs these. Localhost 13D command. search lists Hub policy.onnx; you then start --repo / pull. Not Jobs. Not robotctl. |
scripts/dataset.sh check|pack|replay |
Validate/pack --record JSONL; replay commands in sim. Not consumed by train.sh. |
scripts/gate_check.py <policy.onnx> |
[1,61]→[1,14]; skip initializers. Called via uv run --with onnx. |
scripts/export_publish.sh … |
Official export to $RL_ROOT/.microduck-plugin-export.onnx only, then Hub. |
Report back
Say what rolled out ("bows, then face-plants 1 in 3"), not "it works". Training is hours — submit Jobs, then wait.
1---2name: microduck-skill3description: Train, export, publish, drive a simulated Microduck over localhost HTTP, and deploy Microduck reinforcement-learning policies (PPO on MuJoCo Warp via mjlab) onto a real robot via robotctl. Use when the user wants to teach a Microduck a new trick, train a gait or episodic policy, run microduck_rl, export ONNX, command a sim duck, publish to Hugging Face Hub, use Hugging Face Jobs, or install a published policy on a duck they own. After Hub publish, try preview.sh (preview.mp4 on that card; skip if play cannot record). Always walk deploy. Print robotctl; run it only when that user explicitly asks to install on their robot. Never SSH or robotctl on a machine they do not own.4license: MIT5---67# Microduck RL89Close the loop: **spec → sim → package → Hub → localhost control → robot**. You are training a 61→14 PPO policy, not an LLM. Hub publish is not the end — deploy is in scope. A published repo is a deliverable for whoever owns a duck, not a baked-in official weight.1011Canonical playbook: `AGENTS.md` in `pollen-robotics/microduck_rl`. This skill is the job ticket; that file wins if they disagree.1213`$SKILL` = directory that contains this `SKILL.md`. Always invoke scripts with that absolute path. The skill id is `microduck-skill`.1415## Preconditions16171. Run `$SKILL/scripts/doctor.sh` (add `--clone --sync` if there is no checkout). It must print `doctor ok`.182. Default compute is **Hugging Face Jobs**. Require `HF_TOKEN` (or `hf auth login`) **and** `MICRODUCK_HF_NAMESPACE` (user or org). No namespace → Jobs prompts and the agent hangs.193. Local train only if `MICRODUCK_TRAIN_LOCAL=1` **and** CUDA is present. Smoke uses the same switch.204. Stop if doctor fails. Do not invent another trainer (Isaac Sim, AutoTrain, Colab-only hacks).2122## Hard rules2324- Never skip the 64-env × 5-iter smoke test (`$SKILL/scripts/smoke.sh`).25- Never hand-convert a `.pt` to ONNX. Only upstream `scripts/export.py`.26- Observation stays **61D**; action stays **14D**. Unused command slots are zero-padded, never deleted.27- Do not hardcode joint indices. Servo helpers in `mdp.py` only.28- Community publish is **constant-command** episodic/perpetual only. Phase / posture-flag stay official.29- **Do not run `robotctl` / SSH** unless the user explicitly says to install on a real robot. Print the commands.3031## Workflow (do not skip stages)32331. **Spec** — one-line behavior, `kind` (`episodic` | `perpetual`), closest template. [references/TRAIN.md](references/TRAIN.md).342. **Sim** — edit env → CPU `pytest tests/` → `$SKILL/scripts/smoke.sh` → `$SKILL/scripts/train.sh`. If wandb is logged in, watch the run page (curves; Jobs cannot record `--video` — no GL in the image). Keep penalty `Episode_Reward/*` ≤ 0. If not, tensorboard + `--no-wandb` so Jobs do not hang. Replay a checkpoint with `$SKILL/scripts/play.sh` (Viser + local mp4).353. **Package** — `$SKILL/scripts/export_publish.sh`. [references/PUBLISH.md](references/PUBLISH.md). After a tensorboard run, export from `--checkpoint-file` (or an already-gated `--onnx`), not a wandb path. Then try `$SKILL/scripts/preview.sh --repo <this-run-repo> --task …` (or `--mp4` if a clip already exists). That is a sim checkpoint replay on **this** Hub card (`preview.mp4`), not ONNX control, not a robot, not a ranking. `play.sh` is a viewer and does not exit; preview starts it, waits for the clip, then stops it. Play/upload failure is not a failed publish — say `preview skipped` and continue. Do not put mp4 in the plugin git.364. **Sim control** — you run `$SKILL/scripts/control.sh` yourself (localhost HTTP). Do not paste these commands for the human to type. `search` lists Hub `policy.onnx` (not a store). You pick a repo by name/README match, then `start --repo` / `pull --as`. Worked Hub examples (not bundled, not official Pollen): `neil-jo/microduck-walk` (perpetual; `start --repo`) and `neil-jo/microduck-polite-bow` (`pull --as` then `do`). Read `status.command_notes` before twisting — walk speed caps are not universal. Read `status.body_state` to say what the body did (`tilt_deg`, feet, joints vs HOME) — same card for every policy. Do not call it fallen. Episodic Hub graphs: `pull --as name` then `do name` (same swap as kick). Do not `start --repo` them. Exercise twist/head/`do`, and report from that card. [references/CONTROL.md](references/CONTROL.md). `status.skills` is `loaded` or `untrained`. `--record` + `dataset.sh` is datacollect only. Bind stays localhost. Do not start a train from a search hit.375. **Deploy** — always this stage after publish. Print the install lines from [references/DEPLOY.md](references/DEPLOY.md) for **this run's** `--repo` (never a hardcoded test repo). If the user explicitly says to install on a Microduck they own, run those `robotctl` lines. If they have no robot or did not ask, stop after printing. Do not claim hardware success until they report it.3839## Scripts4041| Script | Does |42|---|---|43| `scripts/doctor.sh [--clone] [--sync]` | Tools, checkout, Jobs env. |44| `scripts/smoke.sh <TASK_ID>` | 64×5. Jobs unless `MICRODUCK_TRAIN_LOCAL=1`. wandb → curves; `--video` only on local CUDA. |45| `scripts/train.sh <TASK_ID> [args…]` | Same compute switch. Default 4096 envs. Same wandb/video rules. |46| `scripts/play.sh <TASK_ID> --checkpoint-file\|--wandb-run-path …` | Local Viser webpage + mp4. Checkpoint watch. Not Jobs. |47| `scripts/preview.sh --repo USER/NAME …` | Optional. `play.sh` (or `--mp4`) → Hub `preview.mp4` + README embed. Failure exits 0. Not a store. |48| `scripts/control.sh start\|search\|pull\|twist\|head\|body\|sit\|stand\|do\|stop\|status\|shutdown` | Agent runs these. Localhost 13D command. `search` lists Hub `policy.onnx`; you then `start --repo` / `pull`. Not Jobs. Not robotctl. |49| `scripts/dataset.sh check\|pack\|replay` | Validate/pack `--record` JSONL; replay commands in sim. Not consumed by train.sh. |50| `scripts/gate_check.py <policy.onnx>` | `[1,61]→[1,14]`; skip initializers. Called via `uv run --with onnx`. |51| `scripts/export_publish.sh …` | Official export to `$RL_ROOT/.microduck-plugin-export.onnx` only, then Hub. |5253## Report back5455Say what rolled out ("bows, then face-plants 1 in 3"), not "it works". Training is hours — submit Jobs, then wait.