New: Python SDK

# Secure sandboxes that boot in milliseconds. Your data stays.

Give your AI agents and scripts a safe place to run. Every sandbox is completely isolated, boots instantly, and syncs your files to the cloud automatically. Perfect for agents, scheduled jobs, and anything that needs to run without risk.

Quickstart API Reference
CLI, Python, and Node.js — pick your tool. Sandboxes in ~300ms. Files persist to the cloud between runs.

    mags run 'echo Hello World'

    mags run -w myproject 'pip install flask'
    mags ssh myproject

Run a script, keep your files, then jump in with SSH.

    from mags import Mags

    m = Mags()
    result = m.run_and_wait("echo Hello World")
    print(result["status"])  # "completed"

pip install magpie-mags

    const Mags = require('@magpiecloud/mags');
    const mags = new Mags();

    const result = await mags.runAndWait('echo Hello World');
    console.log(result.logs);

npm install @magpiecloud/mags

Quickstart

## Three steps. Your first sandbox in under a minute.

### 1. Install

    npm install -g @magpiecloud/mags

### 2. Authenticate

    mags login

Or set a token directly:

    export MAGS_API_TOKEN="your-token"

### 3. Run

    mags run 'echo Hello World'

Add `-w myproject` to keep files between runs, synced to the cloud.

### 1. Install

    pip install magpie-mags

### 2. Set your token

    export MAGS_API_TOKEN="your-token"

Or pass it directly: `Mags(api_token="...")`

### 3. Run

    from mags import Mags

    m = Mags()
    result = m.run_and_wait("echo Hello World")
    for log in result["logs"]:
        print(log["message"])

### 1. Install

    npm install @magpiecloud/mags

### 2. Set your token

    export MAGS_API_TOKEN="your-token"

Or pass it directly: `new Mags({ apiToken: "..." })`

### 3. Run

    const Mags = require('@magpiecloud/mags');
    const mags = new Mags();

    const result = await mags.runAndWait('echo Hello');
    console.log(result.status); // "completed"

Usage Patterns

## Run agents. Schedule jobs. Deploy apps. All sandboxed.

### Install

    npm install -g @magpiecloud/mags
    mags login

### Commands

Command | Description
--- | ---
`mags run <script>` | Execute a script in a fresh sandbox
`mags ssh <workspace>` | SSH into a sandbox (auto-starts if needed)
`mags list` | List recent jobs
`mags status <id>` | Get job status
`mags logs <id>` | Get job output
`mags stop <id>` | Stop a running job
`mags sync <workspace>` | Sync workspace to the cloud now
`mags url <id> [port]` | Enable public URL access
`mags workspace list` | List persistent workspaces
`mags workspace delete <id>` | Delete workspace + cloud data
`mags cron add [opts] <script>` | Create a scheduled cron job
`mags cron list` | List cron jobs
`mags cron remove <id>` | Delete a cron job

### Run Flags

Flag | Description
--- | ---
`-w, --workspace <id>` | Keep files across runs (synced to the cloud)
`--base <workspace>` | Clone a workspace as a starting point (read-only)
`-p, --persistent` | Keep sandbox alive after script (sleeps when idle)
`--no-sleep` | Never auto-sleep this VM (requires `-p`)
`-e, --ephemeral` | No cloud sync — fastest execution
`-f, --file <path>` | Upload file(s) into the sandbox (repeatable)
`-n, --name <name>` | Name the job for easy reference
`--url` | Enable public HTTPS URL (requires `-p`)
`--port <port>` | Port to expose for URL (default: 8080)
`--startup-command <cmd>` | Command to run when sandbox wakes from sleep

### Examples

    # Run a one-off command
    mags run 'echo Hello World && uname -a'

    # Persistent workspace — files survive across runs
    mags run -w myproject 'pip install flask requests'
    mags run -w myproject 'python3 app.py'

    # Base image — create a golden image, sync it, then reuse
    mags run -w golden -p 'apt install -y nodejs && npm install -g typescript'
    mags sync golden                                # persist to cloud
    mags run --base golden 'npm test'               # read-only, changes discarded
    mags run --base golden -w fork-1 'npm test'     # fork: load golden, save to fork-1

    # SSH into a workspace (auto-starts sandbox if needed)
    mags ssh myproject

    # Persistent sandbox with public URL
    mags run -w webapp -p --url --port 8080 \
      --startup-command 'python3 -m http.server 8080' \
      'python3 -m http.server 8080'

    # Always-on sandbox (never auto-sleeps)
    mags run -w worker -p --no-sleep 'python3 worker.py'

    # Upload files and run
    mags run -f script.py -f data.csv 'python3 script.py'

    # Ephemeral (fastest — no cloud sync)
    mags run -e 'uname -a && df -h'

    # Cron job
    mags cron add --name backup --schedule "0 0 * * *" \
      -w backups 'tar czf backup.tar.gz /data'

