# Documentation

Everything you need to get started with Mags — from installation to advanced workspace management.

# Overview

Mags gives AI agents and developers secure, isolated sandboxes (microVMs) that boot in <100ms. Workspaces persist automatically to the cloud. Run code, schedule jobs, and let agents work safely.

Mags is available via four interfaces, so you can pick whatever fits your workflow:

- CLI — quick tasks, scripting, and interactive SSH sessions
- Python SDK — integrate sandboxes into Python agents and pipelines
- Node.js SDK — integrate sandboxes into JavaScript/TypeScript projects
- REST API — full programmatic control from any language (see API Reference)

Every sandbox is a real microVM with its own kernel, filesystem, and network stack — not a container. This means full isolation with no risk of breakout, making Mags ideal for running untrusted code from AI agents.

## Quickstart

Get up and running in under 60 seconds.

### 1. Install the CLI

Terminal

    npm install -g @magpiecloud/mags

### 2. Authenticate

Terminal

    mags login

This opens your browser for a one-time authentication flow. Once complete, your session is saved locally.

### 3. Run your first sandbox

Terminal

    mags run 'echo Hello World'

That's it. Mags spins up an isolated microVM, executes your command, streams the output, and tears down the sandbox. The entire cycle takes under a second for simple commands.

## Authentication

Mags supports two authentication methods:

### Browser login (interactive)

Run `mags login` to open a browser-based login flow. This is the recommended approach for local development and CLI usage. Your session token is stored securely on disk.

### API token (programmatic)

For CI/CD pipelines, servers, and SDK usage, generate an API token from the Dashboard and set it as an environment variable:

Terminal

    export MAGS_TOKEN=your-token

Both the Python and Node.js SDKs will automatically pick up the `MAGS_TOKEN` environment variable. You can also pass it explicitly when initializing the client.

## Running Scripts

The `mags run` command is the primary way to execute code in a sandbox. It accepts inline commands, script files, and a wide range of flags for customizing behavior.

### Inline script

Terminal

    mags run 'echo Hello World'

### Script file

Terminal

    mags run script.sh

### Named workspace

Assign a name to the workspace so you can reconnect to it later:

Terminal

    mags run -w name 'command'

### Persistent workspace

Add `-p` to sync the workspace to the cloud so it survives restarts:

Terminal

    mags run -p 'command'

### With file upload

Upload local files into the sandbox before execution:

Terminal

    mags run -f file.txt 'command'

## Sandboxes

Manage sandbox lifecycle directly from the CLI.

### Create a sandbox

Terminal

    mags new name

### SSH into a sandbox

Terminal

    mags ssh name

### Stop a sandbox

Terminal

    mags stop name

### List all sandboxes

Terminal

    mags list

### View logs

Terminal

    mags logs name

## Management

Commands for managing workspaces, URLs, and scheduled jobs.

### Workspaces

Terminal

    # List all workspaces
    mags workspace list

    # Delete a workspace
    mags workspace delete name

### Public URLs

Terminal

    # Enable a public URL for a sandbox
    mags url enable name

    # Set a custom alias
    mags url alias name alias

### Cron jobs

Terminal

    # Create a cron job (runs every 5 minutes)
    mags cron create '*/5 * * * *' 'command'

## Flags

Complete reference for all `mags run` flags.

Flag | Description
--- | ---
`-n, --name <name>` | Set the job/workspace name (used as both). `-w, --workspace` is an alias.
`-p, --persistent` | Keep the VM alive after the script completes, and sync its workspace to the cloud.
`--no-sleep` | Never auto-sleep this VM. Requires `-p`.
`--base <workspace>` | Mount an existing workspace read-only as a base image (copy-on-write).
`-e, --ephemeral` | No workspace, no S3 sync — fastest execution. Cannot combine with `-n`, `-p`, or `--base`.
`-f, --file <path>` | Upload file(s) into the VM before execution. Repeatable.
`--disk <GB>` | Custom disk size in GB (default: 2).
`--url` | Enable a public HTTPS URL for the VM. Requires `-p`.
`--port <port>` | Port to expose for the public URL (default: 8080).
`--startup-command <cmd>` | Command to run when the VM wakes from sleep.
`--server` | Scale-to-zero server mode — implies `-p`, freezes the VM when idle and wakes it on the next request.
`-t, --type <type>` | VM rootfs type: `standard`, `claude`, or `pi`.

