repolane v0.11.0 · open source

Concepts

Where state lives

What Repolane saves, where, what a resume brings back, what `lane done` deletes, and what is never kept.

On this page

Everything Repolane remembers is a file, and almost all of it is plain text inside your workspace. This page lists each piece, what scopes it, what survives a restart, and what is removed when work ends. For files that land outside the folder, see What it changes on your machine.

In brief. Everything Repolane remembers is a plain file in your workspace, plus git itself: no database, no daemon. A resume repairs and reconnects; it never restores, because nothing was elsewhere. lane done deletes worktrees (and the ignored files in them) but keeps the lane file and, by default, the branches. Conversation text is never stored by Repolane.

The short version

QuestionAnswer
Is there a database?No. Files, and git itself.
Does anything run in the background?No daemon. lane board is a server you start and stop; see The board.
Where does a lane’s context live?One file, .repolane/registry/lanes/<id>.md: goal, resume note, findings, log.
What survives closing the terminal or rebooting?All of it. Nothing is held in memory by Repolane.
What does lane done delete?The worktrees (including git-ignored files in them) and the lane folder. It archives the lane file; it keeps the branches unless you pass --delete-branches. It may delete Claude’s saved sessions for the lane if you say yes.
Does Repolane record what Claude said?No. It records one line of state per session, and which files Claude’s edit tools touched. Conversations stay in Claude Code’s own folder.

What is stored where

Paths are from the workspace root. The “workspace repo” column applies when you made the workspace a git repo of your own with lane init --git; without it, nothing in the workspace is tracked anywhere.

