Cursor Rules for Runloop
We provide Cursor rules files (.mdc) that give your AI assistant context about the Runloop SDK — covering devbox lifecycle, file operations, command execution, blueprints, snapshots, tunnels, and more.
Setup
1
Create the rules directory
mkdir -p .cursor/rules
2
Copy the rules for your language
Copy the file below into
.cursor/rules/, keeping the .mdc extension. Cursor reads every
.mdc file in that directory, so both can coexist in a polyglot project.3
Start coding
Cursor will automatically use the rules to provide SDK-aware suggestions and completions.
Python — .cursor/rules/runloop-python-client.mdc
Rules for runloop_api_client, the async Python SDK.
runloop-python-client.mdc
---
description: Runloop client python spec
globs:
alwaysApply: false
---
You are working with runloop_api_client, a Python SDK for deploying and managing remote devboxes for AI agents. Use this guide to properly interact with the SDK.
Devbox Overview
A Devbox is a virtual development environment designed for running AI-generated or arbitrary code in an isolated sandbox. It provides configurable compute resources, supports execution of shell commands, and can be managed via API.
Each Devbox has a unique ID, a status (e.g., running, suspended, or shutdown), and metadata for user-defined settings. It includes launch parameters for customizing resource size, execution behavior, and available ports.
Key attributes:
ID (string, required) – Unique identifier of the Devbox.
Status (enum, required) – Current state of the Devbox (e.g., provisioning, running, shutdown).
Create time (integer, required) – Timestamp (ms) when the Devbox was created.
Launch parameters (object, required) – Includes startup commands, resource configuration, idle timeout, and network settings.
Capabilities (list, required) – Defines supported tools such as computer usage APIs and browser usage.
Blueprint/Snapshot ID (string, optional) – Identifier if created from a predefined Blueprint or Snapshot.
Failure/Shutdown reason (enum, optional) – Reason for termination if applicable (e.g., out of memory, idle shutdown).
Devboxes can be started, suspended, resumed, or shut down, and they support file operations, shell command execution, and network tunneling.
CORE SDK USAGE
Initialize client:
from runloop_api_client import AsyncRunloopSDK
runloop = AsyncRunloopSDK() # API Key is automatically loaded from "RUNLOOP_API_KEY" environment variable
BLUEPRINT OPERATIONS
List Blueprints:
blueprints = await runloop.blueprint.list()
for blueprint in blueprints:
print(blueprint.id)
Create a Blueprint:
blueprint = await runloop.blueprint.create(name="name")
print(blueprint.id)
Retrieve a Blueprint:
blueprint = await runloop.blueprint.from_id("id")
info = await blueprint.get_info()
print(info.id)
Get Blueprint Logs:
blueprint = await runloop.blueprint.from_id("id")
logs = await blueprint.logs()
print(logs.blueprint_id)
DEVBOX OPERATIONS
List Devboxes:
devboxes = await runloop.devbox.list()
for devbox in devboxes:
print(devbox.id)
Create a Devbox:
devbox = await runloop.devbox.create()
print(devbox.id)
Retrieve a Devbox:
devbox = runloop.devbox.from_id("id")
info = await devbox.get_info()
print(info.id)
Suspend a Devbox:
devbox = runloop.devbox.from_id("id")
await devbox.suspend()
Resume a Devbox:
devbox = runloop.devbox.from_id("id")
await devbox.resume()
Shutdown a Devbox:
devbox = runloop.devbox.from_id("id")
await devbox.shutdown()
FILE OPERATIONS
Write File Contents:
devbox = runloop.devbox.from_id("id")
await devbox.file.write(file_path="file_path", contents="contents")
Read File Contents:
devbox = runloop.devbox.from_id("id")
contents = await devbox.file.read(file_path="file_path")
print(contents)
Upload a File:
devbox = runloop.devbox.from_id("id")
file = open("local_file.txt", "rb")
await devbox.file.upload(file_path="file_path", file=file)
Download a File:
devbox = runloop.devbox.from_id("id")
contents = await devbox.file.download(file_path="file_path")
print(contents)
SHELL COMMAND EXECUTION
Execute Command (recommended - waits for completion):
devbox = runloop.devbox.from_id("id")
result = await devbox.cmd.exec("command")
print(await result.stdout())
print(result.exit_code)
Execute with streaming callbacks:
devbox = runloop.devbox.from_id("id")
result = await devbox.cmd.exec(
"command",
stdout=lambda line: print(line),
stderr=lambda line: print(line),
)
Execute Command Asynchronously:
devbox = runloop.devbox.from_id("id")
command = await devbox.cmd.exec_async("command")
result = await command.result()
print(result.exit_code)
NETWORK OPERATIONS
Create a tunnel on a devbox:
devbox = runloop.devbox.from_id("id")
tunnel = await devbox.net.create_tunnel(port=8080)
print(tunnel.url)
Or create a devbox with tunnel enabled:
devbox = await runloop.devbox.create(
tunnel={"auth_mode": "open"}
)
print(devbox.id)
DEVBOX PERSISTENCE
List Snapshots:
snapshots = await runloop.snapshot.list()
for snapshot in snapshots:
print(snapshot.id)
Create a Snapshot:
devbox = runloop.devbox.from_id("id")
snapshot = await devbox.snapshot_disk()
print(snapshot.id)
Delete a Snapshot:
snapshot = await runloop.snapshot.from_id("id")
await snapshot.delete()
DEVBOX OBSERVABILITY
Retrieve Devbox Logs:
devbox = runloop.devbox.from_id("id")
logs = await devbox.logs()
print(logs)
EXECUTION GUIDELINES:
Always shutdown Devboxes after use to free up resources.
Use exec for most commands (recommended - waits for completion).
Use exec_async for long-running commands or when you need streaming output.
Handle API errors using try/except blocks.
Use tunnels for exposing services running inside Devboxes.
Use snapshots to persist Devbox states.
TypeScript — .cursor/rules/runloop-typescript-client.mdc
Rules for @runloop/api-client.
runloop-typescript-client.mdc
---
description: Runloop client typescript spec
globs:
alwaysApply: false
---
You are working with @runloop/api-client, a typescript SDK for deploying and managing remote devboxes for AI agents. Use this guide to properly interact with the SDK.
Devbox Overview
A Devbox is a virtual development environment designed for running AI-generated or arbitrary code in an isolated sandbox. It provides configurable compute resources, supports execution of shell commands, and can be managed via API.
Each Devbox has a unique ID, a status (e.g., running, suspended, or shutdown), and metadata for user-defined settings. It includes launch parameters for customizing resource size, execution behavior, and available ports.
Key attributes:
ID (string, required) – Unique identifier of the Devbox.
Status (enum, required) – Current state of the Devbox (e.g., provisioning, running, shutdown).
Create time (integer, required) – Timestamp (ms) when the Devbox was created.
Launch parameters (object, required) – Includes startup commands, resource configuration, idle timeout, and network settings.
Capabilities (list, required) – Defines supported tools such as computer usage APIs and browser usage.
Blueprint/Snapshot ID (string, optional) – Identifier if created from a predefined Blueprint or Snapshot.
Failure/Shutdown reason (enum, optional) – Reason for termination if applicable (e.g., out of memory, idle shutdown).
Devboxes can be started, suspended, resumed, or shut down, and they support file operations, shell command execution, and network tunneling.
CORE SDK USAGE
Initialize clients:
import { RunloopSDK } from '@runloop/api-client';
const runloop = new RunloopSDK(); //API Key is automatically loaded from "RUNLOOP_API_KEY" environment variable
BLUEPRINT OPERATIONS
List Blueprints:
const blueprints = await runloop.blueprint.list();
for (const blueprint of blueprints) {
console.log(blueprint.id);
}
Create a Blueprint:
const blueprint = await runloop.blueprint.create({ name: 'name' });
console.log(blueprint.id);
Retrieve a Blueprint:
const blueprint = runloop.blueprint.fromId('id');
const blueprintInfo = await blueprint.getInfo();
console.log(blueprintInfo.id);
Get Blueprint Logs:
const blueprint = runloop.blueprint.fromId('id');
const logs = await blueprint.logs();
console.log(logs.blueprint_id);
DEVBOX OPERATIONS
List Devboxes:
const devboxes = await runloop.devbox.list();
for (const devbox of devboxes) {
console.log(devbox.id);
}
Create a Devbox:
const devbox = await runloop.devbox.create();
console.log(devbox.id);
Retrieve a Devbox:
const devbox = runloop.devbox.fromId('id');
const devboxInfo = await devbox.getInfo();
console.log(devboxInfo.id);
Suspend a Devbox:
const devbox = runloop.devbox.fromId('id');
await devbox.suspend();
Resume a Devbox:
const devbox = runloop.devbox.fromId('id');
await devbox.resume(); // Waits until running
Shutdown a Devbox:
const devbox = runloop.devbox.fromId('id');
await devbox.shutdown();
Keep Devbox Alive:
const devbox = runloop.devbox.fromId('id');
await devbox.keepAlive();
FILE OPERATIONS
Write File Contents:
const devbox = runloop.devbox.fromId('id');
await devbox.file.write({ file_path: 'file_path', contents: 'contents' });
Read File Contents:
const devbox = runloop.devbox.fromId('id');
const contents = await devbox.file.read({ file_path: 'file_path' });
console.log(contents);
Upload a File:
const devbox = runloop.devbox.fromId('id');
await devbox.file.upload({ path: 'path' });
Download a File:
const devbox = runloop.devbox.fromId('id');
const response = await devbox.file.download({ path: 'path' });
const content = await response.blob();
console.log(content);
SHELL COMMAND EXECUTION
Execute Command (recommended - waits for completion):
const devbox = runloop.devbox.fromId('id');
const result = await devbox.cmd.exec('command');
console.log(await result.stdout());
console.log(result.exitCode);
Execute with streaming callbacks:
const devbox = runloop.devbox.fromId('id');
const result = await devbox.cmd.exec('command', {
stdout: (line) => console.log(line),
stderr: (line) => console.error(line),
});
Execute Command Asynchronously:
const devbox = runloop.devbox.fromId('id');
const execution = await devbox.cmd.execAsync('command');
const result = await execution.result();
console.log(result.exitCode);
Retrieve Execution Status:
const execution = await devbox.cmd.execAsync('command');
const state = await execution.getState();
console.log(state.status);
NETWORK OPERATIONS
Create a tunnel on a devbox:
const devbox = runloop.devbox.fromId('id');
const tunnel = await devbox.net.createTunnel({ port: 8080 });
console.log(tunnel.url);
Or create a devbox with tunnel enabled:
const devbox = await runloop.devbox.create({ tunnel: { auth_mode: "open" } });
console.log(devbox.id);
Remove a Devbox Tunnel:
const devbox = runloop.devbox.fromId('id');
await devbox.net.removeTunnel({ port: 0 });
Create SSH Key:
const devbox = runloop.devbox.fromId('id');
const sshKey = await devbox.net.createSSHKey();
console.log(sshKey.id);
DEVBOX PERSISTENCE TOOLS
List Disk Snapshots:
const snapshots = await runloop.snapshot.list();
for (const snapshot of snapshots) {
console.log(snapshot.id);
}
Create a Snapshot:
const devbox = runloop.devbox.fromId('id');
const snapshot = await devbox.snapshotDisk();
console.log(snapshot.id);
Create a Devbox from a Snapshot:
const snapshot = runloop.snapshot.fromId('id');
const devbox = await snapshot.createDevbox();
console.log(devbox.id);
Delete a Snapshot:
const snapshot = runloop.snapshot.fromId('id');
await snapshot.delete();
DEVBOX OBSERVABILITY TOOLS
Retrieve Devbox Logs:
const devbox = runloop.devbox.fromId('id');
const logs = await devbox.logs();
console.log(logs);
EXECUTION GUIDELINES:
Always shutdown Devboxes after use to free up resources.
Use exec for most commands (recommended - waits for completion).
Use execAsync for long-running commands or when you need streaming output.
Handle API errors using try/catch blocks.
Use tunnels for exposing services running inside Devboxes.
Use snapshots to persist Devbox states.
These rules are the maintained source of truth for Runloop cursor rules. They cover the current SDK surface including
AsyncRunloopSDK (Python) and RunloopSDK (TypeScript) with auto-loaded API keys from the RUNLOOP_API_KEY environment variable.