# Deploy

`mags deploy` turns any Docker image into a managed, always-reachable Mags app with a public URL — no Dockerfile rewrites, no orchestration to manage. Mags pulls the image, builds a microVM rootfs, boots it, and exposes it at `https://<name>.apps.mags.run`. By default the app runs in scale-to-zero server mode: it freezes when idle and wakes on the next request.

Terminal

    # Deploy an image and get a public URL
    mags deploy --image nginx:latest --name my-nginx --port 80

## Deploy Flags

Flag | Description
--- | ---
`-i, --image <image>` | Docker image to deploy (required).
`-n, --name <name>` | Deployment name (required). Determines the subdomain.
`-p, --port <port>` | App port to expose (default: 8080).
`-e, --env <KEY=VALUE>` | Set an environment variable. Repeatable.
`--no-server` | Always-on mode — never freeze on idle (default is freeze-on-idle server mode).
`--cmd <cmd>` | Override the image's Docker `CMD`.
`--entrypoint <ep>` | Override the image's Docker `ENTRYPOINT`.
`--heavy` | Lazy-load very large images (>5GB) from object storage. See below.
`-V, --volume <spec>` | Attach a persistent volume. Repeatable. See Volumes.

Terminal

    # Node API with env vars on port 3000
    mags deploy -i node:20 -n my-api -p 3000 -e "DB_URL=postgres://..." -e "SECRET=xyz"

    # Always-on (no freeze on idle)
    mags deploy -i node:20 -n my-api -p 3000 --no-server

## Heavy Images (`--heavy`)

Large images — multi-gigabyte ML/CUDA stacks like `pytorch/pytorch` — would be slow to materialize as a full rootfs on every boot. The `--heavy` flag instead packs the image into chunks in object storage (R2) and lazily streams the rootfs over the network at boot, so only the blocks the app actually reads are fetched. Heavy deploys get a longer build window (up to ~30 min for the initial pack & upload).

Terminal

    mags deploy --image pytorch/pytorch:latest --name ml --port 80 --heavy

Note: heavy deploys require object-storage (R2) credentials to be configured on the orchestrator. If they're missing, the deploy fails fast with a clear error. Once ready, the CLI reports the R2 prefix backing your app.

## Volumes (`-V, --volume`)

Attach persistent storage to a deployment so state survives restarts, freezes, and even cross-host failover. Volumes are specified as `type:name:path` and the flag is repeatable.

Form | Description
--- | ---
`bucket:NAME:PATH` | Shared, durable, object-storage-backed volume. Two deploys that mount the same `NAME` share its data. Mounted at `PATH` inside the VM.
`local:SIZE:PATH` | Ephemeral local disk of the given size (e.g. `5G`). Coming soon — not yet available.

Terminal

    mags deploy -i my/app:latest -n hermes --volume bucket:hermes-state:/opt/data

## Rollback, Freeze & Env

Each deploy creates a new version, so you can roll back instantly. Inspect and manage a running app with:

Terminal

    # Roll back to the previous version
    mags rollback <name>

    # Freeze a running app (force it to sleep)
    mags freeze <name>

    # Manage environment variables
    mags env set <name> KEY=VALUE
    mags env list <name>
    mags env unset <name> KEY

    # SSH in or tail logs
    mags ssh <name>
    mags logs <name>

## Workspaces

Workspaces define how your sandbox's filesystem is managed. Mags supports three distinct modes, each optimized for different use cases.

### Local (default)

The default mode. The workspace lives on the host machine's local disk. It's the fastest option because there is no cloud sync overhead. When the sandbox stops, the local workspace is cleared.

Terminal

    # Local workspace — fast, ephemeral
    mags run 'pip install pandas && python analyze.py'

### Persistent (`-p`)

Persistent workspaces sync to S3 automatically. When a sandbox restarts, Mags restores the workspace from the cloud snapshot, so you pick up exactly where you left off. Ideal for long-running projects, dev environments, and anything you want to keep.

Terminal

    # Persistent workspace — survives restarts
    mags run -w myproject -p 'npm install && npm start'

