> ## Documentation Index
> Fetch the complete documentation index at: https://isol8.notdhruv.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Execution guide

> Run code via CLI, Library, or API: modes, streaming, file I/O, and resource limits.

isol8 provides a unified execution engine accessible through three interfaces: a **CLI** for local development, a **TypeScript Library** for application integration, and an **HTTP API** for remote services.

## Execution Lifecycle

Every execution request follows a strict pipeline to ensure security and isolation.

### Pipeline Overview

```mermaid theme={null}
flowchart TD
  A[Request] --> B{Mode?}
  B -->|Ephemeral| C[Acquire Warm Container]
  B -->|Persistent| D[Load Session Container]
  C --> E[Inject Code & Files]
  D --> E
  E --> F["Install Packages (Optional)"]
  F --> G[Execute with Resource Limits]
  G --> H[Capture Output]
  H --> I[Mask Secrets & Truncate]
  I --> J[Return Result / Stream]
```

<Note>
  In ephemeral mode, simple requests can skip file injection and execute inline (for example `python -c`, `node -e`, `bun -e`, `bash -c`) when no `stdin`, `files`, `outputPaths`, or package installs are requested. The `agent` runtime always uses file injection and passes the code as a prompt to the pi coding agent.
</Note>

## Execution Modes

isol8 supports two execution modes, determined by your use case.

| Mode                    | Behavior                                                                           | Best For                                              |
| :---------------------- | :--------------------------------------------------------------------------------- | :---------------------------------------------------- |
| **Ephemeral** (Default) | Creates a fresh container for every request. State is lost after execution.        | stateless tasks, untrusted code, parallel workloads   |
| **Persistent**          | Reuses a single container across multiple requests. Files and state are preserved. | interactive sessions, multi-step workflows, notebooks |

### Selecting a Mode

<Tabs>
  <Tab title="CLI">
    Use the `--persistent` flag to enable persistent mode.

    ```bash theme={null}
    # Ephemeral (Default)
    isol8 run script.py

    # Persistent (Keeps container alive)
    isol8 run --persistent script.py
    ```

    <Note>
      In CLI persistent mode, the container is tied to the CLI process. To reuse a persistent container across multiple CLI commands, you would need to use the API or Library.
    </Note>
  </Tab>

  <Tab title="Library">
    Configure the mode when initializing the engine.

    ```typescript theme={null}
    // Ephemeral (Default)
    const engine = new DockerIsol8({ mode: "ephemeral" });

    // Persistent
    const session = new DockerIsol8({ mode: "persistent" });
    await session.execute({ ... }); // State preserved for next call
    ```
  </Tab>

  <Tab title="API">
    Include a `sessionId` to trigger persistent mode.

    ```json theme={null}
    // Ephemeral (No sessionId)
    {
      "request": { "code": "x = 1", "runtime": "python" }
    }

    // Persistent (With sessionId)
    {
      "sessionId": "user-session-123",
      "request": { "code": "print(x)", "runtime": "python" }
    }
    ```
  </Tab>
</Tabs>

## Inputs & Outputs

You can pass code, environment variables, and files into the sandbox.

### 1. Source Code

The core of every request.

<Tabs>
  <Tab title="CLI">
    Pass a file path, an inline string, or pipe from stdin.

    ```bash theme={null}
    # File
    isol8 run script.py

    # Inline
    isol8 run -e "print('Hello')" --runtime python

    # Stdin
    echo "print('Piped')" | isol8 run --runtime python
    ```
  </Tab>

  <Tab title="Library">
    Pass the `code` string in the request object.

    ```typescript theme={null}
    await engine.execute({
      code: "console.log('Hello')",
      runtime: "node"
    });
    ```
  </Tab>

  <Tab title="API">
    ```json theme={null}
    {
      "request": {
        "code": "console.log('Hello')",
        "runtime": "node"
      }
    }
    ```
  </Tab>
</Tabs>

### 1.1 Remote Code URLs

isol8 can fetch source code from a URL before execution.

<Warning>
  `code` and `codeUrl` are mutually exclusive. Provide only one per request.
</Warning>

Remote URL execution is controlled by:

* request fields: `codeUrl`, `codeHash`, `allowInsecureCodeUrl`
* CLI flags: `--url`, `--github`, `--gist`, `--hash`, `--allow-insecure-code-url`
* config policy: `remoteCode.*` in `isol8.config.json`

<Tabs>
  <Tab title="CLI">
    ```bash theme={null}
    # Direct URL
    isol8 run --url https://raw.githubusercontent.com/user/repo/main/script.py --runtime python

    # GitHub shorthand
    isol8 run --github user/repo/main/script.py --runtime python

    # Gist shorthand
    isol8 run --gist abcd1234/example.js --runtime node

    # Integrity verification
    isol8 run --url https://example.com/script.py --hash <sha256> --runtime python
    ```
  </Tab>

  <Tab title="Library">
    ```typescript theme={null}
    await engine.execute({
      codeUrl: "https://raw.githubusercontent.com/user/repo/<sha>/script.py",
      codeHash: "<sha256>",
      runtime: "python",
    });
    ```
  </Tab>

  <Tab title="API">
    ```json theme={null}
    {
      "request": {
        "codeUrl": "https://raw.githubusercontent.com/user/repo/<sha>/script.py",
        "codeHash": "<sha256>",
        "runtime": "python"
      }
    }
    ```
  </Tab>
