Metadata-Version: 2.4
Name: opencastor
Version: 1!3.6.1
Summary: The Universal Runtime for Embodied AI
Author-email: OpenCastor Contributors <hello@opencastor.com>
License-Expression: Apache-2.0
Project-URL: Homepage, https://opencastor.com
Project-URL: Repository, https://github.com/craigm26/OpenCastor
Project-URL: Documentation, https://docs.opencastor.com
Project-URL: Bug Tracker, https://github.com/craigm26/OpenCastor/issues
Project-URL: Changelog, https://github.com/craigm26/OpenCastor/blob/main/CHANGELOG.md
Project-URL: Discord, https://discord.gg/jMjA8B26Bq
Keywords: robotics,ai,llm,embodied-ai,rcan
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
Classifier: Environment :: Console
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: System :: Hardware
Requires-Python: <3.14,>=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: anthropic>=0.40.0
Requires-Dist: openai>=1.0.0
Requires-Dist: pyserial>=3.5
Requires-Dist: rc-car-actuator>=0.1.1
Requires-Dist: opencv-python-headless>=4.9.0
Requires-Dist: gTTS>=2.4.0
Requires-Dist: pygame>=2.5.0
Requires-Dist: pyyaml>=6.0
Requires-Dist: jsonschema>=4.20.0
Requires-Dist: requests>=2.31.0
Requires-Dist: fastapi>=0.109.0
Requires-Dist: uvicorn[standard]>=0.27.0
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: httpx>=0.26.0
Requires-Dist: python-multipart>=0.0.7
Requires-Dist: cryptography>=42.0.0
Requires-Dist: dilithium-py>=1.0.0
Requires-Dist: huggingface-hub>=0.25.0
Requires-Dist: streamlit>=1.30.0
Requires-Dist: SpeechRecognition>=3.10.0
Requires-Dist: PyJWT>=2.8.0
Requires-Dist: rich>=13.0.0
Requires-Dist: argcomplete>=3.0.0
Requires-Dist: rcan<4,>=3.5
Requires-Dist: robot-md-gateway>=0.5.0a8
Requires-Dist: zeroconf>=0.131.0
Provides-Extra: core
Provides-Extra: rc-car
Requires-Dist: rc-car-actuator>=0.1.1; extra == "rc-car"
Provides-Extra: rpi
Requires-Dist: adafruit-circuitpython-pca9685>=3.4.0; sys_platform == "linux" and extra == "rpi"
Requires-Dist: adafruit-circuitpython-motor>=3.4.0; sys_platform == "linux" and extra == "rpi"
Requires-Dist: neonize==0.3.18.post0; extra == "rpi"
Requires-Dist: picamera2>=0.3; sys_platform == "linux" and extra == "rpi"
Provides-Extra: elevenlabs
Requires-Dist: elevenlabs>=1.0; extra == "elevenlabs"
Provides-Extra: sdk
Requires-Dist: httpx>=0.27; extra == "sdk"
Provides-Extra: whatsapp
Requires-Dist: neonize==0.3.18.post0; extra == "whatsapp"
Provides-Extra: whatsapp-twilio
Requires-Dist: twilio>=9.0.0; extra == "whatsapp-twilio"
Provides-Extra: telegram
Requires-Dist: python-telegram-bot>=21.0; extra == "telegram"
Provides-Extra: discord
Requires-Dist: discord.py>=2.3.0; extra == "discord"
Provides-Extra: slack
Requires-Dist: slack-bolt>=1.18.0; extra == "slack"
Provides-Extra: mqtt
Requires-Dist: paho-mqtt>=2.0.0; extra == "mqtt"
Provides-Extra: channels
Requires-Dist: neonize==0.3.18.post0; extra == "channels"
Requires-Dist: python-telegram-bot>=21.0; extra == "channels"
Requires-Dist: discord.py>=2.3.0; extra == "channels"
Requires-Dist: slack-bolt>=1.18.0; extra == "channels"
Requires-Dist: paho-mqtt>=2.0.0; extra == "channels"
Provides-Extra: rcan
Requires-Dist: zeroconf>=0.131.0; extra == "rcan"
Requires-Dist: rcan<4,>=3.5; extra == "rcan"
Provides-Extra: dynamixel
Requires-Dist: dynamixel-sdk>=3.7.31; extra == "dynamixel"
Provides-Extra: hlabs
Requires-Dist: python-can>=4.0; extra == "hlabs"
Provides-Extra: lerobot
Requires-Dist: feetech-servo-sdk; extra == "lerobot"
Requires-Dist: dynamixel-sdk>=3.8; extra == "lerobot"
Requires-Dist: gym-pusht; extra == "lerobot"
Requires-Dist: gym-aloha; extra == "lerobot"
Provides-Extra: reachy
Requires-Dist: reachy2-sdk>=1.0; extra == "reachy"
Requires-Dist: zeroconf>=0.120; extra == "reachy"
Provides-Extra: cloud
Requires-Dist: firebase-admin>=6.0.0; extra == "cloud"
Requires-Dist: httpx>=0.27; extra == "cloud"
Provides-Extra: setup
Requires-Dist: qrcode[pil]>=7.0; extra == "setup"
Provides-Extra: esp32
Requires-Dist: websocket-client>=1.7.0; extra == "esp32"
Provides-Extra: ev3
Requires-Dist: python-ev3dev2>=2.1.0.post1; sys_platform == "linux" and extra == "ev3"
Provides-Extra: spike
Requires-Dist: bleak>=0.22.0; extra == "spike"
Provides-Extra: stem-hardware
Requires-Dist: websocket-client>=1.7.0; extra == "stem-hardware"
Requires-Dist: python-ev3dev2>=2.1.0.post1; sys_platform == "linux" and extra == "stem-hardware"
Requires-Dist: bleak>=0.22.0; extra == "stem-hardware"
Provides-Extra: vertex
Requires-Dist: google-genai>=1.0.0; extra == "vertex"
Provides-Extra: homeassistant
Requires-Dist: aiohttp>=3.9.0; extra == "homeassistant"
Provides-Extra: webrtc
Requires-Dist: aiortc>=1.6.0; extra == "webrtc"
Requires-Dist: av>=11.0.0; extra == "webrtc"
Provides-Extra: microduck-webrtc
Requires-Dist: aiortc>=1.6.0; extra == "microduck-webrtc"
Requires-Dist: websockets>=12.0; extra == "microduck-webrtc"
Provides-Extra: ros2
Provides-Extra: onnx
Requires-Dist: onnxruntime>=1.17.0; extra == "onnx"
Provides-Extra: onnx-gpu
Requires-Dist: onnxruntime-gpu>=1.17.0; extra == "onnx-gpu"
Provides-Extra: gestures
Requires-Dist: mediapipe>=0.10.0; extra == "gestures"
Provides-Extra: apple
Provides-Extra: simulation
Provides-Extra: paintbench
Requires-Dist: inspect-robots>=0.58.0; extra == "paintbench"
Provides-Extra: paintbench-agent
Requires-Dist: inspect-robots>=0.58.0; extra == "paintbench-agent"
Requires-Dist: inspect-robots-agent>=0.26.0; extra == "paintbench-agent"
Provides-Extra: all
Requires-Dist: python-telegram-bot>=21.0; extra == "all"
Requires-Dist: discord.py>=2.3.0; extra == "all"
Requires-Dist: slack-bolt>=1.18.0; extra == "all"
Requires-Dist: paho-mqtt>=2.0.0; extra == "all"
Requires-Dist: zeroconf>=0.131.0; extra == "all"
Requires-Dist: dynamixel-sdk>=3.7.31; extra == "all"
Requires-Dist: google-genai>=1.0.0; extra == "all"
Requires-Dist: aiohttp>=3.9.0; extra == "all"
Requires-Dist: aiortc>=1.6.0; extra == "all"
Requires-Dist: av>=11.0.0; extra == "all"
Requires-Dist: onnxruntime>=1.17.0; extra == "all"
Requires-Dist: mediapipe>=0.10.0; extra == "all"
Requires-Dist: pytest>=8.0.0; extra == "all"
Requires-Dist: pytest-asyncio>=0.23.0; extra == "all"
Requires-Dist: pytest-cov>=4.1.0; extra == "all"
Requires-Dist: ruff>=0.2.0; extra == "all"
Requires-Dist: qrcode>=7.4.0; extra == "all"
Provides-Extra: dev
Requires-Dist: inspect-robots>=0.58.0; extra == "dev"
Requires-Dist: pytest>=8.0.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
Requires-Dist: ruff>=0.2.0; extra == "dev"
Requires-Dist: qrcode>=7.4.0; extra == "dev"
Requires-Dist: cyclonedx-bom>=4.0; extra == "dev"
Requires-Dist: respx>=0.21; extra == "dev"
Dynamic: license-file

