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

# SDK Reference

> The programmatic API, and how it maps to the CLI

The SDK and the CLI are two interfaces over the same store. They write the same files, enforce the same rules, and raise the same error codes — so you can mix them freely.

Reach for the SDK when you are generating environments programmatically, wiring Silo into a test suite, or building tooling on top.

```typescript theme={null}
import { Silo } from "@burn0/silo";

const silo = await Silo.open({ cwd: process.cwd() });
const env = await silo.environments.create({ name: "support", template: "blank" });

await env.data.add("tickets", [{ id: "TKT-001", status: "open" }]);
await env.tasks.add({
  id: "TASK-001",
  title: "Triage the queue",
  instruction: "...",
  verifierId: "VER-001",
  difficulty: "easy",
});
await env.tools.scaffold({ name: "close_ticket", description: "..." });
await env.verifiers.scaffold({ id: "VER-001", taskId: "TASK-001" });

const report = await env.validate();
```

## `Silo.open()`

Binds to one project root.

```typescript theme={null}
const silo = await Silo.open({ cwd: "/path/to/project" });
```

`cwd` defaults to `process.cwd()`. It is captured once rather than read again further down, so a single process can serve several projects at the same time. Opening a path that is not a directory throws `environment_not_found`.

| Member                   | Returns                                      |
| ------------------------ | -------------------------------------------- |
| `silo.cwd`               | The resolved project root                    |
| `silo.environments`      | The environment registry                     |
| `silo.environment(name)` | Shorthand for `silo.environments.open(name)` |

## Environments

```typescript theme={null}
await silo.environments.list();                                   // string[]
await silo.environments.create({ name, template, tools });        // SiloEnvironment
await silo.environments.open(name);                               // SiloEnvironment
```

`create` is `silo init`. `open` binds to one that already exists and throws `environment_not_found` if it does not.

A `SiloEnvironment` exposes `name`, `cwd`, the four resource collections, and `validate()`.

## Resources

Each resource collection mirrors the matching CLI command family.

| SDK                               | CLI               |
| --------------------------------- | ----------------- |
| `env.data.list()`                 | `data list`       |
| `env.data.get(name)`              | `data show`       |
| `env.data.add(name, value)`       | `data add`        |
| `env.data.update(name, value)`    | `data update`     |
| `env.data.put(name, value)`       | *(add or update)* |
| `env.data.remove(name)`           | `data remove`     |
| `env.tasks.list()`                | `task list`       |
| `env.tasks.get(id)`               | `task show`       |
| `env.tasks.add(task)`             | `task add`        |
| `env.tasks.update(task)`          | `task update`     |
| `env.tasks.put(task)`             | *(add or update)* |
| `env.tasks.remove(id)`            | `task remove`     |
| `env.tools.list()`                | `tool list`       |
| `env.tools.scaffold(options)`     | `tool add`        |
| `env.verifiers.list()`            | `verifier list`   |
| `env.verifiers.scaffold(options)` | `verifier add`    |

`put` has no CLI equivalent — it adds or replaces without caring which, which is what you want in a generator that may run twice.

```typescript theme={null}
const entries = await env.data.list();      // DataEntry[]
const tickets = await env.data.get("tickets");
const tasks = await env.tasks.list();       // SiloTask[]
```

Mutating methods return the path they wrote, so a generator can log exactly what it produced.

## Scaffolding

```typescript theme={null}
const result = await env.tools.scaffold({
  name: "close_ticket",
  description: "Close a resolved ticket.",
});

const verifier = await env.verifiers.scaffold({
  id: "VER-001",
  taskId: "TASK-001",
  name: "Ticket closed",
});
```

Both return a `ScaffoldResult` describing the file created and the barrel entry added. As with the CLI, the generated code compiles and **fails on purpose** — it never contains business logic.

## Validation

```typescript theme={null}
const report = await env.validate();

if (!report.ok) {
  for (const finding of report.findings) {
    console.error(`${finding.level} ${finding.code} ${finding.message}`);
  }
}
```

Same shape as `env validate --json`: `ok`, `findings[]` and `counts`. It runs the real TypeScript compiler, not a file-presence check.

## Errors

Every failure throws a `SiloError` with a stable `code`:

```typescript theme={null}
import { SiloError, isSiloError } from "@burn0/silo";

try {
  await env.tasks.add(task);
} catch (error) {
  if (isSiloError(error) && error.code === "task_already_exists") {
    await env.tasks.update(task);
  }
}
```

`isSiloError` is a type guard, so `error.code` and `error.details` are typed inside the branch. See [Error Codes](/silo/reference/error-codes).

## Authoring exports

The SDK also re-exports what environment code itself is written against:

```typescript theme={null}
import {
  defineTool, bindTools, toolError, ToolError,   // tools
  defineVerifier, check, optional,               // verifiers
} from "@burn0/silo";
```

Those are the values your `tools/` and `verifiers/` files import. They are runtime values, not types, so the package must be installed for an environment to run — not only to type-check.

## Running

Running a rollout is currently a CLI concern. To run agents from a script, shell out:

```typescript theme={null}
execFileSync("npx", ["@burn0/silo", "run", "--env", "demo", "--task", "TASK-001"]);
```

Artifacts land in `.silo/runs/<runId>/` either way, and `result.json` is designed to be read back programmatically — see [Run Artifacts](/silo/running/artifacts).