</Tabs>

<Note>
  URL fetching is disabled by default. Enable and tune `remoteCode` policy in config first.
  For full policy fields and security guidance, see <a href="/remote-code">Remote code URLs</a>.
</Note>

### 2. Environment Variables

Inject configuration or secrets.

<Warning>
  **Security Note:** Environment variables are visible to the running process. For sensitive data, use the "Secrets" feature to ensure values are masked in logs and output.
</Warning>

<Tabs>
  <Tab title="CLI">
    The CLI only supports **Secrets** via `--secret`. These are injected as environment variables but their values are masked in stdout/stderr.

    ```bash theme={null}
    isol8 run script.py --secret API_KEY=sk_12345
    ```
  </Tab>

  <Tab title="Library">
    You can pass plain `env` variables (visible) or global `secrets` (masked).

    ```typescript theme={null}
    const engine = new DockerIsol8({
      // Global secrets (masked in output)
      secrets: { API_KEY: "sk_12345" }
    });

    await engine.execute({
      code: "...",
      runtime: "python",
      // Per-request env vars (visible in output)
      env: { LOG_LEVEL: "debug" }
    });
    ```
  </Tab>

  <Tab title="API">
    ```json theme={null}
    {
      "request": {
        "runtime": "python",
        "code": "import os; print(os.getenv('LOG_LEVEL', 'unset'))",
        "env": { "LOG_LEVEL": "debug" }
      }
    }
    ```
  </Tab>
</Tabs>

### 3. Files

Inject files *before* execution and retrieve them *after*.

<Tabs>
  <Tab title="CLI">
    <Note>
      The CLI supports file injection for the `agent` runtime via `--files <dir>`, which recursively copies a local directory into `/sandbox`. For other runtimes, use the Library or API for generic file injection (`files`) or retrieval (`outputPaths`). All runtimes support `--out` to capture stdout to a file.
    </Note>

    ```bash theme={null}
    # Capture stdout to file
    isol8 run script.py --out result.txt

    # Inject project files for agent runtime
    isol8 run -e "add tests" --runtime agent \
      --files ./my-project \
      --net filtered --allow "api.anthropic.com" \
      --secret "ANTHROPIC_API_KEY=sk-..."
    ```
  </Tab>

  <Tab title="Library">
    Full support for virtual file I/O.

    ```typescript theme={null}
    const result = await engine.execute({
      code: "print(open('/sandbox/data.txt').read())",
      runtime: "python",
      // Inject files
      files: {
        "/sandbox/data.txt": "Hello from file!"
      },
      // Retrieve files
      outputPaths: ["/sandbox/output.json"]
    });

    const fileContent = result.files["/sandbox/output.json"]; // base64 encoded
    ```
  </Tab>

  <Tab title="API">
    ```json theme={null}
    {
      "request": {
        "runtime": "python",
        "code": "print(open('/sandbox/data.txt').read())",
        "files": {
          "/sandbox/data.txt": "Hello from file!"
        },
        "outputPaths": ["/sandbox/output.json"]
      }
    }
    ```
  </Tab>
</Tabs>

## Streaming Output

Real-time output is essential for long-running tasks or LLM code generation.

<Tabs>
  <Tab title="CLI">
    Streaming is **enabled by default**. Use `--no-stream` to wait for completion.

    ```bash theme={null}
    # Streams output as it appears
    isol8 run long_task.py

    # Waits until finished, then prints all output
    isol8 run long_task.py --no-stream
    ```
  </Tab>

  <Tab title="Library">
    Use `executeStream` instead of `execute`.

    ```typescript theme={null}
    const stream = engine.executeStream({
      code: "...",
      runtime: "python"
    });

    for await (const event of stream) {
      if (event.type === 'stdout') process.stdout.write(event.data);
      if (event.type === 'stderr') process.stderr.write(event.data);
      if (event.type === 'exit') console.log(`Exited with ${event.data}`);
    }
    ```
  </Tab>

  <Tab title="API">
    ```bash theme={null}
    curl -N -X POST http://localhost:3000/execute/stream \
      -H "Authorization: Bearer $ISOL8_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "request": {
          "runtime": "python",
          "code": "import time\nfor i in range(3):\n print(i)\n time.sleep(1)"
        }
      }'
    ```
  </Tab>
</Tabs>

<Info>
  When using `RemoteIsol8`, `executeStream()` automatically selects the best available transport: WebSocket (`/execute/ws`) with automatic SSE (`/execute/stream`) fallback. See the [WebSocket endpoint reference](/server/get-execute-ws) for protocol details.