<p align="center">
  <img src="brand/icon-192.png" alt="OpenCastor" width="200"/>
</p>

<h1 align="center">OpenCastor</h1>

<p align="center">
  Productized open-core RCAN runtime — gateway-as-kernel, drivers, fleet, cloud bridge, UI. The most fully-documented RCAN runtime; not the only one.
</p>

<p align="center">
  <b>Peer runtime:</b> opencastor and <a href="https://github.com/RobotRegistryFoundation/robot-md">robot-md</a> are first-class peer RCAN 3.x runtimes against a single <code>ROBOT.md</code> — see <a href="https://github.com/craigm26/opencastor-ops/blob/master/PEER_RUNTIMES.md">PEER_RUNTIMES.md</a> for the side-by-side.
</p>

<p align="center">
  <a href="https://pypi.org/project/opencastor/"><img src="https://img.shields.io/pypi/v/opencastor?color=blue&label=PyPI" alt="PyPI"></a>
  <a href="https://rcan.dev/compatibility"><img src="https://img.shields.io/badge/RCAN-live%20matrix-brightgreen" alt="RCAN compatibility matrix"></a>
  <a href="https://rcan.dev/docs/safety/"><img src="https://img.shields.io/badge/Protocol%2066-94%25-orange" alt="Protocol 66"></a>
  <a href="https://github.com/craigm26/OpenCastor/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-Apache%202.0-green" alt="License"></a>
  <a href="https://github.com/craigm26/OpenCastor/actions"><img src="https://img.shields.io/github/actions/workflow/status/craigm26/OpenCastor/ci.yml?label=CI" alt="CI"></a>
  <a href="https://app.opencastor.com"><img src="https://img.shields.io/badge/Fleet%20UI-app.opencastor.com-orange" alt="Fleet UI"></a>
  <a href="https://docs.opencastor.com"><img src="https://img.shields.io/badge/Docs-docs.opencastor.com-00bcd4" alt="Docs"></a>
  <a href="https://discord.gg/jMjA8B26Bq"><img src="https://img.shields.io/badge/Discord-join-5865F2?logo=discord&logoColor=white" alt="Discord"></a>