### Install

    pip install magpie-mags
    export MAGS_API_TOKEN="your-token"

### Methods

Method | Description
--- | ---
`run(script, **opts)` | Submit a job (returns immediately)
`run_and_wait(script, **opts)` | Submit + block until complete
`status(request_id)` | Get job status
`logs(request_id)` | Get job logs
`list_jobs()` | List recent jobs
`enable_access(id, port)` | Enable URL or SSH access
`upload_files(paths)` | Upload files, returns file IDs
`list_workspaces()` | List persistent workspaces
`delete_workspace(id)` | Delete workspace + cloud data
`cron_create(**opts)` | Create a cron job
`cron_list()` | List cron jobs
`cron_delete(id)` | Delete a cron job
`usage(window_days)` | Get usage stats

### Run Options

Parameter | Description
--- | ---
`workspace_id` | Keep files across runs (synced to the cloud)
`base_workspace_id` | Mount a workspace read-only as base image
`persistent` | Keep sandbox alive after script completes
`no_sleep` | Never auto-sleep (requires `persistent=True`)
`ephemeral` | No cloud sync (fastest)
`file_ids` | List of uploaded file IDs to include
`startup_command` | Command to run when sandbox wakes

### Examples

    from mags import Mags
    m = Mags()  # reads MAGS_API_TOKEN from env

    # Run a command and wait
    result = m.run_and_wait("echo Hello World")
    print(result["status"])    # "completed"

    # Persistent workspace
    m.run_and_wait("pip install flask", workspace_id="myproject")
    m.run_and_wait("python3 app.py", workspace_id="myproject")

    # Base image
    m.run_and_wait("npm test", base_workspace_id="golden")
    m.run_and_wait("npm test", base_workspace_id="golden", workspace_id="fork-1")

    # SSH access
    job = m.run("sleep 3600", workspace_id="dev", persistent=True)
    ssh = m.enable_access(job["request_id"], port=22)
    print(f"ssh root@{ssh['ssh_host']} -p {ssh['ssh_port']}")

    # Public URL
    job = m.run("python3 -m http.server 8080",
        workspace_id="webapp", persistent=True,
        startup_command="python3 -m http.server 8080")
    access = m.enable_access(job["request_id"], port=8080)

    # Always-on sandbox (never auto-sleeps)
    job = m.run("python3 worker.py",
        workspace_id="worker", persistent=True, no_sleep=True)

    # Upload files
    file_ids = m.upload_files(["script.py", "data.csv"])
    m.run_and_wait("python3 /uploads/script.py", file_ids=file_ids)

    # Workspaces
    workspaces = m.list_workspaces()
    m.delete_workspace("myproject")

    # Cron
    m.cron_create(name="backup", cron_expression="0 0 * * *",
        script="tar czf backup.tar.gz /data", workspace_id="backups")

View on PyPI →

### Install

    npm install @magpiecloud/mags
    export MAGS_API_TOKEN="your-token"

### Methods

Method | Description
--- | ---
`run(script, opts)` | Submit a job (returns immediately)
`runAndWait(script, opts)` | Submit + block until complete
`status(requestId)` | Get job status
`logs(requestId)` | Get job logs
`listJobs()` | List recent jobs
`enableAccess(id, { port })` | Enable URL or SSH access
`uploadFile(path)` | Upload a file, returns file ID
`cronCreate(opts)` | Create a cron job
`cronList()` | List cron jobs
`cronDelete(id)` | Delete a cron job
`usage(windowDays)` | Get usage stats

### Run Options

Parameter | Description
--- | ---
`workspaceId` | Keep files across runs (synced to the cloud)
`baseWorkspaceId` | Mount a workspace read-only as base image
`persistent` | Keep sandbox alive after script completes
`noSleep` | Never auto-sleep (requires `persistent: true`)
`ephemeral` | No cloud sync (fastest)
`fileIds` | Array of uploaded file IDs to include
`startupCommand` | Command to run when sandbox wakes

