agentFS

Unlimited agents. Everything recorded.
No collisions.

Isolation is free. Make as many workspaces as you want. AgentFS knows every change because it is what wrote it.

linux · 1.8 GBmainfeature branch: authauthauth → mainafs new ×0  ·  + 36 more, same costclaude-code · b2d7stagereplaycodex · 88afstageintegrategemini · 4e11stageintegrateclaude-code · 7f3astagereconcilecodex · c21estagereplaypi · 9a04stageintegratereconcile: same file as another → a merge workspace; run it, then integrate
0 workspaces 0 writes made 0 on auth 0 on main 0 in reconcile
Each lane is one agent in its own workspace; each tick is a write the filesystem made — so it knows who, what, which bytes. Snapshots integrate one at a time: disjoint changes replay, a collision becomes a workspace you run first, and afs integrate --into main brings the branch home. Bars to scale, measured on the Linux kernel.

01

The life of an edit

One edit, start to finish. AgentFS is the filesystem, so when an editor or an agent saves, AgentFS is what performs the write. It is in the store the moment it happens — nothing is watched, scanned or reconstructed afterwards. Staging is an attestation: "this state of the tree is one I stand behind", with a message and an id. Integrating puts that snapshot on main.

  1. edit
    task-a · src/auth/session.rsclaude-code:7f3a91
      pub fn validate(&self, now: Instant) -> Result<(), SessionError> {
          if self.revoked {
              return Err(SessionError::Revoked);
          }
    +     if now > self.issued_at + self.ttl {
    +         return Err(SessionError::Expired);
    +     }
          Ok(())
      }
    An ordinary save from an ordinary editor. AgentFS is the thing that carried it out.
  2. op
    The write itself — AgentFS did itafs ops task-a
    op
    write src/auth/session.rs
    by
    claude-code:7f3a91 · Edit
    when
    14:02:09.417
    before
    9834db81 8b7df01e …
    after
    04b6fa59 ebef7161 …
    payload
    splice @1204 +87 B −0 B
    stored: the delta — 87 bytes plus the row. Not a diff taken later: this is the write, with everything the filesystem knew when it made it. Already visible in afs diff task-a.
  3. stage
    Your "commit"immutable snapshot
    $ afs stage task-a -m "add session expiry"
    staged snapshot: a91f3c2e
    Nothing new is written — the bytes were already in the store. Staging pins them: an immutable snapshot with a message, the unit that gets integrated, replayed, materialized and blamed. stored: the snapshot's index; session.rs's new version, once.
  4. integrate
    Onto mainhead move
    $ afs integrate a91f3c2e
    main → a91f3c2e   # other workspaces see it when they advance
    $ afs push -m "add session expiry"           # optional: main → a git commit in your repo
    stored: 0 B of content — main now points at the snapshot.

If you think in git: write ≈ save, afs stage ≈ "commit", afs integrate ≈ fast-forward main. The difference is that nothing waits on the "commit" — the filesystem made every write, so every write is already durable and attributed; staging only says which state you vouch for.

02

Isolated, and on the record

Each workspace sees only its own changes; nothing reaches your repo or another workspace until it is integrated. And AgentFS does not track what changed after the fact — it is the filesystem, so it is the one doing the writing. It knows which workspace, which file, which harness and session, which command, and the bytes before and after, because it wrote them. There is nothing to notice and nothing to miss.

timeworkspaceoppathbycontent
14:02:11 task-a write src/auth/session.rs claude-code:7f3a91· cargo fmt 04b6fa59…
14:02:09 task-a write src/auth/session.rs claude-code:7f3a91 9834db81…
14:01:40 task-a create src/auth/tests/expiry.rs claude-code:7f3a91 bfa7e6dd…
14:01:02 task-b write src/api/routes.rs codex:c21e08 8852fd9b…
13:58:20 task-b rename src/api/v1.rs → src/api/routes.rs codex:c21e08
13:55:04 repo write Cargo.toml you· zsh e07785dd…
Every row is a write AgentFS performed: the writer (harness and session), the command, and the bytes before and after — the contents are in the store, not just the fact of a write. None of it was reconstructed from a diff. The same log answers afs blame, per line, and afs diff, per workspace. Example rows; the field set is the real one.
task-a sees its 2 changes — nobody else's
task-b sees its 1 change — nobody else's
your repo git status: clean, until you integrate

