From purchase in your terminal to your first lane, then every command to continue and find your way back.
This guide describes Treelab 1.3.0, the latest published version.
Text remains selectable. Check paths before pasting a command into your terminal.
Prepare your Mac
You need a Mac running macOS 13 or later and at least one coding agent, Claude Code or Codex, already signed in to your account. Accounts, access and subscriptions for these tools are separate and not included. If missing, Git and jq are installed by the installer through Homebrew, and cmux by lab setup, each time after your consent. gh and its GitHub permissions are only needed to deliver pull requests.
In Terminal, check the macOS version and that your agent is present: each command -v should print a path. If no agent is found, install Claude Code or Codex and sign in before continuing.
sw_vers -productVersion
command -v claude
command -v codex
Buy and install
Paste the command below into Terminal. The installation assistant works in four stages: Prepare, Plan, Activate, Start. Prepare: you choose your agents, your project and your objective; your choices stay on this Mac. Plan: it proposes a first breakdown. Activate: it offers 1 “Buy Treelab” or 2 “Enter a key”. Buying opens the payment page in your browser; then return to the terminal: the key arrives there, and also by email. If you paid through the website’s payment link, choose 2 and paste the key received by email (it starts with tl_key_). Never pay twice: running the same command again resumes where you left off.
A consumer receives the key immediately only if they request supply before the end of the 14-day withdrawal period and acknowledge losing that right; otherwise the key arrives by email when the period ends. The assistant then activates the licence on this Mac, installs Git and jq if missing, and downloads and verifies Treelab.
Start: it runs lab setup, which shows the plan (instructions, skills, agents, hooks, commands, shell profile and backups) and offers cmux separately if missing. Type I accept only if you agree to these changes; if you decline, nothing is installed and lab setup --dry-run shows the plan again at any time. Finally, the assistant registers your project and opens its first lane in cmux, with your objective.
curl -fsS https://treelab.sh/install | /bin/bash
lab setup --dry-run
Check the installation
Open a new terminal to pick up PATH changes. The installed command is treelab; lab is its short name when that name is free. If lab already belongs to another tool, it is kept and you use treelab for direct calls. Lane tabs start the agent with lab launch: this automatic startup assumes lab resolves to Treelab; otherwise, contact support before continuing.
doctor explains each check with a NOTE: fix each failure, then rerun. Codex asks for a one-time hook approval (/hooks); Claude Code loads them without any action. The regular diagnostic may contain private paths: keep it on your Mac.
treelab --version
treelab doctor
command -v lab
Your first lane
A project is your registered Git repository. A lane (formerly couloir) is an isolated working copy under .worktrees/ for one need. A batch (formerly lot) is a verifiable step with a branch and a document; its Goal states the result that must be proved.
When installation ends, your first lane is already open in cmux: the agent starts from the objective chosen during preparation, without repeating the questions, and writes the plan of the first batch. Answer in that tab; afterwards, lab next opens each step with the document’s Goal.
For a new need in the same project, lab new creates another lane; --brief gives the agent the text of your need. For another repository, run lab onboard in its folder: it registers it without touching your files and opens an agent in that project’s “main” tab.
lab next demo premier
lab new demo second --brief besoin.md
cd /chemin/vers/autre-depot
lab onboard
From batch to delivery
In the lane tab: clarify → plan → execute → verify → deliver. Checks include tests, the doctor diagnostic, an independent review and actually trying the screens. Each batch is delivered by lab merge after checks pass; its document keeps the evidence and a Handoff readable without the agent’s memory.
next reads the state and selects the next step; it neither merges nor removes anything. After the last batch comes acceptance: you try the exact result, then the agent records your approval with lab acceptance. close then delivers the last batch and removes the lane, after your explicit confirmation; --dry-run first lists anything that would prevent it. A failed check stops delivery until it is fixed.
lab plan demo
lab status demo
lab close demo premier --dry-run
lab close demo premier
Update, rollback and removal
lab next installs the latest minor or patch version by itself, at most once a day; a major version is only announced, and auto_update=no in ~/.lab/config limits everything to the announcement. lab update does the same on demand: it downloads the version with your licence, checks the archive and its fingerprint, then switches. Open agent sessions keep their version.
The previous version is preserved: lab update --rollback returns to it offline. Every failure ends with RESULT=refused or interrupted, the reason and the file concerned, and the installed version is kept; --resume continues an interrupted update.
For removal, inspect uninstall --dry-run, then run uninstall or uninstall --keep-state to keep the active installation manifest marked as removed. The registry is always preserved; without this option, the completed manifest is archived with backups. Backups remain at the printed path; separate dependencies are not removed. Interrupted removal resumes with uninstall --resume. Fix the stated cause first; do not delete the journal.
lab update --catalogue
lab update --rollback
lab uninstall --dry-run
Data and network
Treelab sends no telemetry. Only three moments use the network: the installer (purchase, then licence activation with your key and a random identifier for this Mac, machine_id), lab update and lab next’s automatic update (your licence and the same identifier, to download the version). Everything else, including your repositories and documents, stays on your Mac and in your own remote repositories.
This site loads no diagnostic service and never asks for your key. The package, its messages and the installation assistant are in English, and the agent replies in your Mac’s language; this guide and the website exist in English and French.
Command reference
Square brackets mark optional arguments, angle brackets mark values to replace, and | marks a choice. These are reference syntaxes, not lines to paste unchanged. projet is optional when the current folder identifies the registered repository. Names and options remain those of the French package.
The installer runs it for you after purchase or key entry; you can run it again at any time. It checks the Mac, summarises what will be installed, then waits for you to type I accept before writing anything. --dry-run shows the plan without installing. --reapply reapplies saved choices. --import takes over an earlier installation: links, hooks, registry, documents and preferences. --dev is for a Treelab development checkout.
Installs instructions, skills, agents, hooks and commands, and offers cmux separately if missing; existing settings are preserved and backed up. No agent session should run during the operation. If the plan changes, rerun and reread it. After the installer, your first lane is already open; run on its own, it suggests lab doctor, then lab onboard in a project folder.
doctor · Diagnose
lab doctor [project] [--root <checkout|worktree>] [--project-only] [--report|--freeze] [--json]
Without a project, checks the Mac’s installation; with a project, its working setup. Each check passes, warns or fails, and a failure says what to fix. --root selects the checkout or worktree; --project-only skips global checks. The regular diagnostic may show private paths: keep it on your Mac.
--report produces an anonymised report, with no writes and nothing sent; --json structures the output. Exit 0: no failure; 1: a failed check; 2: invalid options or diagnostic. --freeze resets the project’s measurement baseline, only for an intended change recorded in the log, never to hide a failure. LAB_DOCTOR_SKILLS_WARN_LIMIT sets an optional warning threshold.
Downloads the latest version with your licence, checks the archive and its fingerprint, then switches to it. Open agent sessions keep their version; the next one starts from the new one. --catalogue only reads the available version. --rollback returns offline to the preserved previous version; --resume continues an interrupted update. --adopt, run from an extracted release, replaces an earlier installation.
Without typing anything, lab next installs the latest minor or patch version at most once a day; a major version is only announced. To receive the announcement only, write auto_update=no in ~/.lab/config. Every failure ends with RESULT=refused or interrupted, plus REASON= and the file concerned: the installed version is kept.
Outside live sessions, inspect --dry-run first. Actual removal requires terminal consent. --keep-state preserves the active installation manifest marked as removed; --resume continues interrupted removal after its cause is fixed.
Removes only manifest-owned elements, restores backed-up settings and preserves unrelated changes. Keeps backups at the printed path and separately installed dependencies. The registry is always preserved. Without --keep-state, only the completed manifest is archived with backups. If the journal or an expected fingerprint no longer matches, preserve files and restore their integrity before resuming.
onboard · Guided tour
lab onboard [--agent claude|codex]
Run it in your Git repository folder. Three screens introduce the vocabulary, the cycle and the safeguards. The repository is then registered as a project, without touching your files, the project’s tower opens in its “tower” tab, and an agent opens in the project’s “main” tab: it asks about your need and opens your first lane.
Running it again creates no duplicates. --agent selects Claude Code or Codex. Without cmux, it prints the command to run yourself (NEXT_COMMAND).
lab onboard does this for you the first time. From an existing Git repository, name names the project and --root selects its root. --docs repo puts future documents in worktrees; local keeps them outside Git. --owner shared|other describes ownership without authorising writes to the main checkout. --agent sets the default agent.
Writes the local registry, detects the base, remote and project commands; attempts a fetch. Leaves the main checkout unchanged. PROJECT and ROOT identify the registered repository. If the repository cannot be found, set --root to its Git root.
From the registered repository, choose a short lane name. --brief stores the text of your need with the lane documents: the agent starts from it. --batch names the first batch, --kind selects the branch type, --base its base, --title its title and --agent its agent. --no-open skips the tab; --no-install skips project dependency installation; --permanent creates the lane already permanent.
Creates .worktrees/<lane>, its branch, metadata and the first batch document; normally installs dependencies, then opens the cmux tab with the agent, which starts with a few scoping questions. WORKTREE, BRANCH and LOT identify the result. The main repository must have no pending changes. If the lane already exists, use open.
next · Move to the next step
lab next [project] <lane> [--agent claude|codex] [--goal <criteria>] [--auto] [--local]
lab next [project] <lane> --batch <slug> [--kind feat|fix|chore] [--title <text>]
Reads where the lane stands and starts what is needed: run or resume the batch, open the next batch after delivery, or prepare your final trial. --goal adds criteria; --agent selects the agent. Run from the lane session, it replaces that session with a fresh one in the same tab; --auto is still accepted as a synonym. With cmux and Cloud set to yes, the batch runs on a Cloud machine (CLOUD_RUN=) and comes back to the Mac to close, unless its batch file asks for the Mac (Execution line, lab deploy or lab lock in its steps); the choice is announced in one line (EXECUTION=) and --local always keeps the Mac.
The second form forces the next batch, for example a fix after your trial (--kind fix). A red last nightly run of the main branch is announced (NIGHT=) with a suggested fix lane (NIGHT_FIX=), without blocking anything. next neither merges nor removes anything. Another live session or a missing delivery requires finishing the reported step before retrying.
permanent · Keep a lane open for good
lab permanent [project] <lane> [on|off]
Without a value, or with on, the lane becomes permanent: it chains its batches, each one delivered by its own pull request. off makes it ordinary again. lab new … --permanent creates it already permanent.
A permanent lane is never offered for a trial (acceptance), removal or closing: lab close and lab close --abandon refuse it and name the remedy. When no batch is left, lab next opens a free session that waits for your request. PERMANENT=yes or no gives the result; lab status, lab list, lab plan and lab sweep show PERMANENT=yes.
Every project has a tower: lab onboard creates it for a new project. The first call creates the tower: the permanent lane tower, started under Claude in bypassPermissions mode (the first start may ask you once to confirm that mode). Its session applies the tower skill: about every 30 minutes it checks every lane, relaunches a stopped one, delivers what is ready and lists what waits for you. It never answers in your place. A tower under Codex is refused.
Next calls print TOWER=present, then one block per lane: LANE=, WAITS_FOR= (you, acceptance, date, ci or nothing), WHY= and SESSION=. In every project, with or without a tower, a question, a permission request, an acceptance ready or a refused lab next sends a cmux alert to the tab of its lane. --all offers a tower to each registered project without one: one [y/N] question per project in a terminal, nothing created without a terminal (CONFIRM=needed); --no-install skips installing dependencies. lab wake restarts a tower without a session within the hour, and lab doctor shows each project’s tower, as information.
plan · See progress
lab plan [project] [--json]
Recomputed at each display from the batch documents: each lane’s current batch, completed batches out of the total, and its phase.
Read-only. Readable table on stderr, fields or JSON on stdout. If empty, create a first lane with new.
status · Read detailed state
lab status [project]
The project (folder, branch, merge target, default agent), then each lane as in list, pending deliveries, what is online and files touched by two lanes at once.
Read-only; a lock whose process has exited may be removed while reading. If the project is unclear, supply its registered name.
list · List lanes
lab list [project]
One block per lane: folder, branch, batch and state, agent, pull request, current session. Without a project: every registered project.
Read-only. If a project is missing, check init from its root without recreating work files.
top · See who uses this Mac and cut with one click
lab top [--fast]
lab top --cut <pid|family|idle|lane-done>
lab top --wake <tab>
lab top --explain <pid|family>
Without an option, a read-only snapshot: memory pressure, compressed memory, swap, load and thermal state; each claude or codex session tied to its project, lane and cmux tab; the families outside Treelab (Chrome, test browsers, virtual machines, node, cmux); finally what could be cut, each with its reason, what the cut implies and the command of its click. Sessions put to sleep by lab are listed with their wake command.
One gesture at a time, without confirmation: lab checks the reason again when acting and refuses otherwise, naming the refusal. --cut puts an idle session to sleep in its tab (woken in place by --wake), closes the tab of a finished lane after checking its Handoff, uncommitted files and idleness, stops a process outside agents (stop signal, 10 seconds, then forced stop; a family by its root, a Lima VM by limactl stop); --cut idle and --cut lane-done handle a whole reason. An agent is never killed, nor a session on screen or running a background command; cmux, the calling session, the parents of sessions, root processes and top_keep= names are never proposed. --explain opens a tab where Claude, in plan mode, explains before any cut.
sysmon · Measure the Mac for the menu bar modules
lab sysmon
A single collection pass returns six blocks: processor, memory, disks, network, battery and temperatures. macmon (installed by brew) gives performance and efficiency core usage, the GPU, power, temperatures and fans; native tools give memory, disks, network throughput and the battery. Each block carries its figures and, for processor and memory, the five largest consumers tied to their project and lane for agent sessions.
Without macmon, temperatures and power disappear, the other modules stay whole. One collector feeds the six menu-bar modules (lab widget): each plugin only reads its cache, never reruns macmon. KEY=value blocks on stdout, a readable view on stderr. Read-only, nothing is cut.
mcp · See the tool servers
lab mcp
lab mcp --pin|--bump|--undo [--yes]
Lists each tool server (MCP) configured for Claude and Codex, globally and in each registered project: scope, transport, package and whether its version is pinned (@latest or no version: not pinned, each start may fetch a new one). Then the running copies grouped by package: copies, processes and resident memory; agent sessions are never counted.
No secret is ever shown: no environment variables, headers, addresses or arguments other than the package name. lab doctor warns above 1024 MB (mcp_rss_warn_mb= in the lab configuration) or for an unpinned version. KEY=value blocks on stdout, a readable view on stderr. Without an option, read-only. --pin pins each server launched by npx to the version it runs (read from the npx cache, no network); --bump offers the latest version published on npm; each shows the change (package before → after, never a file’s content) and asks for agreement, then saves each file before writing it; --undo restores the last save. A server launched otherwise (uvx, pipx) is named with its reason, never pinned.
install puts in place the lab top dot (every 60 s: colored by memory pressure, agent sessions, proposed cuts; its menu cuts with one click) and six system modules (processor, memory, disks, network, battery, temperatures) refreshed every 10 s, each a bar item with its detailed menu. lab installs macmon through brew for temperatures and power; without it, the native modules stay. modules list shows the active modules, off removes one, on puts it back.
SwiftBar is never installed by lab: without it, install shows brew reinstall --cask swiftbar and stops. The plugins go into the folder SwiftBar already uses, otherwise into a lab folder registered in its preferences; SwiftBar opens at login. One collector feeds the six modules (lab sysmon), as the budget requires. remove takes the dot and the six modules away, and the login item if lab added it; macmon, preferences and other plugins stay. A chevron, left of the dot, tidies the bar: closed, it pushes every icon on its left off the screen; its menu draws a map of the bar, flags a hidden lab icon, a new app or an order that moved, and walks through tidying in four steps. order save keeps the order, order apply puts it back (a running app relaunches only with --relaunch, never cmux, agents nor SwiftBar), and refuses while Bartender, Ice or Hidden Bar runs; tidy tightens the spacing, hides Control Center duplicates and stops iStat Menus, each step announced and undone by remove.
After the last batch, you try the result; the agent records your decision in one command. The tried revision is captured, the “Lane acceptance” section of the last document (“Recette du couloir” in a French one) is written and committed alone. Approval requires at least one --evidence; a refusal may carry your --feedback.
Refused if the lane is not in acceptance or changes are unsaved. ACCEPTANCE=valid or rejected, REVISION= and COMMIT= identify the decision. If the result changes afterwards, acceptance must be repeated before close.
close · Deliver, then remove the lane
lab close [project] <lane> [--confirm <lane>] [--retire <sha>…] [--night-red-ok <reason>]
lab close [project] <lane> --abandon [--confirm <lane>]
lab close [project] <lane> --dry-run [--abandon]
Presents what will be delivered and removed, then asks you to retype the lane name; --confirm supplies it after approval already given. It requires your trial and approval, recorded by acceptance. It then merges the last batch and removes the working copy, branches and tab. --dry-run lists every obstacle at once (OBSTACLE=, then RESULT=ok or blocked) without changing anything.
Just before merging, the main branch is re-read up to date: if the merge would remove lines added by another lane, close refuses and names them; --retire <sha> confirms that removal. If the last nightly run of the main branch is red, close refuses and suggests a fix lane; --night-red-ok "<reason>" goes ahead by writing a dated agreement in the acceptance section of the document. --abandon removes a lane with nothing to deliver, after the same confirmation. Unsaved files, a live session or stale acceptance block it: confirmation never overrides a failure.
sweep · Inventory pending lanes
lab sweep [project] [--dry-run]
For each lane: its branch, whether it is merged, and what it is waiting for (a trial, a closure, the rest of the batch).
An inventory only: removes nothing and performs no fetch or prune. Only close removes a lane.
open · Find the tab
lab open [project] <lane> [--agent claude|codex] [--prompt <text>|-]
Recovery command: finds the lane tab, or reopens it with its agent, without choosing a new step. --prompt supplies text, while - reads it from standard input.
To move forward, use next. If cmux is unavailable, open the application before retrying. Do not start a second session while the first is working.
You do not type it: new and next write it in the lane tab. It rereads the batch document, rebuilds the agent’s full instruction (the Goal) and hands over to the agent.
A short line goes to the tab and the Goal is rebuilt on arrival, without truncation. Automatic startup calls the short name lab: if another tool owns that name, use treelab for direct calls and contact support. Put a long supplement in the document, not in --goal.
Merges the batch pull request into staging when it exists, otherwise into the main branch, as soon as automated checks pass. If they are still running, a watcher merges after they pass and the command returns (ACTION=armed). --title and --body-file set the request title and body. The agent runs it at the end of each batch.
Before merging, the command and then the watcher repeat a dry run on the fresh base and refuse a merge that would remove lines added by another lane (REGRESSION=): the refusal names file, lines and commit; --retire <sha> allows an intended removal. gh and permissions on the remote repository are required.
sync · Bring the base into a lane
lab sync [project] <lane>
Merges changes from the base branch into the lane, without pushing anything. launch does it before each session.
SYNC=up-to-date, merged, conflict or ignored. A conflict is aborted and named (CONFLICT_FILES=): the lane stays intact until it is resolved.
promote · Promote staging to production
lab promote [project] [--confirm <project>]
Without --confirm: presents what would go from staging to the main branch, writing nothing. With --confirm: opens the dated pull request and merges it at the exact revision after checks pass.
Run it yourself; an agent runs it only at your explicit request. PROMOTE=preview, armed, merged or none; PR=, INCLUDED= and INFLIGHT= detail the content.
batch · Read batch documents
lab batch current
lab batch list
lab batch new [--title <text>]
lab batch processes
lab batch wait <Cn> <YYYY-MM-DD|YYYY-MM-DDTHH:MM:SSZ|+Nd> "<reason>"
lab batch wait --done <Cn>
Run in a lane folder. current gives the current batch document and its state; list gives each document and its state; new creates a batch document, --title sets its title; processes names what still runs in the lane folder, except the calling session: nothing is stopped, the agent stops each one or justifies it in the batch document. wait puts a criterion on hold for a dated measure: the document becomes “waiting”, the batch is delivered like any other and the lane goes on.
Agents use it during a batch. new does not replace next for changing branch and session; do not create a competing document to bypass an active batch. At the date, lab next reopens the document for that criterion only, before the next batch; one postponement per criterion; wait --done marks it measured. Acceptance and closing wait until every measure of the lane is done.
handoff · Check the handoff
lab handoff [project] [lane] [--template]
Checks that the batch document says where the work stands and which batch follows, commits the lane documents, then prints the next command (NEXT_COMMAND). If the Handoff section (Reprise in a French document) is missing, adds its template to the document and asks you to fill it. --template only prints the expected form.
The agent runs it at the end of a batch. It does not deliver the batch and does not verify completeness of evidence: objective, reading order, evidence, remaining work and next batch must still be written.
wake · Reopen waiting batches at their date
lab wake
lab wake --install
lab wake --remove
lab wake --status
Without an option: for each lane of the registered projects whose awaited measure is due and that has no live session, runs lab next, which reopens the document for that criterion; a project’s tower without a live session is restarted the same way. --install sets the macOS alarm: a launch agent that calls lab wake every hour and at login; lab batch wait sets it too.
Each run is written to wake.log in the state folder, with CMUX=reachable or absent. --status says whether the alarm is loaded and its last run; --remove takes it away. A Mac that is off at the date catches up when it wakes; without the alarm, or when cmux refuses processes it did not start, the next lab next reopens the document (PENDING=).
now · Timestamp
lab now
Prints the current instant in universal time, as AAAA-MM-JJTHH:MM:SSZ. Agents use it to date logs and handoffs.
LAB_NOW sets the value, for tests.
due · Track deadlines
lab due [project]
lab due [project] add <YYYY-MM-DD|YYYY-MM-DDTHH:MM:SSZ> <subject…>
lab due [project] done <id> <sha>
lab due [project] reschedule <id> <due date>
lab due [project] cancel <id> <reason…>
Without an action: the project’s open deadlines, overdue first, then those within 48 hours, then the rest. add records a deadline taken during a batch (follow-up, promised delivery).
fait closes a deadline with the commit that proves it; redater moves it; annuler closes it with a reason. Deadlines live neither in batch documents nor in the handoff.
Account 1 is your /login. add guides three steps: your /login becomes the account’s badge, claude setup-token gives the token stored in the macOS keychain (never in a file), then that token joins CodeRouter, the team accounts the Cloud machines use; a failed step keeps the previous ones. coderouter later sends a stored token to CodeRouter; a label already in the team is never replaced. remove removes it; without an action, the list shows which account is available.
When an account reaches its 5-hour or 7-day limit, the same conversation resumes in its tab on the next account; when all are exhausted, the tab waits for the reset time. suivant switches account immediately, from the lane’s Claude session. resume restarts one by one, 25 s apart (LAB_RESUME_GAP), the waiting tabs and the lane sessions stopped by a limit or a 401, after a real call checks each token; add and free do it themselves, --dry-run only shows what would be restarted. badge stores the current /login connection as the badge of the account linked to its e-mail; use, and the rotation at the limit, set that badge for the whole Mac (Chrome extension, pages, dictation without /login), after re-saving the active badge. A /login typed in a session is adopted as its account’s badge. At the limit, the main tab and a claude typed by hand are resumed in their cmux tab through run, with their options; outside cmux, the next account’s badge is set and the log says what to type. reserve on marks a last-resort account: taken only when no other account can serve, left at the next launch once another is free; add --last-resort adds one without sending it to CodeRouter.
Without a value, shows the rule in force and where it comes from: CLOUD= and CLOUD_SOURCE= (lane, project, Mac setting or default). The lane overrides the project, the project overrides cloud= in ~/.lab/config, and the default is yes. no keeps every batch on the Mac; with yes, each batch file chooses, without a question.
yes or no writes the rule for the project, or for the lane when it is named or when the command runs in its folder; reset removes the rule at that level. An unreadable value is refused with the command that fixes it; ~/.lab/config is read, never written. image prepares the project machine once and freezes it. Every Cloud batch gets, with no manual step, a repository deploy key created by gh: the pair is generated on the VM, only the public key goes up, the VM clones and pushes over SSH, and the key is revoked on GitHub at the end, even if the VM is paused. A Cloud session blocked on a need of the Mac (“blocked: need <need>: <detail>”) comes back alone to the Mac and the need is remembered outside the repository: needs lists them, needs reset forgets them; without a value, lab cloud also shows the needs (NEED=) and the 5 last Cloud sessions (SESSION=). suite runs the bats suite of the current commit on a disposable Cloud machine sized from the plan (one bats job per vCPU, stale image rebuilt first), deleted afterwards even on failure: SUITE=green, red or unavailable, exit code 0, 1 or 3, without any token. If the plan is still full after the cleanup, the same suite starts on the Mac at once (RUN=mac), with the alert that a larger plan would keep it on the Cloud. clean frees the plan: project VMs nothing uses any more and snapshots older than the previous one, never the image, an open lane or another project’s machine; --dry-run only names them. The same cleanup runs before each suite and each Cloud batch start.
add copies a batch’s screenshots, outputs and measurements outside the repository, with each file’s SHA-256 fingerprint in a manifest.json; a file already under version control is only referenced. --step files the evidence under a named step.
verify recomputes each fingerprint and reports modified or missing evidence.
lock · Hold a shared resource
lab lock [project] <resource> [--pid <pid>]
Reserves for the current lane a resource declared in the project configuration (resources=): a simulator, a local database, a port. --pid names the holding process.
If another live lane holds it, the command refuses and names it; a dead holder is replaced. unlock releases it.
unlock · Release a resource
lab unlock [project] <resource>
Releases a resource held by the current lane, or by a session that no longer exists.
A resource held by another live lane stays with it.
served · Record the served build
lab served <port> [--pid <pid>]
Called by the project’s development script: records the lane, its revision, the port and the process serving the application.
At session start, the agent therefore knows which version is running locally.
Runs the project hook, a single executable file committed with the code: scripts/lab-services. lab finds it by its presence alone and calls it with the verb stop, from the lane’s folder — that lane’s Docker stack, database or containers are stopped and removed.
close and close --abandon run it themselves just before removing the folder; this command runs it again afterwards, for example after a first failure. The hook gets LAB_PROJECT, LAB_LANE and LAB_WORKTREE (empty when the folder is already gone: the main checkout’s copy is used instead, and named, since it may be older). It has 120 seconds; beyond that, it and its children are stopped. A failure never blocks a closing: lab names it and removes the lane anyway. With the verb list, the hook names what the lanes still hold, one resource per line: list shows them lane by lane, lab sweep and lab doctor name those of an already closed lane (15 seconds at most, never stopping anything), and stop --orphans stops them all, one lane after the other. A ready-made example for a Compose stack named after the lane: templates/project/lab-services.
Deploys a target declared in the project configuration, always from the up-to-date main branch; from a lane, its branch is added, and --with adds others. --dry-run shows the plan and what would be lost (LOST=). --record registers what is live without deploying. --add declares a target from a worker, rsync or cloudrun template; --include names private files copied before each deployment.
A registry records what is served. If the target serves an unmerged lane you do not include, lab refuses and names it: include it with --with, or remove it with --retire. The probe then checks the served revision. In a project that declares a target, a direct deployment is refused: use lab deploy.
watch · The delivery watcher
lab watch <project> <lane> <branch>
Internal command: you do not run it. merge and close start it in the background to wait for automated checks, then merge.
Internal command: Claude Code and Codex call it with JSON on standard input, at the start and end of a session, and before a risky command. session-start provides context and the lock; session-end releases the session; notify records a question or a permission and alerts the lane tab; guard-bash and guard-tool refuse common dangerous operations by default, with the safe alternative.
An internal automation error never blocks your work. Codex asks for a one-time hook approval (/hooks); doctor checks they are in place.
help prints the commands grouped by moment (install, start, move forward, finish); help <command> explains what it is for, its syntax and an example; help glossary lists each of lab’s words with its former French name. --help and -h print the complete technical reference on stderr and exit 2. --version prints VERSION=… from the running copy.
--json converts any command’s KEY=value output to JSON; explanations stay on stderr. Interpret a non-zero code in the command’s context; doctor distinguishes 1 and 2.
Troubleshooting
Missing tool
Check and action
Run the installation command again: it offers to install Git and jq through Homebrew; lab setup offers cmux. Also check macOS and command -v for your agent.
Expected result
Each tool prints a path; installation resumes without a new purchase.
Key not received
Check and action
Wait a few minutes and check your spam folder. A purchase with deferred supply receives its key when the withdrawal period ends. Then run the installation command again and choose 2 “Enter a key”, or write to support from the payment address.
Expected result
The tl_key_ key is pasted and activated; no second payment.
lab name occupied
Check and action
Compare command -v lab and command -v treelab. Use treelab without replacing the unrelated command.
Expected result
treelab --version identifies the right copy for direct calls. Automatic startup still calls lab: if occupied, preserve the other tool and contact support.
Unregistered repository
Check and action
From the intended Git root, check lab list, then run lab onboard again, or lab init with --root.
Expected result
PROJECT and ROOT match the intended repository.
Missing tab
Check and action
Check lab status, open cmux, then use lab open with the existing lane name.
Expected result
The lane tab is found or recreated.
Session still alive
Check and action
Return to the owning tab and end the session normally. For automatic continuation by its agent, save the handoff first, then run lab next from that session.
Expected result
Only one session works; maintenance is possible after it ends. Do not delete its lock.
Failed diagnostic
Check and action
Read NOTE in the local doctor output, fix the reported check and rerun the same diagnostic. --freeze is not a way to hide the failure.
Expected result
The check passes without artificially moving the baseline.
Blocked delivery
Check and action
Check the pull request target, remote checks, conflicts, gh permissions and final-batch acceptance; lab close --dry-run lists the obstacles. Fix the cause before retrying; preserve the lane.
Expected result
Checks and diagnostic pass, then the pull request is actually merged.
Update refused
Check and action
Read RESULT, REASON and FILE printed by update. Check connectivity and this Mac’s licence, then retry; --resume continues an interrupted update.
Expected result
No replacement on failure; update only after a verified archive.
Previous version absent
Check and action
Read the update --rollback refusal; preserve the current version and backups. Do not fabricate previous-release.
Expected result
Installation preserved; a reviewed report can accompany a support request.
Interrupted operation
Check and action
Fix the reported permissions or integrity issue, keep backups, then use update --resume for updates or uninstall --resume for removal requested by the diagnostic.
Expected result
Transaction completed or restored; check doctor before resuming work.
In your terminal, run lab doctor --report. Review stdout and stderr before sharing: this mode anonymises the existing diagnostic, not comments you add. The regular diagnostic without --report may contain private paths. Do not attach it unchanged.
lab doctor --report
Optional variant from a private local folder: choose a new filename, because > replaces an existing file. Exit 1 means a failed diagnostic check, not failed anonymisation; exit 2 means an error to resolve before sharing. The file receives stdout JSON; stderr stays in the terminal and must also be reviewed.
lab doctor --report --json > treelab-report.json
Check for names, personal paths, addresses, keys and project content. Remove unnecessary information, then add the report manually if you wish. This site does not read, receive or retain the file. The email link contains no diagnostic; only your email application can send it after your action.