### Base Image (`--base <workspace>`)

Any persistent workspace can be mounted read-only as a base image for other runs. You set it up once with all your dependencies, then new sandboxes mount it with `--base` and get a copy-on-write overlay — they can make changes without affecting the base. Great for standardized environments where many sandboxes need the same starting state.

Terminal

    # Set up a persistent workspace once
    mags run -n python-ml -p 'pip install numpy pandas scikit-learn torch'

    # Mount it read-only as a base for fast, throwaway runs
    mags run --base python-ml 'python train.py'

    # Mount the base but save your changes to a new named workspace
    mags run --base python-ml -n experiment-1 'python train.py'

## Long-Running & Server Mode

By default, a sandbox shuts down after the script completes. To keep one running as a server, use `-p` to keep it alive, and choose how it behaves when idle:

- Scale-to-zero (`--server`): The VM freezes when idle and wakes automatically on the next incoming request. Ideal for web apps and APIs with bursty traffic. Implies `-p`.
- Always-on (`--no-sleep`): The VM never auto-sleeps — best for background workers that must stay live. Requires `-p`.
- Wake hook (`--startup-command`): A command Mags runs each time the VM wakes from sleep, e.g. to relaunch your server process.

Terminal

    # Scale-to-zero web app with a public URL
    mags run -n api-server --server --url --startup-command 'node server.js' 'node server.js'

    # Always-on background worker
    mags run -n worker -p --no-sleep 'node worker.js'

## Public URLs

Expose any port in your sandbox to the internet with a single flag. Mags provisions an HTTPS URL with automatic TLS termination.

Terminal

    # Enable a public URL
    mags url enable name

    # Set a custom alias for a friendlier URL
    mags url alias name my-app

You can also enable public URLs at creation time with the `--url` flag on `mags run`. URLs follow the pattern `https://<name>.mags.run`, or `https://<alias>.mags.run` if you set an alias.

## Cron Jobs

Schedule recurring tasks using standard 5-field cron expressions. Mags spins up a sandbox at the scheduled time, runs your command, and tears it down.

Terminal

    # Create — run every 5 minutes
    mags cron create '*/5 * * * *' 'python scrape.py'

    # List all cron jobs
    mags cron list

    # Delete a cron job
    mags cron delete job-id

## File Upload

Upload local files into the sandbox before your script runs. Use the `-f` flag one or more times to include files. Files are placed in the sandbox's working directory.

Terminal

    # Upload multiple files
    mags run -f file1.txt -f file2.csv 'python process.py'

    # Combine with persistent workspace
    mags run -w data-pipeline -p -f dataset.parquet 'python etl.py'

## Python SDK — Installation

Install the Mags Python SDK from PyPI:

Terminal

    pip install mags

The SDK requires Python 3.8 or later. Authentication is handled automatically via the `MAGS_TOKEN` environment variable or a prior `mags login` session.

## Python SDK — Methods

The `Mags` client exposes the following methods:

Method | Description
--- | ---
`client.run(script, **options)` | Execute a script in a new or existing sandbox. Returns a Job object.
`client.status(job_id)` | Get the current status of a job (queued, running, completed, failed).
`client.logs(job_id)` | Retrieve the full stdout/stderr output of a job.
`client.stop(job_id)` | Stop a running job and its sandbox.
`client.list()` | List all active sandboxes and jobs.
`client.workspace.list()` | List all saved workspaces.
`client.workspace.delete(name)` | Delete a saved workspace.

## Python SDK — Options

The `client.run()` method accepts the following keyword arguments:

Option | Type | Description
--- | --- | ---
`script` | `str` | The command or script to execute (required).
`workspace` | `str` | Named workspace identifier.
`persist` | `bool` | Sync workspace to cloud storage. Default `False`.
`url` | `bool` | Enable a public HTTPS URL. Default `False`.
`ssh` | `bool` | Enable SSH access. Default `False`.
`files` | `list[str]` | List of local file paths to upload into the sandbox.
`always_on` | `bool` | Keep the sandbox running as a persistent server. Default `False`.
`timeout` | `int` | Maximum execution time in seconds.
`base_image` | `str` | Name of a base image workspace to inherit from.
`ephemeral` | `bool` | No workspace — fastest execution. Default `False`.

