C3PO, part 1: Claude Code drives a robot in Isaac Sim
I’m giving Claude a body.
The project is called C3PO, and it started as a school project with a simple realization: we have frontier LLMs that can reason and use tools, and we have genuinely capable humanoid hardware — and they mostly live in separate worlds. So why not connect them? The end goal is Claude controlling a real Unitree G1 humanoid: perceiving, deciding, and moving in the physical world. The G1 costs real money and breaks in real ways, so before any hardware: simulation.
The dumbest thing that could work
The first implementation is deliberately crude. Three pieces:
- Isaac Sim on a separate Ubuntu host, running a G1
- A Python bridge that exposes the robot’s controls as MCP tools and talks DDS (CycloneDDS + Unitree’s SDK) to the sim
- Claude Code as the brain
That last part is the trick: the bridge is just an MCP server registered in the project’s .mcp.json, so any Claude Code session opened in the repo has tools like walk_to and get_state sitting next to its normal file tools. No custom UI, no backend, no orchestration. I type what I want in the terminal, and Claude calls robot tools the same way it usually calls grep.
The core tools: get_state (live pose, battery, posture, faults — streamed from the sim at ~100 Hz), walk_to (a velocity control loop toward a world coordinate, with a minimum stop distance so it doesn’t faceplant into things), turn, and stop_everything, which cancels every running task and slams velocity to zero. On top of that sits a catalogue of the G1’s built-in postures and gestures — sit, squat, wave, shake hands, hug — twenty tools in all.
And it works, end to end: the robot walks a meter or two per command, rotates 90° or 180° on demand, and reports where it is the whole time.
It’s also full of the quirks that make robotics fun. The sim’s walk policy is so conservative that the effective forward speed is 10–15% of what you command. DDS multicast doesn’t work reliably on macOS, so the bridge writes a unicast peer config by hand.
You can watch it reason about the gap between what it asked for and what it got: “moved 0.74 m of the 1 m target before reaching stop_distance”, and on the turn, “total 177° — within 3° of the 180° target, finished cleanly.”
What I learned
MCP turns out to be a surprisingly good robotics interface. Skills are just tools with JSON schemas; the model never needs to know DDS topics or firmware modes exist. And having a frontier model as the driver on day one meant I could validate the whole skill interface in hours instead of weeks.
Next
Claude Code as the driver is a bootstrap, not the destination — the control flow lives inside a code editor on my laptop, and nobody else can use it. Next step: pull the agent out into a proper backend with a real interface. That’s part 2.
The whole thing is open source: github.com/mercho40/C3PO.