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

# Work with files

> Transfer and manage files and directories in a Devbox with the TypeScript SDK.

Use `devbox.fs` to transfer files between the local machine and a Devbox, read and write bytes, and manage remote files and directories.

<Info>
  Filesystem operations start a stopped Devbox automatically. Relative remote paths are passed unchanged to the Devbox's SFTP or command session. Use absolute paths when the location must be unambiguous. The SDK caches the connection and SFTP channel for reuse.
</Info>

## `fs.upload()`

Upload one local file to the Devbox. This method does not upload directories.

### Example

```typescript {2} theme={null}
const devbox = await client.devboxes.get("sdk-example");
await devbox.fs.upload("./package.json", "/workspace/package.json");
```

### API reference

```typescript theme={null}
upload(localPath: string, remotePath: string, options?: TransferOptions): Promise<void>
```

#### Arguments and options

<ResponseField name="localPath" type="string" required>
  A path on the machine running the SDK. Relative paths resolve from that process's current working directory.
</ResponseField>

<ResponseField name="remotePath" type="string" required>
  The destination file path in the Devbox.
</ResponseField>

<ResponseField name="options" type="TransferOptions">
  Transfer and operation controls.

  <Expandable title="properties" defaultOpen>
    <ResponseField name="onProgress" type="(transferredBytes: number, totalBytes: number) => void">
      Called during transfer with the cumulative bytes transferred and total file size. It is not called when omitted.
    </ResponseField>

    <ResponseField name="signal" type="AbortSignal">Cancels the operation when aborted.</ResponseField>
    <ResponseField name="timeoutMs" type="number">Total activation, connection, and transfer budget in milliseconds. There is no default timeout. The value must be finite and non-negative.</ResponseField>
  </Expandable>
</ResponseField>

***

## `fs.download()`

Download one remote file to the local filesystem. This method does not download directories.

### Example

```typescript {2-3} theme={null}
const devbox = await client.devboxes.get("sdk-example");
await devbox.fs.download("/workspace/results.json", "./results.json", {
  onProgress: (transferred, total) => console.log(`${transferred}/${total}`),
});
```

### API reference

```typescript theme={null}
download(remotePath: string, localPath: string, options?: TransferOptions): Promise<void>
```

#### Arguments and options

<ResponseField name="remotePath" type="string" required>The source file in the Devbox.</ResponseField>
<ResponseField name="localPath" type="string" required>A local destination path. Relative paths resolve from the SDK process's current working directory.</ResponseField>
<ResponseField name="options" type="TransferOptions">The same `onProgress`, `signal`, and `timeoutMs` fields as `upload()`.</ResponseField>

***

## `fs.copy()`

Copy a file or directory within the Devbox. The operation invokes remote `cp` and rejects when it exits unsuccessfully.

### Example

```typescript {2} theme={null}
const devbox = await client.devboxes.get("sdk-example");
await devbox.fs.copy("/workspace/src", "/workspace/src-backup", { recursive: true });
```

### API reference

```typescript theme={null}
copy(sourcePath: string, destinationPath: string, options?: CopyOptions): Promise<void>
```

#### Arguments and options

<ResponseField name="sourcePath" type="string" required>The remote source path.</ResponseField>
<ResponseField name="destinationPath" type="string" required>The remote destination path.</ResponseField>

<ResponseField name="options" type="CopyOptions">
  <Expandable title="properties" defaultOpen>
    <ResponseField name="recursive" type="boolean" default="false">Passes `-R` to `cp`, allowing directories to be copied recursively.</ResponseField>
    <ResponseField name="signal" type="AbortSignal">Cancels the operation when aborted.</ResponseField>
    <ResponseField name="timeoutMs" type="number">Total operation budget in milliseconds. There is no default timeout.</ResponseField>
  </Expandable>
</ResponseField>

***

## `fs.readFile()`

Read an entire remote file into memory as raw bytes. The SDK does not decode its contents.

### Example

```typescript {2} theme={null}
const devbox = await client.devboxes.get("sdk-example");
const text = new TextDecoder().decode(await devbox.fs.readFile("/workspace/message.txt"));
```

### API reference

```typescript theme={null}
readFile(remotePath: string, options?: OperationOptions): Promise<Uint8Array>
```

#### Arguments and options

<ResponseField name="remotePath" type="string" required>The remote file to read.</ResponseField>
<ResponseField name="options" type="OperationOptions">Optional `signal` and `timeoutMs` operation controls.</ResponseField>

#### Return value

A `Uint8Array` containing the file's unmodified bytes.

***

## `fs.writeFile()`

Write a string or raw bytes to a remote file. The file is created or truncated. Strings are written as UTF-8.

### Example

```typescript {2} theme={null}
const devbox = await client.devboxes.get("sdk-example");
await devbox.fs.writeFile("/workspace/config.json", JSON.stringify({ enabled: true }), { mode: 0o600 });
```

### API reference

```typescript theme={null}
writeFile(remotePath: string, data: string | Uint8Array, options?: WriteFileOptions): Promise<void>
```

#### Arguments and options

<ResponseField name="remotePath" type="string" required>The remote file to create or replace.</ResponseField>
<ResponseField name="data" type="string | Uint8Array" required>UTF-8 text or bytes to write.</ResponseField>

