Skip to main content
The Dropbox VFS mounts a Dropbox account at some prefix such as /dropbox/. All operations involve network I/O to the Dropbox v2 HTTP API: /2/files/list_folder for directories, /2/files/download for content, and /2/files/upload / create_folder_v2 / delete_v2 / move_v2 / copy_v2 for writes. Files are served as raw bytes. Both READ and WRITE modes are supported; single-call uploads cap at ~150 MB (Dropbox’s upload limit). rmdir fails ENOTEMPTY on a non-empty folder instead of using the API’s recursive delete; rm -r is the recursive path. For credential setup (app key, secret, refresh token), see the Dropbox Setup guide. The TypeScript packages ship the same backend for Node and the browser, see Dropbox (TypeScript).

Config

The access token is fetched from the long-lived refresh token and cached in memory, refreshing ~5 minutes before expiry.

Config Reference

Fields marked secret are redacted in snapshots.

VFS.md

The VFS.md an agent reads with Dropbox mounted at /<path>.

Virtual Filesystem

Supported Unix Commands for VFS

Unix commands work on each path as on a local filesystem, as far as the path supports them:

Limitations of Unix Commands for VFS

Where a path differs from a local filesystem:Run man <cmd> or <cmd> --help for one command’s usage.

Mount a subfolder

Pass root_path to expose a single Dropbox folder as the mount root instead of the whole account. Every command and FUSE/VFS op is scoped to that folder; paths outside it are unreachable.
root_path accepts Team/data, /Team/data, or /Team/data/ (all normalized the same way); .. segments are rejected.

Integration

What Dropbox answers through its own API, so fewer files are read. Integration explains each command. grep -rw and rg -w read only the files Dropbox search names. Every file is read when the search fails, reaches its 10,000-match limit or finds nothing. Search lists how each option uses the search. Dropbox can leave out a file that holds the word, so walk_limit: -1 in the mount’s "@all" command limit reads every file instead:
  • Full-text search needs a Dropbox Professional, Essentials or Business plan. On other plans Dropbox matches file names only, so files that hold the word are left out.
  • Dropbox searches the text it extracted, not the bytes grep reads, and indexes a write some time after it lands. A file that holds the word can be left out: an office file, PDF or archive, the end of a large file, a word Dropbox splits differently (foo.bar), or a recent write.

Cache

The Dropbox VFS caches directory listings via IndexCacheStore to reduce repeated API calls during traversal; with no index: configured, listings live for the mount’s ttl (600 s by default), at most 24 hours; a configured index: uses its own ttl, still capped by the mount’s ttl:. File reads go through the standard read cache (caches_reads = True). Under read: fresh, a cached file is checked against its content_hash before it is served: one get_metadata per warm read, never a folder listing. A download names the hash in its Dropbox-API-Result header, full or ranged, so a read stamps it with no extra request. server_modified is not used: Dropbox repeats it across same-size rewrites.

Names missing from a listing

A name missing from a cached listing that the running command did not fetch is looked up on Dropbox by path before mirage answers that it does not exist: one get_metadata for a stat, or the download itself for a read. A file another client created after the listing is therefore found, and >>, touch and sed -i act on it instead of replacing it. A listing the running command fetched itself is trusted as is, for the whole command. Each command of a script is its own command, but one long-running command, such as a program a runtime runs, does not see a file another client creates after it listed the folder. Some lookups run outside any shell command: FUSE, programmatic calls, [ ] and [[ ]] tests, and a redirect on anything but a simple command (a brace group, subshell, loop, if or case). No listing is the caller’s own there, so each lookup of a name missing from a cached listing costs one request.

Writes

A write records the content_hash its upload reply names, so a fresh read right after a tee or sed -i downloads nothing.

Conditional writes

A rewrite that observes a missing file requires atomic create-only support, which this backend does not currently enable. Appending to a missing file therefore returns an unsupported-operation error under either write policy. An intentional write with > can create the file, and subsequent appends to that existing file retain the selected policy. A Dropbox mount accepts write: conditional. A write that holds a version looks the file up once (get_metadata), refuses a file whose content_hash changed since it was read, and uploads in update mode with the file’s rev, so Dropbox refuses (409 path/conflict) a change that lands in between; a delete sends the rev as parent_rev. rm -r walks the folder file by file, and a mv within the mount is Dropbox’s own move, which is not refused when its source changed (a mv to another mount is a copy and a conditioned delete, so there a changed source stays and mv reports the failed removal).

Example

grep classifies the bytes it reads, including downloaded attachments. Use -I to skip binary inputs or -a (--binary-files=text) to search them as text. Text mode bypasses the content-search index and scans files directly.