</Info>

### StreamEvent reference

Each value yielded by `executeStream` is a `StreamEvent`:

| Field   | Type                                        | Description                                                                                                                   |
| :------ | :------------------------------------------ | :---------------------------------------------------------------------------------------------------------------------------- |
| `type`  | `"stdout" \| "stderr" \| "exit" \| "error"` | Event kind. `exit` carries the process exit code as a string in `data`.                                                       |
| `data`  | `string`                                    | Payload: output text for stdout/stderr, exit code string for exit, error message for error.                                   |
| `phase` | `"setup" \| "code"`                         | Which stage produced the event. `"setup"` = from a `setupScript`; `"code"` = from the main code/command. Always set by isol8. |

Use `phase` to distinguish `setupScript` output from main code output when both are present:

```typescript theme={null}
for await (const event of engine.executeStream({
  runtime: "bash",
  setupScript: "git clone https://$GITHUB_TOKEN@github.com/my-org/repo.git /sandbox/repo",
  code: "ls /sandbox/repo",
})) {
  if (event.phase === "setup") {
    process.stderr.write(`[setup] ${event.data}`);
  } else if (event.type === "stdout") {
    process.stdout.write(event.data);
  }
}
```

If a `setupScript` exits non-zero, `executeStream` yields an `error` event then an `exit` event (both with `phase: "setup"`) and stops — no `phase: "code"` events follow. See [Setup scripts](/setup-scripts#error-handling) for full details.

## Resource Limits & Safety

isol8 enforces strict limits to contain untrusted code.

| Parameter   | CLI Flag       | Library Option  | Default | Description                               |
| :---------- | :------------- | :-------------- | :------ | :---------------------------------------- |
| **Timeout** | `--timeout`    | `timeoutMs`     | 30s     | Hard execution time limit.                |
| **Memory**  | `--memory`     | `memoryLimit`   | 512m    | RAM limit for the container.              |
| **CPU**     | `--cpu`        | `cpuLimit`      | 1.0     | CPU shares (1.0 = 1 core).                |
| **Network** | `--net`        | `network`       | none    | `none`, `host`, or `filtered`.            |
| **Output**  | `--max-output` | `maxOutputSize` | 1MB     | Max stdout/stderr size before truncation. |

### Output Truncation

If a script produces excessive output, isol8 truncates it to prevent memory issues.

* `result.truncated` will be `true`.
* The output will end with a truncation message.

### Secret Masking

If you provide `secrets` (via CLI `--secret` or Library config), isol8 scans `stdout` and `stderr` and replaces occurrences of secret values with `***`.

```bash theme={null}
# Input
isol8 run -e "print('my-secret-value')" --secret KEY=my-secret-value

# Output
***
```

## Troubleshooting

<AccordionGroup>
  <Accordion title="Execution Timed Out">
    The code ran longer than `timeoutMs`.

    * **Fix:** Increase limit via `--timeout` or optimize the code.
    * **Note:** Infinite loops are a common cause.
  </Accordion>

  <Accordion title="Output Truncated">
    The script printed more data than `maxOutputSize` allowed.

    * **Fix:** Reduce logging or increase the limit via `--max-output`.
  </Accordion>

  <Accordion title="File Not Found">
    Remember that the code runs in an isolated container.

    * It **cannot** see files on your host machine unless you explicitly inject them (Library/API).
    * CLI users should pipe data via stdin or use inline strings for simple inputs.
  </Accordion>
</AccordionGroup>

## FAQ

<AccordionGroup>
  <Accordion title="Should I pass timeout in request or options?">
    Use `request.timeoutMs` when you want a per-execution timeout. Use `options.timeoutMs` as a baseline engine default for a client/session.
  </Accordion>

  <Accordion title="When should I use codeUrl instead of code?">
    Use `codeUrl` for pinned remote artifacts (for example immutable GitHub raw URLs). Keep `code` for direct inline or generated source. Never set both in one request.
  </Accordion>

  <Accordion title="Why does persistent mode not carry over between separate CLI invocations?">
    CLI runs are process-scoped. For durable cross-call state, use a stable `sessionId` through the API or `RemoteIsol8`.
  </Accordion>
</AccordionGroup>

## Related pages

<CardGroup cols={2}>
  <Card title="Option mapping" icon="sliders" href="/option-mapping">
    Exact option mapping across CLI, config, API, and library.
  </Card>

  <Card title="Runtime reference" icon="square-terminal" href="/runtimes">
    Runtime-specific behavior, extensions, and package semantics.
  </Card>

  <Card title="Setup scripts" icon="scroll" href="/setup-scripts">
    Run shell commands before execution — streaming output, phase events, and early-exit on failure.
  </Card>

  <Card title="Remote code URLs" icon="link" href="/remote-code">
    URL-based source fetching policy and integrity controls.
  </Card>

  <Card title="Troubleshooting" icon="wrench" href="/troubleshooting">
    Symptom-based fixes for execution and session issues.
  </Card>
</CardGroup>
