Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Getting started

mado is Linux-only and needs FUSE (/dev/fuse). Every command below is a subcommand of the mado binary — a custom jj CLI: mado log, mado describe, and every other jj verb work exactly as in upstream jj, backed by mado’s stores.

Local: a mounted jj working copy

mkdir myrepo && cd myrepo
mado init                          # a jj repo whose backend + working copy are mado
mado mount --mountpoint ~/mnt &    # FUSE daemon: serves @, folds edits back into @
cd ~/mnt                           # work here: read lazily, edit freely
echo hello > hello.txt             # ...idle edits auto-snapshot into @ (~1 s)
mado log                           # the full jj CLI, backed by mado stores

mado init creates a jj repository whose object backend and working copy are mado. By default the local store uses the loose-file at-rest format (fs), one object per file — the format that lets a mado mount daemon and a mado CLI process share the same store side by side. (--store-format fjall selects the embedded LSM format instead; it is held exclusively by one process at a time and is meant for import/serve stores, not side-by-side local use.)

The mount daemon

mado mount --mountpoint <dir> runs a daemon that:

  • serves the working-copy commit @ through the mountpoint (which must be a path other than the workspace root);
  • collects edits made through the kernel into a durable overlay journal (overlay.snapshot), restoring them on restart;
  • auto-snapshots those edits into @ after a short idle period — an in-process jj transaction, so an agent’s work is captured in jj history without it running any command. Pass --no-auto-snapshot to turn that off and rely on the overlay journal plus explicit mado snapshot.

mado snapshot is the manual, on-demand equivalent of the daemon’s idle fold: it pulls the live overlay from the running daemon over the control socket and amends @. It is quiet and idempotent.

To let another user (or a container / guest VM) read the mount, add --allow-other (requires user_allow_other in /etc/fuse.conf). --read-only mounts a reference checkout the kernel refuses writes to before they reach the VFS.

Daily jj use

Once mounted, work inside the mountpoint and drive history with ordinary jj verbs through the mado binary:

cd ~/mnt
mado new master                    # start a new change on top of master
$EDITOR src/lib.rs                 # edits fault content in on first read,
                                   # land in the overlay, auto-snapshot into @
mado describe -m "fix the thing"   # set @'s description
mado log
mado diff
mado rebase -d main
mado undo                          # jj's operation log works normally

Nothing needs pre-warming: a cold read inside the mount faults the blob in over whatever backend the workspace uses (local disk or a remote server) and caches it. See Performance for what “cold” costs and how to make a whole subtree warm in one fetch.

Networked: one server, many clients

A shared mado serve server lets many thin clients check out the same history lazily. See Operations for running the server; the client side is:

mkdir ~/client1 && cd ~/client1
export MADO_REMOTE_ADDR=http://server:50051   # object reads/writes go here
mado init --workspace alice                    # register a UNIQUE workspace name
mado new master                                # position @; objects fetch lazily
mado mount --mountpoint ~/mnt1 &               # a 50k-file repo mounts instantly

Every client of a shared server must use a distinct --workspace name. Two workspaces sharing one name fight over the same working-copy commit — each checkout makes the other stale and resets its mount. Against a remote, a name already registered on the server is refused (unless you are resuming — see Workspaces).

Clients share the op-log through the server (concurrent operations merge exactly like jj’s --at-op), fetch blobs lazily through a local disk cache, and fold their mount edits into their own @.

Scratch directories (build output)

Build output (target/, node_modules/, …) is large and write-hot, and you almost never want it in the jj snapshot. Mount with a scratch backing directory and redirect those paths to plain local disk:

mado mount --mountpoint ~/mnt \
    --scratch ~/scratch-alice \
    --redirect target --redirect node_modules

Paths listed with --redirect (merged with whatever the repo’s .mado-redirections manifest declares) are served from disk under --scratch instead of the virtual tree, so they never enter a jj snapshot. Give each agent its own scratch directory so their build trees don’t collide. Scratch state travels with mado ws pause / resume — see Workspaces.