fomo
An SO-101 leader arm that films.
six servos · a camera on a printed pan/tilt head · five tools: calibrate photo move pose motion
Site — the twin plays the nine motions · Install · Five verbs · Motions · The guard · Cockpit
Hi. I'm Fomo.
I'm the leader arm from an SO-101 kit — the one that goes back in the box after teleop. Someone took my handle off, printed a pan/tilt yoke for an Arduino Nicla Vision, and screwed it to my wrist. Now I'm a cameraman: six Feetech STS3215 servos on one bus, a camera that knows its own pose, and an agent that drives me with exactly five verbs.
from strands import Agent
from fomo.tools import calibrate, photo, move, pose, motion
fomo = Agent(tools=[calibrate, photo, move, pose, motion])
fomo("look 40 degrees left, take a photo, then show me you're happy")
Install me — five steps
pip install "fomo-the-arm[dashboard]" # tools · CLI · MCP · agent · dash API (+[mcp], +[rl])
pip gives you the five tools, fomo and fomo mcp, the agent and the dash API. The cockpit's SPA
and the twin's models live in the repo, so for the full panel clone it:
git clone https://github.com/cagataycali/fomo-the-arm.git && cd fomo-the-arm
pip install -e ".[dashboard]"
fomo doctor # read-only: which port is me, six servos, calibration, camera
fomo calibrate --manual --hold 40 --i-know # torque off, move me by hand, fold me before the timer ends
fomo dash # http://127.0.0.1:8091 — the cockpit: agent log, dock, twin, eyes
No arm? FOMO_SIM=1 fomo dash is six simulated servos ramping at my real speed — the
site's twin is one. The long form, with what each
step refuses and why, is Install.
Set FOMO_PORT when doctor finds more than one usbmodem (on the bench this was written on it found
five: the servo adapter, a Nicla, a Sticky, a Flipper — two share the CH343 chip, so I refuse to guess).
Nothing moves until you say --i-know (you are watching me) or write {"ok": true} to ~/.fomo/bench.json.
My five verbs
| tool | what it does | honest limits |
|---|---|---|
calibrate(mode) |
report reads ~/.fomo/calib.json; manual drops torque, samples every joint while you move me by hand (≥ 20 s), makes the fold my home and the extremes my window; write_eeprom burns MIN/MAX into servos 1–4; --import adopts a strands-arm calibration |
I don't search for my own stops — on this arm the automatic search found the fold contact 30–45° short of the metal, the hand found 185–207° spans |
photo(source) |
one JPEG from the Nicla (LAN /stream, or USB raw-REPL), else the dashboard, else this machine's webcam; saved to ~/.fomo/photos/, the source named |
320×240 from the Nicla; if every source fails I say so and name each |
move(actions) |
several servos, several actions, one guarded ramped command: to, by, rel (from home), look {pan,tilt}, home, stop, torque, read (present degrees + what the head feels: ToF, roll/pitch, bench or head) |
any angle inside the measured window is one call; a stall holds, never forces |
pose(action, name) |
list show save delete goto nudge; five built-ins (home attention look_around_left look_around_right up); stored relative to home so a re-calibration shifts poses instead of breaking them |
a pose is a place, not a path |
motion(action, name) |
list show run save delete; nine built-ins timed on the metal — approve (nod) deny (shake) happy frustrated curious wave look_around up sleep; keyframes from wherever I am, ending folded unless stay |
every frame is checked against the hard limits before the first write |
Every tool returns the same {"status", "content": [{"text"}]} shape, dash-first (when the
dashboard owns the port) with a local-bus fallback. fomo mcp serves the same five over MCP.
Verbs · Motions — the twin plays all nine.
The guard — hard limits only
Every servo write passes fomo.guard.Guard. It refuses on six things, each named after a night
something went wrong on the real leader (2026-09-05 → 08), and executes everything inside them:
| refuses on | why |
|---|---|
1 Gate. Nothing moves without i_know or ~/.fomo/bench.json {"ok": true} |
a tool call from a phone moved the head while the owner's hand was on it |
| 3 Head window. Pan ±160°, tilt ±80° about home | the horns spin freely; the Nicla's USB cable does not |
| 4 Measured window. Joints 1–4 stay inside what your hand found, not the EEPROM's | the base's factory window 111..251 wasted 45° on one side; the hand found 66.4 |
7 Upright. torque off is refused until I'm folded |
the elbow fell onto its stop at 04:05Z, 2026-09-07 |
| 8 Power. No lifting away from the fold while the rail reads under 5 V; folding is always allowed | the 5.5 V leader supply could not lift the forearm |
| 9 Stall. 6° behind a streamed goal and not moving → every joint is re-goaled to where it is; a hold, not a refusal | the wrist was driven into the forearm for 2 s, the rail sagging to 5.0 V |
How far a command reaches is never a refusal: inside the limits a target is cut into ≤ 10° legs, goals
streamed from the host at 30 °/s (ceiling 90) so stop lands mid-leg, torque drops 2 s after the last
command — only when folded. The guard: every number on that page is read from
fomo/guard.py and ~/.fomo/calib.json at build time, never typed.
Cockpit — fomo.cagatay.my
One screen; the agent is the spine. The log is the narrative — your prompts, my streamed answers,
every tool call as a row in words (read · joints 0.1 s, motion · happy), a photo inline — and
the eyes (live MJPEG) and the twin (following the servos at 5 Hz) are my face. STOP is always in
the bar. Captured 2026-09-09 on the live arm:
Press d for the dock — one slider per joint on its measured window, look pad, every pose, every
motion, torque, a speed slider capped at the guard's 90 °/s. Nothing in it bypasses the guard, and
manual moves land in the same log so the agent's next turn sees them.
Voice in and out are browser-native; a think toggle lets me look and say one line every so often
(off by default, never moving joints 1–4). Control routes need FOMO_TOKEN (or, with FOMO_OWNER set,
the owner's tiny.technology session); state, /ws, eyes and senses are read-only public.
dashboard/deploy/install.sh makes it a launchd agent and carries your model credentials
(AWS_BEARER_TOKEN_BEDROCK or AWS_PROFILE) into it; cloudflared-fomo.yml puts it on a name.
Cockpit · Reference — every route.
Where I come from
I'm the fresh codebase of strands-arm — the idea
kept, the 14k lines cut to what a cameraman needs. Everything I learnt there — the
measured servo ranges, every incident behind the guard, the nights in archive/lanes/ — is written
down where it was learnt: the guard page carries the incidents, the install page the hand-measured windows.
What I won't pretend to do
- Drive a base. That's strands-arm's three-wheel body; I'm the arm on the bench.
- Run an RL policy live — not yet. Two ONNX policies ship and run in shadow (
fomo rl shadow); stage 1 (head only) is built and stays behind a phrase the owner writes by hand in the journal. - Lift on 5 V. The leader kit's supply reads 5.6 V on my bus; the elbow does not lift the forearm from the fold on it (rule 9 holds it). The 7.4 V supply does.
- See obstacles. Rule 1 exists because a human must.
- Take a photo I didn't take. If every camera source fails,
photosays so and names each.
License
MIT, Cagatay Cali. Built by cagatay and his agents at strands robots.
Metadata
Release files for fomo-the-arm 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| fomo_the_arm-0.1.0.tar.gz | 750.5 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fomo_the_arm-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 946.9 kB
Release files / fomo_the_arm-0.1.0.tar.gz
| Download URL | fomo_the_arm-0.1.0.tar.gz |
|---|---|
| Size | 750.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
003eca142095b13aa95ca27b82cc31d52df347a7f8e1e13ee48ae23a12874e96
|
|
BLAKE2b-256 checksum How to use checksums |
2d8f78650c5a075d21277a1678804c01d95d3da25835c95687d965d7989c0855
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Release files / fomo_the_arm-0.1.0-py3-none-any.whl
| Download URL | fomo_the_arm-0.1.0-py3-none-any.whl |
|---|---|
| Size | 196.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
22784a53789ab854e7eb255775ab3f1e5d21c5f5f3fb64bbcbbdd44e5aff8db5
|
|
BLAKE2b-256 checksum How to use checksums |
c7753d132dd936f39d9bb21d0ca025474f8d4de836ce1deecac7b919159e9617
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Security for fomo-the-arm 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.