## Python SDK — Examples

### Basic execution

python

    from mags import Mags

    client = Mags()

    # Run a simple command
    job = client.run("echo hello")
    print(job.logs)

### Persistent workspace with public URL

python

    from mags import Mags

    client = Mags()

    job = client.run(
        script="python app.py",
        workspace="myapp",
        persist=True,
        url=True,
        files=["data.csv"]
    )
    print(job.url)

### Job lifecycle

python

    from mags import Mags

    client = Mags()

    # Start a long-running job
    job = client.run(
        script="python train.py",
        workspace="ml-training",
        persist=True
    )

    # Check status
    status = client.status(job.id)
    print(status)  # "running"

    # Stream logs
    logs = client.logs(job.id)
    print(logs)

    # Stop when done
    client.stop(job.id)

## Node.js SDK — Installation

Install the Mags Node.js SDK from npm:

Terminal

    npm install @magpiecloud/mags

The SDK requires Node.js 18 or later. Authentication is handled automatically via the `MAGS_TOKEN` environment variable or a prior `mags login` session.

## Node.js SDK — Methods

The `Mags` client exposes the following async methods:

Method | Description
--- | ---
`mags.run(script | options)` | Execute a script in a new or existing sandbox. Returns a Job object.
`mags.status(jobId)` | Get the current status of a job (queued, running, completed, failed).
`mags.logs(jobId)` | Retrieve the full stdout/stderr output of a job.
`mags.stop(jobId)` | Stop a running job and its sandbox.
`mags.list()` | List all active sandboxes and jobs.
`mags.workspace.list()` | List all saved workspaces.
`mags.workspace.delete(name)` | Delete a saved workspace.

## Node.js SDK — Options

When passing an options object to `mags.run()`:

Option | Type | Description
--- | --- | ---
`script` | `string` | The command or script to execute (required).
`workspace` | `string` | Named workspace identifier.
`persist` | `boolean` | Sync workspace to cloud storage. Default `false`.
`url` | `boolean` | Enable a public HTTPS URL. Default `false`.
`ssh` | `boolean` | Enable SSH access. Default `false`.
`files` | `string[]` | List of local file paths to upload into the sandbox.
`alwaysOn` | `boolean` | Keep the sandbox running as a persistent server. Default `false`.
`timeout` | `number` | Maximum execution time in seconds.
`baseImage` | `string` | Name of a base image workspace to inherit from.
`ephemeral` | `boolean` | No workspace — fastest execution. Default `false`.

## Node.js SDK — Examples

### Basic execution

javascript

    import { Mags } from '@magpiecloud/mags';

    const mags = new Mags();

    // Run a simple command
    const job = await mags.run('echo hello');
    console.log(job.logs);

### Persistent workspace with public URL

javascript

    import { Mags } from '@magpiecloud/mags';

    const mags = new Mags();

    const app = await mags.run({
      script: 'npm start',
      workspace: 'myapp',
      persist: true,
      url: true,
      files: ['package.json', 'index.js']
    });
    console.log(app.url);

### Job lifecycle

javascript

    import { Mags } from '@magpiecloud/mags';

    const mags = new Mags();

    // Start a long-running job
    const job = await mags.run({
      script: 'node worker.js',
      workspace: 'background-worker',
      persist: true,
      alwaysOn: true
    });

    // Check status
    const status = await mags.status(job.id);
    console.log(status); // "running"

    // Stream logs
    const logs = await mags.logs(job.id);
    console.log(logs);

    // Stop when done
    await mags.stop(job.id);

## API Authentication

All API requests require a Bearer token in the `Authorization` header. Get your token from the API Tokens dashboard.

HTTP Header

    Authorization: Bearer YOUR_API_TOKEN

## Base URL

All endpoints are relative to:

    https://api.magpiecloud.com/api/v1

## Jobs Endpoints

Submit, monitor, and control sandbox jobs.

