> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.scrapybara.com/cursor-rules/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.scrapybara.com/_mcp/server. # Cursor Rules ## .cursorrules #### Python **`.cursorrules`** ```md .cursorrules You are working with Scrapybara, a Python SDK for deploying and managing remote desktop instances for AI agents. Use this guide to properly interact with the SDK. **CORE SDK USAGE:** - Initialize client: from scrapybara import Scrapybara; client = Scrapybara(api_key="KEY") - Instance lifecycle: instance = client.start_ubuntu(timeout_hours=1) instance.pause() # Pause to save resources instance.resume(timeout_hours=1) # Resume work instance.stop() # Terminate and clean up - Instance types: ubuntu_instance = client.start_ubuntu(): supports bash, computer, edit, browser browser_instance = client.start_browser(): supports computer, browser windows_instance = client.start_windows(): supports computer **TYPE IMPORTS:** - Core types: from scrapybara import Scrapybara - Instance types: from scrapybara.client import UbuntuInstance, BrowserInstance, WindowsInstance - Tool types: from scrapybara.tools import Tool, BashTool, ComputerTool, EditTool - Model types: from scrapybara.anthropic import Anthropic - Message types: from pydantic import BaseModel from typing import List, Union, Optional, Any - Error types: from scrapybara.core.api_error import ApiError **CORE INSTANCE OPERATIONS:** - Screenshots: instance.screenshot().base_64_image - Bash commands: instance.bash(command="ls -la") - Mouse control: instance.computer(action="move_mouse", coordinates=[x, y]) - Click actions: instance.computer(action="click_mouse", button="right", coordinates=[x, y]) - Drag actions: instance.computer(action="drag_mouse", path=[[x1, y1], [x2, y2]]) - Scroll actions: instance.computer(action="scroll", coordinates=[x, y], delta_x=0, delta_y=0) - Key actions: instance.computer(action="press_key", keys=[keys]) - Type actions: instance.computer(action="type_text", text="Hello world") - Wait actions: instance.computer(action="wait", duration=3) - Get cursor position: instance.computer(action="get_cursor_position").output - File operations: instance.file.read(path="/path/file"), instance.file.write(path="/path/file", content="data") **ACT SDK (Primary Focus):** - Purpose: Enables building computer use agents with unified tools and model interfaces - Core components: 1. Model: Handles LLM integration (currently Anthropic) from scrapybara.anthropic import Anthropic model = Anthropic() # Or model = Anthropic(api_key="KEY") for own key 2. Tools: Interface for computer interactions - BashTool: Run shell commands - ComputerTool: Mouse/keyboard control - EditTool: File operations tools = [ BashTool(instance), ComputerTool(instance), EditTool(instance), ] 3. Prompt: - system: system prompt, recommend to use UBUNTU_SYSTEM_PROMPT, BROWSER_SYSTEM_PROMPT, WINDOWS_SYSTEM_PROMPT - prompt: simple user prompt - messages: list of messages - Only include either prompt or messages, not both response = client.act( model=Anthropic(), tools=tools, system=UBUNTU_SYSTEM_PROMPT, prompt="Task", on_step=handle_step ) messages = response.messages steps = response.steps text = response.text output = response.output usage = response.usage **MESSAGE HANDLING:** - Response Structure: Messages are structured with roles (user/assistant/tool) and typed content - Content Types: - TextPart: Simple text content TextPart(type="text", text="content") - ImagePart: Base64 or URL images ImagePart(type="image", image="base64...", mime_type="image/png") - ReasoningPart: Model reasoning content ReasoningPart( type="reasoning", id="id", reasoning="reasoning", signature="signature", instructions="instructions" ) - ToolCallPart: Tool invocations ToolCallPart( type="tool-call", tool_call_id="id", tool_name="bash", args={"command": "ls"} ) - ToolResultPart: Tool execution results ToolResultPart( type="tool-result", tool_call_id="id", tool_name="bash", result="output", is_error=False ) **STEP HANDLING:** def handle_step(step: Step): if step.reasoning_parts: print(f"Reasoning: {step.reasoning_parts}") if step.text: print(f"Text: {step.text}") if step.tool_calls: for call in step.tool_calls: print(f"Tool: {call.tool_name}") if step.tool_results: for result in step.tool_results: print(f"Result: {result.result}") print(f"Tokens: {step.usage.total_tokens if step.usage else 'N/A'}") **STRUCTURED OUTPUT:** Use the schema parameter to define a desired structured output. The response's output field will contain the validated typed data returned by the model. class HNSchema(BaseModel): class Post(BaseModel): title: str url: str points: int posts: List[Post] response = client.act( model=Anthropic(), tools=tools, schema=HNSchema, system=SYSTEM_PROMPT, prompt="Get the top 10 posts on Hacker News", ) posts = response.output.posts **TOKEN USAGE:** - Track token usage through TokenUsage objects - Fields: prompt_tokens, completion_tokens, total_tokens - Available in both Step and ActResponse objects **EXAMPLE:** from scrapybara import Scrapybara from scrapybara.anthropic import Anthropic from scrapybara.prompts import UBUNTU_SYSTEM_PROMPT from scrapybara.tools import BashTool, ComputerTool, EditTool client = Scrapybara() instance = client.start_ubuntu() instance.browser.start() response = client.act( model=Anthropic(), tools=[ BashTool(instance), ComputerTool(instance), EditTool(instance), ], system=UBUNTU_SYSTEM_PROMPT, prompt="Go to the YC website and fetch the HTML", on_step=lambda step: print(f"{step}\n"), ) messages = response.messages steps = response.steps text = response.text output = response.output usage = response.usage instance.browser.stop() instance.stop() **EXECUTION PATTERNS:** 1. Basic agent execution: response = client.act( model=Anthropic(), tools=tools, system="System context here", prompt="Task description" ) 2. Browser automation: cdp_url = instance.browser.start().cdp_url auth_state_id = instance.browser.save_auth(name="default").auth_state_id # Save auth instance.browser.authenticate(auth_state_id=auth_state_id) # Reuse auth 3. File management: instance.file.write("/tmp/data.txt", "content") content = instance.file.read("/tmp/data.txt").content 4. Environment variables: instance.env.set({"API_KEY": "value"}) instance.env.get().variables instance.env.delete(["VAR_NAME"]) **ERROR HANDLING:** from scrapybara.core.api_error import ApiError try: client.start_ubuntu() except ApiError as e: print(f"Error {e.status_code}: {e.body}") **IMPORTANT GUIDELINES:** - Always stop instances after use to prevent unnecessary billing - Use async client (AsyncScrapybara) for non-blocking operations - Handle API errors with try/except ApiError blocks - Default timeout is 60s; customize with timeout parameter or request_options - Instance auto-terminates after 1 hour by default - For browser operations, always start browser before BrowserTool usage - Prefer bash commands over GUI interactions for launching applications ``` #### TypeScript **`.cursorrules`** ```md .cursorrules You are working with Scrapybara, a TypeScript SDK for deploying and managing remote desktop instances for AI agents. Use this guide to properly interact with the SDK. **CORE SDK USAGE:** - Initialize client: import { ScrapybaraClient } from "scrapybara"; const client = new ScrapybaraClient({ apiKey: "KEY" }); - Instance lifecycle: const instance = await client.startUbuntu({ timeoutHours: 1 }); await instance.pause(); // Pause to save resources await instance.resume({ timeoutHours: 1 }); // Resume work await instance.stop(); // Terminate and clean up - Instance types: const ubuntuInstance = client.startUbuntu(); // supports bash, computer, edit, browser const browserInstance = client.startBrowser(); // supports computer, browser const windowsInstance = client.startWindows(); // supports computer **TYPE IMPORTS:** - Core types: import { ScrapybaraClient, UbuntuInstance, BrowserInstance, WindowsInstance } from "scrapybara"; - Tool types: import { bashTool, computerTool, editTool } from "scrapybara/tools"; - Model types: import { anthropic } from "scrapybara/anthropic"; - Message types: import { z } from "zod"; - Error types: import { ScrapybaraError } from "scrapybara"; - Request/Response types: import { Scrapybara } from "scrapybara"; // Namespace containing all request/response types **CORE INSTANCE OPERATIONS:** - Screenshots: const base64Image = await instance.screenshot().base64Image; - Bash commands: await instance.bash({ command: "ls -la" }); - Mouse control: await instance.computer({ action: "move_mouse", coordinates: [x, y] }); - Click actions: await instance.computer({ action: "click_mouse", button: "right", coordinates: [x, y] }); - Drag actions: await instance.computer({ action: "drag_mouse", path: [[x1, y1], [x2, y2]] }); - Scroll actions: await instance.computer({ action: "scroll", coordinates: [x, y], delta_x: 0, delta_y: 0 }); - Key actions: await instance.computer({ action: "press_key", keys: ["a", "b", "c"] }); - Type actions: await instance.computer({ action: "type_text", text: "Hello world" }); - Wait actions: await instance.computer({ action: "wait", duration: 3 }); - Get cursor position: await instance.computer({ action: "get_cursor_position" }); - File operations: await instance.file.read({ path: "/path/file" }), await instance.file.write({ path: "/path/file", content: "data" }); **ACT SDK (Primary Focus):** - Purpose: Enables building computer use agents with unified tools and model interfaces - Core components: 1. Model: Handles LLM integration (currently Anthropic) import { anthropic } from "scrapybara/anthropic"; const model = anthropic(); // Or model = anthropic({ apiKey: "KEY" }) for own key 2. Tools: Interface for computer interactions - bashTool: Run shell commands - computerTool: Mouse/keyboard control - editTool: File operations const tools = [ bashTool(instance), computerTool(instance), editTool(instance), ]; 3. Prompt: - system: system prompt, recommend to use UBUNTU_SYSTEM_PROMPT, BROWSER_SYSTEM_PROMPT, WINDOWS_SYSTEM_PROMPT - prompt: simple user prompt - messages: list of messages - Only include either prompt or messages, not both const { messages, steps, text, output, usage } = await client.act({ model: anthropic(), tools, system: UBUNTU_SYSTEM_PROMPT, prompt: "Task", onStep: handleStep }); **MESSAGE HANDLING:** - Response Structure: Messages are structured with roles (user/assistant/tool) and typed content - Content Types: - TextPart: Simple text content { type: "text", text: "content" } - ImagePart: Base64 or URL images { type: "image", image: "base64...", mimeType: "image/png" } - ReasoningPart: Model reasoning content { type: "reasoning", id: "id", reasoning: "reasoning", signature: "signature", instructions: "instructions" } - ToolCallPart: Tool invocations { type: "tool-call", toolCallId: "id", toolName: "bash", args: { command: "ls" } } - ToolResultPart: Tool execution results { type: "tool-result", toolCallId: "id", toolName: "bash", result: "output", isError: false } **STEP HANDLING:** const handleStep = (step: Step) => { console.log(`Text: ${step.text}`); if (step.toolCalls) { for (const call of step.toolCalls) { console.log(`Tool: ${call.toolName}`); } } if (step.toolResults) { for (const result of step.toolResults) { console.log(`Result: ${result.result}`); } } console.log(`Tokens: ${step.usage?.totalTokens ?? 'N/A'}`); }; **STRUCTURED OUTPUT:** Use the schema parameter to define a desired structured output. The response's output field will contain the validated typed data returned by the model. const schema = z.object({ posts: z.array(z.object({ title: z.string(), url: z.string(), points: z.number(), })), }); const { output } = await client.act({ model: anthropic(), tools, schema, system: UBUNTU_SYSTEM_PROMPT, prompt: "Get the top 10 posts on Hacker News", }); const posts = output.posts; **TOKEN USAGE:** - Track token usage through TokenUsage objects - Fields: promptTokens, completionTokens, totalTokens - Available in both Step and ActResponse objects **EXAMPLE:** import { ScrapybaraClient } from "scrapybara"; import { anthropic } from "scrapybara/anthropic"; import { UBUNTU_SYSTEM_PROMPT } from "scrapybara/prompts"; import { bashTool, computerTool, editTool } from "scrapybara/tools"; const client = new ScrapybaraClient(); const instance = await client.startUbuntu(); await instance.browser.start(); const { messages, steps, text, output, usage } = await client.act({ model: anthropic(), tools: [ bashTool(instance), computerTool(instance), editTool(instance), ], system: UBUNTU_SYSTEM_PROMPT, prompt: "Go to the YC website and fetch the HTML", onStep: (step) => console.log(`${step}\n`), }); await instance.browser.stop(); await instance.stop(); **EXECUTION PATTERNS:** 1. Basic agent execution: const { messages, steps, text, output, usage } = await client.act({ model: anthropic(), tools, system: "System context here", prompt: "Task description" }); 2. Browser automation: const cdpUrl = await instance.browser.start().cdpUrl; const authStateId = await instance.browser.saveAuth({ name: "default" }).authStateId; // Save auth await instance.browser.authenticate({ authStateId }); // Reuse auth 3. File management: await instance.file.write({ path: "/tmp/data.txt", content: "content" }); const content = await instance.file.read({ path: "/tmp/data.txt" }).content; 4. Environment variables: await instance.env.set({ API_KEY: "value" }); const vars = await instance.env.get().variables; await instance.env.delete(["VAR_NAME"]); **ERROR HANDLING:** import { ApiError } from "scrapybara/core"; try { await client.startUbuntu(); } catch (e) { if (e instanceof ApiError) { console.error(`Error ${e.statusCode}: ${e.body}`); } } **IMPORTANT GUIDELINES:** - Always stop instances after use to prevent unnecessary billing - Use async/await for all operations as they are asynchronous - Handle API errors with try/catch blocks - Default timeout is 60s; customize with timeout parameter or requestOptions - Instance auto-terminates after 1 hour by default - For browser operations, always start browser before browserTool usage - Prefer bash commands over GUI interactions for launching applications ``` ## llms-full.txt Need more context? Check out [llms-full.txt](/llms-full.txt). > Recommended .cursorrules for working with Cursor