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

# Read And Write Operations

> Read, write, inspect, and manage files and directories inside a sandbox

Use the local filesystem API to inspect paths, read and write content, and manage files and directories inside a running sandbox.

## Read And Write Files

<CodeGroup>
  ```typescript Node.js theme={null}
  await sandbox.files.writeText("/tmp/hello.txt", "hello from sandbox");

  const text = await sandbox.files.readText("/tmp/hello.txt");
  const bytes = await sandbox.files.readBytes("/tmp/hello.txt");

  console.log(text);
  console.log(bytes.toString("utf8"));
  ```

  ```python Python theme={null}
  sandbox.files.write_text("/tmp/hello.txt", "hello from sandbox")

  text = sandbox.files.read_text("/tmp/hello.txt")
  data = sandbox.files.read_bytes("/tmp/hello.txt")

  print(text)
  print(data.decode("utf-8"))
  ```
</CodeGroup>

Batch writes are also supported:

<CodeGroup>
  ```typescript Node.js theme={null}
  await sandbox.files.write([
    { path: "/tmp/a.txt", data: "alpha" },
    { path: "/tmp/b.bin", data: Buffer.from([1, 2, 3]) },
  ]);
  ```

  ```python Python theme={null}
  from hyperbrowser.models import SandboxFileWriteEntry

  sandbox.files.write(
      [
          SandboxFileWriteEntry(path="/tmp/a.txt", data="alpha"),
          SandboxFileWriteEntry(path="/tmp/b.bin", data=bytes([1, 2, 3])),
      ]
  )
  ```
</CodeGroup>

## Read Ranges And Different Formats

Use `read()` when you want to control offset, length, or representation.

Supported formats include:

* `text`
* `bytes`
* `blob`
* `stream`

## List And Inspect Paths

<CodeGroup>
  ```typescript Node.js theme={null}
  const exists = await sandbox.files.exists("/tmp/hello.txt");
  const info = await sandbox.files.getInfo("/tmp/hello.txt");
  const entries = await sandbox.files.list("/tmp", { depth: 1 });

  console.log(exists);
  console.log(info.permissions, info.owner, info.group);
  console.log(entries.map((entry) => entry.path));
  ```

  ```python Python theme={null}
  exists = sandbox.files.exists("/tmp/hello.txt")
  info = sandbox.files.get_info("/tmp/hello.txt")
  entries = sandbox.files.list("/tmp", depth=1)

  print(exists)
  print(info.permissions, info.owner, info.group)
  print([entry.path for entry in entries])
  ```

  ```bash CLI theme={null}
  hx file exists <sandbox-id> /tmp/hello.txt
  hx file stat <sandbox-id> /tmp/hello.txt
  hx file ls <sandbox-id> /tmp --depth 1
  ```
</CodeGroup>

## Move, Copy, Remove, And Update Permissions

<CodeGroup>
  ```typescript Node.js theme={null}
  await sandbox.files.makeDir("/tmp/data", { parents: true });
  await sandbox.files.writeText("/tmp/data/source.txt", "payload");

  await sandbox.files.copy({
    source: "/tmp/data/source.txt",
    destination: "/tmp/data/copied.txt",
  });

  await sandbox.files.rename("/tmp/data/copied.txt", "/tmp/data/renamed.txt");
  await sandbox.files.chmod({ path: "/tmp/data/renamed.txt", mode: "0644" });
  await sandbox.files.remove("/tmp/data/source.txt");
  ```

  ```python Python theme={null}
  sandbox.files.make_dir("/tmp/data", parents=True)
  sandbox.files.write_text("/tmp/data/source.txt", "payload")

  sandbox.files.copy(
      source="/tmp/data/source.txt",
      destination="/tmp/data/copied.txt",
  )

  sandbox.files.rename("/tmp/data/copied.txt", "/tmp/data/renamed.txt")
  sandbox.files.chmod(path="/tmp/data/renamed.txt", mode="0644")
  sandbox.files.remove("/tmp/data/source.txt")
  ```

  ```bash CLI theme={null}
  hx file mkdir <sandbox-id> /tmp/data --parents
  hx file cp <sandbox-id> /tmp/data/source.txt /tmp/data/copied.txt
  hx file mv <sandbox-id> /tmp/data/copied.txt /tmp/data/renamed.txt
  hx file chmod <sandbox-id> /tmp/data/renamed.txt 0644
  hx file rm <sandbox-id> /tmp/data/source.txt
  ```
</CodeGroup>

## Behavior Notes

The current filesystem implementation has a few practical guarantees worth knowing:

* `remove` is idempotent for missing paths.
* Removing a symlink removes the link, not the target.
* Directory listings do not recurse through symlink loops.
* Recursive copies preserve symlinks instead of expanding them indefinitely.
