This might help some folks with complex workflows: How to Use Cursor-Agent (and/or Claude-Code-SDK) from Inside Cursor IDE

How to Use Cursor-Agent from Inside Cursor IDE

This document explains how to spawn and orchestrate cursor-agent instances from within the Cursor IDE, enabling hierarchical AI orchestration - where Claude running in your IDE can delegate complex tasks to independent agent instances.

This is a bit like cursor agents, except they can work on your own private stuff, instead of being limited to github and cloud files etc.

The Big Picture

┌─────────────────────────────────────────────────────────────────────┐
│                        YOU (Human)                                  │
│                    Types in Cursor IDE                              │
└────────────────────────────┬────────────────────────────────────────┘
                             │
                             ▼
┌─────────────────────────────────────────────────────────────────────┐
│              Claude in Cursor IDE (Opus 4.5)                        │
│         • 300s timeout limit                                        │
│         • Context window limits                                     │
│         • human-input only                                          │
│         • Can use MCP tools (python, browser, etc.)                 │
└────────────────────────────┬────────────────────────────────────────┘
                             │ spawns via Python MCP tool
                             ▼
┌─────────────────────────────────────────────────────────────────────┐
│              cursor-agent instances (Windows or WSL)                │
│         • No timeout (runs until complete)                          │
│         • Fresh context per task                                    │
│         • Can spawn their own sub-agents                            │
│         • Event-driven, not limited by IDE                          │
└────────────────────────────┬────────────────────────────────────────┘
                             │ can spawn more
                             ▼
┌─────────────────────────────────────────────────────────────────────┐
│              Sub-agents for specific tasks                          │
│         • Focused on implementation details                         │
│         • Don't pollute orchestrator's context                      │
│         • Can be Windows or WSL agents                              │
└─────────────────────────────────────────────────────────────────────┘

Why This Matters

Problem: Claude in the Cursor IDE has limitations:

  • 300 second timeout on operations
  • Context window gets exhausted with implementation details
  • Can only respond to your typed input (no event hooks)
  • Long tasks fail or timeout

Solution: Use the Python MCP tool to spawn cursor-agent CLI instances that:

  • Run independently with no timeout
  • Have fresh context windows
  • Can orchestrate their own sub-agents
  • Report results back when done

Prerequisites

Windows cursor-agent (Community Patch)

The official cursor-agent CLI only supports Linux/macOS. For Windows, use the community-patched version:

  1. Download: GitHub - gitcnd/cursor-agent-cli-windows: This is a **community patched** version of the Cursor Agent CLI that runs natively on Windows.
  2. Location: C:\Users\<you>\Downloads\cursor\vibe\cursor_agent_mod\2026.01.02-80e4d9b-windows\
  3. Requires: Node.js 18+ (winget install OpenJS.NodeJS.LTS)

cursor-agent-sdk-python

The Python SDK that wraps the CLI with a clean async interface:

Quick Start: Using from Python MCP Tool

Method 1: Direct Import (Recommended)

import sys
import asyncio

# Add SDK to path
sdk_path = r'C:\Users\cnd\Downloads\cursor\vibe\claude-agent-sdk\cursor-agent-sdk-python\src'
if sdk_path not in sys.path:
    sys.path.insert(0, sdk_path)

from cursor_agent_sdk import query, CursorAgentOptions, AssistantMessage, TextBlock, ResultMessage

async def run_agent(task: str, workspace: str = None):
    """Run a cursor-agent and collect its response."""
    options = CursorAgentOptions(
        cwd=workspace or r'C:\Users\cnd\Downloads\cursor\vibe',
    )
    
    response_parts = []
    async for msg in query(prompt=task, options=options):
        if isinstance(msg, AssistantMessage):
            for block in msg.content:
                if isinstance(block, TextBlock):
                    response_parts.append(block.text)
                    print(block.text, end='', flush=True)  # Stream output
        elif isinstance(msg, ResultMessage):
            print(f'\n[Done in {msg.duration_ms}ms]')
    
    return ''.join(response_parts)

# Run it
result = asyncio.run(run_agent("Create a hello.py file that prints 'Hello World'"))

Method 2: Using the Helper Script

