flockfs

CLI

Global options: --url (FLOCKFS_URL, default http://127.0.0.1:4317), --token (FLOCKFS_TOKEN), --token-file (FLOCKFS_TOKEN_FILE, default data/token), --actor (label for your edits when the server does not derive one from the token), --drive (FLOCKFS_DRIVE; see Drives).

CommandWhat it does
flockfs serve [--bind 127.0.0.1:4317] [--data data] [--web web/dist] [--database-url …]Run the server: API, live WebSocket, web app, hosted MCP at /mcp.
flockfs setup [DIR] [--check | --stop] [--open] [--no-autostart]Connect DIR (default ~/flockfs, or ~/flockfs-<slug> with --drive for a drive other than the default), start always-on sync, verify both directions; prints JSON.
flockfs sync DIR [--once]Keep a folder in sync (filesystem events + live change feed). --once = one pass.
flockfs sync DIR --install [--no-load] / --uninstallmacOS LaunchAgent: start at login, restart on crash.
flockfs status DIR [--json]Drive, daemon, connection, last sync, tracked files, conflicts, autostart.
flockfs resolve DIR PATH --take local|remoteSettle a preserved conflict.
flockfs mcpMCP server on stdio (actor mcp-agent unless --actor; --drive picks the drive).
flockfs drives list [--json] [--deleted]Drives you can open (* = the server's default).
flockfs drives create NAME [--slug S], rename DRIVE [--name N] [--slug S]New drive (org owners); rename (old slugs keep working).
flockfs drives delete DRIVE [--yes], restore DRIVE [--slug S]Soft delete (purged after 30 days; asks you to type the slug unless --yes); undo.
flockfs export [-o FILE.zip | --dir DIR] [--history]The drive as a zip (files + .flockfs/manifest.json; default <slug>.zip, -o - for stdout), or unpacked as ordinary files into a new folder; --history adds every version under .flockfs/history/.
flockfs ls [PREFIX], get PATH [-o FILE], put PATH [-i FILE] [--revision N]List, read, write (stdin/stdout by default).
flockfs mkdir, append PATH TEXT, mv SRC DST, rm PATHFolders, atomic append, move/rename, delete.
flockfs search QUERY, links PATHNames and contents; outgoing links and backlinks.
flockfs history PATH, restore PATH REVISIONVersions; restore one as a new revision.
flockfs restore --to TIME [--path FOLDER]Put the drive (or a folder) back to how it was at a time within the history window.
flockfs sessions [--actor A] [--limit N] [--json]Recent sessions (who did what, when): the units flockfs undo works on.
flockfs undo --session S [--dry-run] [--json]Undo everything one session changed, keeping later edits by others.
flockfs watch [--after N] [--prefix FOLDER]Stream change events as JSON lines; --prefix keeps one folder or file (moves in/out included).
flockfs timeline [--agent NAME|ID] [--path P] [--session S] [--since 1h] [--json] [--follow]What agents did: MCP tool calls and logged actions (time, actor, tool, path, ok/error, duration). See Timeline.
flockfs mount [DRIVE] DIR [--read-only] [--port N] [--no-mount], flockfs unmount DIRA drive as a live folder with no local copy (user-space NFS on 127.0.0.1; see Mount).
flockfs run [--path FOLDER] [--read-only] [--agent-token-name NAME [--scope FOLDER]] [--sync | --mount] [--dir DIR] [--keep] [-q] -- COMMAND…Run any program or agent in a live workspace: mounted into a temporary folder, writes saved and folder removed when it exits; its exit code is returned. See Run.
flockfs org plan [PLAN]Show the org's plan, limits and usage; with PLAN, set it (server operator only).
flockfs migrate-sqlite PATHImport a database from the earlier SQLite prototype.

Drives

A server holds one or more drives (separate trees with their own members, tokens and history; see API.md). Every command works on one drive, chosen by:

  1. --drive DRIVE (id, slug or slug-id), else
  2. FLOCKFS_DRIVE, else
  3. the folder's own drive for sync, status and resolve (stored as the drive's permanent id in DIR/.flockfs/state.json), else
  4. the drive of an agent token (flockfs_<driveid>_…), else
  5. the server's default drive.

A synced folder belongs to exactly one drive: naming another one fails with "folder belongs to drive X" (folders synced before the server had drives belong to its default drive). Renaming a drive is safe: folders and LaunchAgents (--drive <id>) refer to it by id. Give each drive its own folder (flockfs setup --drive research uses ~/flockfs-research, next to ~/flockfs).

flockfs drives create Research               # research  k3vzq2m7xa4b  owner  Research
flockfs --drive research put notes/a.md -i a.md
flockfs setup --drive research               # ~/flockfs-research, always in sync
flockfs mount research /tmp/research         # or: flockfs --drive research mount /tmp/research
flockfs --drive research export --dir ./research-backup

Sync

The folder is plain files. Local saves sync within ~100 ms (FSEvents, debounced; only the changed paths are re-examined, with a full rescan every 30 s as a safety net); remote edits arrive over a long-poll feed. Saves are sent with the revision they were based on, so concurrent text edits merge; overlapping edits, or concurrent edits of a binary file, are preserved as conflicts under DIR/.flockfs/conflicts/ and shown by flockfs status. Renames and folder moves keep file identity. .git, editor swap files and OS metadata never sync; symlinks are neither synced nor followed. .flockfs/ holds the checkpoint, logs and status.json (state: starting, saved, conflicted, offline, error, stopped). Ctrl-C or SIGTERM (e.g. launchctl bootout) stops the daemon gracefully: a pass in progress finishes and saves its checkpoint first.

Mount

flockfs mount DIR makes an empty folder a live window onto a drive (flockfs mount DRIVE DIR for a specific one) with no local copy and no kernel extension: it runs an NFSv3 server on 127.0.0.1 and mounts it with the OS's own NFS client (no sudo on macOS for a folder you own; Linux prints a sudo mount command). Changes from elsewhere appear within milliseconds (driven by the change feed); writes are sent ~300 ms after the last write to a file: appends via the atomic append API, everything else with its base revision and base content so the server merges concurrent text edits (unmergeable versions are kept as name (conflict …).ext). Atomic saves (write-temp + rename, vim/JetBrains backup renames) keep the file's identity; .DS_Store, ._* and editor scratch files stay in memory. Someone else's lock fails writes with "Permission denied" without losing the buffered data; a read-only token mounts read-only. Ctrl-C, SIGTERM or flockfs unmount DIR unmount cleanly after committing pending writes. Details, mount options and measurements: mount.md.

Run

flockfs run -- COMMAND gives any program or agent a live flockfs workspace in one command:

flockfs run -- claude                                        # a coding agent, working in the drive
flockfs run --drive research --path inbox -- python agent.py # start in research's inbox/
flockfs run --read-only -- grep -r TODO .                    # writes fail with "Read-only file system"
flockfs run --agent-token-name triage --scope inbox -- python agent.py   # least privilege (owners)

It mounts the drive into a new /tmp/flockfs-run-… folder (or --dir DIR), starts COMMAND there (in --path FOLDER, created if missing) with stdio passed through, and when COMMAND exits saves its pending writes, unmounts, removes the folder (--keep keeps it) and exits with COMMAND's exit code (128 + N if signal N ended it). Ctrl-C and SIGTERM/SIGHUP go to COMMAND first; cleanup always runs. Where mounting is not possible (Linux without root), it falls back to a temporary folder kept live by the sync daemon (--sync forces this, --mount forbids the fallback). COMMAND gets FLOCKFS_URL, FLOCKFS_DRIVE (the drive id), FLOCKFS_TOKEN_FILE (a 0600 file deleted afterwards; the token is never on a command line, and FLOCKFS_TOKEN is removed), FLOCKFS_WORKSPACE (the folder) and FLOCKFS_SESSION (a UUID sent as X-Flockfs-Session by every flockfs client in the run, so its changes can be grouped). flockfs commands inside the run pick all of these up. --agent-token-name NAME (drive owners) runs COMMAND, and the workspace itself, with a new agent token labelled NAME (write, or read with --read-only; limited to --scope FOLDER, default --path), valid one day and revoked when COMMAND exits: its changes are attributed to NAME and it cannot touch anything outside the scope. Details: mount.md.

Packaging

./scripts/install-cli.sh      # build + install ~/.local/bin/flockfs (FLOCKFS_INSTALL_ROOT to change)
./scripts/package-cli.sh      # release archive .dev/releases/flockfs-<ver>-<os>-<arch>.tar.gz + .sha256
docker build -t flockfs .        # server image (needs FLOCKFS_DATABASE_URL at run time; see Self-hosting)

The archive contains the binary, an install.sh (never overwrites without --replace) and a README. It is unsigned and not notarized.

Exclusive creation

flockfs put PATH --exclusive creates the file only if its path is absent. It accepts stdin or --input FILE; concurrent creators have one winner, and existing content is never replaced. This cannot be combined with --revision. See Coordinating agents with plain files.

On this page