</p>

<p align="center">
  <b>94,438 lines of Python · 7,334 tests · Python 3.10–3.13</b>
</p>

---

## What is OpenCastor

OpenCastor is an open-source runtime for embodied AI. It implements the [RCAN open protocol](https://rcan.dev/spec/) and handles the hard parts: safety gates, multi-provider AI routing, hardware drivers, messaging channels, and fleet management.

Point it at any LLM (Gemini, GPT-4.1, Claude, Ollama, and 13 more) and any robot body (Raspberry Pi, Jetson, Arduino, ESP32, LEGO) via a single YAML config. Your robot answers to WhatsApp, Telegram, Discord, Slack, and Home Assistant — and learns from its own experience through the Sisyphus self-improvement loop.

> **RCAN ≠ OpenCastor.** [RCAN](https://rcan.dev) is an independent open protocol — like DNS and ICANN, but for robotics. Any robot can implement RCAN without using OpenCastor. OpenCastor is one implementation that helped inform the spec.

## Quick Start

### 1. Install

```bash
pip install "opencastor>=3.1"
```

> **The `>=3.1` is load-bearing, not decoration.** A bare `pip install
> opencastor` resolves the old CalVer line (`2026.4.23.0`), because under
> PEP 440 a date sorts above `3.x` — and that wheel has no `castor up` in it.
> Every install instruction in this repository uses this exact string. See
> [docs/setup/pairing.md](docs/setup/pairing.md#which-install-command).

### 2. Bring the robot up

```bash
castor up            # one command: scans the bus, writes the units, prints a pairing QR
```

`castor up` is the path the OpenCastor iOS app and the
[flashable Pi image](docs/IMAGE.md) both use. It detects what is on the
I²C bus, picks an archetype, writes four systemd **user** units, and prints a QR
to scan. It starts on **simulated wheels** by design — turning on real PWM is a
deliberate later edit in `gateway-policy.env`.

Prefer the long-form wizard, or have no robot to detect yet?

```bash
castor setup                 # 4-step wizard, writes an rcan.yaml
castor init --shape rc-car   # just a ROBOT.md, shaped like a car
```

`castor init` asks what shape the robot is before anything else — `arm`,
`rc-car` or `sim` — because every default it used to offer described an arm.
The `rc-car` manifest points at `castor up`, which is the only bring-up program
that knows that shape.

The wizard will:
- Name your robot and assign an RRN (Robot Registration Number)
- Generate a config file at `~/.config/opencastor/<name>.rcan.yaml`
- Show a QR code to connect to the Fleet UI at [app.opencastor.com](https://app.opencastor.com)
- Configure your AI brain provider (Gemini, Claude, OpenAI, or local Ollama)

> **Have a [Pollen Microduck](docs/hardware/microduck.md)?** Skip the wizard — one command does everything:
>
> ```bash
> castor duck
> ```
>
> It finds the duck on your network, checks SSH and `robot` group access (printing the exact fix if either is missing), asks `robotd` for live health, and writes the config. Then `castor duck test` makes it walk.

### 3. Start your robot

```bash
# Start the AI brain + REST API (port 8000 standalone; 8081 under `castor up`)
castor gateway --config ~/.config/opencastor/bob.rcan.yaml

# Start the cloud bridge (connects robot to Fleet UI — outbound-only)
castor bridge --config ~/.config/opencastor/bob.rcan.yaml
```

#### Ports — the one table

Every port below comes from `castor/up.py`: three adjacent services at
`--base-port` (default **8080**), plus one fixed helper. Nothing else in this
repository should quote a different number for a `castor up` robot.

| Service | systemd user unit | Port | Answers |
|---|---|---|---|
| Gateway (`robot-md-gateway`) | `<name>-gateway.service` | **8080** (`base + 0`) | `/v1/invoke` with signed receipts — **the port in the pairing QR** |
| Runtime (OpenCastor) | `<name>-castor.service` | **8081** (`base + 1`) | `/health`, `/api/stop`, `/ws/telemetry` |
| Console | `<name>-console.service` | **8082** (`base + 2`) | chat brains, `/surface`, `/gaps` |
| RRF key-resolver stub | `<name>-rrf-stub.service` | **8090** (fixed) | loopback `kid` lookup |

`castor up --base-port 8110` moves the first three to 8110/8111/8112; the RRF
stub does not move, so a second robot on one host needs the stub's port
adjusted by hand. Standalone `castor gateway` (no `castor up`) still defaults to
**8000** — that is a different program on a different port, not this table.

### 4. One-command systemd setup

```bash
castor bridge setup   # generates and optionally installs systemd services
```

### Docker

```bash
docker run -it \
  -v ~/.config/opencastor:/config \
  -e OPENCASTOR_CONFIG=/config/bob.rcan.yaml \
  ghcr.io/craigm26/opencastor:2026.4.1.0 \
  castor gateway
```


<!-- SETUP_CATALOG:BEGIN -->
| Profile | Description | Requires |
|---|---|---|
| `apple_native` | Mac with Apple Silicon (M1–M4) — runs models on-device via Apple Foundation Models. No API key needed. | macOS, Apple Silicon |
| `mlx_local_vision` | Mac with Apple Silicon — open-source models via MLX (Llama, Mistral, Qwen). More model choice than apple_native. | macOS, Apple Silicon |
| `ollama_universal_local` | Any machine — runs local models via Ollama. Works on Mac, Linux, and Windows. | [Ollama](https://ollama.com) installed |

**On Apple Silicon, `apple_native` is the default.** The wizard will ask which Apple model profile fits your use case:

| Apple Profile | Use case | Guardrails |
|---|---|---|
| `apple-balanced` ⭐ | General chat and robot commands — best starting point | Default |
| `apple-creative` | Creative tasks, less restrictive output | Permissive Content Transformations |
| `apple-tagging` | Classifying or labeling objects/scenes | Default |
<!-- SETUP_CATALOG:END -->

## Features

- **Protocol 66 safety** — ESTOP never blocked, local safety always wins, confidence gates run on-device
- **[RCAN protocol](https://rcan.dev/compatibility)** — hybrid signing (ML-DSA-65 + Ed25519), mandatory LoA, canonical JSON wire format, §22-26 compliance builders, BLE/LoRa/MQTT carriers
- **Multi-provider AI** — Gemini, Claude, OpenAI, Ollama, MLX (Apple Silicon), Groq, DeepSeek, and 7 more; hot-swap via YAML
- **Fleet UI** — real-time fleet dashboard at [app.opencastor.com](https://app.opencastor.com); no port forwarding needed
- **SO-ARM101 arm support** — auto-detected via USB, guided setup for follower/leader/bimanual configurations
- **18 hardware presets** — Raspberry Pi, Jetson, Arduino, ESP32, LEGO Mindstorms, OAK-D, LeRobot SO-ARM101, and more
- **Self-improving loop** — Sisyphus PM→Dev→QA→Apply pipeline learns from every episode
- **Messaging channels** — WhatsApp, Telegram, Discord, Slack, Home Assistant, MQTT
- **castor setup wizard** — guided onboarding with QR codes; works headless on Pi

## Architecture

```
[ app.opencastor.com / Fleet UI ]
          │  Firebase / Firestore
          │
   [ Cloud Functions ]            R2RAM enforcement + rate limiting
          │
   [ castor bridge ]              outbound-only Firestore connection
          │
   [ castor gateway ]             FastAPI REST + messaging channels
          │
   ┌──────────────────────┐
   │   Protocol 66 Safety │       ESTOP | confidence gates | bounds
   └──────────────────────┘
          │
   [ Tiered Brain ]               Gemini / Claude / GPT / Ollama / …
          │
   [ RCAN Config + Drivers ]      .rcan.yaml → hardware abstraction
          │
   [ Robot Hardware ]             Pi / Jetson / Arduino / SO-ARM101 / …
```

## [RCAN Protocol](https://rcan.dev/compatibility) Features

- **Replay prevention** — hybrid signatures (ML-DSA-65 + Ed25519) over canonical JSON bodies
- **Level of Assurance (LoA)** — mandatory in the [RCAN protocol](https://rcan.dev/compatibility); gates control-plane operations behind HiTL authorization
- **Canonical JSON wire format** — `rcan.canonical_json(body)` produces byte-identical serialization across Python and TypeScript SDKs
- **§22-26 compliance artifacts** — emit §23 safety benchmarks, §24 IFU, §25 post-market incident reports, §26 EU register entries via `rcan.build_*` builders
- **Federation + constrained transport** — BLE / LoRa / MQTT carriers; RRN-based identity resolution via rcan.dev
- **Post-quantum ready** — NIST FIPS 204 ML-DSA-65 is the primary signing scheme (Q-Day 2029 is NOW)

## castor CLI Reference

| Command | Description |
|---|---|
| `castor setup` | Interactive onboarding wizard — config, RRN, Fleet UI QR code |
| `castor gateway` | Start AI brain + REST API + messaging channels |
| `castor bridge` | Start cloud bridge (Fleet UI connection) |
| `castor scan` | Auto-detect connected hardware (USB, I2C, V4L2) |
| `castor doctor` | System health check — providers, channels, hardware |
| `castor fix` | Auto-fix common configuration issues |
| `castor status` | Provider and channel readiness summary |
| `castor improve` | Run Sisyphus self-improvement on recent episodes |
| `castor audit --verify` | Verify audit chain integrity |
| `castor incidents verify` | Walk the incident log's hash chain across rotations (0 links hold, 1 break, 2 no log) |
| `castor approvals` | Review and approve pending high-risk commands |
| `castor deploy` | Push config to a remote robot over SSH |
| `castor fleet` | Discover and monitor all robots on the local network |
| `castor upgrade` | Pull latest version + pip install + service restart |

Full reference: [docs.opencastor.com/runtime/cli](https://docs.opencastor.com/runtime/cli/)

## Configuration

Minimal `bob.rcan.yaml`:

```yaml
rcan_version: "3.0"
metadata:
  robot_name: bob
agent:
  provider: google
  model: gemini-2.5-flash
drivers:
  - id: wheels
    protocol: pca9685
channels: {}
```

That's it. `castor gateway --config bob.rcan.yaml` starts the REST API, messaging channels, and the self-improving loop.

Swap the AI brain with one line:

```yaml
agent:
  provider: anthropic
  model: claude-sonnet-4-6
```

## Protocol 66

Protocol 66 is RCAN's mandatory safety layer. Current OpenCastor conformance: **94%**.

Key invariants:
- ESTOP delivered at QoS 2 (EXACTLY_ONCE) — never blocked by backpressure
- Local safety always wins — cloud commands pass through the same confidence gates as local commands
- Audit chain required for all flagged commands
- `GuardianAgent` has veto authority over unsafe actions

Stopping a robot and un-stopping it: [`docs/safety/hold.md`](docs/safety/hold.md)
covers the latch file, `castor pause` / `castor resume`, the e-stop clear code
and why a sensor latch clears only at the robot. It is a best-effort software
hold, not a hardware cut.

P66 manifest: [`sbom/`](sbom/) · Full spec: [rcan.dev/docs/safety/](https://rcan.dev/docs/safety/)

## Fleet UI

**[app.opencastor.com](https://app.opencastor.com)** — sign in with Google to see your fleet.

- Real-time status cards for all registered robots
- Robot detail: telemetry, command history, chat-scope instructions
- ESTOP button on every screen
- Consent management — approve/deny R2RAM access requests
- Revocation display — shows if a robot's identity has been revoked
- LoA display — shows operator Level of Assurance on control commands

Robots connect via `castor bridge` (outbound-only Firestore). No open ports on the robot side.

## SO-ARM101 Arm Support

The LeRobot SO-ARM101 6-DOF serial bus servo arm is auto-detected via USB VID/PID (CH340, `0x1A86/0x7523`).

```bash
pip install "opencastor[lerobot]>=3.1"
castor scan                          # detects arm + suggests preset
castor wizard --preset so_arm101     # guided config: follower / leader / bimanual
castor gateway --config so_arm101.rcan.yaml
```

`castor scan` counts connected Feetech boards and automatically suggests the right preset: single arm (follower or leader), or bimanual pair (ALOHA-style). Koch arms use the same detection path.

## Where OpenCastor sits

OpenCastor is **Layer 4** of the OpenCastor stack — the productized
robot-facing runtime. It depends on:

- [`robot-md-gateway`](https://github.com/RobotRegistryFoundation/robot-md-gateway) — Layer 3, the open safety kernel. *Same code in commercial and community deployments.*
- [`continuonai/rcan-spec`](https://github.com/continuonai/rcan-spec) — Layer 5, the wire protocol.
- [Robot Registry Foundation](https://robotregistryfoundation.org) — Layer 6, the neutral registry.

The **safety story is identical** at every tier — hobbyist running
gateway directly, or enterprise running OpenCastor full. What you
pay for is operational ergonomics, fleet scale, compliance prep,
and support.

OpenCastor is a productized open-core RCAN runtime — gateway-as-kernel plus drivers, fleet management, cloud bridge, and commercial support. RCAN-the-protocol is implementation-independent; OpenCastor is the most fully-documented runtime that speaks it.

Everything else in the ecosystem is independent; adopt one, or all seven.

| Layer | Piece | What it is |
|---|---|---|
| **Declaration** | [ROBOT.md](https://github.com/RobotRegistryFoundation/robot-md) | The file a robot ships at its root. YAML frontmatter + markdown prose. Declares identity, capabilities, safety gates. Spec + Python CLI. |
| **Agent bridge** | [robot-md-mcp](https://github.com/RobotRegistryFoundation/robot-md-mcp) | MCP server that exposes a `ROBOT.md` to Claude Code, Claude Desktop, Cursor, Zed, Gemini CLI — any MCP-aware agent. |
| **Wire protocol** | [RCAN](https://rcan.dev/spec/) | How robots, gateways, and planners talk. Signed envelopes, LoA enforcement, PQC crypto. Think HTTP for robots. |
| **Python SDK** | [rcan-py](https://github.com/continuonai/rcan-py) | `pip install rcan` — `RCANMessage`, `RobotURI`, `ConfidenceGate`, `HiTLGate`, `AuditChain`. |
| **TypeScript SDK** | [rcan-ts](https://github.com/continuonai/rcan-ts) | `npm install rcan-ts` — same API surface for Node + browser. |
| **Registry** | [Robot Registry Foundation](https://robotregistryfoundation.org) | Permanent RRN identities. Public resolver at `/r/<rrn>`. Like ICANN for robots. |
| **Productized runtime** ← *this* | [OpenCastor](https://github.com/craigm26/OpenCastor) | **This repo.** Productized open-core RCAN runtime — connects LLM brains to hardware bodies. Safety gates, multi-provider AI routing, 18+ hardware drivers, messaging channels, fleet management. |

See also: the [`ROBOT.md` quickstart](docs/robot-md-claude-code.md) — one command puts a Bob-class robot in Claude Code via the MCP bridge.

## Ecosystem (versions)

| Project | Version |
|---|---|
| **OpenCastor** (this) | v2026.4.17.0 |
| [Fleet UI](https://app.opencastor.com) | live |
| [RCAN Protocol](https://rcan.dev/compatibility) | [live matrix](https://rcan.dev/compatibility) |
| [rcan-py](https://github.com/continuonai/rcan-py) | v2.0.0 |
| [rcan-ts](https://github.com/continuonai/rcan-ts) | v2.0.0 |
| [ROBOT.md](https://github.com/RobotRegistryFoundation/robot-md) | v0.2.0 (schema v1.1) |
| [robot-md-mcp](https://github.com/RobotRegistryFoundation/robot-md-mcp) | v0.1.3 |
| [Robot Registry Foundation](https://robotregistryfoundation.org) | v3.0 |

## Contributing

OpenCastor is Apache 2.0 and community-driven.

- **Discord**: [discord.gg/jMjA8B26Bq](https://discord.gg/jMjA8B26Bq)
- **Issues**: [github.com/craigm26/OpenCastor/issues](https://github.com/craigm26/OpenCastor/issues)
- **PRs**: See [CONTRIBUTING.md](CONTRIBUTING.md)
- **Docs**: [`docs/claude/`](docs/claude/) — structure, API reference, env vars

<!-- BEGIN: ecosystem certification disclaimer (canonical, derived from spec §10) -->
> **Conformance is not certification.**
>
> Conformance to RCAN tracks (L1–L4 protocol, Gateway Authority, HIL Runtime Safety) is *self-asserted via signed bundles* and *independently replayable from those bundles*. Conformance is not certification. Certification requires audit by a qualified third-party body, which is intentionally out of scope for this project in 2026.
<!-- END: ecosystem certification disclaimer -->

<!-- BEGIN: ecosystem authority disclaimer (canonical; revised 2026-10-08 from spec §10 after EV-03; keep identical in robot-md, robot-md-gateway and OpenCastor) -->
> **Where safety is meant to be enforced.**
>
> Physical limits are meant to be enforced at Layer 3 (`robot-md-gateway` and the actuator driver it calls), and only for commands that pass through it. OpenCastor (Layer 4) does not embed the gateway yet, so actuators it drives directly are not covered. Declaration alone (Layer 1) does not enforce safety. Agent host alone (Layer 2) is not the safety boundary. If a deployment lacks Layer 3, no safety claim attaches to it. Layer 3 is not a certified safety function, and hostile-input testing in simulation (October 2026) found motions it does not yet bound.
<!-- END: ecosystem authority disclaimer -->

## License

Apache 2.0 · by [Craig Merry](https://github.com/craigm26)

Implements the [RCAN open protocol](https://rcan.dev/spec/). RCAN is an independent open standard — any robot or runtime can implement it.
