Reference
Teams
What is machine-local and what is shareable, what happens when someone leaves, and the parts that are honestly still single-player.
On this page
“A ticket touches three repos” is an organisational problem, and Repolane is a tool that runs on one laptop. Those two facts do not cancel out, but it is worth being exact about where the line sits — so this page says what the code actually supports today, and names the parts that do not exist.
The short version: Repolane is single-player. It coordinates one person across many repos. It does not coordinate many people across one lane. Where people meet is still git — branches, remotes and pull requests — as always.
Machine state and source of truth
The split is drawn in the workspace, and lane init --git writes it into a .gitignore for you.
| Machine state: deletable, rebuildable | .repolane/repos/ (the base clones), lanes/ (the worktrees), .repolane/cache/, every .claude/settings.local.json |
| Source of truth: small, plain text, what git can track | CLAUDE.md, .claude/settings.json, .repolane/config.yml, .repolane/env.sh, .repolane/registry/ (the repo list, the lane files, your rules), .repolane/memory/, .repolane/knowledge/ and .repolane/scripts/local/ |
| Repolane’s, refreshed on upgrade | .repolane/REPOLANE.md, .repolane/LANE.md, .repolane/version: commit them, never edit them |
A lane file is a few dozen lines: the goal, the repos and branches it touches, the note you left when you parked it, findings, and an appended log. Nothing in it is a secret and nothing in it is big. It is the part worth keeping.
Can two people work the same lane?
Not as one shared thing, no. There is no server, no locking, no notion of a second user anywhere
in the code. Lane ids are local names; two people can each have a lane called ABC-123 on their
own machines and neither will know about the other.
What they can share is what they always shared. Lane branches are named after the lane id in
each repo by default, they are pushed to the normal remote, and lane gh <repo> pr create opens a pull
request the usual way. So the handover is a branch and a PR, plus, if you want the context to
travel too, the lane file, which is a text file you can paste into the ticket or commit
somewhere.
Should the workspace be committed somewhere shared?
Your own workspace repo is the normal way to back it up and to carry it to another machine:
lane init --git, commit, push to a private remote, clone it elsewhere and run lane init there
(see Install). Repolane never pushes it.
Sharing one workspace repo between people is a different thing. A team that wants everyone to start
from the same repo list, rules and commands can keep one workspace repo and clone it on each machine:
.repolane/registry/repos.yaml, .repolane/registry/rules.yaml and .repolane/scripts/local/ are
ordinary tracked files. What should stay per person (.repolane/memory/, .repolane/knowledge/, the
lane files, config.yml with its owner name) is up to you: leave it out of the shared repo, or add it
to .gitignore.
Two things to know before you do. .repolane/registry/old-checkouts.json and any lane file with an
attached reference contain absolute paths from the machine that wrote them (/Users/you/...), and
config.yml names one owner. They were written to be read by a person and by the hooks on that
machine, not to be merged between machines. Sharing them as reading material (here is what I was
doing and where I got to) works. Sharing them as state two machines both write to is not something
the tool supports, and you would be hand-resolving conflicts in a log file.
For rules alone, lane rules pull is the lighter way: every machine pins the same commit of a
separate rules repo, and nobody’s own files are touched.
What happens when someone leaves
Honestly: whatever was only on their laptop goes with the laptop. The goal, the resume note and
the findings for an in-flight lane live in .repolane/registry/lanes/<id>.md on that machine. Nothing
is replicated anywhere by default.
The parts that survive without any action are the parts that were already pushed: the branches, the commits, the PRs. That is the same exposure a team has today with someone’s local branches. Repolane does not make it worse, but it does not fix it either, and it collects more context worth losing than a bare checkout does.
If that context matters to you, the mitigation is the one above: keep the workspace in a private
git repo of your own and push it. With lane init --git, the lane files, the repo list, memory and
knowledge are all tracked; only the machine-local parts are ignored.
Rolling this out to twelve people
There is no fleet configuration, no central policy file and no server that pushes a change to
everyone. Each person runs pipx install repolane and lane init in a folder of their own, and
answers up to three questions (or passes flags; see Install).
What that actually involves:
- Each person gets their own copy of every repo. The base clone under
.repolane/repos/<name>is a full clone, shared between that person’s lanes but not between people. Twelve people is twelve clones, as it is today. .repolane/config.ymlis the per-person file. It holds the owner’s name, the tracker URL and a few defaults (stale_days,delete_sessions_on_done,sync_days). Only the tracker line is likely to be the same for everybody.- There are two ways to share setup.
lane rules pullkeepsrules.yaml(and optionally scripts and notes) in a git repo that each person pulls, pinned to a commit SHA; see Extending, including what comes with it: scripts that become commands and notes that are injected into every session. Or a shared workspace repo, as above. The built-in guard itself comes with the package, so everyone on the same version has the same guard;lane upgrademoves each machine forward. lane doctoris the only compliance check, and it is local. It tells the person at that machine whether their guard compiles and is still wired into every lane. Nothing reports anywhere.
Know that before you promise anyone central control: there is none.
The board’s token, and what it does and does not protect
lane board starts a Python server bound to 127.0.0.1 only, never 0.0.0.0, so nothing on your
network can reach it. On top of that, each run generates a fresh token (secrets.token_urlsafe(24)).
It is not printed in the terminal: it is embedded in the page the server sends your browser, and
every /api call is rejected with 403 unless it carries that token in an X-Token header.
What the token is for: it stops a form post or a cross-origin fetch from another site in your
browser, which cannot set a custom header, from driving the board.
What it is not:
- It is not a login. The page that carries the token is served to anyone who can reach the port, so another local account on a shared machine can fetch it and read the token. If other people have shell accounts on the machine you run this on, do not run the board there.
- DNS rebinding is blocked. Every request, the page at
/included, must carry aHostof127.0.0.1:<port>orlocalhost:<port>(and anOriginof the same when sent), or the server answers403. A web page that makes your browser resolve a name it controls to127.0.0.1cannot load/and read the token. The check does nothing about another local account that connects to the port and sets the rightHost. See the security model for the routes that token opens, which include discarding changes and pushing. - It does not protect against another process running as you. That process can already read your repos.
The board also reaches the network, so “it never leaves your machine” is not accurate. Its page
makes no outbound requests (the fonts ship with it), but while it is open the server polls GitHub through
gh pr view every 60 seconds to fill the pull request column. Push and Pull run git push and
git pull. With gh not installed that column is empty.