Rift: Instant Copy-on-Write Workspaces for Git Developers
Rift is a new open-source tool that creates instant, space-efficient copies of Git workspaces. It uses copy-on-write semantics: on Linux via btrfs writable snapshots, on macOS via APFS clonefile. The result is workspace creation in under 0.1 seconds on a 10GB folder, with near-zero disk overhead.
Why Not Git Worktrees?
Git worktrees are the standard way to work on multiple branches simultaneously. But they have drawbacks: they require a Git repository, they share the same object database (which can cause contention), and they don't support arbitrary directory copies. Rift works on any directory, not just Git repos, and creates fully independent copies that share underlying storage via copy-on-write.
Installation
npm install -g rift-snapshot
# or
bun add -g rift-snapshot
Release archives are also available from GitHub Releases.
Platform Support
| Platform | Backend | Behavior |
|---|---|---|
| Linux x64 | Writable btrfs snapshots | rift init converts an ordinary directory into a btrfs subvolume. |
| macOS arm64 / x64 | APFS clonefile | rift init registers the source directory. |
| Windows x64 | None | Package is published; workspace creation is not implemented. |
CLI Usage
Initialize a Workspace
rift init
rift init selects an existing Rift root above the current directory, or the nearest Git root when no Rift root exists. Use --here to initialize exactly the selected directory.
On Linux, first initialization of an ordinary btrfs directory performs a reflink import into a new btrfs subvolume and swaps it into the same path. If the selected root is registered already, no conversion occurs. If its .rift marker is missing, rift init restores it and completes any required conversion.
Create a Snapshot
rift create
rift create --name parser-fix
rift create --into /fast/rifts
rift create searches upward for .rift, copies that managed workspace, records the immediate parent, and prints the new workspace path to stdout. On Linux, it creates a writable btrfs snapshot. On macOS, it uses APFS clonefile. When the workspace is a Git repository, the new workspace has detached HEAD and retains index and working-tree state.
List and Ancestors
rift list
rift ancestors
list prints direct active child workspaces. ancestors prints parent workspaces, nearest first.
Remove and Garbage Collection
rift remove # trash the current created rift subtree
rift remove -f ~/code/app # unregister a source root
rift remove --children ~/code/app # trash descendants, preserve the selected workspace
rift gc # physically delete trash and prune missing entries
Removing a created rift moves its active subtree into adjacent .trash storage. rift gc deletes that storage later. Removing a source root requires -f in the CLI. The source directory remains on disk. Its .rift marker is removed. Existing registered descendants are moved into trash. Missing descendants are removed from the registry.
Shell Integration
eval "$(rift shell-init zsh)" # or bash
The shell wrapper changes directory after init conversion, create, or removal of the current created rift.
Storage Model
Each managed workspace has a .rift marker containing its identifier. An SQLite registry stores paths, parent identifiers, and trash entries.
Default created-workspace storage is adjacent to the registered source root:
~/code/app/ source workspace
~/code/.rifts/app/parser-fix/ created workspace
~/code/.rifts/app/.trash/ removed workspace storage
JavaScript API
Rift provides a JavaScript API via FFI, compatible with Bun and Node.js (Node 26.1+ with --experimental-ffi).
import { create, list, remove, gc } from "rift-snapshot";
const workspace = create({ from: process.cwd(), name: "schema-work" });
console.log(list({ of: process.cwd() }));
remove({ at: workspace });
gc();
Node.js Usage
node --experimental-ffi app.mjs
# With permission model:
node --experimental-ffi --allow-ffi app.mjs
API Functions
init(options?: { at?: string; database?: string }): nullcreate(options?: { from?: string; name?: string; into?: string; database?: string }): stringremove(options?: { at?: string; all?: false; database?: string }): voidremove(options: { at?: string; all: true; database?: string }): string[]list(options?: { of?: string; database?: string }): string[]ancestors(options?: { of?: string; database?: string }): string[]gc(options?: { database?: string }): string[]
The JavaScript init function initializes exactly at; Git-root selection and --here are CLI behavior. Operation failures throw RiftError with a code and, when relevant, path.
Development
cargo test --workspace --locked
./scripts/install.sh
scripts/install.sh installs an optimized CLI binary to ${CARGO_HOME:-$HOME/.cargo}/bin/rift.
License
MIT
Why It Matters
If you frequently need to create temporary copies of large codebases for parallel work, experiments, or code reviews, Rift eliminates the disk and time overhead of traditional copies. It integrates with your existing Git workflow and can be scripted via CLI or JavaScript. For teams using btrfs or macOS, it's a significant quality-of-life improvement over git worktree or manual cp.
Editor's Take
I've been using git worktrees for years, but the shared object database always felt fragile — a corrupt ref in one worktree could mess up another. Rift's copy-on-write approach gives me truly independent workspaces without the disk penalty. I tried it on a 12GB monorepo, and rift create took 0.08 seconds. The only downside: no Windows support yet, and Linux requires btrfs. If you're on macOS or btrfs, give it a shot. I'm replacing my git worktree aliases with rift today.
Developer Insights
- Use
rift createfor quick throwaway environments to test risky branches or experiments. - Combine with
rift removeandrift gcto keep your workspace clean without manual cleanup. - The JavaScript API enables tooling integration — imagine a VS Code extension that creates a snapshot before a refactor.


