lane README

The project's README from github.com/lukeed/lane. As one markdown file: README.md.

lane CI

Copy-on-write Git worktrees with memory that survives them.

Lane creates isolated worktrees without leaving behind the ignored build caches that make a checkout fast. It can also attach durable notes to a file or symbol, then flag them when the relevant code changes. Lane never calls a model.

[!TIP] Why another worktree tool?

When you run git worktree add, it creates a clean checkout but leaves behind everything Git ignores: target/, node_modules/, virtual environments, generated files, and local .env files. This means you must reinstall and/or build from scratch, despite already having all your caches warm on disk. On a reflink filesystem, lane clones those entries by reference. The new lane starts warm while allocating new storage only for the blocks it changes.

Lane uses clonefile(2) on APFS and FICLONE on Linux filesystems that support it, including btrfs and XFS with reflink enabled. If reflinks are unavailable, lane creates a normal worktree and does not byte-copy ignored caches. When desired, lane new --dirty also carries tracked edits and untracked, non-ignored files; without reflinks, those changed files are copied normally.

Lanes live under .lane/trees/ and are excluded through .git/info/exclude, so the worktrees themselves are never committed.

Lane can also attach durable notes/memories to a file or symbol, then flag them when the relevant code changes.

Lane never calls a model.

Install

Prebuilt binaries are available for macOS and Linux on arm64 and x86_64:

$ curl -fsSL https://lane.lukeed.com | sh

The installer writes to ~/.local/bin by default. Set LANE_INSTALL to choose another directory, or LANE_VERSION to pin a release.

You may also install with Cargo:

$ cargo binstall --git https://github.com/lukeed/lane lane
# or
$ cargo install --git https://github.com/lukeed/lane

Lane requires Rust 1.85 or newer when building from source.

Setup

For each new shell, install the lane shellenv wrapper to automatically cd into and out of lanes. Add this to .zshrc or .bashrc:

eval "$(lane shellenv)"

Or add the Fish wrapper to ~/.config/fish/config.fish:

lane shellenv fish | source

The wrapper completes lane names for lane rm, lane push, lane enter, and lane merge.

While not necessary, this is more convenient than manually running cd .lane/trees/<new lane> repeatedly.

Then initialize each repository:

$ cd yourrepo
$ lane init
$ git add .lane AGENTS.md
$ git commit -m 'initialize lane'

This creates the memory store, adds a short agent protocol to AGENTS.md, and reports whether the filesystem supports reflinks.

Optional tooling can capture Why: commit trailers or install the fuller agent workflow:

$ lane install hooks  # capture targeted Why: trailers from commits
$ lane install skill  # install the fuller workflow for coding agents

Usage

$ lane new fix-login
$ lane why src/auth.rs
$ lane note add src/auth.rs -a 'fn verify' \
    'must stay constant-time; early return leaks token length'

# edit and commit as usual
$ lane check
$ lane merge
# or
$ lane push

lane new creates a branch and worktree under .lane/trees/. On APFS, btrfs, and reflink-enabled XFS, ignored files are cloned by reference. Otherwise, Lane creates a normal Git worktree and skips ignored files.

Notes record what must stay true, not what a commit changed. They are stored as Markdown under .lane/memory/ and anchored to a declaration, Markdown section, component block, or whole file.

For repositories with protected branches, use lane push instead of lane merge. After the pull request lands, run lane prune.

Run lane --help for the command list, or visit the usage guide for the full workflow. See Audit for how to review existing memories before landing.

Memory

Memory is ordinary Markdown committed with the repository:

.lane/
  memory/<path>/<ulid>-<slug>.md   live notes and confirmed fingerprints
  attic/<path>/<ulid>-<slug>.md    retired notes, still recoverable
  trees/<name>/                    local worktrees, never committed

New notes use distinct files, so parallel lanes can annotate the same code without editing the same bytes. lane note confirm <id> re-vouches for a drifted note by updating its confirmed fingerprint. Pin and unpin likewise update retention metadata. If two branches make conflicting judgments about the same note, Git makes that disagreement visible.

