locsnap

command module
v0.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 11, 2026 License: MIT Imports: 2 Imported by: 0

README

locsnap

locsnap is a CLI that continuously snapshots a codebase while agents or tools modify it. It observes the filesystem from the outside, writes snapshots to an isolated .locsnap/ store, and never touches the repository's normal Git index, refs, or history.

Status: Stable for local timeline capture and recovery. Debouncing captures states that persist through the configured quiet period, not every transient write. Keep an independent off-device backup for protection from disk loss, repository deletion, or host compromise.

Features

  • Recursive filesystem watching with fsnotify
  • Debounced snapshots for bursty writes and atomic-save workflows
  • Periodic reconciliation scans that recover persistent changes after missed watcher events
  • One serialized writer per stream, with streams running in parallel
  • Cross-process writer and maintenance locking to prevent competing writers and GC/read races
  • Durable object and ref writes using file and directory synchronization
  • Crash-safe commit ordering with rebuildable indexes
  • Persistent health reporting for watcher and snapshot failures
  • Isolated .locsnap/ Git-style object store
  • Git-compatible blobs, nested trees, commits, and stream refs
  • Content-addressed deduplication
  • Optional alternates pointing at .git/objects
  • bbolt index.db for fast timeline and metadata queries
  • Gitignore-compatible ignore matching
  • Built-in ignores for .locsnap, .git, node_modules, .venv, dist, build, and .next
  • Large-file skip threshold
  • Snapshot restore to a target directory
  • Basic retention and unreachable-object GC

Install

Install the latest release with curl:

curl -fsSL https://raw.githubusercontent.com/patriceckhart/locsnap/main/install.sh | sh

By default this installs locsnap to $HOME/.local/bin. To choose another directory:

curl -fsSL https://raw.githubusercontent.com/patriceckhart/locsnap/main/install.sh | LOCSNAP_INSTALL_DIR=/usr/local/bin sh

Install a specific release:

curl -fsSL https://raw.githubusercontent.com/patriceckhart/locsnap/main/install.sh | LOCSNAP_VERSION=0.1.0 sh

You can also install with Go:

go install github.com/patriceckhart/locsnap@latest

For local development:

go build -o locsnap .

Quick start

locsnap init
locsnap watch

In another terminal, edit files in the repository. locsnap watch will create snapshots whenever the tree reaches a stable state.

Open the built-in snapshot viewer while watching:

locsnap watch --ui

The UI opens in the default browser. It lists snapshots across all streams, previews captured files and changes from the parent snapshot, and restores a selected snapshot to a target directory.

View status:

locsnap status

List snapshots:

locsnap log main

Inspect a snapshot:

locsnap show <snapshot>

Restore a snapshot:

locsnap restore <snapshot> --to /tmp/restored-tree

If the target directory already exists and is not empty, pass --force. This merges the snapshot into the directory and leaves unrelated existing files in place:

locsnap restore <snapshot> --to /tmp/restored-tree --force

Built-in snapshot viewer

Start the watcher and viewer together:

locsnap watch --ui

locsnap starts an HTTP server on a random loopback port and opens the viewer in the default browser. The server stops when the watch process exits. UI assets are embedded in the executable, so no separate frontend installation or internet connection is required.

The viewer provides:

  • A reverse-chronological timeline across all configured streams
  • Snapshot search and stream filtering
  • Capture time, trigger, changed-file count, and changed-byte metadata
  • A searchable file tree for each snapshot
  • Text-file previews with changes from the parent snapshot highlighted
  • Safe handling of binary files without rendering them as text
  • Automatic timeline refresh while new snapshots are captured
  • Restore controls for the selected snapshot

To restore from the viewer:

  1. Select a snapshot.
  2. Click Restore snapshot.
  3. Enter a target directory.
  4. Enable Merge into a non-empty target only when existing content may be overwritten.
  5. Confirm the restore.

Restore behavior matches the CLI. Existing files with matching paths are replaced, while unrelated files remain in place. Restoring into .locsnap/ is always rejected.

UI security
  • The server binds only to 127.0.0.1 on a random port.
  • Restore requests require a cryptographically random token generated for that watch process.
  • The token is delivered only to the locally served viewer.
  • Browser security headers restrict scripts, network connections, framing, and referrer data.
  • Request bodies are size-limited and strictly decoded.
  • Restore paths use the same traversal and symlink protections as CLI restores.

The UI is available only while locsnap watch --ui is running. Use locsnap log, locsnap show, and locsnap restore when a browser is unavailable.

Commands

locsnap init

Creates .locsnap/, initializes the object store, writes .locsnap/config, sets up alternates when .git/objects exists, creates the bbolt index, and adds .locsnap/ to .gitignore.

locsnap add <dir> [--stream <id>]

Registers a watch root as a stream. Each watch root maps to one stream.

locsnap add . --stream main
locsnap add worktrees/agent-1 --stream agent-1
locsnap watch [--ui]

Starts watchers for all configured streams. Each stream has its own serialized writer queue, while streams run in parallel. Pass --ui to start the local snapshot viewer on a random loopback port and open it in the default browser. Restore requests require a per-process security token and cannot target .locsnap/.

locsnap status

Shows configured streams, their latest snapshots, latest snapshot time, store size, and the latest persisted health report. It can run while locsnap watch is active. Failures are also appended to .locsnap/errors.log so a later success cannot erase the failure history.

locsnap log [stream]

Lists snapshots in reverse chronological order. Defaults to main.

locsnap show <snapshot>

Shows snapshot metadata, a diff summary versus the parent snapshot when available, and the files in the snapshot.

locsnap restore <snapshot> --to <dir> [--force]

Materializes a snapshot into a target directory. The target must be empty unless --force is provided.

locsnap gc

Applies retention policy and removes unreachable objects from .locsnap/objects. GC performs a full integrity preflight and aborts without pruning if any reachable object is missing or corrupt.

locsnap version

Prints the release version, commit, and build date.

Configuration

Configuration lives in .locsnap/config.

Example:

[core]
  repositoryformatversion = 0
  filemode = true
  bare = true

[locsnap]
  debounce-ms = 200
  scan-interval-ms = 5000
  max-file-size = 10485760
  use-alternates = true
  self-copy-blobs = true

[stream "main"]
  root = "."

[stream "agent-1"]
  root = "worktrees/agent-1"

[retention]
  keep-full-hours = 24
  thin-to = "hourly"
  max-store-bytes = 2147483648
Options
  • debounce-ms: quiet period after filesystem events before snapshotting.
  • scan-interval-ms: periodic full reconciliation interval.
  • max-file-size: files larger than this are skipped. 0 disables the limit.
  • use-alternates: read existing objects from .git/objects when available.
  • self-copy-blobs: always write blob copies into .locsnap/objects, even if found through alternates. New stores default to true so snapshots remain durable if the repository's Git objects are pruned.
  • keep-full-hours: keep all snapshots for this many hours before thinning.
  • thin-to: currently supports hourly thinning.
  • max-store-bytes: store-size cap used by retention.

Storage layout

.locsnap/
  objects/                       Git loose object store
  objects/info/alternates        Optional pointer to ../../.git/objects
  refs/locsnap/streams/<id>        Stream heads
  index.db                       bbolt query index
  lock.db                        cross-process writer lock
  maintenance.db                 GC and read-operation exclusion lock
  health.json                    latest operation or watcher health report
  errors.log                     durable append-only failure history
  config                         locsnap config plus Git-compatible core config

Git compatibility

Snapshots are Git commit objects stored in .locsnap/objects. You can inspect them with Git plumbing:

git --git-dir .locsnap cat-file -t <snapshot>
git --git-dir .locsnap ls-tree -r <snapshot>

locsnap does not use or modify the repository's normal Git index, branches, refs, or history.

Current limitations

  • Symlinks and other non-regular files are skipped.
  • Files larger than max-file-size are omitted from snapshots.
  • Debouncing can coalesce transient intermediate states.
  • restore --force merges into its target rather than deleting unrelated files.
  • Retention can rewrite commit ancestry, so snapshot IDs removed or rewritten by locsnap gc should not be treated as permanent identifiers.
  • The shell installer supports Linux and macOS. Windows users can use go install or a release archive.

Development

Run tests:

go test ./...

Format code:

gofmt -w .

Build:

go build -o locsnap .

License

MIT

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL