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

# Filesystem

> Read, write, list, and manage files on the sandbox disk through five governed operations.

The agent reaches the [computer](/docs/computer/index)'s disk through five file operations. They are deliberately small and explicit — there is no separate upload/download channel and no hidden sync. Scratch work lives here; anything the agent should hand back is promoted to [Files](/docs/capabilities/files) with `publish_file`.

<Info>
  **This page is the canonical sandbox file API.** The `fs/*` routes below (`fs/write`, `fs/read`, `fs/list`, `fs/mkdir`, `fs/remove`) are the single source of truth for reading and writing a computer's disk. Sandbox scratch files are distinct from persistent, org-scoped [Files](/docs/capabilities/files) — the latter are what an agent publishes to keep beyond a run.
</Info>

<Note>
  File operations on a **sleeping** computer wake it automatically. On a **parked** computer they are **rejected** — resume it first. See [lifecycle](/docs/computer/sandbox#lifecycle).
</Note>

## Binary files

There is no dedicated upload or download operation. To move binary data in or out of the sandbox, use `write` / `read` with `encoding: "base64"`.

<CodeGroup>
  ```bash CLI theme={"system"}
  # write a text file, then read it back
  vetta computer fs write box /workspace/notes.txt --content "hello"
  vetta computer fs read box /workspace/notes.txt

  # write binary via base64
  vetta computer fs write box /workspace/logo.png \
    --encoding base64 --content "$(base64 -i ./logo.png)"
  ```

  ```typescript TypeScript theme={"system"}
  // One method, one operation per call: `read`, `write`, `list`, `mkdir`, `remove`.
  await vetta.computers.fs(computer.id, "write", {
    path: "/workspace/notes.txt",
    content: "hello",
  });

  const { content } = await vetta.computers.fs(computer.id, "read", {
    path: "/workspace/notes.txt",
  });

  // binary round-trip
  await vetta.computers.fs(computer.id, "write", {
    path: "/workspace/logo.png",
    encoding: "base64",
    content: pngBuffer.toString("base64"),
  });
  ```

  ```bash cURL theme={"system"}
  curl https://api.vetta.sh/v1/computers/$COMPUTER_ID/fs/write \
    -H "Authorization: Bearer $VETTA_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{ "path": "/workspace/notes.txt", "content": "hello", "encoding": "utf-8" }'
  ```
</CodeGroup>

## Working directory

The filesystem operations take **absolute paths** — they do not carry a working directory. The current directory is a per-exec concern: pass `cwd` to the [`bash` tool](/docs/computer/shell) to control where a command runs. Nothing about `cwd` persists between calls.

## Limits at a glance

| Operation | Limit                                  |
| --------- | -------------------------------------- |
| `write`   | 4 MiB per file                         |
| `read`    | 4 MiB per file                         |
| `list`    | Immediate children only (incl. hidden) |
| `remove`  | Refuses `/`; recursive otherwise       |

## Operations

<Tabs>
  <Tab title="write">
    Write bytes to a path, creating or overwriting the file.

    <ParamField path="path" type="string" required>Absolute path of the file to write.</ParamField>
    <ParamField path="content" type="string" required>The file contents. Interpreted according to `encoding`.</ParamField>
    <ParamField path="encoding" type="string" default="utf-8">`utf-8` for text, or `base64` for binary payloads.</ParamField>

    <Warning>Maximum **4 MiB** per file per write. Split larger payloads across multiple writes or generate them in-sandbox with the [shell](/docs/computer/shell).</Warning>
  </Tab>

  <Tab title="read">
    Read a file back.

    <ParamField path="path" type="string" required>Absolute path of the file to read.</ParamField>
    <ParamField path="encoding" type="string" default="utf-8">`utf-8` or `base64`. Use `base64` to pull binary content back out.</ParamField>

    <ResponseField name="content" type="string">The file contents in the requested encoding.</ResponseField>

    <Warning>Reads are capped at **4 MiB**. Larger files must be chunked or processed in-sandbox.</Warning>
  </Tab>

  <Tab title="list">
    List the **immediate children** of a directory, including hidden entries (dotfiles). Not recursive.

    <ParamField path="path" type="string" required>Absolute path of the directory to list.</ParamField>

    <ResponseField name="entries" type="object[]">One entry per child with its name and type (file or directory).</ResponseField>
  </Tab>

  <Tab title="mkdir">
    Create a directory, including any missing parents (`mkdir -p`).

    <ParamField path="path" type="string" required>Absolute path of the directory to create.</ParamField>
  </Tab>

  <Tab title="remove">
    Remove a file or directory recursively (`rm -rf`).

    <ParamField path="path" type="string" required>Absolute path to remove.</ParamField>

    <Warning>`remove` **refuses `/`** outright. It is otherwise recursive and irreversible — there is no trash.</Warning>
  </Tab>
</Tabs>

<Card title="Next: shell" icon="terminal" href="/docs/computer/shell">
  Run commands with the `bash` tool and read the buffered output.
</Card>
