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

# Box Mount

> Mount a Box folder into an agent runtime as a POSIX filesystem, kept in two-way sync, with Box permissions and governance applied to every operation.

Box Mount brings Box content into any agent runtime as a standard POSIX filesystem. Agents read, write, and edit files using familiar file operations, with Box security, governance, and access controls applied to every operation. Continuous two-way sync keeps agent and Box content aligned, so people and agents collaborate in the same folders with built-in conflict protection.

<Note>
  Box Mount is in private preview. It is not publicly available, it is not covered by a production SLA, and features can change before general availability. Box provides the binary and setup guidance to preview participants. To request access, complete the [Box Mount private preview form](https://bit.ly/box-mount-preview).
</Note>

## How Box Mount works

Box Mount runs a background sync process, the daemon, that maps a Box folder to a local directory inside the sandbox your product provisions. It works with any supported Linux sandbox, including Daytona, Docker, E2B, and Vercel Sandbox, and is not tied to one vendor.

* **Content stays in Box.** Your agent works against a local path, and every operation flows through the Box API.
* **Governance follows the content.** Every operation runs as the identity Box Mount authenticates with, so that identity's permissions, retention, legal hold, ethical walls, and audit trail apply to the agent, along with any Box Shield security policies driven by classification. In OAuth mode the identity is the user who authorized the app, so the agent can never reach content that the user cannot. In JWT mode the identity is the service account, so scope that account to the content the agent needs.
* **Sync runs both ways.** Changes an agent makes in the mount upload to Box, and updates from people or other agents are reflected back in the mount.
* **Conflicts are preserved, not overwritten.** When two writers change the same file at the same time, Box Mount detects the conflict at upload and keeps both results, either as a new Box version or as a separate conflict copy, so a reviewer can merge the work or roll back using Box version history.

Because the agent works with plain files, most tools work against Box content without knowing it is Box. Read [Known limitations](#known-limitations) first, because applications that save a file by replacing it rather than editing it in place behave differently.

## See Box Mount in action

This demo builds a contract review agent that mounts a Box folder into an E2B sandbox, runs the agent against that workspace, and syncs the finished review back to Box for a person to review.

<iframe width="100%" height="500" src="https://www.youtube.com/embed/bLyPe0FTc5w" title="Build a Contract Review Agent with Box Mount and E2B" frameborder="0" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen />

For the architecture behind the demo and more workflow patterns, read [Meet Box Mount: A Box workspace for sandboxed AI agents](https://blog.box.com/meet-box-mount-box-workspace-sandboxed-ai-agents) on the Box blog.

## Before you begin

You need:

* Access to the Box Mount private preview, including the Box Mount binary. To request access, complete the [Box Mount private preview form](https://bit.ly/box-mount-preview).
* A Box app in the [Developer Console](https://app.box.com/developers/console), configured for either [OAuth 2.0](/guides/authentication/oauth2/oauth2-setup) or [JWT](/guides/authentication/jwt/jwt-setup) authentication.
* The ID of the Box folder you want to mount. This is the number at the end of the folder URL on Box.

### Supported platforms

Box Mount supports Linux runtimes on the x86\_64 and ARM64 architectures. macOS is not supported.

## Commands

| Command                                         | What it does                                                                                  |
| ----------------------------------------------- | --------------------------------------------------------------------------------------------- |
| `box-mount config`                              | Configures credentials and sync settings interactively                                        |
| `box-mount mount "<local-dir>" "<box-id>"`      | Mounts a Box folder to `<local-dir>`, an absolute local path. `<box-id>` is the Box folder ID |
| `box-mount status`                              | Reports the state of the current mount                                                        |
| `box-mount unmount "<local-dir>"`               | Unmounts the local directory, using its absolute path                                         |
| `box-mount unmount --reset-force "<local-dir>"` | Unmounts and force-deletes all local mount contents                                           |

A first session looks like this:

```bash theme={null}
box-mount config
mkdir -p /mnt/box
box-mount mount "/mnt/box" "123456789"
box-mount status
```

Your agent now works against `/mnt/box`.

## Configure credentials

Box Mount reads Box credentials from a `box-config.json` file in `~/.box-mount/`, or in the path you pass to `--data-path`.

The `config` command handles configuration interactively in one step and writes `~/.box-mount/box-config.json`:

```bash theme={null}
box-mount config
```

Box Mount supports two authentication modes, OAuth and JWT. OAuth is the default. Enter `oauth` or `jwt` when prompted. Restrict the config file, and any JWT private key JSON it points at, as described in [Secure your credentials](#secure-your-credentials).

### Configure OAuth manually

Create `~/.box-mount/box-config.json` and fill in your Box app credentials:

```json theme={null}
{
  "client_id":     "YOUR_BOX_CLIENT_ID",
  "client_secret": "YOUR_BOX_CLIENT_SECRET",
  "access_token":  "",
  "refresh_token": "",
  "redirect_uri":  "http://localhost:3000/callback"
}
```

| Field           | Required   | Notes                                                                        |
| --------------- | ---------- | ---------------------------------------------------------------------------- |
| `client_id`     | Yes        | From the Developer Console                                                   |
| `client_secret` | Yes        | From the Developer Console                                                   |
| `access_token`  | Yes        | Run `box-mount config` to obtain one through OAuth                           |
| `refresh_token` | OAuth only | Run `box-mount config` to obtain one through OAuth. Rotated on every refresh |
| `redirect_uri`  | No         | Must match the Box app setting exactly. Used when configuring OAuth          |

The OAuth config has no `auth_type` field because OAuth is the default mode. Set `auth_type` only to switch to JWT.

### Configure JWT manually

For a JWT service account, the config needs only two fields:

```json theme={null}
{
  "auth_type": "jwt",
  "jwt_config_path": "/path/to/box-jwt-config.json"
}
```

| Field             | Required | Notes                                           |
| ----------------- | -------- | ----------------------------------------------- |
| `auth_type`       | Yes      | Must be `jwt`                                   |
| `jwt_config_path` | Yes      | Absolute path to the Developer Console JWT JSON |

`jwt_config_path` must point to the JSON file generated by the Developer Console. To create it, open your app's **Configuration** tab and, in **App Settings**, select **Generate a Public/Private Keypair**. JWT authentication does not need an `access_token` or a `refresh_token`, because the SDK obtains short-lived access tokens automatically.

### Use environment variables

You can supply credential fields through environment variables instead of the JSON file. Environment variables take precedence over file values, and the JSON file is optional when you provide every required field this way.

| Variable              | Config key        | Notes                                                                                   |
| --------------------- | ----------------- | --------------------------------------------------------------------------------------- |
| `BOX_CLIENT_ID`       | `client_id`       | OAuth app client ID                                                                     |
| `BOX_CLIENT_SECRET`   | `client_secret`   | OAuth app client secret                                                                 |
| `BOX_ACCESS_TOKEN`    | `access_token`    | Current access token. Updated in-process and written back to the config file on refresh |
| `BOX_REFRESH_TOKEN`   | `refresh_token`   | Current refresh token. Same write-back behavior as the access token                     |
| `BOX_AUTH_TYPE`       | `auth_type`       | Set to `jwt` to enable JWT mode                                                         |
| `BOX_JWT_CONFIG_PATH` | `jwt_config_path` | Path to the Developer Console JWT JSON. JWT mode only                                   |

<Warning>
  Do not persist `BOX_ACCESS_TOKEN` or `BOX_REFRESH_TOKEN` in shell startup files such as `.zprofile` or `.bashrc`. When Box Mount refreshes tokens it writes the new values to `~/.box-mount/box-config.json`, which leaves any copies baked into the environment stale, and stale tokens cause authentication failures on the next run. Export these variables only for the duration of a session.

  Do not put `BOX_*` credentials in the environment of an LLM agent or any other untrusted process. See [Secure your credentials](#secure-your-credentials).
</Warning>

### Use a developer token

[Developer tokens](/guides/authentication/tokens/developer-tokens) are short-lived tokens you generate in the Developer Console. They are valid for 60 minutes, cannot be refreshed, and are useful for quick testing without the full OAuth flow.

Set `access_token` in `~/.box-mount/box-config.json` and leave `refresh_token` empty:

```json theme={null}
{
  "client_id":     "YOUR_BOX_CLIENT_ID",
  "client_secret": "YOUR_BOX_CLIENT_SECRET",
  "access_token":  "PASTE_DEVELOPER_TOKEN_HERE",
  "refresh_token": ""
}
```

You can also pass the token through the environment and skip the config file:

```bash theme={null}
export BOX_ACCESS_TOKEN="PASTE_DEVELOPER_TOKEN_HERE"
box-mount mount "/local/path" "123456789"
```

Because developer tokens cannot be refreshed, Box Mount stops syncing when the token expires. Generate a new token in the Developer Console and update `access_token`, or re-export the environment variable, to resume.

## Token lifecycle

In OAuth mode:

* Access tokens expire after about 60 minutes, and the SDK refreshes them automatically.
* Each refresh rotates the refresh token, and the old one is invalidated immediately.
* Rotated tokens are written back to `~/.box-mount/box-config.json`.
* Refresh tokens expire after 60 days without use. Run `box-mount config` again to repeat the OAuth flow.

In JWT mode:

* The SDK signs a JWT assertion, exchanges it for a short-lived access token, and refreshes that token automatically. Tokens are held in memory only, so nothing is written to `box-config.json`.
* Authentication needs no user interaction as long as the JWT config JSON and private key are valid.

## Secure your credentials

Box credentials are a Box API identity, and that identity is usually broader than the folder you mount. This applies to the OAuth client secret and tokens in `box-config.json`, the `BOX_*` environment variables, and the JWT private key JSON on disk. Anyone who reads them can call the Box API as that app or user, not only read the files in the mount.

The daemon that `box-mount mount` starts needs those credentials, and the mount directory is the only surface other processes should share. Keep `~/.box-mount/`, which holds the config, database, process ID, and logs, private to the account that runs Box Mount.

### Recommended setup on an agent sandbox

When an LLM agent runs on the same machine as Box Mount, do not run the agent as the same Unix user as the daemon. Use two users:

| Role             | Unix user | What it can access                                     |
| ---------------- | --------- | ------------------------------------------------------ |
| Box Mount daemon | User A    | `~/.box-mount/`, the JWT JSON, and the mount directory |
| LLM agent        | User B    | The mount directory only                               |

1. Create the two users. Run `box-mount config` as user A so that `~/.box-mount/` lives in the home directory of user A. Do not mount yet, because bootstrap fills the tree and the share permissions must be set on an empty mount directory first.

2. Restrict the credentials so that only user A can read them, then confirm ownership with `ls -l`. Mode `644`, which is world-readable, is not appropriate for these files.

   ```bash theme={null}
   chmod 700 ~/.box-mount
   chmod 600 ~/.box-mount/box-config.json
   chmod 600 /path/to/box-jwt-config.json   # JWT mode only
   ```

3. Share only the mount directory with user B, using a shared group, setgid, and a default POSIX ACL. Setgid copies group ownership onto new inodes, and the default ACL inherits group write access. Apply this to an empty directory, then mount. The `setfacl` command ships in the `acl` package.

   ```bash theme={null}
   sudo mkdir -p /path/to/mount
   sudo groupadd boxmount
   sudo usermod -aG boxmount userA
   sudo usermod -aG boxmount userB
   sudo chown userA:boxmount /path/to/mount
   sudo chmod 2770 /path/to/mount
   sudo setfacl -m g:boxmount:rwx -m d:g:boxmount:rwx /path/to/mount
   box-mount mount "/path/to/mount" "<box-id>"   # as user A
   ```

   User B must not have read access to the home directory of user A, to `--data-path`, or to the JWT file. User B must also be able to traverse every directory above the mount, which is why the example puts the mount outside any home directory. If you place the mount inside the home directory of user A instead, a home directory set to `750` blocks user B even when the mount directory itself is `2770`.

4. Start the agent as user B. Do not export `BOX_CLIENT_ID`, `BOX_CLIENT_SECRET`, `BOX_ACCESS_TOKEN`, `BOX_REFRESH_TOKEN`, or `BOX_JWT_CONFIG_PATH` in the shell, systemd unit, or container spec of the agent. Those values are visible in the process environment and belong only to the daemon process of user A.

5. In JWT mode, use a service account scoped to the content the agent needs, rather than an enterprise admin keypair.

On a personal machine, where you are the only process using the mount, running Box Mount as your own user is expected, and follows the same model as SSH keys in `$HOME`. That layout is not appropriate when the other process is an untrusted agent.

<Warning>
  This isolation does not protect against root on the machine, kernel exploits, or running the agent as user A. It also does not reduce what the agent can do inside the mount, because user B has normal filesystem access to that tree.
</Warning>

## Data and log locations

By default, `--data-path` points to `~/.box-mount/`, and Box Mount derives all other paths from it:

| Path                             | Contents                                                                                                                                            |
| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `~/.box-mount/mount.json`        | Mount record                                                                                                                                        |
| `~/.box-mount/box-config.json`   | Box credentials                                                                                                                                     |
| `~/.box-mount/local-config.json` | Local sync settings                                                                                                                                 |
| `~/.box-mount/data/`             | `sync.sqlite3`, `bdlc.pid`, and `teardown.json`, which is present only during an incomplete reset or unmount                                        |
| `~/.box-mount/logs/`             | `box-mount-sync.stdout.log` and `box-mount-sync.stderr.log` for daemon output, plus a `box-mount-sync-YYYYMMDD-HHMMSS-ffffff.log` file for each run |

Treat this tree as private to the daemon. See [Secure your credentials](#secure-your-credentials).

## Known limitations

### No support for atomic save

Box Mount does not support atomic save, also called safe write, where an application saves a file by writing a temporary file and renaming it over the original instead of editing in place. Files saved this way lose their Box version history, because Box Mount syncs the replacement as a new file rather than as a new version of the existing file.

### Workload limits

For the preview, use non-production workloads of up to 5 GB of content and 10,000 files per mount.

## Related tools

Box Mount complements the other ways agents reach Box content. Use Box Mount when an agent needs to do file work in place, and use the following tools for API-level and command-line access:

| Tool                              | Use it for                                                                 |
| --------------------------------- | -------------------------------------------------------------------------- |
| [Box MCP server](/guides/box-mcp) | Giving agents tool-based access to Box search, Box AI, and file operations |
| [Box CLI](/guides/cli)            | Running routine or bulk Box actions from the command line                  |
| [Box SDKs](/guides/tooling/sdks)  | Building applications directly against the Box API                         |