Notes are written directly to .lane/memory/ without a baseline. The next audit baselines them after any rebase, follows source-file renames, and moves superseded, unpinned missing, or unpinned over-budget notes to .lane/attic/ rather than deleting them.

Anchors include declarations such as fn verify, Markdown headings such as ## Rate limiting, component blocks such as #script, and @file for a whole file. Run lane anchors src/auth.rs to list the canonical values and their line ranges. A unique bare name such as verify is stored as its canonical value; a name shared by multiple declaration kinds is refused with the available choices. Comments and whitespace are normalized out of fingerprints.

Audit

Run lane check to get the status report for existing memories:

$ lane check

Freshness is computed for the anchored span, not the whole file:

result meaning
fresh the anchored span is unchanged
content-changed its implementation changed
contract-changed its declaration changed
anchor-missing the symbol no longer resolves
unverifiable lane has no grammar for that anchor

Resolve drift with exactly one of these actions:

$ lane note confirm <id>                  # still true
$ lane note replace <id> '<replacement>'  # needs an update
$ lane note retire <id>                   # no longer applies

Run lane note edit <id> for a guided terminal menu over the same actions, including pinning or unpinning the note.

Replacement inherits the live note's path and anchor. Retire and restore move bytes unchanged between live memory and the attic; pin and unpin control eviction. For a new note, supplied text never prompts and defaults to @file without -a; omit text to use the interactive anchor selector and one-line prompt.

Development

$ ./scripts/build.sh          # release-build and install the local lane binary
$ cargo fmt --all --check
$ cargo clippy --workspace --all-targets -- -D warnings
$ cargo test --workspace
$ ./scripts/test.sh           # end to end against temporary Git repositories
$ ./scripts/check-linux.sh    # run the same gates without reflink support
$ ./scripts/release.ts patch  # bump the version, then tag and push the release

License

MIT © Luke Edwards

lane (lukeed/lane)

Searching Database…

160 ·GitHub
What is this?Lane is a CLI tool that creates copy-on-write Git worktrees so a new checkout starts with warm build caches instead of empty ones, and it can attach durable Markdown notes to code that get flagged when the annotated code changes.
Is this a CLI tool or something I run alongside git?It's a single-binary command-line tool, not a library or GUI app; you run `lane` commands alongside your normal git workflow.
How do I get lane running?Install a prebuilt binary (macOS/Linux, arm64/x86_64) or run `cargo install`, add the lane shell wrapper to your .zshrc/.bashrc or Fish config, then run `lane init` in each repo to set up the memory store and AGENTS.md.
Do I need Rust or a special filesystem first?Building from source requires Rust 1.85 or newer; getting the copy-on-write speed benefit requires a reflink-capable filesystem such as APFS, btrfs, or XFS with reflink enabled.
What happens if my filesystem doesn't support reflinks?Lane falls back to a plain git worktree and skips byte-copying ignored caches, so you lose the warm-cache speedup; also, only macOS and Linux binaries are provided, no Windows build.
Which platforms are prebuilt binaries available for?macOS and Linux, on both arm64 and x86_64; Windows isn't offered.
Does lane ever call an AI model?No — the README states lane never calls a model; it's a deterministic worktree and note-tracking tool, not an AI feature.
How does lane know when a note is stale?Notes are anchored to a declaration, Markdown heading, component block, or whole file, and `lane check` reports fresh, content-changed, contract-changed, anchor-missing, or unverifiable based on whether that anchored span changed.
What happens to old or superseded notes?Lane doesn't delete superseded, unpinned missing, or unpinned over-budget notes — an audit moves them to .lane/attic/ instead, so they can be restored later.
Can two branches disagree about the same note?Yes — new notes are written to distinct files so parallel lanes don't collide, and if two branches make conflicting judgments about the same note, Git surfaces that conflict just like any other merge.
What are similar projects?turbocrypt, eza, diff-so-fancy, cz-cli, git-ai, difftastic, gitui, tatr
Creator
lukeed
Size
1.2 MB
Stars
160
Age
1mo
Commits · 90 Days