A pre-made helper is saved at:
C:\Users\cnd\AppData\Roaming\AuraFriday\user_data\python_scripts\cursor_agent_helper.py

# Load the helper
with open(r'C:\Users\cnd\AppData\Roaming\AuraFriday\user_data\python_scripts\cursor_agent_helper.py') as f:
    exec(f.read())

# Simple query
result = await ask_cursor_agent("What files are in this directory?")

# With options
result = await ask_cursor_agent(
    prompt="Refactor the logging module",
    model="gpt-4",           # or "claude", "grok", etc.
    auto_approve=True,       # auto-approve file changes
    verbose=True             # print intermediate steps
)

# Synchronous wrapper
result = ask_cursor("Explain this codebase")

Advanced: Multi-Agent Orchestration

Pattern 1: Sequential Task Delegation

async def orchestrate_feature(feature_spec: str):
    """Break a feature into sub-tasks and delegate to agents."""
    
    # Step 1: Planning agent creates task breakdown
    plan = await ask_cursor_agent(
        f"Break this feature into 3-5 implementation tasks. "
        f"Output as numbered list only:\n\n{feature_spec}",
        verbose=False
    )
    
    # Step 2: Parse tasks
    tasks = [line.strip() for line in plan.split('\n') if line.strip() and line[0].isdigit()]
    
    # Step 3: Execute each task with fresh agent
    results = []
    for task in tasks:
        print(f"\n{'='*60}\nExecuting: {task}\n{'='*60}")
        result = await ask_cursor_agent(
            task,
            auto_approve=True,
            cwd=r'C:\Users\cnd\Downloads\cursor\vibe\my_project'
        )
        results.append({'task': task, 'result': result})
    
    return results

Pattern 2: Parallel Agent Execution

import asyncio

async def parallel_code_review(files: list[str]):
    """Review multiple files in parallel using separate agents."""
    
    async def review_file(filepath: str):
        return await ask_cursor_agent(
            f"Review this file for bugs and improvements: {filepath}\n"
            "Be concise. List issues as bullet points.",
            verbose=False
        )
    
    # Run all reviews in parallel
    results = await asyncio.gather(*[review_file(f) for f in files])
    
    return dict(zip(files, results))

Pattern 3: Supervisor Agent with Workers

async def supervised_development(project_goal: str):
    """
    Supervisor pattern: One agent coordinates, others implement.
    This keeps the supervisor's context clean.
    """
    
    # Supervisor creates the plan
    supervisor_prompt = f"""
    You are a development supervisor. Create a detailed implementation plan for:
    {project_goal}
    
    Output a JSON array of tasks, each with:
    - "id": unique identifier
    - "description": what to implement
    - "depends_on": list of task IDs this depends on (or empty)
    - "workspace_path": which folder to work in
    
    Output ONLY valid JSON, no other text.
    """
    
    plan_json = await ask_cursor_agent(supervisor_prompt, verbose=False)
    tasks = json.loads(plan_json)
    
    # Execute tasks respecting dependencies
    completed = set()
    results = {}
    
    while len(completed) < len(tasks):
        # Find tasks ready to run
        ready = [
            t for t in tasks 
            if t['id'] not in completed
            and all(dep in completed for dep in t.get('depends_on', []))
        ]
        
        if not ready:
            break  # No progress possible (circular dependency?)
        
        # Run ready tasks in parallel
        async def execute_task(task):
            result = await ask_cursor_agent(
                task['description'],
                cwd=task.get('workspace_path'),
                auto_approve=True
            )
            return task['id'], result
        
        batch_results = await asyncio.gather(*[execute_task(t) for t in ready])
        
        for task_id, result in batch_results:
            completed.add(task_id)
            results[task_id] = result
    
    return results

Running Long Tasks from Terminal

For very long operations, you can write a Python script and run it in a terminal:

Step 1: Create the orchestrator script

# File: orchestrator.py
import sys
sys.path.insert(0, r'C:\Users\cnd\Downloads\cursor\vibe\claude-agent-sdk\cursor-agent-sdk-python\src')

import asyncio
import json
from datetime import datetime
from cursor_agent_sdk import query, CursorAgentOptions, AssistantMessage, TextBlock, ResultMessage

