MCPcopy Index your code
hub / github.com/NomaDamas/agentdir

github.com/NomaDamas/agentdir @v0.1.6

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.1.6 ↗ · + Follow
662 symbols 2,694 edges 51 files 65 documented · 10% updated 16d agov0.1.6 · 2026-06-11★ 52
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

agentdir

Rust-built virtual file tree infrastructure for agent-ready file layouts across macOS, Linux, and Windows

crates.io PyPI npm License: MIT

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.


Why agentdir

  • Better agent context — expose task-specific file layouts instead of forcing agents through whatever folder structure happened to grow over time
  • Originals stay put — rearrange the virtual namespace with mv, cp, rename, mkdir, and rmdir without moving the source files
  • No duplicate-data tax on CoW filesystems — big PDFs, images, media, and datasets can appear in multiple layouts without copying file data on supported filesystems
  • General-purpose files, not just developer projects — works with documents, spreadsheets, presentations, PDFs, images, media, datasets, plain text, binaries, and more
  • Cross-platform native core — Rust library, CLI, Python bindings, and Node.js bindings

Features

  • Virtual namespace — map source directories into a virtual tree at arbitrary mount points, then move, copy, and rename entries without touching the originals
  • CoW materialization — files are cloned via reflinks on APFS (macOS) and Btrfs/XFS (Linux); falls back to byte-copy on NTFS (Windows)
  • Accurate change tracking — detects additions, modifications, and deletions in source directories via metadata (mtime + size) and propagates them to the virtual tree automatically
  • Multiple materialization strategiesreflink (default), symlink, virtual
  • Snapshot support — CoW forks of the workspace for isolated concurrent workspaces
  • File-format-agnostic — works with any file the OS can stat: documents, spreadsheets, presentations, PDFs, images, media, datasets, plain text, binaries, and more
  • Cross-platform — macOS, Linux, Windows; virtual paths always use / internally regardless of host OS
  • Three distribution channels — Rust library, Python bindings (PyO3), Node.js bindings (NAPI-RS)

Installation

Rust

Add the library to your Rust application:

cargo add agentdir

Install the CLI:

cargo install agentdir-cli

This installs a binary named agentdir.

Python

Requires Python >= 3.9.

pip install agentdir

Node.js

Requires Node >= 18. The package is scoped under @nomadamas:

npm install @nomadamas/agentdir

Prebuilt binaries are available for:

  • x86_64-apple-darwin
  • aarch64-apple-darwin
  • x86_64-pc-windows-msvc
  • x86_64-unknown-linux-gnu
  • x86_64-unknown-linux-musl

Keep the View Synced

Installation 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.


CLI Usage

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.

Quick start

# 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 reference

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) |


Library Usage

For full API documentation, see the binding-specific READMEs:

The Rust library is documented on docs.rs.


How It Works

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.


Non-Goals

agentdir is intentionally narrow in scope. The following are not goals of this project:

  • AI/LLM integration, semantic understanding, or intelligent file routing
  • File content parsing, full-text indexing, or search
  • The orchestrator or agent that decides what to restructure or why
  • File format conversion or transformation
  • Dependency graph analysis, AST parsing, or language-aware features
  • Access control, permissions, or multi-tenancy

Repository Structure

crates/
  agentdir/         Core Rust library
  agentdir-cli/     CLI binary
bindings/
  python/           Python bindings (PyO3 + maturin)
  node/             Node.js bindings (NAPI-RS)

License

MIT. See LICENSE.

Extension points exported contracts — how you extend this code

ProgressReporter (Interface)
Progress reporter for batch operations. [2 implementers]
crates/agentdir/src/materializer.rs
BatchMapSummary (Interface)
(no doc)
bindings/node/index.d.ts
Backend (Interface)
(no doc) [1 implementers]
crates/agentdir/src/backend/mod.rs
MapSummary (Interface)
(no doc)
bindings/node/index.d.ts
RefreshSummary (Interface)
(no doc)
bindings/node/index.d.ts
StatResult (Interface)
(no doc)
bindings/node/index.d.ts
StatusResult (Interface)
(no doc)
bindings/node/index.d.ts

Core symbols most depended-on inside this repo

to_path_buf
called by 188
crates/agentdir/src/types.rs
map
called by 129
crates/agentdir/src/workspace.rs
as_str
called by 72
crates/agentdir/src/types.rs
map
called by 58
bindings/node/src/lib.rs
as_path
called by 44
crates/agentdir/src/types.rs
len
called by 33
crates/agentdir/src/catalog.rs
exists
called by 32
bindings/python/src/lib.rs
exists
called by 28
bindings/node/src/lib.rs

Shape

Function 328
Method 255
Class 62
Enum 9
Interface 8

Languages

Rust73%
Python23%
TypeScript3%

Modules by API surface

crates/agentdir/src/workspace.rs43 symbols
crates/agentdir/src/catalog.rs40 symbols
bindings/node/src/lib.rs35 symbols
crates/agentdir/src/reconciler.rs31 symbols
bindings/python/src/lib.rs31 symbols
crates/agentdir/src/types.rs29 symbols
crates/agentdir/src/materializer.rs29 symbols
bindings/python/tests/test_virtual_ops.py20 symbols
bindings/python/tests/test_query_apis.py18 symbols
crates/agentdir/tests/query_apis.rs17 symbols
crates/agentdir/tests/edge_fs.rs17 symbols
crates/agentdir/tests/edge_reconciliation.rs16 symbols

For agents

$ claude mcp add agentdir \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact