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

# Binary File Operations

> Write and read arbitrary binary data — PNGs, compiled artifacts, base64-decoded payloads — through the Declaw sandbox filesystem.

The `sbx.files.write()` API accepts both strings and raw bytes. When you pass
`bytes` (Python) or `Uint8Array` (TypeScript), the SDK automatically routes
the payload to the binary-safe `PUT /files/raw` endpoint
(`Content-Type: application/octet-stream`, 500 MiB cap) instead of the
text-only JSON endpoint. Callers pass whatever type they have — no manual
base64 dance required.

## What You'll Learn

* Writing raw bytes with `sbx.files.write(path, b"...")`
* Reading bytes back with `format="bytes"` and verifying byte-identical round-trip
* Writing real binary formats (a PNG) and proving the sandbox can decode them
* The `base64.b64decode(...)` → `files.write(...)` pattern common in LLM tool-use pipelines
* Mixed batch writes — `WriteEntry` entries with `str` and `bytes` data in a single `write_files()` call

## Prerequisites

<Snippet file="snippets/env-setup.mdx" />

## Code Walkthrough

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    import base64
    import os
    from declaw import Sandbox, WriteEntry

    # 1x1 transparent PNG — 67 bytes.
    PNG_B64 = (
        "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwC"
        "AAAAC0lEQVR42mNgYAAAAAMAASsJTYQAAAAASUVORK5CYII="
    )

    sbx = Sandbox.create(template="base", timeout=300)
    ```

    **Random binary blob — the classic round-trip test:**

    ```python theme={null}
    blob = os.urandom(4096)
    sbx.files.write("/tmp/blob.bin", blob)
    got = sbx.files.read("/tmp/blob.bin", format="bytes")
    assert bytes(got) == blob
    ```

    **Real PNG — write it, then let the sandbox decode it:**

    ```python theme={null}
    png_bytes = base64.b64decode(PNG_B64)
    sbx.files.write("/tmp/pixel.png", png_bytes)

    result = sbx.commands.run("file /tmp/pixel.png")
    print(result.stdout.strip())
    # /tmp/pixel.png: PNG image data, 1 x 1, 8-bit/color RGBA, non-interlaced
    ```

    **Base64-decoded payload — the LLM tool-use pattern:**

    ```python theme={null}
    payload_b64 = base64.b64encode(b"\x00\x01\xff\xfe\x80\x81").decode()
    decoded = base64.b64decode(payload_b64)
    sbx.files.write("/tmp/decoded.bin", decoded)
    ```

    **Mixed batch — `str` and `bytes` entries in a single call.** The SDK
    partitions entries internally (str → JSON batch, bytes → raw PUT) and
    returns results in the original input order:

    ```python theme={null}
    results = sbx.files.write_files([
        WriteEntry(path="/tmp/readme.txt", data="Hello from a mixed batch."),
        WriteEntry(path="/tmp/config.bin", data=os.urandom(256)),
    ])
    for r in results:
        print(r.path, r.size)
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    import { Sandbox } from "@declaw/sdk";
    import type { WriteEntry } from "@declaw/sdk";
    import { Buffer } from "node:buffer";
    import { randomBytes } from "node:crypto";

    const PNG_B64 =
      "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNgYAAAAAMAASsJTYQAAAAASUVORK5CYII=";

    const sbx = await Sandbox.create({ template: "base", timeout: 300 });
    ```

    **Random binary blob:**

    ```typescript theme={null}
    const blob = new Uint8Array(randomBytes(4096));
    await sbx.files.write("/tmp/blob.bin", blob);
    const got = await sbx.files.read("/tmp/blob.bin", { format: "bytes" });
    ```

    **Real PNG:**

    ```typescript theme={null}
    const pngBytes = new Uint8Array(Buffer.from(PNG_B64, "base64"));
    await sbx.files.write("/tmp/pixel.png", pngBytes);
    const result = await sbx.commands.run("file /tmp/pixel.png");
    console.log(result.stdout.trim());
    ```

    **Mixed batch:**

    ```typescript theme={null}
    const entries: WriteEntry[] = [
      { path: "/tmp/readme.txt", data: "Hello from a mixed batch." },
      { path: "/tmp/config.bin", data: new Uint8Array(randomBytes(256)) },
    ];
    await sbx.files.writeFiles(entries);
    ```
  </Tab>
</Tabs>

## When to use the URL helpers instead

`/files/raw` caps request bodies at 500 MiB, but the JSON gateway in front
caps the text endpoint at 10 MiB. For very large uploads (hundreds of MB or
GB-class), prefer `sbx.upload_url(path)` and `sbx.download_url(path)` — they
return URLs your client can `PUT`/`GET` streams against directly.

```python theme={null}
url = sbx.upload_url("/data/huge.tar.gz")
# Use `requests`, `httpx`, or curl to PUT a large stream at this URL.
```

## Expected Output (Python)

```
Sandbox created: sbx_abc123

--- Section 1: Random binary blob ---
Wrote and read back 4096 random bytes, sha=<hex>

--- Section 2: Real PNG ---
`file` output: /tmp/pixel.png: PNG image data, 1 x 1, 8-bit/color RGBA, non-interlaced

--- Section 3: Base64-decoded payload ---
Wrote 8 decoded bytes, round-trip OK

--- Section 4: Mixed batch write ---
  wrote /tmp/readme.txt (25 bytes)
  wrote /tmp/config.bin (256 bytes)
Both entries round-tripped cleanly.
```
