Rust-built virtual file tree infrastructure for agent-ready file layouts across macOS, Linux, and Windows
agentdir lets your tools present the same original files in purpose-built, read-only folder structures without moving the originals. AI agents, scripts, and humans can navigate documents, media, datasets, generated artifacts, plain text, binaries, or any other OS-visible files through a layout optimized for the task at hand.
Built in Rust, agentdir runs on macOS, Linux, and Windows. On CoW-capable filesystems such as APFS, Btrfs, and XFS, alternate layouts and snapshots use reflinks, so large files do not get duplicated just because the folder structure changes. When CoW is unavailable, agentdir falls back to byte-copy materialization.
The point is simple: keep the human-facing file layout stable, give agents a better working layout, and keep the two mapped together as original files change.
mv, cp, rename, mkdir, and rmdir without moving the source filesreflink (default), symlink, virtual/ internally regardless of host OSAdd the library to your Rust application:
cargo add agentdir
Install the CLI:
cargo install agentdir-cli
This installs a binary named agentdir.
Requires Python >= 3.9.
pip install agentdir
Requires Node >= 18. The package is scoped under @nomadamas:
npm install @nomadamas/agentdir
Prebuilt binaries are available for:
x86_64-apple-darwinaarch64-apple-darwinx86_64-pc-windows-msvcx86_64-unknown-linux-gnux86_64-unknown-linux-muslInstallation only installs the library or CLI. After you map original files, you should also choose how the workspace will stay current. This is not a nice-to-have: the virtual tree is a live navigation view, and original-file changes are propagated only when you run reconciliation.
For CLI-driven work, run the watcher next to the agent or script that consumes the workspace:
agentdir -w ./workspace watch --interval 60
watch reacts to filesystem events for fast updates and also performs periodic full rescans so missed OS events are recovered. It runs in the foreground; put it under your process manager, terminal multiplexer, service supervisor, or task runner if you need it to stay alive.
If you do not want a long-running watcher, call refresh before each agent session, before exporting mappings, or on your own schedule:
agentdir -w ./workspace refresh
Library users should do the same through their runtime surface: call Workspace.refresh() whenever the source may have changed, or use refresh_with_hash_verification(true) when you want an additional SHA-256 verification pass for unchanged mtime/size metadata.
The binary is named agentdir. Most commands accept a -w/--workspace <dir> flag to specify the workspace directory; if omitted, the current directory is used.
# Initialize a new workspace
agentdir init ./workspace
# Map a source directory into the virtual tree
agentdir -w ./workspace map ./team-files /files
# Keep the virtual tree current while agents consume it
agentdir -w ./workspace watch --interval 60
# Check workspace status
agentdir -w ./workspace status
# Move an entry in the virtual namespace (original files are untouched)
agentdir -w ./workspace mv /files/q1-report.pdf /reports/q1-report.pdf
| Command | Description |
|---|---|
init <path> [--strategy reflink\|symlink\|virtual] |
Initialize a new workspace |
| `map |
| Map a source directory into the virtual tree |
|map-batch --from-json | Apply a batch mapping from a JSON file{"source_path":"virtual_path",...}|
|unmap | Remove a source mapping |
|status| Show workspace status |
|stat
| Export source/virtual mapping as JSON |
|watch [-i/--interval ]` | Watch for source changes and auto-sync (foreground, default interval 60s) |
For full API documentation, see the binding-specific READMEs:
bindings/python/README.mdbindings/node/README.mdThe Rust library is documented on docs.rs.
When you map a source directory, agentdir records the mapping in an atomic JSON manifest (written via write-tmp + fsync + rename, so no partial writes). On refresh or via the background watcher, it scans source metadata and computes a diff against the last known state. Changed entries are materialized into the workspace directory as CoW clones (or byte-copies where CoW isn't available). The virtual namespace is an in-memory catalog with O(1) lookup; virtual paths always use / as the separator on all platforms.
Snapshots are CoW forks of the workspace directory, giving you isolated copies for concurrent workloads without duplicating data on supporting filesystems.
Source symlinks are detected but not followed during scanning.
agentdir is intentionally narrow in scope. The following are not goals of this project:
crates/
agentdir/ Core Rust library
agentdir-cli/ CLI binary
bindings/
python/ Python bindings (PyO3 + maturin)
node/ Node.js bindings (NAPI-RS)
MIT. See LICENSE.
$ claude mcp add agentdir \
-- python -m otcore.mcp_server <graph>