varn.flawme.sbs — documentation

DOCUMENTATION

Varn CLI reference & guides

Installation

Option 1 — Install script (recommended)

Auto-detects your platform, downloads the binary, and adds it to your PATH. Supported platforms: Linux and macOS on x86_64 and aarch64. Windows users: use Option 2 below.

curl -fsSL https://raw.githubusercontent.com/flawme/varn/main/install.sh | sh

To install a specific version, append the version tag:

curl -fsSL https://raw.githubusercontent.com/flawme/varn/main/install.sh | sh -s -- v0.3.0
FlagDescription
--bin-dir <path>Override the install directory
--no-modify-pathDo not modify shell config
<version>Install a specific version (e.g. v0.3.0)

Option 2 — Download prebuilt binary manually

Prebuilt binaries are available on the releases page.

Linux (x86_64)

curl -L https://github.com/flawme/varn/releases/latest/download/varn-linux-x86_64 -o ~/.local/bin/varn
chmod +x ~/.local/bin/varn

If ~/.local/bin is not on your PATH:

echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

macOS (x86_64)

curl -L https://github.com/flawme/varn/releases/latest/download/varn-macos-x86_64 -o /usr/local/bin/varn
chmod +x /usr/local/bin/varn

On a permission-denied error, use sudo or install to ~/.local/bin instead.

Windows (x86_64)

curl -L https://github.com/flawme/varn/releases/latest/download/varn-windows-x86_64.exe -o "$env:USERPROFILE\.cargo\bin\varn.exe"

Or download the file directly from the releases page and place it in a directory on your PATH.

Option 3 — Cargo

Requires Rust 1.85+. Builds from source and installs to ~/.cargo/bin/:

cargo install --git https://github.com/flawme/varn.git

Option 4 — Build from source

git clone https://github.com/flawme/varn.git
cd varn
cargo build --release

The binary is at target/release/varn.

Add to PATH — Linux / macOS:

mkdir -p ~/.local/bin
cp target/release/varn ~/.local/bin/
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

Add to PATH — Windows (PowerShell):

Copy-Item target\release\varn.exe "$env:USERPROFILE\.cargo\bin\"

Verify installation

varn --version
# varn 0.3.0

Quick start

Three commands between you and a rollback point. Initialize in any directory — varn init only creates .varn/ and never touches existing files:

varn init
varn checkpoint "before changes"
# ... make changes ...
varn diff <checkpoint-id>
varn restore <checkpoint-id>

varn diff classifies every change as added, modified, or deleted. varn restore plans the restore, asks for confirmation if anything would be overwritten or deleted, captures a safety checkpoint of the current state, executes, and verifies the result.

Checkpoint IDs

A checkpoint ID is the first 12 hex characters of a SHA-256 hash over the snapshot's description, timestamp, root path, and all entry metadata — deterministic, so checkpointing the same state twice is a no-op (reported as status: "unchanged" in JSON mode). IDs can be used by prefix, as long as the prefix is unambiguous:

varn diff a91f           # Prefix match
varn restore a91f3c2b    # Longer prefix

If a prefix matches multiple checkpoints, Varn reports an ambiguity error rather than guessing.

varn init

varn init              # Initialize in current directory
varn init /path/to/dir # Initialize in a specific directory
varn init --gitignore  # Also add .varn/ to the root .gitignore

Creates a .varn/ directory with storage layout and config. Does not touch any existing files. Inside a git repository, Varn also creates .varn/.gitignore containing *, which makes Git ignore the entire store — protecting against a blind git add -A staging tens of thousands of content objects. Nothing outside .varn/ is modified.

With --gitignore, Varn additionally appends .varn/to the enclosing repository's root .gitignore (no duplicate entries). The flag fails with an actionable error if the directory is not inside a git repository.

varn checkpoint

varn checkpoint "before agent task"

Captures the current filesystem state: a unique ID, timestamp, description, root path, and the full tree (paths, metadata, content hashes). File contents go into the content-addressed object store with deduplication. Checkpointing the same state twice is a no-op. Scanning is incremental — a persistent cache reuses content hashes for files whose size and mtime are unchanged; the cache is advisory and never affects correctness.

varn list

ID             TIME                 DESCRIPTION
a91f3c2b4d5e   2026-08-19 20:14    before agent task
b72c1a3e5f7d   2026-08-19 20:27    after agent task

varn diff

varn diff a91f          # Use a checkpoint ID prefix
varn diff a91f3c2b4d5e  # Use a full checkpoint ID
ADDED
  src/new_file.rs

MODIFIED
  src/main.rs

DELETED
  old_config.json
Output: every change classified as added, modified, or deleted.

varn restore

varn restore a91f                          # Interactive (prompts on conflicts)
varn restore a91f --yes                    # Skip confirmation prompts
varn restore a91f --yes --no-safety        # Skip safety checkpoint too

By default, restore creates a safety checkpoint of the current state before restoring, so a failed or unwanted restore can be undone. If conflicts are detected (modified or unexpected files), Varn lists what would be overwritten or deleted, asks for confirmation unless --yes is passed, executes, and verifies the result matches the checkpoint.

varn gc

varn gc             # Delete unreferenced objects
varn gc --dry-run   # Preview what would be deleted

Removes objects no snapshot references. Safe to run at any time — objects referenced by any existing snapshot are always preserved.

varn migrate

varn migrate             # Run pending migrations
varn migrate --dry-run   # Check if migration is needed

Migrates the storage format to the current version and backfills the store-level git guard (.varn/.gitignore) for legacy stores. If the repository is already current, nothing changes; if it is newer than this Varn supports, an error is returned.

Ignore patterns

Place a .varnignore file at the root of your Varn-managed directory. It is loaded automatically by varn checkpoint and varn diff. The syntax follows gitignore conventions:

# Comments and blank lines are ignored
*.log                    # Match by extension (any depth)
target/                  # Directory-only (trailing slash)
/build                   # Anchored to root (leading slash)
**/cache/                # Match at any depth
!important.log           # Negation (re-include)
PatternMatches
*.logAny file ending in .log, at any depth
target/A directory named target (and all its contents)
/buildA path named build at the root only
**/cache/A directory named cache at any depth
!important.logRe-includes a file previously excluded
file[0-9].txtOne character from the set 0-9
?Any single character except /

Ignored directories are not recursed into. The matcher is recursive with backtracking, so **/*.log matches app.log at the root as well as nested paths.

Git coexistence

Varn is designed to coexist with Git in the same directory:

  • varn init creates .varn/.gitignore containing *, so Git ignores the entire store automatically. Nothing outside .varn/ is modified.
  • Varn never reads or writes Git metadata (.git/, index, refs).
  • varn checkpoint skips .varn/during scans, so checkpointing a git-managed directory does not capture Git's internals.
  • If the store is not excluded from git (a legacy store), commands warn with a one-line fix: echo '.varn/' >> .gitignore. varn init --gitignore applies it for you; varn migrate backfills the store-level guard.

JSON output

Every command accepts a global --json flag. Errors are also emitted as JSON (to stderr), making Varn suitable for consumption by AI agents and automation tools:

varn --json checkpoint "before changes"
varn --json list
varn --json diff a91f
varn --json restore a91f --yes
varn --json gc --dry-run
varn --json migrate --dry-run

varn --json checkpoint

{
  "status": "ok",
  "checkpoint_id": "a91f3c2b4d5e",
  "description": "test",
  "created_at": 1787162040,
  "root": "/project",
  "entries": 12,
  "saved": true,
  "warnings": []
}

varn --json diff

{
  "status": "ok",
  "checkpoint": "a91f3c2b4d5e",
  "changes": [
    { "kind": "added", "path": "src/new_file.rs" },
    { "kind": "modified", "path": "src/main.rs" },
    { "kind": "deleted", "path": "old_config.json" }
  ]
}

varn --json restore

{
  "status": "ok",
  "checkpoint": "a91f3c2b4d5e",
  "safety_checkpoint": "b72c1a3e5f7d",
  "files_written": 3,
  "dirs_created": 1,
  "symlinks_created": 0,
  "deleted": 2,
  "verified": true,
  "warnings": []
}

Errors

{
  "status": "error",
  "error": "checkpoint not found: xyz"
}

Safety model

Varn treats restoration as a potentially destructive operation. Core guarantees: destructive operations are never silent; restoration is always explicit; init never modifies anything outside .varn/; Varn never touches Git metadata; and there is no network communication, no telemetry, no account.

The restore pipeline has four phases:

  1. Plan — compare the target snapshot with the current filesystem; enumerate every action plus any conflicts.
  2. Confirm — conflicts require explicit confirmation (or --yes).
  3. Execute — restore contents from the object store, delete unexpected files, recreate directories.
  4. Verify — re-scan the filesystem and confirm it matches the snapshot: kind, content hash, symlink target, readonly flag, and mtime.

A conflict means the current state differs from the snapshot in a way that would cause data loss: a file modified since the checkpoint (would be overwritten), or a file that exists now but not in the checkpoint (would be deleted). Conflicts require confirmation before proceeding.

The engine is hardened against adversarial filesystems: path traversal is rejected (.. components, absolute paths); symlink escape is checked on every ancestor directory before any write (CVE-2026-71556 class); hard-link targets are verified not to be symlinks (CVE-2026-32232 class); object content is re-hashed after leaving the store and before touching the disk; and a pre-flight check confirms all referenced objects exist before anything is modified — a restore can fail, but it cannot fail halfway.

Full docs in the repository: usage.md, safety.md, architecture.md.