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

# Eve

> Run Eve sandboxes on Box with the @asciidev/eve-box backend: a zero-to-one guide for newcomers to either tool.

[Eve](https://www.npmjs.com/package/eve) is a TypeScript framework for building coding agents. It runs each agent inside a **sandbox**, which is an isolated filesystem and shell the agent reads, writes, and executes in. Eve lets you choose where that sandbox actually runs.

[Box](/box/quickstart) is Ascii's cloud sandbox: a full Linux machine you create over an API, run commands in, and read and write files in.

`@asciidev/eve-box` connects the two. It is an Eve **sandbox backend** that maps Eve's filesystem and process operations onto the Box API, so your Eve agents run on real Box machines instead of your laptop.

<Note>
  New to both? You only need two things to follow this guide: Node.js 18+ and a Box API key. No prior Eve or Box experience required.
</Note>

## How it fits together

* **Eve** owns your agent logic and calls a sandbox to do filesystem and shell work.
* **`@asciidev/eve-box`** is the adapter you plug into Eve.
* **Box** is the machine the work actually happens on.

```
your Eve agent ──> Eve sandbox API ──> @asciidev/eve-box ──> Box machine
```

## Set it up

<Steps>
  <Step title="Create a Box account">
    Sign in at [box.ascii.dev](https://box.ascii.dev) with GitHub and start a Box plan, which includes a free 7-day trial. You need an account to create boxes. See the [Box quickstart](/box/quickstart) for the full onboarding walkthrough.
  </Step>

  <Step title="Get a Box API key">
    Create a key from the [API keys](/box/api-keys) tab of the Box dashboard. Keep it secret: store it in an environment variable, never in source control.

    ```bash theme={null}
    export BOX_API_KEY=box_your_real_key_here
    ```
  </Step>

  <Step title="Install the packages">
    ```bash theme={null}
    npm install @asciidev/eve-box eve
    ```

    Use a modern TypeScript config (`"module": "NodeNext"`, `"target": "ES2022"`, `"lib": ["ES2022", "DOM"]`) and `"type": "module"` in `package.json`.
  </Step>

  <Step title="Define the sandbox backend">
    Point Eve's sandbox at Box. In an Eve project this lives in your sandbox definition file:

    ```ts title="sandbox.ts" theme={null}
    import { defineSandbox } from "eve/sandbox";
    import { asciiBox } from "@asciidev/eve-box";

    export default defineSandbox({
      backend: asciiBox({
        apiKey: process.env.BOX_API_KEY!,
        ttlSeconds: 3600, // auto-stop the Box one hour after creation
      }),
    });
    ```

    That's it: Eve agents in this project now run on Box.
  </Step>
</Steps>

## A complete example

This standalone script creates a Box-backed sandbox session and exercises the operations Eve relies on: running commands, reading files, and writing files. It runs on its own so you can verify your setup before wiring the backend into a larger Eve agent.

```ts title="hello-box.ts" theme={null}
import { asciiBox } from "@asciidev/eve-box";

async function main() {
  const backend = asciiBox({
    apiKey: process.env.BOX_API_KEY!,
    name: "eve-hello",
    ttlSeconds: 600,
  });

  // Create a session (this provisions a Box and waits until it is ready).
  const handle = await backend.create({
    templateKey: null,
    sessionKey: "hello-session",
    runtimeContext: { appRoot: process.cwd() },
  });
  const session = await handle.useSessionFn({ networkPolicy: "allow-all" });

  // Write a file, run a command against it, and read the result back.
  await session.writeTextFile({ path: "notes/hello.txt", content: "hello from Box\n" });
  const result = await session.run({ command: "cat notes/hello.txt && uname -a" });
  console.log("exit:", result.exitCode);
  console.log(result.stdout);

  // Paths resolve under /workspace, matching Eve's sandbox contract.
  console.log(session.resolvePath("notes/hello.txt")); // -> /workspace/notes/hello.txt
}

main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});
```

```bash theme={null}
BOX_API_KEY=box_... npx tsx hello-box.ts
```

You should see the file contents, the machine's `uname` output, and exit code `0`.

## What the backend maps

| Eve operation                        | Box behaviour                                                                         |
| ------------------------------------ | ------------------------------------------------------------------------------------- |
| `run`                                | Executes a bounded command in the Box work directory.                                 |
| `spawn`                              | Starts a background process, with streamed `stdout`/`stderr`, `wait()`, and `kill()`. |
| `readTextFile` / `writeTextFile`     | Reads and writes files under the Box work directory.                                  |
| `readBinaryFile` / `writeBinaryFile` | Same, using base64 transfer for binary content.                                       |
| `removePath`                         | Removes files and directories in the workspace.                                       |
| `resolvePath`                        | Anchors relative paths to `/workspace`.                                               |
| create / resume                      | Creates a new Box, or reconnects to one from Eve's persisted session state.           |

## Configuration

`asciiBox(options)` accepts:

| Option             | Default                   | Description                                                             |
| ------------------ | ------------------------- | ----------------------------------------------------------------------- |
| `apiKey`           | `process.env.BOX_API_KEY` | Box API key.                                                            |
| `baseUrl`          | public Box API            | Box API base URL.                                                       |
| `name`             | `eve-<sessionKey>`        | Name, or `(input) => string`, for boxes Eve creates.                    |
| `ttlSeconds`       | `3600`                    | Auto-stop TTL in seconds. `null` disables auto-stop.                    |
| `noEnv`            | `false`                   | Withhold your account's secrets and credentials from boxes (see below). |
| `env`              | none                      | Per-box environment variables for every box Eve creates (see below).    |
| `pollMs`           | `500`                     | Poll cadence for `spawn()` streams and `wait()`.                        |
| `commandTimeoutMs` | none                      | Timeout for blocking `run()` commands.                                  |
| `networkPolicy`    | none                      | Initial network policy (see below).                                     |

## Running agents for other people

<Warning>
  By default a box inherits **your** Box account, including your secrets, secret files, GitHub-credentialed repos, and SSH identity. Fine for your own agents; if anyone else can drive the agent, set `noEnv: true` so they can't read your secrets or act as you.
</Warning>

With `noEnv: true` the box starts empty and confined to itself. You then give it exactly what it needs: secrets through `env`, and files and setup through Eve's `onSession` hook.

```ts title="sandbox.ts" theme={null}
import { defineSandbox } from "eve/sandbox";
import { asciiBox } from "@asciidev/eve-box";

export default defineSandbox({
  backend: asciiBox({
    apiKey: process.env.BOX_API_KEY!,
    noEnv: true,
    // Scoped secrets: the only env this box gets:
    env: { MY_APP_TOKEN: process.env.MY_APP_TOKEN! },
  }),
  async onSession({ use }) {
    const sandbox = await use();
    // Seed files and run setup with the session API. These wrap Box's file
    // and command APIs, so you don't need `box scp` or `box ssh`.
    await sandbox.writeTextFile({ path: "config/app.json", content: JSON.stringify({ mode: "prod" }) });
    await sandbox.run({ command: "git clone https://github.com/acme/public-repo . && npm ci" });
  },
});
```

`env` keys merge over your account variables (per-box wins; at most 100 variables, 64 KB total; reserved Box-internal names are rejected). `writeFile`/`readFile` move bytes in and out and `run`/`spawn` execute commands as the Eve-native equivalents of [`box scp`](/box/ssh-access#copy-files) and `box ssh <id> <cmd>`. A no-env box can't reach your private repos, so clone public ones or have the user authenticate inside the box. See [No-env boxes](/box/secrets#no-env-boxes).

## Reusing a prepared environment

Setup runs when each session's box is first created. If you want many sessions to start from the same fully prepared state, fork a box: prepare one, stop it so its snapshot completes, then fork it; each clone keeps the entire filesystem. See [Fork box](/box/api/reference/boxes/fork-box).

## Network policies

Box does not yet enforce Eve's fine-grained network policies. The backend accepts `"allow-all"` and throws `EveBoxUnsupportedError` for stricter policies (`"deny-all"`, allow-lists, subnet rules), so you never get a false sense of isolation. If you need firewall-backed policies, run that Eve agent on a backend that supports them.

## Resources

<CardGroup cols={2}>
  <Card title="npm package" icon="npm" href="https://www.npmjs.com/package/@asciidev/eve-box">
    `@asciidev/eve-box` on npm.
  </Card>

  <Card title="Source on GitHub" icon="github" href="https://github.com/ariana-dot-dev/eve-box">
    Issues, examples, and the adapter source.
  </Card>

  <Card title="Box quickstart" icon="rocket" href="/box/quickstart">
    Install Box and create your first sandbox.
  </Card>

  <Card title="Box API keys" icon="key" href="/box/api-keys">
    Create and manage the key this adapter needs.
  </Card>
</CardGroup>