Method | Path | Description
--- | --- | ---
`POST` | `/mags-jobs` | Submit a new job
`GET` | `/mags-jobs/:id` | Get job status
`GET` | `/mags-jobs/:id/logs` | Get job logs
`GET` | `/mags-jobs` | List all jobs
`POST` | `/mags-jobs/:id/stop` | Stop a job
`POST` | `/mags-jobs/:id/access` | Enable SSH/URL access
`PATCH` | `/mags-jobs/:id` | Update job settings
`POST` | `/mags-jobs/:id/upload` | Upload file
`POST` | `/mags-jobs/:id/sync` | Sync workspace

### Submit a Job

Create a new sandbox and run a script. The `script` field is required.

Field | Type | Description
--- | --- | ---
`script` | string | The script to execute (required)
`type` | string | `"inline"` or `"file"`
`workspace` | string | Named workspace
`persist` | bool | Persist workspace to cloud
`url` | bool | Enable public URL
`ssh` | bool | Enable SSH access
`startup_command` | string | Command to run on startup
`base_image` | bool | Use as base image template
`ephemeral` | bool | No workspace, fastest execution
`timeout` | int | Job timeout in seconds

curl

    curl -X POST https://api.magpiecloud.com/api/v1/mags-jobs \
      -H "Authorization: Bearer $TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "script": "echo Hello World",
        "type": "inline",
        "workspace": "my-app",
        "persist": true
      }'

Python

    from mags import Mags
    client = Mags()
    job = client.run(script="echo Hello", workspace="my-app", persist=True)

Node.js

    const job = await mags.run({
      script: 'echo Hello',
      workspace: 'my-app',
      persist: true,
    });

### Get Job Status

curl

    curl https://api.magpiecloud.com/api/v1/mags-jobs/$JOB_ID \
      -H "Authorization: Bearer $TOKEN"

### Get Job Logs

curl

    curl https://api.magpiecloud.com/api/v1/mags-jobs/$JOB_ID/logs \
      -H "Authorization: Bearer $TOKEN"

## Workspaces Endpoints

Method | Path | Description
--- | --- | ---
`GET` | `/workspaces` | List all workspaces
`DELETE` | `/workspaces/:name` | Delete a workspace

## URL Aliases Endpoints

Method | Path | Description
--- | --- | ---
`POST` | `/url-aliases` | Create a URL alias
`GET` | `/url-aliases` | List URL aliases
`DELETE` | `/url-aliases/:alias` | Delete a URL alias

## Cron Endpoints

Method | Path | Description
--- | --- | ---
`POST` | `/cron-jobs` | Create a cron job
`GET` | `/cron-jobs` | List cron jobs
`PATCH` | `/cron-jobs/:id` | Update a cron job
`DELETE` | `/cron-jobs/:id` | Delete a cron job

## Error Codes

Code | Description
--- | ---
`400` | Bad request — invalid parameters or missing required fields
`401` | Unauthorized — missing or invalid API token
`404` | Not found — job or resource does not exist
`409` | Conflict — resource already exists or is in an incompatible state
`500` | Internal server error

## Claude Skill Installation

Give Claude Code the ability to execute scripts in isolated microVMs. Install in three steps:

### Step 1: Install the CLI

terminal

    npm install -g @magpiecloud/mags

### Step 2: Set up the Claude skill

terminal

    mags setup-claude

### Step 3: Log in

terminal

    mags login

That's it. Claude can now execute code in isolated sandboxes. Workspaces persist between runs, and you can use SSH or public URLs when needed.

## Example Prompts

With the Mags skill installed, just describe what you want in plain English:

- "Create a Python environment with numpy and pandas, then run a script that generates sample data"
- "Set up a Node.js web server, install express, and give me the public URL"
- "Upload my data.csv file, install pandas, and run analysis.py on it"
- "Create a persistent workspace called 'ml-project', install tensorflow, and SSH in"
- "Schedule a cron job that runs every morning to scrape news headlines"
- "Build my Go project in a clean environment and show me the test results"

## VM Environment

Every sandbox runs on Alpine Linux with these specs:

Resource | Value
--- | ---
Base OS | Alpine Linux
CPU | 1 vCPU
Memory | 512MB RAM
Storage | Ephemeral or persistent (S3 sync)
Network | Full access with optional public URLs

Pre-installed tools: `python3`, `pip`, `node`, `npm`, `git`, `curl`, `wget`, `jq`, `openssh`, `gcc`, `make`.