async def main():
    # Your complex orchestration logic here
    tasks = [
        "Implement user authentication module",
        "Create database migration scripts",
        "Write unit tests for auth module",
        "Update API documentation",
    ]
    
    log_file = f"orchestrator_log_{datetime.now():%Y%m%d_%H%M%S}.json"
    results = []
    
    for i, task in enumerate(tasks):
        print(f"\n[{i+1}/{len(tasks)}] Starting: {task}")
        
        response = []
        async for msg in query(prompt=task, options=CursorAgentOptions(
            cwd=r'C:\path\to\project',
            permission_mode='acceptEdits'
        )):
            if isinstance(msg, AssistantMessage):
                for block in msg.content:
                    if isinstance(block, TextBlock):
                        response.append(block.text)
            elif isinstance(msg, ResultMessage):
                results.append({
                    'task': task,
                    'response': ''.join(response),
                    'duration_ms': msg.duration_ms,
                    'session_id': msg.session_id
                })
        
        # Save progress after each task
        with open(log_file, 'w') as f:
            json.dump(results, f, indent=2)
        print(f"[{i+1}/{len(tasks)}] Complete. Saved to {log_file}")
    
    print(f"\nAll tasks complete! Results in {log_file}")

if __name__ == '__main__':
    asyncio.run(main())

Step 2: Run from terminal

# Windows PowerShell
python orchestrator.py

# Or run in background
Start-Process -NoNewWindow python -ArgumentList "orchestrator.py" -RedirectStandardOutput "out.log"

Cross-Platform: Windows + WSL

The MCP server can run on both Windows and WSL simultaneously. This means:

  1. Windows cursor-agent: Uses the community-patched Node.js version
  2. WSL cursor-agent: Uses the native Linux binary
# Option A: Run on Windows (default)
result = await ask_cursor_agent("task", cwd=r'C:\path\to\project')

# Option B: Run on WSL via subprocess
import subprocess
wsl_result = subprocess.run(
    ['wsl', '-e', 'bash', '-c', 
     'echo "your task" | cursor-agent --print --output-format text agent -'],
    capture_output=True, text=True, cwd='/mnt/c/path/to/project'
)

Session Management

cursor-agent returns a session ID that can be used to resume conversations:

async def resumable_task():
    session_id = None
    
    # First query
    async for msg in query(prompt="Start implementing feature X"):
        if isinstance(msg, ResultMessage):
            session_id = msg.session_id
            print(f"Session: {session_id}")
    
    # Later: resume the session
    if session_id:
        async for msg in query(
            prompt="Continue where we left off",
            options=CursorAgentOptions(resume=session_id)
        ):
            ...

Best Practices

  1. Keep orchestrators lightweight: Don’t put implementation details in the top-level agent. Delegate to sub-agents.

  2. Use fresh contexts for focused work: Each agent starts with a clean context window - use this to your advantage.

  3. Save progress frequently: Long orchestration jobs should checkpoint their state.

  4. Choose appropriate workspaces: Set cwd to the relevant project folder for each agent.

  5. Use auto_approve=True cautiously: Only for trusted, well-defined tasks.

  6. Stream output for visibility: Print agent responses as they arrive to monitor progress.

  7. Handle failures gracefully: Wrap agent calls in try/except and log errors.

Troubleshooting

“cursor-agent not found”

Ensure the Windows patched version is at:
C:\Users\<you>\Downloads\cursor\vibe\cursor_agent_mod\2026.01.02-80e4d9b-windows\index.js

Or specify the path explicitly:

options = CursorAgentOptions(
    cli_path=r'C:\path\to\index.js'
)

“Node.js not found”

Install Node.js 18+:

winget install OpenJS.NodeJS.LTS

Agent takes too long

Consider breaking the task into smaller sub-tasks, or adjusting the model:

options = CursorAgentOptions(model='gpt-4')  # or a faster model

Context overflow in orchestrator

This is exactly what the hierarchical pattern solves! Have your orchestrator delegate implementation details to sub-agents, keeping only high-level status in the orchestrator’s context.

See Also

3 Likes

Epic stuff, especially the community native Windows install. Definitely needed that !!! <3

1 Like