### Examples

    const Mags = require('@magpiecloud/mags');
    const mags = new Mags({ apiToken: process.env.MAGS_API_TOKEN });

    // Run a command and wait
    const result = await mags.runAndWait('echo Hello World');
    console.log(result.status);   // "completed"

    // Persistent workspace
    await mags.runAndWait('pip install flask', { workspaceId: 'myproject' });
    await mags.runAndWait('python3 app.py', { workspaceId: 'myproject' });

    // Base image
    await mags.runAndWait('npm test', { baseWorkspaceId: 'golden' });
    await mags.runAndWait('npm test', { baseWorkspaceId: 'golden', workspaceId: 'fork-1' });

    // SSH access
    const job = await mags.run('sleep 3600', { workspaceId: 'dev', persistent: true });
    const ssh = await mags.enableAccess(job.requestId, { port: 22 });
    console.log(`ssh root@${ssh.sshHost} -p ${ssh.sshPort}`);

    // Public URL
    const webJob = await mags.run('python3 -m http.server 8080', {
      workspaceId: 'webapp', persistent: true,
      startupCommand: 'python3 -m http.server 8080',
    });
    const access = await mags.enableAccess(webJob.requestId, { port: 8080 });
    console.log(access.url);

    // Always-on sandbox (never auto-sleeps)
    await mags.run('python3 worker.py', {
      workspaceId: 'worker', persistent: true, noSleep: true,
    });

    // Upload files
    const fileId = await mags.uploadFile('script.py');
    await mags.runAndWait('python3 /uploads/script.py', { fileIds: [fileId] });

    // Cron
    await mags.cronCreate({
      name: 'backup', cronExpression: '0 0 * * *',
      script: 'tar czf backup.tar.gz /data', workspaceId: 'backups',
    });

View on npm →

Persistent Workspaces

## Your files survive. Every sandbox starts clean.

### Backed up to object storage

- Files, packages, and configs persist automatically
- Optional backup to S3-compatible object storage
- Clone a workspace as a read-only base for new sandboxes
- Survives reboots, sleep, and agent restarts

### Fully isolated

- Every sandbox runs in its own isolated environment
- No cross-user access — workspaces are private
- Processes, memory, and ports reset between runs
- Agents can't escape or affect the host

SDKs + API

## Let your agents spin up sandboxes programmatically.

### Install

    pip install magpie-mags

### Quick example

    from mags import Mags

    m = Mags()  # reads MAGS_API_TOKEN from env

    # Run and wait
    result = m.run_and_wait(
        "echo Hello from a sandbox!",
        workspace_id="demo",
    )
    print(result["status"])
    for log in result["logs"]:
        print(log["message"])

### Available methods

- `run(script, **opts)` — submit a job
- `run_and_wait(script, **opts)` — submit + block
- `status(request_id)` — get job status
- `logs(request_id)` — get job logs
- `list_jobs()` — list recent jobs
- `enable_access(id, port)` — URL or SSH
- `upload_files(paths)` — upload files
- `list_workspaces()` — list workspaces
- `delete_workspace(id)` — delete workspace
- `cron_create(**opts)` — create cron
- `cron_list()` / `cron_delete(id)`
- `usage(window_days)` — usage stats

PyPI →

### Install

    npm install @magpiecloud/mags

### Quick example

    const Mags = require('@magpiecloud/mags');

    const mags = new Mags({
      apiToken: process.env.MAGS_API_TOKEN,
    });

    const result = await mags.runAndWait('echo Hello World');
    console.log(result.status);
    console.log(result.logs);

### Available methods

- `run(script, opts)` — submit a job
- `runAndWait(script, opts)` — submit + block
- `status(requestId)` — get job status
- `logs(requestId)` — get job logs
- `listJobs()` — list recent jobs
- `enableAccess(id, { port })` — URL or SSH
- `uploadFile(path)` — upload a file
- `cronCreate(opts)` — create cron
- `cronList()` / `cronDelete(id)`
- `usage(windowDays)` — usage stats

npm →

### Submit a job

    curl -X POST https://api.magpiecloud.com/api/v1/mags-jobs \
      -H "Authorization: Bearer $MAGS_API_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "script": "echo Hello World",
        "type": "inline",
        "workspace_id": "myproject"
      }'

### Endpoints

- `POST /mags-jobs` — submit job
- `GET /mags-jobs` — list jobs
- `GET /mags-jobs/:id/status` — status
- `GET /mags-jobs/:id/logs` — logs
- `POST /mags-jobs/:id/access` — URL/SSH
- `PATCH /mags-jobs/:id` — update
- `POST /mags-files` — upload file
- `GET /mags-workspaces` — list ws
- `DELETE /mags-workspaces/:id` — delete ws
- `POST /mags-cron` — create cron
- `GET /mags-cron` — list cron
- `DELETE /mags-cron/:id` — delete cron

Full API reference →

Resources

## Everything you need to get started.

### Login

Sign in with Google or email to access jobs and tokens.

Open login

### Usage + jobs

View usage summaries and recent jobs.

Open usage

### API tokens

Create and manage tokens for CLI and SDK access.

Open tokens

### Claude skill

Install the Claude Code skill to run sandboxes from Claude.

Open Claude skill

### Cookbook

Copy ready-to-run recipes for common workflows.

Open cookbook