ROBOT.md: The Session-Start File for Every Agent That Drives a Robot
Claude Code loads CLAUDE.md plus the current git state at session start. The planner begins warm: it knows the project conventions, the file layout, what not to touch, and how the codebase talks to itself. It doesn’t have to rediscover context — it arrives with it. That’s the whole trick, and it’s not magic. It’s just giving the model the right context before it starts work.
So what’s the robotics equivalent?
Not AGENTS.md (too configuration-y). Not URDF (describes what the robot is, not what it can do). Not the ROS parameter server (volatile, no history). Not event logs (no LLM context window can absorb 48 hours of raw motor telemetry). A single file at the robot’s root — declarative, schema-validated, read once at session start.
We shipped it today. It’s called ROBOT.md.
If you’ve ever written a CLAUDE.md, you already know how to write one.
What’s in one
Here’s the smallest valid ROBOT.md — a minimal wheeled robot with two degrees of freedom and a software E-stop:
---
rcan_version: "3.0"
metadata:
robot_name: my-robot
physics:
type: wheeled
dof: 2
capabilities:
- nav.move
safety:
estop: { software: true, response_ms: 200 }
---
# my-robot
## Identity
Minimum robot for testing.
## What my-robot Can Do
- Drive forward/backward/turn.
## Safety Gates
- Stops on software E-stop within 200 ms.
Two blocks. YAML frontmatter on top — machine-readable, JSON-Schema-validated identity, physics, capabilities, safety. Markdown body underneath — the human and LLM-readable narrative the planner reads at session start.
A more substantial example — Bob, our reference 6-DOF arm:
---
rcan_version: "3.0"
metadata:
robot_name: bob
rrn: RRN-000000000003
physics:
type: arm+camera
dof: 6
drivers:
- { id: arm_servos, protocol: feetech, port: /dev/ttyUSB0, count: 6 }
capabilities:
- arm.pick
- arm.place
- vision.describe
safety:
payload_kg: 0.5
max_joint_velocity_dps: 180
estop: { software: true, response_ms: 100 }
hitl_gates:
- { scope: destructive, require_auth: true }
---
That’s identity, capability, and safety envelope. Everything else is optional. One file. The whole declaration.
Why session-start is the right primitive
The adoption argument writes itself once you look at which agent harnesses already support session-start context injection:
- Claude Code. A
SessionStarthook in~/.claude/settings.jsonruns a shell script before the first turn. Its stdout lands in the session context. Our v0.1 ships exactly this — a 15-linesession-start.shthat runsrobot-md context ./ROBOT.mdand emits a block Claude reads immediately. - ChatGPT custom GPTs. An instructions field. Paste the prose body of
ROBOT.md. Three clicks. - Gemini (AI Studio / Vertex). A system-instructions field. Same paste model.
- Ollama. A
SYSTEMdirective in a modelfile. Same. - LangChain / AutoGen / CrewAI / Letta. A system-prompt slot. Same.
Every agent harness worth shipping already has a session-start slot. ROBOT.md fills it with the robot. No new SDK. No new protocol. No dependency on any particular runtime.
Three tiers of runtime. Pick whichever.
The point you’re about to read is the one I’d underline twice if I could: OpenCastor is optional. ROBOT.md ships to work with Claude Code alone, and for a single robot that’s genuinely all you need.
Three tiers, each with a different trade:
- Tier 0 — Claude Code alone. A
ROBOT.mdat the robot’s root + the SessionStart hook. Claude’s Bash tool is the dispatch path —lsusbto discover hardware, a serial write to command a servo, acurlto post to an MQTT broker,i2cdetectto find a sensor. Planner and executor are one process. No SDK to install, no gateway to stand up, no runtime process. This is the under-60-second flow for a single robot. - Tier 1 — Claude Code + your own scripts. When shell-round-trip latency isn’t fast enough — a servo-control loop that needs 100 Hz, say — add Python or Bash drivers next to your ROBOT.md. Still no formal runtime process. Just Claude plus the files you’d already write.
- Tier 2 — OpenCastor. Production fleets, regulated deployments, reactive VLA control, P66 hardware interlocks, EU AI Act audit, 7,800+ tests. Open-source, Claude Opus 4.7 as reference planner. Opt-in when you need the batteries; skip it when you don’t.
ROBOT.md works the same way on all three tiers. You don’t re-author the file when you graduate upward; you only add layers below it.
Where it sits in the stack
Four layers, each independently useful:
ROBOT.md → what the robot IS (RobotRegistryFoundation/robot-md)
OpenCastor → what the robot RUNS (craigm26/OpenCastor)
RCAN → what the robot SPEAKS (rcan.dev)
Robot Registry → where the robot LIVES (robotregistryfoundation.org)
No layer depends on the others. You can have a robot that speaks RCAN but has no ROBOT.md. A ROBOT.md that’s never registered with RRF. An OpenCastor runtime with no public registration. Compose the subset you need.
Adoption path for providers
If you ship an agent harness, ROBOT.md is a free upgrade to your robotics story that doesn’t require you to build anything. Point your session-start primitive at the file. That’s the whole integration.
- Spec: https://robotmd.dev/spec/v1
- Schema: https://robotmd.dev/schema/v1/robot.schema.json
- Reference CLI:
RobotRegistryFoundation/robot-md(Apache 2.0)
The CLI has three verbs — validate, render, context — all three are small, focused, and forkable. If you want to ship your own implementation in your harness’s native language, please do. We’d rather see five clean parsers than wait for one blessed SDK.
Three Claude surfaces, three integration patterns:
- Claude Code — SessionStart hook (shipping in v0.1 today).
- Claude Desktop — MCP server wrapping ROBOT.md as resources + an
invoke_skilltool (documented pattern; code lands in v0.2). - Claude Mobile — URL-fetch pattern with ROBOT.md hosted at a stable public URL (documented pattern; reference Cloudflare Worker lands in v0.2).
Governance
No provider should own the file format their competitors’ agents have to read. That’s why ROBOT.md’s home, from day one of the public launch, is the Robot Registry Foundation — the same neutral body that stewards the robot registry itself. Not a vendor, not a single-maintainer account, not a working handle that gets transferred later.
- Format spec: CC BY 4.0.
- CLI and schema: Apache 2.0.
- Repo:
RobotRegistryFoundation/robot-md(public), shared-brand with robotregistryfoundation.org. - Contribution bar: small quality PRs welcome; breaking schema changes require a design-doc PR first. See
CONTRIBUTING.md.
What’s shipping when
Today (v0.1): format spec, JSON Schema, four worked examples (minimal, SO-ARM101, TurtleBot 4, and Bob), Python CLI, Claude Code SessionStart hook, documented MCP and URL-bridge patterns, landing page at robotmd.dev.
Next two weeks (v0.2): robot-md register for RRF integration, working Claude Desktop MCP server, Cloudflare Worker serving robotmd.dev/r/<rrn> as a stable public URL per robot, TypeScript port for npm.
Q3 2026 (v1.0): format freeze, conformance test suite, multi-language bindings, potentially a formal SDO submission.
Try it in 60 seconds
The Tier 0 adoption flow, from zero to “robot answers your first prompt”:
# 1. Install the CLI + the Claude Code SessionStart hook. (~15 sec)
pip install git+https://github.com/RobotRegistryFoundation/robot-md.git#subdirectory=cli
mkdir -p ~/.claude/hooks
curl -fsSL https://robotmd.dev/hook > ~/.claude/hooks/robot-md.sh && chmod +x ~/.claude/hooks/robot-md.sh
# Add the hook to ~/.claude/settings.json — one line; see the repo's integrations/claude-code/README.md.
# 2. cd to your robot's repo. Start Claude. Ask it to write ROBOT.md. (~30 sec)
cd ~/my-robot
claude
# > Scan the hardware connected to this machine and write a ROBOT.md per
# > the spec at https://robotmd.dev/spec/v1. Use lsusb, i2cdetect, and
# > dmesg for discovery, and validate when you're done.
#
# Claude's Bash tool does the discovery — USB servo buses, I2C sensors,
# serial ports, cameras — and writes the manifest. One tool, one session,
# one file out.
# 3. You're ready.
robot-md validate ROBOT.md # green check
From here, Claude Code operates the robot directly. Its Bash tool dispatches commands — a Feetech WRITE_POS over /dev/ttyUSB0, a frame pulled from an OAK-D over HTTP, an MQTT publish, whatever your hardware listens to. No separate runtime process. The planner and the executor are one. That’s Tier 0.
Want a public identity for your robot? robot-md register ROBOT.md (shipping in v0.2, this month) posts to the Robot Registry Foundation and writes the assigned RRN-XXXXXXXXXXXX back into your manifest — the robot now has an entry at robotregistryfoundation.org, signs its messages under that identity, and speaks RCAN to any other registered robot on the network.
Want production-grade fleet orchestration, reactive VLA control, P66 hardware interlocks, or EU AI Act audit? Add OpenCastor (Tier 2) when you need them. Until then, ROBOT.md plus Claude Code is all a single-robot setup requires.
That’s the whole trick.
ROBOT.md lives at RobotRegistryFoundation/robot-md. The ecosystem it composes with: OpenCastor (runtime), rcan.dev (wire protocol), robotregistryfoundation.org (registry).