Octopus brings embedded hardware to life — automatically.
Plug in a device. Run one command. An AI coding agent reads our specs, figures out what the device is, writes the driver code, and exposes the hardware as an MCP interface that any AI agent can call.
We don't ship the code. We ship the specs and an agent that writes the code itself — on your machine, for your hardware. A new universal remote that programs itself, instead of asking you to read the manual.
curl -fsSL https://raw.githubusercontent.com/qsimeon/octopus-hw/main/install.sh | bash
Needs OPENROUTER_API_KEY exported in your shell — the agent
uses it to call models (Gemini 3 Flash, Sonnet, Kimi K2, and others; swap in
octopus.toml). Get a key at
openrouter.ai.
export OPENROUTER_API_KEY=sk-or-... before you run the install.
How it works
Once you run the install command, the agent doesn't do anything magical. It does five things in order, each one writing a file the next step reads. If a step fails, the agent retries — and on retry it's allowed to rewrite the spec that told it what to do. Most software can't edit its own instructions. Ours can.
These only run if the camera and the SO-ARM101 robot arm are plugged in. They give the agent extra context about hardware we demo on a lot, but they're optional — a fresh install on a machine without these never runs them.
Features
What's in our repo is five markdown files and a runner. Everything else is generated. That's why one install command does so much, and why the same command does different things on different machines.
Pick any model that OpenRouter routes to — Gemini 3 Flash, Sonnet 4.6, Kimi K2, Opus 4.7, and ~6 more. One line in octopus.toml. Set OPENROUTER_API_KEY once, swap whenever.
If your OS can see the device, the agent figures out the rest. No driver registry, no per-device wiring code in our repo.
The five spec files describe what to do, not how. Same files on Mac, Linux, and Windows (WSL) produce different code that does the same job.
A background daemon tails the server's logs and asks the agent to patch anything that breaks.
When a camera is plugged in, the agent uses it as a second mirror — visually confirming the hardware actually did what it told it to. Self-watching at the hardware layer, paired with the daemon's self-watching at the software layer.
Claude Desktop, ChatGPT desktop, OpenClaw, Claude Code, your local Ollama, our own bridge — anything that speaks MCP connects to the same URL.
Demo
Run one install command on a Pi with hardware plugged in. ~20 minutes later you have an MCP server tailored to whatever you plugged in, with no per-device code in our repo. The clip below runs through that whole flow on our reference rig — install, Claude Desktop picks up the server, Claude calls a tool, arm moves. The buttons in the next section drive this same rig live, right now.
~40 s walkthrough — Pi install completes, Claude Desktop connects to the public tunnel, arm physically responds.
The five spec stages run in order on any platform. If the camera or the arm are detected,
two extra framework steps run after — they give the agent extra context about
hardware we demo on a lot. A background daemon then keeps the server healthy by tailing
its logs and asking the agent to patch anything that breaks. A single
octopus expose command publishes the whole thing over a Cloudflare
quick-tunnel, so any MCP client on the public internet can reach it.
arm_set_joint_angle, arm_home,
arm_set_all_joints, plus diagnostics). Zero hand-written hardware code in
our repo.Try it yourself
You don't need a Pi or an arm. The buttons below talk to a real SO-ARM101 in our apartment over a public Cloudflare tunnel — every click is a real MCP tool call, every camera frame is a real capture. Three ways to connect, depending on what you're building.
Just an HTTPS POST. Works from any language, any notebook, any shell. No MCP client needed. The buttons below hit the Pi directly.
(click any button — the response shows up below. Every arm command also captures a fresh camera frame, so you can see the arm actually moved.)
# list available tools
curl -s -X POST https://mellow-miracle-production-b572.up.railway.app/tools/invoke \
-H 'Content-Type: application/json' \
-d '{"action":"list"}'
# move arm to rest pose
curl -s -X POST https://mellow-miracle-production-b572.up.railway.app/tools/invoke \
-H 'Content-Type: application/json' \
-d '{"action":"invoke","tool_name":"arm_home","parameters":{}}'
# grab a fresh camera frame
curl -s https://mellow-miracle-production-b572.up.railway.app/camera/latest.png \
--output frame.png && open frame.png
Connect any client that speaks MCP — Claude Desktop, the MCP Inspector, your local Ollama setup, OpenClaw, Claude Code. Your agent gets the typed tool list and calls them directly.
Live tunnel URL (auto-updates from Pi):
loading…
(click a button to copy a ready-to-paste config)
// Claude Desktop → Settings → Connectors → Add custom
{ "name": "octopus-pi", "url": "LIVE_URL/mcp" }
// OpenClaw / any streamable-http MCP config
{ "transport": "streamable-http", "url": "LIVE_URL/mcp" }
// Local MCP Inspector (requires Node)
npx @modelcontextprotocol/inspector LIVE_URL/mcp
Join39 is a marketplace where AI agents
discover apps. If you're building an agent there, add
octopus-hardware to its app list and your agent can call the arm
during conversation. Join39 forwards the call through our bridge to the Pi.
App: octopus-hardware
Note: the Cloudflare tunnel URL rotates whenever the Pi restarts. The Railway bridge URL (used by the buttons in lane 01) is stable — that's the safer link if you're sharing with someone else.
Philosophy
We landed on eight in our internal philosophy doc. These four are the ones that drove every architectural decision in the repo.
The five markdown files in protocol/ aren't configuration —
they're the program. An Agent reads the Specs
and acts on the Platform in front of it. What comes out —
the running, agent-callable hardware — is what we call
Infrastructure.
I = A(S, P)
So the real infrastructure isn't shipped — it emerges from the agent's interaction with the specs and the machine, constrained by the scaffolding we provide (the orchestrator, RALPH, the principles below). Our repo is small. What it produces on your hardware is the actual product.
Every pipeline stage, every daemon tick, every self-heal action is the same four-step loop: read the current state, hand it to the agent, let the agent act, check whether it passed. No other control structures anywhere in the system. Adapted from Geoffrey Huntley's RALPH loop — his version is a coding agent re-prompted with the same goal until it converges; ours is the same spirit but split into four named steps that we re-use across the pipeline, the daemon, and heal.
Software face: failed pipeline stages can edit the spec that
governs them on retry; the daemon tails its own server's logs and patches what
breaks.
Hardware face: the camera watches the arm the agent
just moved — it grounds the system in the physical world by giving the agent
a way to see the consequences of its own actions.
Anywhere we'd normally write tangled, edge-case-heavy logic — parsing a half-structured device descriptor, mapping a vendor ID through a registry of one-off names, deciding whether a tool's output looks like an error, classifying which kind of failure a log line represents — we ask the model instead. A short prompt with the input is more honest about the fuzziness than a 200-line if/else tree, and it keeps working when an edge case we never thought of shows up.
The narrower instance ("no per-device switch statements") is the most visible one. The general principle: when the logic you're about to write is dirty enough that your enumerated cases will leak, replace the code with a model call.