Getting started
devlanes runs a project’s dev services once per Git worktree. Each worktree is a lane with its own ports, hostnames and data, and a per-user daemon keeps the processes running after the terminal closes. This page goes from install to two lanes running side by side.
Install
Section titled “Install”brew install devlanes-run/tap/devlanesThe README lists the Homebrew, npm, PyPI, cargo and install.sh options and the source build. devlanes runs on macOS, Linux and Windows 11 (Windows covers its install and differences). The release installs give you the latest release, and devlanes update keeps it current (updates covers builds of main and older releases). devlanes uninstall removes it again (a project’s own dependency and source builds stay), and asks before deleting ~/.devlanes.
First config
Section titled “First config”Put a devlanes.yaml at the root of the repository and commit it, so every worktree has it:
project: acmeservices: api: run: pnpm --filter api dev hosts: "api.${{ lane.domain }}" web: preset: vite run_script: file: web/package.json name: dev env: VITE_API_URL: "${{ services.api.public_url }}" hosts: "${{ lane.domain }}"devlanes gives every service a port from the lane’s block and passes it as PORT. A service must listen on that port; preset: vite adds Vite’s --port and --host flags for you. A preset needs run_script, which names a script in a project file; prefer it to run whenever the command is such a script (run and run_script). lane.domain is acme.localhost in lane 0 (the worktree on the primary branch) and acme<N>.localhost in lane N, such as acme2.localhost. Expressions such as ${{ services.api.public_url }} are evaluated per lane, so the web app of lane 2 talks to the API of lane 2.
devlanes config check validates the file and points at the line of any mistake. examples/minimal.yaml adds shared Postgres with a database per lane, examples/devlanes.yaml shows every form, and the config reference lists each field.
Changes only you want, such as a service turned off on your machine or a server you run yourself, go in devlanes.local.yaml next to it, which you keep out of Git (local overrides).
Commands find the project from the current directory: the nearest devlanes.yaml above it, up to the repository root, so they work from any subdirectory, and a subdirectory with its own devlanes.yaml is a separate project (monorepo with several apps). Another project file in the same directory, such as a devlanes.prod.yaml that runs the same apps the production way, is named once with devlanes --file devlanes.prod.yaml start and afterwards with --project and its project name (several projects in one directory).
Coming from another process manager
Section titled “Coming from another process manager”If the repository already runs its dev processes with mprocs, dekit, process-compose, a Procfile (foreman, overmind, hivemind, honcho), pm2, tmuxinator, tmuxp, concurrently or npm-run-all in package.json, mise tasks or Docker Compose, install the devlanes skill and ask your coding agent to migrate it. The skill’s references/migration.md maps each tool to devlanes.yaml: fixed ports become each lane’s own port, one-shot commands become tasks, containers become infra, and the agent tells you what devlanes cannot express (restart policies, dependencies between services, .env loading).
Start and inspect
Section titled “Start and inspect”devlanes start # this worktree's lane, followed in the TUIdevlanes status # lanes and units with state, ports, URLs, CPU and memorydevlanes logs api -f # follow one service; Ctrl-C stops following, not the servicedevlanes url ls # routed hostnamesdevlanes url open web # open a service in the browserdevlanes stop # stop the laneThe daemon starts on first use or with devlanes daemon start, and stops on its own about 15 seconds after the last TUI closes while nothing runs (the summary printed when the TUI closes says so), or after about 5 minutes when neither a TUI nor a command showing progress ever watched it, as when only scripts or agents used it (daemon.exit_when_idle). start is safe to repeat: running services are left alone. An edit to devlanes.yaml leaves them alone too: devlanes status shows which services it changed, added or removed, and devlanes reload restarts, starts or stops only those (editing the project file). A lane without requests, connections or commands for 15 minutes is frozen, and the next request, connection or command resumes it (idle lanes).
On a terminal, start opens the TUI on the lane and runs the start inside it: the header shows the phase (infra, setup, tasks, services), the tree shows each service coming up, and a service that fails shows its reason and the end of its log in the details pane. When the start ends, the header keeps the result and the TUI stays open. Quitting keeps services running unless you choose otherwise: while lanes run, q asks whether to keep or stop them (tui.on_quit in ~/.devlanes/config.yaml answers for you). The exit status is 0 when the start was ready, 1 when it failed, and 130 when you quit before it ended (the start keeps going in the daemon). A start the daemon refuses outright, such as a worktree without devlanes.yaml or an unknown unit, prints its error before any TUI opens. restart, lane resume and lane new --start work the same way.
--no-ui, DEVLANES_NO_UI=1 or tui.open_on_start: false in ~/.devlanes/config.yaml print the start as text instead: it returns once every service is ready, and a failure exits 1 with the end of the service’s log. Agents, scripts, CI and piped output always get the text. devlanes debug why api explains why a unit is not up.
For a second lane, add a worktree and start it there:
git worktree add ../acme-checkout -b feat/checkoutcd ../acme-checkoutdevlanes startA worktree becomes a lane the first time devlanes runs in it (here, start); a worktree that only exists gets no lane, except the one on the primary branch. The daemon follows moved and removed worktrees by itself. devlanes lane ls lists every lane, and commands take a lane reference such as 2, feat/checkout or acme@2:api from any directory. Removing a worktree stops its lane and keeps its data and ports; devlanes lane gc --yes cleans lanes whose folder is gone, and lanes.removed_worktrees: clean has the daemon do it by itself (removed worktrees). devlanes lane clean <lane> --yes removes one lane’s data and frees its ports by hand.
To run a folder twice, for example with two profiles, devlanes lane new --name review in it adds a second lane with its own index, ports and domain. --lane review addresses it; commands run in the folder keep using its first lane.
HTTPS and certificates
Section titled “HTTPS and certificates”The proxy serves https://api.acme.localhost and the other hostnames on port 443, or 8443 when 443 cannot be bound. Browsers resolve *.localhost to your machine without any setup. To make browsers and command-line tools accept the certificates, trust the devlanes CA once:
devlanes setup # trust stores, plus /etc/hosts when *.localhost does not resolve; asks oncedevlanes doctor # checks the daemon, Docker, proxy, CA and hosts fileNode and Python services get the CA through NODE_EXTRA_CA_CERTS and SSL_CERT_FILE without trusting it system-wide.
Run devlanes with no command (or devlanes ui) on a terminal. It lists every lane of the project, the state of each unit and a live terminal for the selected one. Closing the TUI leaves everything running. M opens the resource monitor and D the daemon page. While the daemon restarts, stops or does not answer, every view shows what is happening above the daemon log and comes back once the daemon answers. B opens the boxes view, where you connect remote boxes and pair other machines with this one. Connected boxes’ projects follow the local ones, read-only.
Coding agents
Section titled “Coding agents”Agents should start services through devlanes instead of backgrounding pnpm dev & in their shell. The agent plugin packages a guide for them as a Claude Code and Codex plugin, a skill for the skills CLI and a Codex AGENTS.md to paste into a repository; the plugin also has a hook that rejects backgrounded dev servers. When devlanes detects an agent it switches to terse output with failures first; devlanes exec --name NAME -- COMMAND runs a one-off process as a unit, and devlanes wait and budgeted devlanes logs let the agent check on it.
In CI, devlanes with -- pnpm test:e2e starts the lane, runs the command with the lane’s URLs in its environment, stops what it started and exits with the command’s code.
GUI tools
Section titled “GUI tools”devlanes does not stream windows. A GUI tool that serves HTTP or TCP is an ordinary service: give it the service’s port and, for a browser UI, a hostname.
services: ios-sim: run: npx serve-sim --port ${{ self.port }} hosts: "sim.${{ lane.domain }}" autostart: falseXpra’s HTML5 client, ws-scrcpy and an adb server follow the same pattern. On a remote box, devlanes remote connect mirrors these ports and hostnames to your machine; only TCP is mirrored. Remote boxes has the Xpra and adb examples.
Troubleshooting
Section titled “Troubleshooting”When a service fails, the start names it with the reason and a next command. A program that cannot run says which one and why, for example api could not start: fixture-server: command not found on PATH. Services get the PATH of the shell that ran devlanes start, and devlanes env show api prints the environment the service got. The same line is in the service’s log, so devlanes logs api shows it too.
devlanes debug why api # why a unit is not running or not ready, with a fixdevlanes debug errors # failed units, crash counts and recent error linesdevlanes -v start # what the CLI and the daemon did, step by step, on stderrdevlanes daemon logs --tail 200 # the daemon's own logdevlanes doctor # daemon, Docker, proxy, CA and hosts file-v works with every command and output mode and ends with a table of how long each step took; -vv prints more. To report a problem, devlanes debug bundle -- start writes an archive with versions, doctor, status, the end of the daemon’s log and a verbose run of devlanes start, with secret-looking values removed, and prints where it is. Read it before you send it.
For more detail in the daemon’s log, restart it with a level: DEVLANES_LOG=debug devlanes daemon restart.
Next steps
Section titled “Next steps”- CLI reference: every command and option.
- Config reference: every field of
devlanes.yamland the userconfig.yaml. - Guides: run and run_script, languages, framework presets, ports and environment, hostnames and HTTPS, infra, service patterns, lane lifecycle, terminals, remote setup.
- Remote boxes: run lanes on another machine and use them locally.
- Design: lanes, ports, the daemon and startup order.
- Observability: the daemon’s spans and diagnostics, and plans for tracing and benchmarks.