03

When workspaces race

Snapshots integrate one at a time. When several are waiting, the outcome depends only on whether they touched the same files — a fact, not a guess, since the filesystem made every one of those writes. Nothing ever merges on its own.

mainsession.rsaroutes.rsapi.rsbsession.rsexpiry.rscintegratefirst in, instale headreplaydifferent filesconflictrejectedreconcile workspacefix · build · testafs reconcile cstageintegrateafter you ran itsame file as aall three left here
Each chip is a file that snapshot wrote — known, not inferred, because AgentFS made the write. a is first in. b finds a stale head but touched different files, so it replays onto the new one without asking. c wrote the same file as a: its integrate is rejected with conflict. afs reconcile then makes a workspace from the head it collided with, with c's changes merged in — clean hunks merged, collisions marked. You fix it, build it, test it, stage it, and that snapshot integrates. Nothing merges silently.
  1. afs integrate <snap-a> Integrates First in, in. main moves.
  2. afs integrate <snap-b> → afs replay Different files → replays automatically Stale head, so the snapshot is replayed onto the new one. Disjoint paths, no questions asked.
  3. afs integrate <snap-c> → conflict → afs reconcile Same file → rejected → a merge workspace The integrate is refused. Reconcile makes a workspace from the new head with the snapshot merged in: clean hunks merged, collisions marked. Fix, build, test, stage, integrate. Nothing merges silently.

04

Your repo stays your repo

Does the path change?

No. afs adopt --mount puts AgentFS at your repo's own path. Editors, scripts and agent memory keyed on the path keep working.

Does git still work?

Yes, natively. Your .git is untouched; the mount points at it the way a git worktree does. Commit, pull, rebase as always.

What is not captured?

Whatever git ignores — .env, secrets, build output. It stays in your directory and never leaves the machine.

Can I undo it?

afs unmount puts the plain directory back, byte for byte, plus your edits. Nothing is ever deleted.

05

Using it

# once: your repo becomes an AgentFS workspace, in place
$ afs adopt myrepo . --mount

# per task: a fresh workspace, warm caches, agent memory inherited
$ afs new task-a
$ afs enter task-a            # or start an agent with cwd = /mnt/task-a

# when it's done: checkpoint, then put it on main
$ afs stage task-a -m "add session expiry"      # → snapshot id
$ afs integrate <snap>         # onto main; replay / reconcile if it bounces
$ afs push -m "add session expiry"   # main → your repo, as a git commit

Ships with Wigwam; wigwam sync replicates the record between your machines, end-to-end encrypted.

06

Platforms

The mount is what makes copies free; the filesystem underneath is what makes warm caches free. Isolation, the record, integration and replication are the same everywhere. What differs is how a workspace presents its build directories — target/, node_modules/, dist/ — and afs doctor tells you which you have.

Requires
FUSE 3 — /dev/fuse and fusermount3 (package fuse3). Kernel 6.9+ recommended for FUSE passthrough. Unprivileged user namespaces and bubblewrap for afs enter sandboxes.
Filesystem
btrfs or XFS with reflinks, with the store, your repo and its build caches on the same volume. This is what makes warm build caches free: a fork's target/ is a copy-on-write clone of your last build — 0 bytes until a file diverges.
Build dirs
Real directories. A fresh workspace's target/ and node_modules/ are ordinary directories inside the workspace. Relative links resolve where you expect, realpath stays in the repo, and mv target target.old or cargo clean behave as they do on a plain directory.
You get
Everything on this page: mount in place, isolated workspaces, the record, replication, warm build caches.
Without reflinks
ext4 and friends lose exactly one thing: free warm-cache seeding. Mount, isolation and the record are identical. Seeding is then off by default — a fork's first build recompiles your own crates — or afs seed-mode set copy copies the seed for a warm first build, paying disk and copy time per workspace. afs doctor says which you have.
Get Started