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

# Run OpenCode in Tensorlake Sandboxes

> Route OpenCode's file and shell tools into a Tensorlake sandbox with a single plugin — the model edits, runs, and searches inside an isolated environment instead of on your machine.

[OpenCode](https://opencode.ai) is a terminal coding agent. The [`tensorlake-opencode`](https://www.npmjs.com/package/tensorlake-opencode) plugin redirects the agent's hands — its file and shell tools — into a Tensorlake sandbox, so the model's commands and edits run in an isolated environment you control rather than on your laptop.

## The model: brain local, hands in the sandbox

OpenCode keeps running locally — the TUI, the model loop, and your session all stay on your machine. The plugin only intercepts the **tool calls** and routes them to a sandbox:

| OpenCode tool | Runs in the sandbox as                     |
| ------------- | ------------------------------------------ |
| `bash`        | `sandbox.run('sh', { args: ['-c', cmd] })` |
| `read`        | `sandbox.readFile(path)`                   |
| `write`       | `sandbox.writeFile(path, content)`         |
| `edit`        | read + string replace + write              |
| `ls`          | `sandbox.listDirectory(path)`              |
| `glob`        | `find … -name "pattern"` via bash          |
| `grep`        | `grep -rn …` via bash                      |

`webfetch` and `websearch` are **not** intercepted — they stay local, since they don't touch your filesystem.

The sandbox itself runs on Tensorlake: fast boot, sub-second resume from a suspended snapshot, and state that persists across OpenCode restarts. See [Sandbox lifecycle](/sandboxes/lifecycle) for the suspend/resume and snapshot model underneath.

## Why route tool calls into a sandbox

* **Isolation.** The agent's `bash` and `write` never touch your host. A bad command, a runaway install, or an `rm` lands in a disposable environment, not your working tree.
* **Reproducible environment.** Every session gets the same image, CPU, and memory regardless of what's on the developer's machine — pin a custom image with the right toolchain once and every session inherits it.
* **State that survives restarts.** Sandboxes are named and persisted to disk, so a session reconnects to its sandbox across OpenCode restarts; a suspended sandbox resumes with `/tmp/workspace`, installed deps, and warm caches intact.

## Prerequisites

* An [OpenCode](https://opencode.ai) installation.
* A Tensorlake account and API key — sign up at [cloud.tensorlake.ai](https://cloud.tensorlake.ai).

## Setup

<Steps>
  <Step title="Add the plugin to your OpenCode config">
    Add the package name to `~/.config/opencode/opencode.json` (create the file if it doesn't exist):

    ```json theme={null}
    {
      "$schema": "https://opencode.ai/config.json",
      "plugin": [
        "tensorlake-opencode"
      ]
    }
    ```

    OpenCode treats bare names as npm packages and installs them into its own cache (`~/.cache/opencode/packages/`) — you don't run `npm install` yourself.
  </Step>

  <Step title="Set your API key">
    Export it in the same shell you launch OpenCode from:

    ```bash theme={null}
    export TENSORLAKE_API_KEY=your_api_key_here
    ```

    If you use a Personal Access Token instead of a project-scoped key, also set `TENSORLAKE_ORGANIZATION_ID` and `TENSORLAKE_PROJECT_ID`.
  </Step>

  <Step title="Start OpenCode">
    ```bash theme={null}
    opencode
    ```

    On startup the plugin loads but **no sandbox is created yet**. Confirm it loaded by tailing its log:

    ```bash theme={null}
    tail -f ~/.local/share/opencode/log/tensorlake.log
    ```

    You should see a single line: `OpenCode started with TensorLake plugin`.
  </Step>
</Steps>

## Lazy sandbox creation

<Note>
  The sandbox is created **lazily, on the first intercepted tool call** in a session — not when you launch OpenCode. If you start OpenCode and nothing appears to happen, that's expected. A session that only uses `webfetch`/`websearch` will never spin one up, because neither is intercepted.
</Note>

To trigger creation, ask the model to run something that uses a file or shell tool:

```
Run: uname -a
```

On that first `bash` call the plugin provisions the sandbox. You'll see a **"Sandbox created"** toast and new log lines:

```
[INFO] Creating new sandbox for session abc123
[INFO] Sandbox created sandbox-xyz in 2300ms
```

`uname -a` will report **Linux** (the sandbox), confirming the command ran remotely rather than on your Mac.

## Verify it's working

Ask the model to write and read a file back:

```
Write the text "Hello Tensorlake" to /tmp/workspace/test.txt, then read it back.
```

The `write` call routes to `sandbox.writeFile()` and the `read` call to `sandbox.readFile()`, both over the SDK. The agent's working directory inside the sandbox is `/tmp/workspace`.

## Configure the sandbox

The plugin reads a set of environment variables **at sandbox-creation time** to decide what the sandbox looks like — its image, CPUs, memory, and disk. There is no config file for this; you set the variables in the shell, then launch OpenCode from that same shell.

<Note>
  The variables are read **once, when the sandbox is created** (the first intercepted tool call of a session). Set them *before* you run `opencode`. Changing a variable in another terminal, or after the sandbox already exists, has no effect on the running session — start a new session to pick up new values.
</Note>

### How it fits together

```bash theme={null}
# 1. Authenticate (always required)
export TENSORLAKE_API_KEY=your_api_key_here

# 2. Size the sandbox VM
export TENSORLAKE_CPUS=4
export TENSORLAKE_MEMORY_MB=8192
export TENSORLAKE_DISK_MB=20480

# 3. Choose the toolchain image (optional — omit for the platform default)
export TENSORLAKE_IMAGE=my-custom-image

# 4. Launch — the next sandbox this session creates uses all of the above
opencode
```

Every value above describes the sandbox the plugin spins up for that OpenCode session — not OpenCode itself, and not your local machine.

### All variables

| Variable                     | Default                 | What it controls                                                                                 |
| ---------------------------- | ----------------------- | ------------------------------------------------------------------------------------------------ |
| `TENSORLAKE_API_KEY`         | (required)              | Authentication — which Tensorlake account/project the sandbox is created in                      |
| `TENSORLAKE_ORGANIZATION_ID` | (required for PAT keys) | Organization ID — needed only when using a Personal Access Token                                 |
| `TENSORLAKE_PROJECT_ID`      | (required for PAT keys) | Project ID — needed only when using a Personal Access Token                                      |
| `TENSORLAKE_IMAGE`           | (platform default)      | Registered image the sandbox boots from — bake your runtimes, build tools, and repo deps in here |
| `TENSORLAKE_CPUS`            | `2`                     | vCPUs allocated to the sandbox                                                                   |
| `TENSORLAKE_MEMORY_MB`       | `4096`                  | RAM allocated to the sandbox, in MB                                                              |
| `TENSORLAKE_DISK_MB`         | `10240`                 | Ephemeral disk allocated to the sandbox, in MB                                                   |

### Making the settings persistent

`export` only lasts for the current shell. To apply the same sandbox config every time, add the exports to your shell profile (`~/.zshrc` or `~/.bashrc`):

```bash theme={null}
echo 'export TENSORLAKE_API_KEY=your_api_key_here' >> ~/.zshrc
echo 'export TENSORLAKE_IMAGE=my-custom-image' >> ~/.zshrc
echo 'export TENSORLAKE_CPUS=4' >> ~/.zshrc
```

Open a new terminal (or `source ~/.zshrc`) and every `opencode` session inherits them.

### Use a custom image

`TENSORLAKE_IMAGE` is the most impactful setting for real work: it lets every OpenCode session start from an environment that already has your language runtimes, system packages, and project dependencies — so the agent isn't reinstalling them on each session. Register an image, then point the variable at its name:

```bash theme={null}
tl sbx image create Dockerfile --registered-name my-custom-image
export TENSORLAKE_IMAGE=my-custom-image
```

See [Sandbox images](/sandboxes/images) for building and managing images.

## Next steps

<CardGroup cols={2}>
  <Card title="Plugin source" icon="github" href="https://github.com/tensorlakeai/opencode-tensorlake-plugin">
    The full plugin: tool interceptors, session manager, and lifecycle handling.
  </Card>

  <Card title="Sandbox lifecycle" icon="arrows-rotate" href="/sandboxes/lifecycle">
    The suspend/resume and snapshot model that persists session state.
  </Card>

  <Card title="Sandbox images" icon="layer-group" href="/sandboxes/images">
    Build a custom image so every OpenCode session gets the same toolchain.
  </Card>

  <Card title="Tool calls" icon="robot" href="/sandboxes/tool-calls">
    The general pattern: expose sandboxes as tools to any LLM agent.
  </Card>
</CardGroup>
