Tiny Engineer is a desk robot controlled over Wi‑Fi HTTP and/or USB serial. Prefer the unified tiny-engineer CLI for Cursor, Claude Code, and Antigravity hooks. For custom agents, other IDEs, or scripts, call the REST API or the serial protocol.
HTTP: robot on the same network; base URL http://tiny-engineer.local (or OLED IP). Full HTTP reference: api.md. USB serial (corporate Wi‑Fi bans, USB-only mode): serial.md.
| Path | Best for | How |
|---|---|---|
tiny-engineer CLI (default) |
Cursor, Claude Code, Antigravity hooks | tiny-engineer setup → hook <ide> → anim over HTTP or serial |
| REST API (advanced) | Custom agents, other IDEs, CI | POST /anim?name=… (api.md) |
| USB serial | No Wi‑Fi / USB-only device | --transport serial (serial.md) |
flowchart TB
subgraph preferred [Preferred]
Setup["tiny-engineer setup"]
Setup --> Hooks[IDE hook config]
Hooks --> Cli["tiny-engineer hook ide"]
Cli --> Anim["POST /anim"]
end
subgraph advanced [Advanced / custom]
Script[Any script or IDE] --> Rest["POST /anim REST"]
end
Anim --> Robot[Tiny Engineer on Wi-Fi]
Rest --> Robot
Prerequisites: flash firmware, join 2.4 GHz Wi-Fi, confirm http://tiny-engineer.local/health (or the OLED IP) responds.
Package: packages/tiny-engineer-cli. Bin name: tiny-engineer.
Supported IDEs: Cursor, Claude Code, Antigravity — one CLI (tiny-engineer setup / hook <ide>). No separate per-IDE packages for new installs.
Maps IDE hook events to poses and POSTs /anim. Also installs/uninstalls hook entries, checks wiring (doctor), and can anim / play without writing your own HTTP client.
Published on npm as tiny-engineer (no repo clone).
npx -y tiny-engineer --help
npx -y tiny-engineer setup
npx -y tiny-engineer setup cursor --yes
npx -y tiny-engineer doctor- Cold
npxcan be slow:setupwrites hooktimeout≥ 30. - Connection prefs (transport, URL, port, token) live in user config (
~/.config/tiny-engineer/envon macOS/Linux,%APPDATA%\tiny-engineer\envon Windows; override withTINY_ENGINEER_CONFIG_DIR). Setup never edits project.env. - Load order: flag → process env → project
.env(override) → userenv→ defaults. Setup anddoctorwarn when project.envoverrides user config. - Optional:
--url http://192.168.x.x(defaultTINY_ENGINEER_URL, elsehttp://tiny-engineer.local). - Host transport:
--transport http|serialorTINY_ENGINEER_TRANSPORT(setup writes this into user config). Defaulthttp. Distinct from the device AP Connection step (link_mode). - Auth (HTTP only): if the device has an
access_token, setTINY_ENGINEER_TOKEN(process env, user config, or project.envoverride). The CLI sendsAuthorization: Bearer …. A user/process token is not sent when the URL came only from project.env(request continues without Bearer; stderr warns). Serial skips Bearer. - Prefer registry
npxovernpx github:…(SSH often fails in IDE hooks).
This firmware repo (local CLI development):
node packages/tiny-engineer-cli/bin/tiny-engineer.js setup
node packages/tiny-engineer-cli/bin/tiny-engineer.js doctornpx -y tiny-engineer setup # interactive: pick IDEs
npx -y tiny-engineer setup cursor --yes
npx -y tiny-engineer setup --all --yes --url http://192.168.1.10
npx -y tiny-engineer doctor
npx -y tiny-engineer uninstall cursor --yes # remove only Tiny Engineer hook entriessetup merges hook commands into the project (Cursor .cursor/hooks.json, Claude Code .claude/settings.json, Antigravity .agents/hooks.json) using npx -y tiny-engineer hook <ide>, and writes connection prefs into user config (labeled as global vs project in the wizard). It does not delete foreign hooks and does not edit project .env. Uninstall removes hooks only (no --purge-env).
This firmware repo already ships configs pointing at the local CLI bin for developing the package.
echo '{"hook_event_name":"stop"}' | npx -y tiny-engineer hook cursorCursor deep dive (event table, sample hooks.json): hooks.md.
tiny-engineer anim ring
tiny-engineer play /tmp/clip.wav
tiny-engineer play /tmp/clip.wav --name thinkingWAV for /play: 16-bit mono PCM at 22050 Hz. Details: api.md#post-play.
Install the shared tiny-engineer-play skill (curl + POST /play). Same skill works in Claude Code, Cursor, and Antigravity:
mkdir -p ~/.claude/skills && ln -s "$PWD/skills/tiny-engineer-play" ~/.claude/skills/ # Claude Code
mkdir -p ~/.cursor/skills && ln -s "$PWD/skills/tiny-engineer-play" ~/.cursor/skills/ # Cursor
mkdir -p ~/.gemini/antigravity/skills && ln -s "$PWD/skills/tiny-engineer-play" ~/.gemini/antigravity/skills/ # AntigravityCall the board directly when you are not using the supported IDE hooks, or when you need full control of mapping and timing. Works with any AI IDE, CI, shell hooks, or plugin that can POST over HTTP.
curl -X POST "http://tiny-engineer.local/anim?name=typing"name |
Typical use |
|---|---|
typing |
Agent writing / editing / running tools |
reading |
Agent reading files / context |
thinking |
Agent reasoning / waiting on a long step |
ring |
Turn finished (attention ping) |
welcome |
Session start / greeting |
wakeup |
Sleep-inertia wake (eyes/head) |
sleep |
Force sleep (eye close + OLED off) |
attention |
Needs user input |
error / abort |
Failure / cancel |
dead |
Out of power (dead.wav, then X X hold) |
none |
Idle / clear pose |
Firmware holds each pose ≥1s and keeps only the latest pending switch — spam-safe. Auth is optional: if you set an access token on the device, send Authorization: Bearer <token> (check GET /auth for required). Prefer short timeouts (e.g. 2s) and ignore network errors so the agent never stalls if the robot is offline.
Shell
curl -4 -sS -m 2 -X POST "http://tiny-engineer.local/anim?name=reading" >/dev/null || trueJavaScript (Node 18+)
await fetch("http://tiny-engineer.local/anim?name=thinking", {
method: "POST",
signal: AbortSignal.timeout(2000),
}).catch(() => {});Python
import urllib.request
urllib.request.urlopen(
urllib.request.Request(
"http://tiny-engineer.local/anim?name=typing",
method="POST",
),
timeout=2,
)Wire these into your IDE’s hook / plugin / lifecycle events (prompt submitted → reading, tool use → typing, turn end → ring, etc.). Mapping is yours; the robot only cares about name.
Health check (no motion):
curl http://tiny-engineer.local/healthFull route list (tests, servo, web UI, /play): api.md.
- Cursor / Claude Code / Antigravity → unified CLI (
tiny-engineer setup). - Custom agent, other IDE, CI, or no Node → REST (
POST /anim). - Both paths hit the same firmware API; the CLI is a thin client.
The old bins tiny-engineer-cursor, tiny-engineer-antigravity, and tiny-engineer-claude-code still run but are deprecated. Prefer tiny-engineer above. Migrate with tiny-engineer setup, then tiny-engineer uninstall to strip leftover hook entries. For custom mapping, use the REST API.
Same POST /anim API. On macOS you can run a small host helper that POSTs sleep / wakeup when the screen locks or unlocks: macos-lock-unlock.md. The robot does not need it.