<ResponseField name="options" type="WriteFileOptions">
  <Expandable title="properties" defaultOpen>
    <ResponseField name="mode" type="number">POSIX permission bits, such as `0o600`. When omitted, the SFTP server applies its default permissions and umask.</ResponseField>
    <ResponseField name="signal" type="AbortSignal">Cancels the operation when aborted.</ResponseField>
    <ResponseField name="timeoutMs" type="number">Total operation budget in milliseconds. There is no default timeout.</ResponseField>
  </Expandable>
</ResponseField>

***

## `fs.exists()`

Check whether a remote file, directory, or other filesystem object exists.

### Example

```typescript {2} theme={null}
const devbox = await client.devboxes.get("sdk-example");
if (await devbox.fs.exists("/workspace/package.json")) console.log("found");
```

### API reference

```typescript theme={null}
exists(remotePath: string, options?: OperationOptions): Promise<boolean>
```

#### Arguments and options

<ResponseField name="remotePath" type="string" required>The remote path to check.</ResponseField>
<ResponseField name="options" type="OperationOptions">Optional `signal` and `timeoutMs` operation controls.</ResponseField>

#### Return value

`false` only when the SFTP server reports that the path does not exist. Other failures reject the promise.

***

## `fs.rename()`

Rename or move a file or directory within the Devbox.

### Example

```typescript {2} theme={null}
const devbox = await client.devboxes.get("sdk-example");
await devbox.fs.rename("/workspace/draft.txt", "/workspace/final.txt");
```

### API reference

```typescript theme={null}
rename(oldPath: string, newPath: string, options?: OperationOptions): Promise<void>
```

#### Arguments and options

<ResponseField name="oldPath" type="string" required>The existing remote path.</ResponseField>
<ResponseField name="newPath" type="string" required>The new remote path.</ResponseField>
<ResponseField name="options" type="OperationOptions">Optional `signal` and `timeoutMs` operation controls.</ResponseField>

***

## `fs.mkdir()`

Create a remote directory, optionally creating each missing parent directory.

### Example

```typescript {2-4} theme={null}
const devbox = await client.devboxes.get("sdk-example");
await devbox.fs.mkdir("/workspace/output/assets", {
  recursive: true,
  mode: 0o755,
});
```

### API reference

```typescript theme={null}
mkdir(remotePath: string, options?: MkdirOptions): Promise<void>
```

#### Arguments and options

<ResponseField name="remotePath" type="string" required>The directory to create.</ResponseField>

<ResponseField name="options" type="MkdirOptions">
  <Expandable title="properties" defaultOpen>
    <ResponseField name="recursive" type="boolean" default="false">Creates missing parents and accepts directories that already exist.</ResponseField>
    <ResponseField name="mode" type="number">POSIX permissions applied to directories created by this call. When omitted, server defaults apply.</ResponseField>
    <ResponseField name="signal" type="AbortSignal">Cancels the operation when aborted.</ResponseField>
    <ResponseField name="timeoutMs" type="number">Total operation budget in milliseconds. There is no default timeout.</ResponseField>
  </Expandable>
</ResponseField>

***

## `fs.remove()`

Remove a remote file or directory. Without recursion, directories must be empty.

### Example

```typescript {2} theme={null}
const devbox = await client.devboxes.get("sdk-example");
await devbox.fs.remove("/workspace/output", { recursive: true });
```

### API reference

```typescript theme={null}
remove(remotePath: string, options?: RemoveOptions): Promise<void>
```

#### Arguments and options

<ResponseField name="remotePath" type="string" required>The remote path to remove.</ResponseField>

<ResponseField name="options" type="RemoveOptions">
  <Expandable title="properties" defaultOpen>
    <ResponseField name="recursive" type="boolean" default="false">Runs remote `rm -rf`, removing a directory tree and ignoring a missing path. When `false`, the SDK removes one file, symlink, or empty directory.</ResponseField>
    <ResponseField name="signal" type="AbortSignal">Cancels the operation when aborted.</ResponseField>
    <ResponseField name="timeoutMs" type="number">Total operation budget in milliseconds. There is no default timeout.</ResponseField>
  </Expandable>
</ResponseField>

***

## `fs.readdir()`

List the immediate children of a remote directory. It does not recurse and excludes `.` and `..`.

### Example

```typescript {2} theme={null}
const devbox = await client.devboxes.get("sdk-example");
const files = (await devbox.fs.readdir("/workspace")).filter((entry) => entry.type === "file");
```

### API reference

```typescript theme={null}
readdir(remotePath: string, options?: OperationOptions): Promise<DirEntry[]>
```

#### Arguments and options

<ResponseField name="remotePath" type="string" required>The remote directory to list.</ResponseField>
<ResponseField name="options" type="OperationOptions">Optional `signal` and `timeoutMs` operation controls.</ResponseField>

#### Return value

```typescript theme={null}
interface DirEntry {
  name: string;
  type: "file" | "directory" | "symlink" | "other";
}
```

Each entry contains its basename and detected type. Symbolic links are reported as `"symlink"`, not as the type of their target.

## Errors and cancellation

All methods reject with the abort signal's reason, or an `AbortError`, when cancelled. A finite, non-negative `timeoutMs` covers activation, connection, and the requested operation. Expiration rejects with `DevboxTimeoutError`. Invalid timeout values reject with `RangeError`; SFTP, transport, permission, and missing-path failures otherwise surface as their underlying errors. `copy()` and recursive `remove()` reject with `Error` when the remote command fails.

See [Handle errors and timeouts](/docs/reference/typescript-sdk/errors) for shared error handling guidance.
