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

# Disk

> Mount a local directory as a Mirage VFS with read/write shell commands and path traversal protection.

The Disk VFS mounts a local directory at some prefix such as `/data/`.
All operations are backed by real files on disk. Path resolution validates
against the root boundary to prevent directory traversal escapes.

## Config

```python theme={null}
from mirage import MountMode, Workspace
from mirage.vfs.disk import DiskVFS

vfs = DiskVFS(root="/path/to/dir")
ws = Workspace({"/data": vfs}, mode=MountMode.READ)
```

`DiskVFS(root=..., folder_versions=True)` takes the `root` path of the
directory to mount. Both `READ` and `WRITE` modes are supported.

| Field | Default | Notes |
| - | - | - |
| `root` | required | The host directory the mount mirrors. |
| `folder_versions` | `True` | Store each listing at its folder's version, so a `read: fresh` mount re-lists only folders that changed. Must be a boolean. Turn it off for a network or FUSE root. |

## Filesystem Layout

The Disk VFS mirrors the structure of the `root` directory. For example,
if `root="/srv/files"` contains:

```text theme={null}
/srv/files/
  notes.txt
  config.json
  reports/
    q1.csv
    q2.csv
```

Then mounting at `/data/` exposes:

```text theme={null}
/data/
  notes.txt
  config.json
  reports/
    q1.csv
    q2.csv
```

Paths like `../../etc/passwd` are rejected - resolution is always confined
to the root boundary.

## Cache

The Disk VFS uses `IndexCacheStore` with `index_ttl = 60` (1 minute).
Directory listings are cached for up to 60 seconds before being refreshed
from disk.

Each listing is stored with its folder's version: the folder's device,
inode, change time and modified time. Under `read: fresh`, a later command
stats the folder and serves the cached listing while the version still matches, so
it pays one local stat per listed folder instead of a scan. A folder changed
in the last 2 seconds gets no version and is re-listed until it has been
quiet that long, since two changes inside one timestamp tick could leave its
times unmoved.

This assumes a local POSIX filesystem, where adding, renaming or removing an
entry moves the folder's change time. A network or FUSE root (NFS, SMB,
rclone, s3fs, mirage's own FUSE) may not, so turn the versions off there:

```python theme={null}
vfs = DiskVFS(root="/mnt/nfs/share", folder_versions=False)
```

That mount then re-lists a cached folder once per command, as every
unversioned backend does. See [the cache](/home/cache#listings-under-fresh).

## Example

```python theme={null}
import asyncio
import shutil
import tempfile
from pathlib import Path

from mirage import MountMode, Workspace
from mirage.vfs.disk import DiskVFS

DATA_DIR = Path("/path/to/files")

tmp = tempfile.mkdtemp()
shutil.copytree(DATA_DIR, Path(tmp) / "files", dirs_exist_ok=True)

vfs = DiskVFS(root=tmp + "/files")


async def main() -> None:
    ws = Workspace({"/data/": vfs}, mode=MountMode.READ)

    r = await ws.shell("ls /data/")
    print(await r.stdout_str())

    r = await ws.shell("cat /data/example.json")
    print(await r.stdout_str())

    r = await ws.shell("tree /data/")
    print(await r.stdout_str())

    r = await ws.shell("find /data/ -name '*.json'")
    print(await r.stdout_str())

    r = await ws.shell("grep example /data/example.json")
    print(await r.stdout_str())

    r = await ws.shell("stat /data/example.json")
    print(await r.stdout_str())


if __name__ == "__main__":
    asyncio.run(main())
```

## Shell Commands

The Disk VFS supports the full set of shell commands since it operates
on real file content (text, binary, JSON, CSV, etc.):

### Read Commands

| Command | Notes |
| - | - |
| `cat` | Read file content |
| `head` / `tail` | First/last N lines |
| `grep` / `rg` | Pattern search (file or directory level) |
| `jq` | Query JSON fields |
| `wc` | Line/word/byte counts |
| `stat` | File metadata (name, size, type, modified) |
| `find` | Recursive search with `-name`, `-maxdepth` |
| `tree` | Directory tree view |
| `nl` | Number lines |
| `du` | Disk usage summary |
| `file` | Detect file type |
| `strings` | Extract printable strings from binary |
| `xxd` | Hex dump |
| `md5` | MD5 checksum |
| `sha256sum` | SHA-256 checksum |

### Text Processing

| Command | Notes |
| - | - |
| `awk` | Pattern scanning and processing |
| `sed` | Stream editor |
| `tr` | Translate or delete characters |
| `sort` | Sort lines |
| `uniq` | Remove duplicate lines |
| `cut` | Extract fields/columns |
| `join` | Join lines on a common field |
| `paste` | Merge lines side by side |
| `column` | Columnate output |
| `fold` | Wrap lines to a specified width |
| `expand` | Convert tabs to spaces |
| `unexpand` | Convert spaces to tabs |
| `fmt` | Simple text formatter |
| `rev` | Reverse lines |
| `tac` | Concatenate and print in reverse |
| `look` | Display lines beginning with a given string |
| `shuf` | Shuffle lines |
| `tsort` | Topological sort |
| `comm` | Compare two sorted files |
| `cmp` | Compare two files byte by byte |
| `diff` | Compare files line by line |
| `patch` | Apply a diff patch |
| `iconv` | Character encoding conversion |

### File Operations

| Command | Notes |
| - | - |
| `cp` | Copy files |
| `mv` | Move/rename files |
| `rm` | Remove files |
| `mkdir` | Create directories |
| `touch` | Create empty file or update timestamp |
| `ln` | Create symbolic links |
| `tee` | Write stdin to file and stdout |
| `mktemp` | Create temporary file |
| `split` | Split file into pieces |
| `csplit` | Split file by context |

### Path Utilities

| Command | Notes |
| - | - |
| `basename` | Strip directory from path |
| `dirname` | Strip filename from path |
| `realpath` | Resolve path |
| `readlink` | Print symbolic link target |
| `ls` | List directory contents |

### Compression

| Command | Notes |
| - | - |
| `gzip` | Compress files |
| `gunzip` | Decompress gzip files |
| `zip` | Create zip archives |
| `unzip` | Extract zip archives |
| `tar` | Archive files |
| `zcat` | Cat compressed files |
| `zgrep` | Grep compressed files |

### Encoding

| Command | Notes |
| - | - |
| `base64` | Base64 encode/decode |

## Use Cases

* **Local directory access**: Mount local directories for AI agents to read and process
* **Sandboxed file access**: Restrict agent file operations to a specific directory tree
* **FUSE mounting**: Expose disk files through a virtual FUSE mount for external tools
* **Data pipelines**: Process local datasets with shell-like commands
* **Development**: Test file operations against real data before deploying to cloud mounts


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.