Reference
Commands
Every Repolane command, what it does, and when you reach for it.
On this page
In brief. Every command is one word after
lane; barelaneislane status. This page lists each command by what you use it for, then exit codes,lane doctor, environment variables and the long-form names. Remember that the guard itself is a guardrail with stated limits (Security model), and that a command which behaves differently from this page is a bug in the page or the tool.
Every command is one word after lane. Run lane on its own for the status of everything going on
right now (the same as lane status), and lane help for this list in your terminal. Every command works
on the workspace that contains your current folder (or the one LANE_WORKSPACE names). Outside a
workspace, every command except init, migrate, help and --version stops with “this folder is not
a workspace yet / run: lane init” and exits 2.
web/SHOP-412: 0 dirty, 1 unpushed
api/SHOP-412: 0 dirty, 1 unpushed
SHOP-418 [active] updated 2026-10-22 ticket=
mobile/SHOP-418: 1 dirty, 0 unpushed
api/SHOP-418: 2 dirty, 0 unpushed
== drift: checkouts outside the workspace (should be none; work happens here)
~/work $ lane brief SHOP-412
━━ SHOP-412 [active] ticket: SHOP-412 updated: 2026-10-22
GOAL
Promo codes are validated on the client only, so a crafted request can apply any discount.
Move the calculation server-side and have the client display what the api returns.
RESUME NOTE
_2026-10-22_: promo math moved to api; web still calculates locally
REPO web @ SHOP-412
worktree: /Users/john.mercer/work/lanes/SHOP-412/web
dirty: 0 unpushed: 1
f54c566 wip: park SHOP-412 2026-10-22
c297c4a Initial commit
memory index (/Users/john.mercer/work/.repolane/memory/web/MEMORY.md):
REPO api @ SHOP-412
worktree: /Users/john.mercer/work/lanes/SHOP-412/api
dirty: 0 unpushed: 1
b915b32 wip: park SHOP-412 2026-10-22
edac2f0 Initial commit
memory index (/Users/john.mercer/work/.repolane/memory/api/MEMORY.md):
LOG (last 5)
- 2026-10-22 started
- 2026-10-22 parked: promo math moved to api; web still calculates locally
~/work $ exit
The last screen of a real asciinema recording, as text. With
JavaScript the player replays the whole session from the start.
lane status across three repos and two lanes, then lane brief on one of them — the goal, the note left behind, and where each repo stands. Recorded 2026-10-22. Output can differ from what you see today; run it to see the current text.Output from real runs of the commands in a demo workspace, for the five you reach for most on day two and after. The ticket ids, repo names and owner are made up and home-directory paths are shortened to ~; nothing else is edited. The captures are recordings: probe counts and message wording in them can differ from what you see today. The lane doctor section below shows current output.
Every base clone, every lane, what is dirty, what is unpushed — the whole picture in one screen, with no model call and no waiting.
$ lane status
guard: 11/11 probes answered as they should, 14/14 places point at guard.py: 4 lane(s), 9 worktree(s), the root — lane doctor for the evidence
== workspace (its own git repo, if you made one: docs/install.md)
not a git repo — memory/, knowledge/, CLAUDE.md are not tracked anywhere
== repos (primary mirrors)
api: main, behind origin by 0, worktrees=3
billing-core: main, behind origin by 0, worktrees=1
mobile: main, behind origin by 0, worktrees=1
web: main, behind origin by 0, worktrees=2
worker: main, behind origin by 0, worktrees=2
== lanes
INFRA-661 [parked] updated 2026-10-22 ticket=
worker/INFRA-661: 0 dirty, 2 unpushed
api/INFRA-661: 0 dirty, 0 unpushed
PAY-4155 [active] updated 2026-10-22 ticket=
web/PAY-4155: 2 dirty, 1 unpushed
PAY-4182 [active] updated 2026-10-22 ticket=PAY-4182
worker/PAY-4182: 1 dirty, 1 unpushed
billing-core/PAY-4182: 0 dirty, 1 unpushed
api/PAY-4182: 2 dirty, 1 unpushed
PAY-4207 [active] updated 2026-10-22 ticket=
api/PAY-4207: 0 dirty, 0 unpushed
mobile/PAY-4207: 1 dirty, 2 unpushed
web/PAY-4207: 2 dirty, 2 unpushed
== drift: checkouts outside the workspace (should be none; work happens here) The command that makes a lane survivable: the goal, the note you left yourself, recent commits per repo, and the memory index for each of them.
$ lane brief PAY-4182
━━ PAY-4182 [active] ticket: PAY-4182 updated: 2026-10-22
GOAL
Settlement batches post to the ledger as one atomic transaction, and the nightly job reports drift
per account. Done when a partially-failed batch leaves no half-posted entries, refunds post as new
entries rather than edits, and drift is visible as a metric.
RESUME NOTE
_2026-10-22_: the write path is committed in all three repos. Left: refunds that span two batches
need a single transaction (api), and paging on sustained drift (worker). The new index is written
but not applied — it must run CONCURRENTLY, so it goes out with the infra change, not this deploy.
REPO worker @ PAY-4182
worktree: ~/work/lanes/PAY-4182/worker
dirty: 1 unpushed: 1
1a229e2 Emit a gauge for per-account drift
e0dbf4c Log drift per account rather than in aggregate
ec1c73c Raise the visibility timeout to 300s
8e8c810 Initial commit
M src/jobs/reconcile.py
memory index (~/work/.repolane/memory/worker/MEMORY.md):
- [Queues need 300s visibility](queues-need-300s-visibility.md) — Any queue the reconcile job uses needs a visibility timeout of at least 30
REPO billing-core @ PAY-4182
worktree: ~/work/lanes/PAY-4182/billing-core
dirty: 0 unpushed: 1
822cb6e Add Drift for the nightly reconcile
edc6705 Recompute balance instead of caching it
5cb4e68 Initial commit
memory index (~/work/.repolane/memory/billing-core/MEMORY.md):
- [Ledger is append only](ledger-is-append-only.md) — The ledger is append-only. Corrections are new entries, never edits or deletes.
REPO api @ PAY-4182
worktree: ~/work/lanes/PAY-4182/api
dirty: 2 unpushed: 1
ad4886c Post partial refunds as new ledger entries
b1d534d Index ledger entries by account
3248c88 Post a settlement batch in one transaction
aa8b033 Key the rate limiter on tenant, not API key
3036592 Initial commit
M src/services/ledger.ts
?? src/db/migrations/
memory index (~/work/.repolane/memory/api/MEMORY.md):
- [Migrations are a pipeline step](migrations-are-a-pipeline-step.md) — Schema migrations run as their own pipeline step before the deploy,
- [Rate limits key on tenant](rate-limits-key-on-tenant.md) — The public API rate limit keys on tenant, never on API key.
FINDINGS (live only — archived when this lane finishes)
- 2026-10-22 — the ledger index has to be created CONCURRENTLY
- 2026-10-22 — settlement totals are integer cents in api but Money in billing-core
LOG (last 5)
- 2026-10-22 started
- 2026-10-22 parked: the write path is committed in all three repos. Left: refunds that span two batches You rarely know on Monday which repos a ticket touches. Add one to work already in flight and a branch and worktree appear.
$ lane with PAY-4207 api
worktree ~/work/lanes/PAY-4207/api on new branch PAY-4207 (from origin/main)
next: cd ~/work/lanes/PAY-4207 && claude When two pieces of work turn out to be one: a per-repo verdict on what joining them would do, and nothing changes until you say so.
$ lane plan PAY-4207 PAY-4182
MERGE PAY-4207 + PAY-4182 -> PAY-4182 (dry run — nothing will change)
api: merge PAY-4207 into PAY-4182 (0 commit(s))
mobile: only in PAY-4207 -> worktree moves into PAY-4182
web: only in PAY-4207 -> worktree moves into PAY-4182
worker: only in PAY-4182 -> unchanged
billing-core: only in PAY-4182 -> unchanged
goal, resume note and findings: combined into PAY-4182 under dated headings
PAY-4207: archived to registry/lanes/done/, pointing at PAY-4182
run it with: lane merge PAY-4207 PAY-4182 --run Checks the guard still refuses a known-denied probe, and that every lane is still wired to it — a session that lost its hooks is unguarded even when the guard is healthy.
$ lane doctor
Workspace ~/work:
ok `lane` on PATH runs this workspace's hooks (~/.local/bin/lane, version 0.10.0)
ok CLAUDE.md imports .repolane/REPOLANE.md
ok .claude/settings.json runs Repolane's lane hook commands
ok .repolane/REPOLANE.md and LANE.md are version 0.10.0's
ok registered in ~/.local/share/lane/planes.json
ok every lane's settings.local.json runs the current hooks (13 file(s))
ok Claude Code's memory is linked into .repolane/memory (6 folder(s) under ~/.claude/projects)
ok Repolane's slash commands and agents are in .claude/ (11 file(s), version 0.10.0's)
ok status line: lane statusline
guard.py compiles; 11/11 probes answered as they should:
deny a worktree with no lane named
deny a worktree opened by path
deny reading a .env
deny a shell that prints a .env
deny writing a memory directly
deny a push to a default branch
deny rewriting the git remote
deny a push to main, written differently
deny grepping a .env (Grep reaches it)
deny deleting a GitHub repo
pass ordinary work is untouched
14/14 places point at guard.py: 4 lane(s), 9 worktree(s), the root
gh is not authenticated — some commands (lane sync, lane gh) will not work until: gh auth login
hundreds more cases behind this (the whole suite): lane doctor -v Setting up
pipx install repolane (or uv tool install repolane) | install the package, once per machine. It puts lane and the long-form names on your PATH. See Install |
lane init [<folder>] [--owner <name>] [--yes] [--git] [--claude-home <dir>] | make the folder (default: the current one) a workspace, or check that it already is one; safe to re-run. Asks for your name, whether to add the import line to an existing CLAUDE.md, and whether to link Claude Code’s memory under ~/.claude into .repolane/memory. --yes takes the defaults; --git makes the workspace a git repo with a .gitignore for the machine-local parts. See Install |
lane add <git-url|path> [name] | bring a repo under management. A path adopts an existing checkout (see Install); one with no origin is registered local-only. --local <path> tells it a checkout of this repo already exists on the machine, so its past conversations are recognised. --from <path> copies the git database from that checkout instead of cloning again, even when you give a URL first. It asks before linking the new base clone’s Claude Code memory (--yes accepts; with no terminal it changes nothing under ~/.claude) |
lane import | bring past Claude conversations in. Entirely optional; copies transcripts into a lane’s folder and never touches the originals. lane import --list only looks (and exits 1 when there is nothing to show); lane import --into <id> <n>… is the non-interactive form; lane import --claude-home <dir> reads another Claude data folder |
lane migrate [<folder>] [--dry-run] [--yes] [--git] [--verbose], lane migrate --undo <backup> | turn a git-clone install into a workspace, in place, with a preview, a backup and an undo. See Moving from a git-clone install |
lane help, lane <command> --help, lane --version | the full list; the usage comment directly under that script’s shebang; the version (for example lane 0.10.0) |
Doing the work
lane start <id> [--base <ref>] <repo>[:<branch>][@<base>]… | start a piece of work: a branch and a worktree in each repo. An existing branch of that name is checked out as it is and the base is ignored |
lane with <id> <repo>[:<branch>]… | add repos to work already started |
lane resume <id> | pick work back up: prunes stale worktree records, recreates missing worktrees, rewrites the guard wiring and marks the lane active (rewriting the wiring is how a lane created earlier picks up the current tool matcher and secret-name deny list) |
lane park <id> "<note>" | leave work for later: wip-commit every dirty worktree and record the note (at least 10 characters). It stages by explicit literal path and never commits a file whose name says secret (the full list is under Rules): those stay on disk, untracked, and it prints left out of the commit (secret file names, still on disk): …. A secret somebody already staged stops the park with nothing committed (git reset -- <file>, then park again). Everything else git does not ignore is committed, so look at git status first |
lane done <id> [--delete-branches] [--delete-sessions|--keep-sessions] [--discard-ignored] [--pushed-to <remote>] | finish and clean up. Refuses while anything is dirty or unpushed, where “unpushed” means commits on HEAD that no origin/* branch has. --pushed-to <remote> checks that remote instead of origin (a fork). A repo with no origin is local-only and does not block: it is noted and the lane finishes. It also refuses while a worktree holds an ignored or untracked secret-named file that deleting the worktree would destroy, naming it, unless you pass --discard-ignored. See what it removes and lane done refusing |
A repo spec can carry a branch and a base: lane start ABC-123 web:feature/login api@release-2
puts web on branch feature/login (checked out as it is if it already exists, otherwise created from
the default branch) and branches api from release-2 under the name ABC-123.
Seeing where things stand
lane or lane status | every repo, every lane, any drift, and the workspace’s own git state. Runs the quiet form of lane doctor first, and runs git fetch -q origin in every base clone under .repolane/repos/ (a failed fetch is ignored), which is the only network access it makes. |
lane brief [<id>] | catch up on one piece of work. For a finished lane it prints an “archived” marker and reads the archive throughout: status, ticket and dates, each repo with “worktree removed when the lane finished”, the references that were attached, the resume note and the log. A lane id with characters outside letters, digits, ., _ and - just reports “no lane” |
lane board | the same thing in a browser; see The board |
lane find <text> [--all] | which lane touched this? Searches goals, resume notes, findings, branch names, commit subjects and the files each branch changed. Read-only. --all lists finished lanes too |
lane audit [repo] | writes .repolane/registry/branch-audit.md: every local branch with no upstream or with unpushed commits |
lane sessions <repo|id> [n] | past Claude conversations, newest first |
lane menu | the long-form menu (needs the long-form names on your PATH) |
Reaching into a repo
You never cd into one. These work from wherever you are:
lane run [--lane <id>] <repo> <cmd…> | run a command inside one repo of the lane. --lane is needed from the workspace root. The repo may be its short alias from .repolane/registry/repos.yaml |
lane gh <repo> <args…> | the GitHub CLI, scoped to one repo |
lane ref <id> add <path> ["note"] [--rw] | attach outside code or docs as a reference (read-only unless --rw). In a Claude session the guard refuses /, your home directory, system and credential directories and secret files |
lane ref <id> rm <path|name>, lane ref <id> list | detach one (the target is never touched); show them |
lane run and lane gh are a shortcut, not a bypass: whatever they carry is judged by exactly the
same rules as a command you typed yourself. Commands run this way inherit WS_HOME,
NX_CACHE_DIRECTORY and NX_DAEMON=false from .repolane/env.sh.
Memory and knowledge
lane note is the only way memories get written; its long form is lane-memory, which is what a
session inside a lane uses.
lane note draft <slug> ["<text>"|-] | write a draft into the inbox (.repolane/cache/memory-inbox/), from the argument or stdin, and print its path; with no text, print the path to write it at |
lane note goal [<id>] "<text>"|- | replace a lane’s ## Goal: the lane you are in (another lane’s is refused), or <id> from the workspace root. How a lane session saves its Goal, since Claude Code refuses Edit and Write outside the lane folder |
lane note show <slug>, lane note list, lane note drop <slug> | show a pending draft; list drafts; discard one |
lane note file <slug> pref|cross|repo <repo>|lane [<id>] | file the draft at that scope and write its index line |
lane note move <name> cross|repo <repo> | re-scope an existing memory, reindexing both sides |
lane note rm <name> [repo <repo>] | delete a memory and its index line |
lane note index [repo|cross] | rebuild the MEMORY.md index lines from the files |
lane note audit | memories whose scope looks wrong |
The procedure (draft, ask which scope, file) is a convention a session is told to follow; the guard
blocks writing the folders directly, and only lane-memory list|show|audit|draft|goal are pre-approved (file, move, rm, drop and index prompt), but nothing makes a session ask you which scope. Every name it is given (slug, repo, lane id, memory name) must be [A-Za-z0-9._-]+.
See Rules and Concepts.
Housekeeping
lane merge <a> <b> [--new-branch <name>] [--as <new-id>] [--run] | two pieces of work turned out to be one. Prints the plan and changes nothing without --run, and --run must be run from the workspace root because worktrees move |
lane plan <a> <b> [--new-branch <name>] [--as <new-id>] | the read-only twin of lane merge; --run is rejected |
lane doctor [--fix] [--yes] [-v|-q] | check the workspace is wired and the safety rules are actually working. --fix repairs what it safely can, asking before it edits CLAUDE.md or anything under ~/.claude (--yes answers). -v lists every location and runs the full guard suite; -q is one line. Exits non-zero if the workspace, the guard or its wiring is broken. The suite’s own result under -v does not change the exit code, so a failing case shows in the output but still exits 0 |
lane nested [--fix] | find worktrees that sit inside another worktree; --fix removes them (never the branch, never one with uncommitted work) |
lane workspace | rewrite the editor workspace files |
lane env [<id-or-repo>] | check each worktree has the env files its base clone has, as links. Names only |
lane keys [<path|dir>] | list the variable names in an env file (default ./.env), never the values. Use it from your own terminal: inside a Claude session the guard refuses this spelling, and only the bare lane-env-keys passes; see Rules |
lane secrets <repo> scan|add|ignore|list|ignored [<path-or-glob>…] | a repo’s own secret filenames; add writes deny rules. See Extending |
lane sync [repo] | check a repo’s real GitHub branch protection (gh api) and record it for the guard. Exits 0 only when at least one repo was read from GitHub and none failed; otherwise 1 (see exit codes) |
lane upgrade [--check] [--refresh-only] [--drop-missing] [--yes] | upgrade the package the way it was installed (pipx upgrade repolane, uv tool upgrade repolane, or for a pip install the pip command to run), then refresh every workspace registered in ~/.local/share/lane/planes.json: the rule files and data migrations, Repolane’s hooks in .claude/settings.json (your own keys and hooks kept), and every lane’s settings and CLAUDE.md. Nothing you wrote is changed. --check shows the installed version against the newest on PyPI and which workspaces are behind, and changes nothing; --refresh-only skips the package step. See Upgrading |
lane rules pull [<url>|--latest], lane rules status | pull a shared, SHA-pinned rules source. It never overwrites a same-named file you put in .repolane/scripts/local/: it keeps yours and says so, unless an earlier pull put that file there (tracked in .repolane/cache/scripts-pulled). See Extending |
Any executable file you drop into .repolane/scripts/local/ also becomes a lane <name> command of
its own, with nothing in the package to edit. It is part of your workspace, a full peer of the built-in
commands, and lane help lists it under “your commands:”. Built-ins always win: if a local script
shares a name with a real command, the built-in runs and lane doctor flags the local file as
shadowed.
lane doctor is the one to run when something feels wrong. It starts with the workspace: lane on
PATH the way the hooks call it (if not, every hook fails and Claude Code runs tools unguarded), the
import line in CLAUDE.md, the lane hook commands in .claude/settings.json and in every lane, the
rule files at the installed version, the registration in planes.json, the memory links and the status
line, each problem with its fix. Then it compiles the guard and fires its named probes at it (eleven
built in, plus one per rule you added under .repolane/registry/rules.yaml), and checks every lane and
worktree is still wired to it. It also prints advisories that never change its exit code: stale lanes
(stale_days); GitHub repos whose branch protection lane sync has not checked lately; unreviewed
candidate secret filenames; whether gh is installed and signed in; lanes whose spec and worktrees
disagree; .repolane/scripts/local/ scripts shadowed by a built-in; and, first and most prominently,
whether a lane rules pull source has drifted from its pinned commit. It fails, and names the place, when a lane’s or the root’s PreToolUse matcher
lacks Glob|Grep (run lane resume <id>). Only a genuinely broken rule or guard fails the command.
Exit codes
Measured against the product, not promised by it. The product’s tests/ suite asserts the codes for lane sync, lane import --list and bare lane outside a workspace. Convention: 0 means it did what you asked, 1 means it refused or failed, and the dispatcher returns 2 for a command it does not recognise.
| You run | Exit code |
|---|---|
lane nosuch | 2 |
lane start with no arguments, lane brief <no such lane>, lane park <id> "short" (a note under 10 characters) | 1 |
lane done <id> while anything is dirty, unpushed, or holds a secret file the deletion would destroy | 1 |
lane merge / lane plan while either lane has uncommitted work | 1 |
lane sync with gh missing or not signed in, with no repos, with any repo failing, or when nothing could be checked (every repo local-only or not on GitHub); lane import --list with nothing to find | 1 |
lane sync when at least one repo was read from GitHub and none failed | 0 |
lane doctor with a healthy guard, with or without advisories (a missing gh is an advisory) | 0 |
lane doctor when the guard does not compile, a probe answers wrongly, a rule does not refuse its example, or a lane’s settings do not point at the guard (!! … NOT in force everywhere) | 1 |
lane plan <a> <b> --run (it never runs a merge; the message tells you to use lane merge … --run) | 2 |
any command other than lane init/migrate/help/--version, run outside a workspace, including bare lane | 2 (“this folder is not a workspace yet”) |
The guard hook has its own codes (How it fails). Scripts that wrap lane should check the code, not parse the words.
Merging, importing and syncing in practice
lane merge and lane plan. Both refuse, with exit 1 and nothing changed, while either lane has
uncommitted work (“commit it or lane-park first”). By default b keeps its branches, a’s commits
are merged into them and a is archived. --new-branch <name> puts every repo on one new branch
carrying both, leaving the original branches as they were; --as <id> makes the result a new lane and
archives both. A repo in both lanes is merged; a repo in only one has its worktree moved. The goal,
resume note and findings are appended under dated headings and references are unioned. Branches are never
deleted, and a conflict stops the merge and leaves the worktree for you.
lane import. It matters only if you want claude --resume on an old conversation from inside a
lane. Picking a conversation copies the transcript into the lane’s folder and leaves the original where
it was. With nothing under ~/.claude/projects it says so, does nothing and exits 1.
lane sync. Manual; nothing runs it for you. It records in .repolane/registry/repos.yaml
(protected_branches: and protection_synced:) which branches GitHub says are protected, and the guard
then refuses pushes to those branches as well as the names it already guesses. lane doctor reminds you
when the record is old.
What a healthy lane doctor looks like
From a real run in a scratch workspace with one lane and one worktree. gh was not
signed in, which is why the advisory is there. It does not fail the command:
$ lane doctor
Workspace ~/one:
ok `lane` on PATH runs this workspace's hooks (~/.local/bin/lane, version 0.10.0)
ok CLAUDE.md imports .repolane/REPOLANE.md
ok .claude/settings.json runs Repolane's lane hook commands
ok .repolane/REPOLANE.md and LANE.md are version 0.10.0's
ok registered in ~/.local/share/lane/planes.json
ok every lane's settings.local.json runs the current hooks (2 file(s))
ok Claude Code's memory is linked into .repolane/memory (2 folder(s) under ~/.claude/projects)
ok status line: lane statusline
guard.py compiles; 11/11 probes answered as they should:
deny a worktree with no lane named
deny a worktree opened by path
deny reading a .env
deny a shell that prints a .env
deny writing a memory directly
deny a push to a default branch
deny rewriting the git remote
deny a push to main, written differently
deny grepping a .env (Grep reaches it)
deny deleting a GitHub repo
pass ordinary work is untouched
3/3 places point at guard.py: 1 lane(s), 1 worktree(s), the root
gh is not authenticated — some commands (lane sync, lane gh) will not work until: gh auth login
hundreds more cases behind this (the whole suite): lane doctor -v
The probes include a push to main written as git push origin 'main'; and a Grep over a .env.
lane doctor -v adds one ok line per location, then runs the whole suite and ends with a line like the one below (the number of cases grows as cases are added):
1884/1884 cases passed
ALL PASS
A line that begins !! is the one to act on; see Troubleshooting.
Environment variables
WS_BOARD_PORT | the board’s starting port (default 7777) |
WS_BOARD_NO_OPEN | any non-empty value: start the board without opening a browser |
WS_BOARD_REFRESH | seconds between the board’s git-state refreshes (default 3) |
LANE_WORKSPACE | the workspace to act on, instead of finding it by looking up from the current folder |
CLAUDE_HOME | where Claude Code keeps its data (default ~/.claude). Read by lane init and lane import. lane add reads it only to look for past conversations; its memory link, lane done, lane sessions, the board and the SessionEnd hook use ~/.claude regardless, so set it consistently or not at all |
LANE_PLAIN | any non-empty value: the session-start script prints plain text instead of the JSON a hook returns. A terminal wrapper uses it; you normally do not |
CLAUDE_PROJECT_DIR | when set (Claude Code sets it for hooks), lane hook and lane statusline find the workspace from it instead of the current directory, because a cd in a session moves the current directory |
Not user settings: WS_HOME, NX_CACHE_DIRECTORY and NX_DAEMON are set by .repolane/env.sh for
the lane scripts, and LANE_PRODUCT names the installed package’s files for your own commands. ALLOW_DEFAULT_BRANCH_PUSH=1 is not an environment variable but a marker typed at
the start of a command; see Rules.
Things worth knowing
lane start writes an editor workspace. Alongside the worktrees you get
lanes/<id>/<id>.code-workspace, a multi-root workspace with every repo of the lane, each on the
right branch. Open it and the whole ticket is in one window:
{ "folders": [
{ "name": "lane", "path": "../.." },
{ "name": "PAY-4182 · api", "path": "api" },
{ "name": "PAY-4182 · billing-core", "path": "billing-core" },
{ "name": "PAY-4182 · worker", "path": "worker" }
],
"settings": { "files.exclude": { "repos": true, "lanes": true, ".cache": true, "…": true } }
}
(Abridged: the real settings also carry search excludes and git-detection options.) The first
folder, lane, is the workspace root. lane workspace
rewrites these files, and also writes a root-level lane.code-workspace covering every active lane
(there the lane folder’s path is . and each repo’s path is lanes/<id>/<repo>). More on The board.
lane run accepts short names. Give a repo a short: in .repolane/registry/repos.yaml and
lane run api mvn -q package works as well as the full name, case-insensitively.
lane note audit finds memories filed at the wrong scope: written about one repo but phrased as true everywhere.
The board has a JSON API. GET /api/board returns every lane with per-repo ahead, behind,
base_behind, staged, unstaged, pr_state and pr_failing. Every call needs the X-Token
header. The board does not print it: load / and read it from the page (window.__T), with a
Host of 127.0.0.1:<port> or localhost:<port> (anything else gets 403); see
The board. The routes are listed in scripts/board/README.md in the Repolane repo.
Long-form names
Most commands also exist as an executable of their own (lane-start, lane-run, lane-memory, …):
27 of them, which the package installs next to lane on your PATH (lane-env-keys and
lane-env-check map to lane keys and lane env). The names do not always match the command:
lane note is lane-memory, lane plan is lane-merge-plan, lane doctor is guard-check, and
lane-help, lane-init, lane-status and lane-sessions exist as well. secrets, sync, rules,
upgrade and migrate have no long form. The guard messages and the agent prompts mostly tell you to type the long forms, and they
run from any directory without a cd.
A command that behaves differently from this page is a bug in the page or the tool; see Contributing and reporting.