---
title: "File System"
description: "Read, write, and manage files inside the sandbox."
sidebarTitle: "File System"
icon: "folder"
---

The filesystem API lets you list, read, write, move, and delete files inside the sandbox, plus upload tar archives in batch.

## Path resolution

- Absolute paths are used as-is.
- Relative paths resolve from the server process working directory.
- Requests that attempt to escape allowed roots are rejected by the server.

## List entries

<CodeGroup>
```ts TypeScript
import { SandboxAgent } from "sandbox-agent";

const sdk = await SandboxAgent.connect({
  baseUrl: "http://127.0.0.1:2468",
});

const entries = await sdk.listFsEntries({
  path: "./workspace",
});

console.log(entries);
```

```bash cURL
curl -X GET "http://127.0.0.1:2468/v1/fs/entries?path=./workspace"
```
</CodeGroup>

## Read and write files

`PUT /v1/fs/file` writes raw bytes. `GET /v1/fs/file` returns raw bytes.

<CodeGroup>
```ts TypeScript
import { SandboxAgent } from "sandbox-agent";

const sdk = await SandboxAgent.connect({
  baseUrl: "http://127.0.0.1:2468",
});

await sdk.writeFsFile({ path: "./notes.txt" }, "hello");

const bytes = await sdk.readFsFile({ path: "./notes.txt" });
const text = new TextDecoder().decode(bytes);

console.log(text);
```

```bash cURL
curl -X PUT "http://127.0.0.1:2468/v1/fs/file?path=./notes.txt" \
  --data-binary "hello"

curl -X GET "http://127.0.0.1:2468/v1/fs/file?path=./notes.txt" \
  --output ./notes.txt
```
</CodeGroup>

## Create directories

<CodeGroup>
```ts TypeScript
import { SandboxAgent } from "sandbox-agent";

const sdk = await SandboxAgent.connect({
  baseUrl: "http://127.0.0.1:2468",
});

await sdk.mkdirFs({ path: "./data" });
```

```bash cURL
curl -X POST "http://127.0.0.1:2468/v1/fs/mkdir?path=./data"
```
</CodeGroup>

## Move, delete, and stat

<CodeGroup>
```ts TypeScript
import { SandboxAgent } from "sandbox-agent";

const sdk = await SandboxAgent.connect({
  baseUrl: "http://127.0.0.1:2468",
});

await sdk.moveFs({
  from: "./notes.txt",
  to: "./notes-old.txt",
  overwrite: true,
});

const stat = await sdk.statFs({ path: "./notes-old.txt" });
await sdk.deleteFsEntry({ path: "./notes-old.txt" });

console.log(stat);
```

```bash cURL
curl -X POST "http://127.0.0.1:2468/v1/fs/move" \
  -H "Content-Type: application/json" \
  -d '{"from":"./notes.txt","to":"./notes-old.txt","overwrite":true}'

curl -X GET "http://127.0.0.1:2468/v1/fs/stat?path=./notes-old.txt"

curl -X DELETE "http://127.0.0.1:2468/v1/fs/entry?path=./notes-old.txt"
```
</CodeGroup>

## Batch upload (tar)

Batch upload accepts `application/x-tar` and extracts into the destination directory.

<CodeGroup>
```ts TypeScript
import { SandboxAgent } from "sandbox-agent";

const sdk = await SandboxAgent.connect({
  baseUrl: "http://127.0.0.1:2468",
});

// Requires `tar` to be installed (it's an optional peer dependency).
const result = await sdk.uploadFsBatch({ sourcePath: "./skills" }, {
  path: "./skills",
});

console.log(result);
```

```bash cURL
tar -cf skills.tar -C ./skills .

curl -X POST "http://127.0.0.1:2468/v1/fs/upload-batch?path=./skills" \
  -H "Content-Type: application/x-tar" \
  --data-binary @skills.tar
```
</CodeGroup>

## Batch download (tar)

Batch download returns `application/x-tar` bytes for a file or directory. If the path is a directory,
the archive contains the directory contents (similar to `tar -C <dir> .`).

<CodeGroup>
```ts TypeScript
import { SandboxAgent } from "sandbox-agent";

const sdk = await SandboxAgent.connect({
  baseUrl: "http://127.0.0.1:2468",
});

// Requires `tar` to be installed if you want to extract (it's an optional peer dependency).
await sdk.downloadFsBatch({ path: "./skills" }, { outPath: "./skills.tar" });
await sdk.downloadFsBatch({ path: "./skills" }, { extractTo: "./skills-extracted" });
```

```bash cURL
curl -X GET "http://127.0.0.1:2468/v1/fs/download-batch?path=./skills" \
  --output ./skills.tar
```
</CodeGroup>