WhatWhereIn your workspace repo?lane resume and lane done
The lane file.repolane/registry/lanes/<id>.mdyesresume: untouched. Done: moved to .repolane/registry/lanes/done/ and kept
Worktreeslanes/<id>/<repo>/no, ignoredresume: missing ones are recreated from their branches. Done: removed, including ignored files inside them
Branches.repolane/repos/<repo>/ (the base clone’s refs) and the remote once pushedno, the base clones are ignored; branches travel by git pushresume: kept. Done: kept, unless --delete-branches
Cross-repo and per-repo memory.repolane/memory/MEMORY.md, .repolane/memory/<slug>.md, .repolane/memory/<repo>/yesboth: untouched
Preferences, shared knowledge.repolane/knowledge/preferences.md, .repolane/knowledge/shared/*.mdyesboth: untouched
The repo list.repolane/registry/repos.yamlyesboth: untouched
Your own rules, pulled team rules.repolane/registry/rules.yaml, .repolane/registry/rules.shared.yamlyes (the pulled repo’s cache, .repolane/registry/.shared-cache/, is ignored)both: untouched
Adopted checkouts, so the guard can freeze them.repolane/registry/old-checkouts.jsonyesboth: untouched
Your settings and Repolane’s hooks.claude/settings.jsonyesboth: untouched (lane upgrade refreshes Repolane’s own hooks in it)
Per-lane permission and hook settings.claude/settings.local.json at the lane root, in each worktree and at the workspace rootno, ignoredresume: regenerated, merged into what was there. Done: removed with the worktrees; the root one is rewritten
Files Claude’s edit tools touchedlanes/<id>/.touchedno, ignoredconsumed at session end; removed with the lane folder
What the first-prompt brief already injected.repolane/cache/sessions/<session-id>.jsonno, ignoredremoved at session end
Memory drafts waiting to be filed.repolane/cache/memory-inbox/no, ignoredboth: untouched
The raw SessionStart input, and the transcript-rename log.repolane/cache/last-session-start.json (overwritten each session), .repolane/cache/transcript-moves.logno, ignoredboth: untouched
Claude Code’s own conversation history~/.claude/projects/<slug-of-the-worktree>/not Repolane’sresume: kept. Done: deleted if you answer yes at the prompt (or pass --delete-sessions)
The list of workspaces on this machine~/.local/share/lane/planes.jsonnoboth: untouched

The lane file

Four sections under a small header. lane start creates it. You edit it by hand from the workspace root; a session inside a lane sets its Goal with lane-memory goal "<text>", because Claude Code refuses Edit and Write outside the lane folder.

---
id: ABC-123
status: active                    # active | parked | done
ticket:
created: 2026-10-14
updated: 2026-10-14
repos:
  - repo: web
    branch: ABC-123
    base: main
---
## Goal              what done looks like
## Resume note       written by `lane park`: where things stand, next step, blockers
## Findings          things that matter only while this work is live
## Log               one dated line per event
  • lane park <id> "<note>" replaces Resume note with your note (10 characters minimum) and appends a line to Log; the other sections, Findings included, are left as they are.
  • At the end of every session the SessionEnd hook appends one line to Log: the time, then for each repo its branch and how far ahead, behind and dirty it is, then up to twelve files the edit tools touched. If any worktree was dirty it ends with UNPARKED. That is one line for the whole lane, not a log per repo, and it only lists files changed through Claude’s Edit, Write, MultiEdit and NotebookEdit tools: a file changed by a shell command is not in it. Nothing reads UNPARKED back to you; it is there when you open the lane file or run lane brief. A line identical to the previous one except for its timestamp is skipped, so read-only runs do not pile up copies.
  • Findings are what you file with lane note file <slug> lane (lane-memory file <slug> lane from a session). They are archived with the lane. Anything still true after the work ships belongs in repo memory instead.

What a resume brings back

lane resume <id> is a repair, not a reload. It prunes stale worktree registrations in every base clone, recreates any worktree whose folder is missing from the branch that still exists, relinks env files, re-anchors the lane folder, rewrites the lane’s settings.local.json files and marks the lane active again. Your lane file, memory and branches were never anywhere else, so there is nothing to restore.

A new Claude session in the lane starts with no conversation, and gets: the whole lane file (header, goal, resume note, findings and log) when the session starts; then, with its first prompt, a state line per repo and the memory indexes (the cross-repo MEMORY.md and one per lane repo, each cut at 3,000 characters), plus .repolane/knowledge/preferences.md and every .repolane/knowledge/shared/*.md, each also cut at 3,000 characters. A session that enters a lane, or starts inside one, is also handed .repolane/LANE.md, the rules for working inside a lane. Individual memory notes are not injected. Claude can resume an old conversation with claude --resume only from the folder it ran in; lane import copies old conversations into a lane’s folder so that works. See Working with Claude.

Scope: what is shared across repos and lanes

ScopeShared with
pref: .repolane/knowledge/preferences.mdevery session in every lane
cross: .repolane/memory/<slug>.md, indexed in .repolane/memory/MEMORY.mdevery session in every lane
repo: .repolane/memory/<repo>/every lane that touches that repo
lane: the lane file’s Findingsthat one lane

Memory is plain markdown, and git does not treat it specially, so which scope a note belongs in is a judgement about how long it stays true. The lane note command enforces the procedure (draft, ask which scope, file it); the guard denies a session from writing those folders directly. The scope choice itself is an instruction in the session’s context, not something a hook can verify.

What is not kept

  • Conversation text. Repolane does not copy or store what you and Claude said. The lane file is what you or Claude wrote into it.
  • A record of refusals. The guard answers deny or allow and nothing writes it down. A refusal exists in the Claude Code transcript and nowhere else.
  • Secrets. Env files are symlinked from the base clone into each worktree, never copied or read. The guard and the board try to keep recognised secret names away from a session or a page; both match by name, by one shared list, and cannot see a secret under a name they do not know (security model). Two caveats are on Install (adoption copies ignored .env* files into the base clone) and Rules (lane park commits everything that is not ignored except files with a secret name, which it leaves on disk).
  • Board state. The board keeps its token and caches in memory only; stopping it discards both.
  • Anything about other people. There is one user. See Teams.

What lane done removes, exactly

  1. Checks every repo before touching any: dirty tree, commits that no origin/* branch has (or none on the remote you named with --pushed-to), a detached HEAD carrying such commits, a missing worktree whose branch is not fully pushed, or an ignored or untracked secret-named file the deletion would destroy (unless --discard-ignored) each stop it with nothing removed. A repo with no origin is noted and does not block.
  2. For each repo: git worktree remove. Git deletes the folder, which takes the other git-ignored files (build output and the like) with it. Symlinked env files from the base clone are only links.
  3. With --delete-branches: git branch -D on the lane’s branch in the base clone.
  4. For each repo, if Claude saved sessions for that worktree: asks, defaulting to what delete_sessions_on_done in .repolane/config.yml says, and deletes the folder under ~/.claude/projects/ if you agree. With no terminal it does not touch them; flags are --delete-sessions and --keep-sessions.
  5. Removes lanes/<id>/, prints any Findings, moves the lane file to .repolane/registry/lanes/done/. (lane brief <id> reads the archived file; see Commands.)

A lane in a local-only repo (no origin) can finish: step 1 notes it and moves on, and the branch stays in .repolane/repos/<repo>. See lane done refusing.

Next steps