Remote robotics lab
skidbot is a real robot in a real 1.5 × 1.0 m room, with noisy lidar and drifting odometry and no simulator underneath. Take a turn from your browser, then drive it by hand or run your own ROS 2 code on it.

How a turn works
One robot, shared fairly. Everyone waits in the same line, people and agents alike.
Ten minutes on the robot, renewable up to an hour while nobody else is waiting.
Steer by hand with live video and lidar, or run rclpy scripts from the browser.

The hardware
A 3D-printed body on a 16 × 12 cm base. No arm, no gripper, no absolute coordinates. The sensors lie a little, so your code has to cope, same as on every real robot.
Lets the robot spin all day without winding up its cable.
A full 360° 2D scan on /scan. Noisy, like every real one.
Runs ROS 2 and the safety supervisor. Your code never runs here.
Fixed, forward facing, streamed to your browser over WebRTC.
Two motors on an ESP32-C3. Wheel odometry that drifts as it turns.
Write code
Write Python in the browser. It runs in an isolated cloud sandbox for up to 60 seconds, reads the robot's real topics and streams its output back to you. Nine starter challenges get you going:
class Listener(Node):
def __init__(self):
super().__init__("challenge_listener")
self.create_subscription(
LaserScan, "/scan", self.on_scan,
qos_profile_sensor_data)
def on_scan(self, msg: LaserScan):
valid = [r for r in msg.ranges
if math.isfinite(r) and r > MIN_VALID]
if not valid:
return
self.get_logger().info(
f"closest obstacle: {min(valid):.2f} m",
throttle_duration_sec=1.0)For AI agents
Add the MCP server and your agent signs in as you with OAuth. It waits in the same queue and answers to the same safety supervisor as anyone in a browser.
Connect an agentclaude mcp add --transport http roboportal \
https://mcp.roboportal.io/mcpSafety
Every command passes through a supervisor on the robot before it reaches the motors. The keep-out fence and its fail-closed behavior were tested on the real robot, not only in simulation.