Changelog
What changed in each release of agentlane, newest first.
0.4.1
Changed
initin a terminal is a proper TUI. It asks which agents you use with an arrow-key picker (space toggles, Enter confirms), with the agents it found checked and the file that gave each away beside it. It shows the files it wrote with skills grouped by folder, streams the package manager's output inside the frame while it adds agentlane and collapses it when that succeeds, and ends with each agent's next step. Output that isn't a terminal, such as an agent or CI runninginit, is unchanged.
0.4.0
New
npx agentlane initwith no flags. init wires the agents whose files the project has (CLAUDE.md,.codex/,.cursor/,.github/copilot-instructions.md,GEMINI.md,.agents/rules/and others) or whose session runs it, and prints the reason for each. In a terminal it lists all six agents, checks the ones it found, and takes Enter, numbers or names. With no terminal and nothing found, it exits 2 and names--agentsand--all, which work as before.- init installs the toolkit. When the project's
package.jsondoesn't listagentlane, init adds it as a dev dependency at its own version with the project's package manager (from thepackageManagerfield or the lockfile: pnpm, yarn, bun or npm). A project with nopackage.jsongets a private one. When the install fails, init keeps the files it wrote, exits 1 and prints the command to run. A project that already lists another version keeps it, and init says so.--checkinstalls nothing.
Fixed
- Maestro starts with the JDK in
AGENTLANE_JAVA_HOMEwhenJAVA_HOMEis another version.up,doctorand the Android build already read it first, butlook,screenshotand the other driving commands read onlyJAVA_HOME, so they refused a Java 21JAVA_HOMEthatdoctorhad passed. upanddoctorno longer fail capture hygiene on a Mac where the simulator reads its pinned status-bar time back as9:41. They accepted only09:41, which is how some Macs print it.initno longer lists 0.2.x's.github/hooks/agent-env.jsonasunchangedin a project that doesn't have it. It lists that file only when it changes or removes it.- Under
execand in the signin hook,maestrois the lane's own Maestro, or it prints why the lane has none and exits 2. A lane whoseagentlane.jsonwas invalid or had nodriverblock, or that held no running simulator or emulator, ran whatevermaestrocame first on PATH, unbound to the lane's device, after one warning that named only the file. The message now gives the config's problems, or what is missing and how to add it. A project that ran its own Maestro underexecwithout adriverblock adds"driver": {}toagentlane.json. - The lane's
maestrorefusesmaestro mcp, which takes its device from each tool call, so the lane can't bind it to its device. The lane's MCP server isnode_modules/.bin/agentlane mcp. maestro test's output goes to the lane's evidence folder only whentestis the subcommand. A flow file namedtest, given to another subcommand, got a--debug-outputfolder too.- On macOS,
agentlane driver install --from <zip>clears thecom.apple.quarantineattribute from the Maestro it unpacks. macOS'sunzipcopied a browser-downloaded zip's quarantine onto every unpacked file. Install still checks the zip's sha256 before unpacking.
The patched Maestro
The patched Maestro build is renamed 2.11.0-agentlane.1, and the toolkit downloads it over https from this repository's release, so first use no longer needs a signed-in gh. Compared with 2.11.0-agentenv.3:
- The MCP
runtool's result lists only theenvthe call passed. It used to list everyMAESTRO_*variable in the driver's own environment as well. Flows still get those variables. - On Android, a
tapOnwithretryTapIfNoChange: trueandwaitToSettleTimeoutMs: 0taps a second time again when the first tap changed nothing. The quick tap, which sendsretryTapIfNoChange: false, still reads no hierarchy after the tap. - When an iOS runner never answers within the startup timeout, Maestro stops the
xcodebuildit launched for it. Before,maestro testleft thatxcodebuildrunning after it exited. - On iOS,
maestro record,maestro hierarchyandmaestro querytake a runner port the OS assigns when you pass no--driver-host-port, asmaestro testalready did. They used the fixed port 22087, so two lanes running them at once collided, and the second failed with "The XCTest runner port 127.0.0.1:22087 is held by a Maestro runner that refuses this process's token". A--driver-host-portyou pass still wins.
0.3.0
The toolkit is called agentlane now, and what each agent session holds is a lane. The package, the command, the config file, the environment variables, the plugin, the output and the JSON all say agentlane and lane. Besides the rename, 0.3.0 adds prune, browsers for Intel Macs and Linux, and the fixes listed under New and Fixed. You still claim and release a lane, so the claim and release commands keep their names. 0.3.0 runs beside 0.2.x on the same Mac, so projects can move one at a time.
Moving from 0.2.x
- Release the project's lanes first. In each worktree, while 0.2.x is still installed, run
node_modules/.bin/agent-env release. A lane 0.2.x started keeps 0.2.x's variables in its services and driver. - Replace the dependency. The package is
agentlane, at 0.3.0, and its bin isnode_modules/.bin/agentlane. - Rename the config.
agent-env.jsonbecomesagentlane.json, and its"$schema"points atagentlane.schema.json.up,doctorandrestartrefuse a project that still has onlyagent-env.json, and their message names these renames. - Rename the variables. Every
AGENT_ENV_variable isAGENTLANE_now, in the config's commands, hooks, scripts, Maestro flows and test configs. Two change more than the prefix:AGENT_ENV_CLAIMisAGENTLANE_LANE, andAGENT_ENV_CLAIM_TOKENisAGENTLANE_LANE_TOKEN. The settings you set yourself follow the prefix:AGENTLANE_STATE_DIR,AGENTLANE_OWNER_PID,AGENTLANE_JAVA_HOME,AGENTLANE_MAESTROandAGENTLANE_PLAYWRIGHT_BROWSERS. - Run
initonce.node_modules/.bin/agentlane init --agents <list>replaces what 0.2.x'sinitwrote instead of adding a second copy. MCP server entries namedagent-envbecomeagentlane, and.codex/config.tomlloses[mcp_servers.agent-env]. Hooks that rannode_modules/.bin/agent-envrunnode_modules/.bin/agentlane, and.github/hooks/agent-env.jsonbecomes.github/hooks/agentlane.json. The skill stubs runagentlane skills get, anddisabledMcpjsonServersnamesagentlane. Untilinithas run,doctorwarns that the wiring is stale. - The Claude Code plugin is
agentlane@agentlane. Where.claude/settings.jsonenablesagent-env@agent-env,initenablesagentlane@agentlaneinstead and renames the marketplace entryagent-envtoagentlane, keeping its source. Rename anagent-env@…entry in your local or user settings by hand. The setup skill is/agentlane:setup, and the MCP server isplugin:agentlane:device. The marketplace's repository is stillnorth-star-hq/agent-env. - Update scripts that read the CLI. The renamed commands, flags and JSON fields are listed below.
- Expect one uncached build. The build cache moves to
.git/agentlane/build-cache. The pinned Maestro, Playwright and agent-browser download again into~/.local/share/agentlane/. Once no worktree of the project runs 0.2.x, you can delete.git/agent-env/, and once nothing on the Mac runs it,~/.local/share/agent-env/.
Renamed
claims --jsonislanes --json. Its output isversion: 2:claimsislanes, a pool device'sclaimIdislaneId, and a pending teardown'sclaimislane.release --claim <id>isrelease --lane <id>.- In
claim --jsonandup --json,claimislane. Inrelease --json, each teardown'sclaimislane.driver status --jsongiveslaneId.doctor'sclaimcheck is thelanecheck, and the refusalclaim-goneislane-gone. - The CLI's output, the MCP tools' descriptions, the schema and the skills say lane.
claimprintsclaimed lane <id>, andstatuslistslanes. - Each lane's folder is
<state dir>/lanes/<id>, where$AGENTLANE_LOGSand$AGENTLANE_EVIDENCEpoint. - New pool devices are
agentlane-pool-*simulators andagentlane-emu-*emulators. - The bench report's schema is
agentlane-bench/1.
Sharing a Mac with 0.2.x
- One registry. While
~/.local/state/agent-env/registry.sqliteexists and~/.local/state/agentlane/registry.sqlitedoesn't, 0.3.0 uses 0.2.x's state folder as it is. Both versions then see every lane, and neither hands out a port, simulator, emulator or browser profile the other holds. A Mac that never ran 0.2.x gets~/.local/state/agentlane/. - 0.2.x's names in 0.2.x's folder. There, 0.3.0 writes only what 0.2.x reads: the registry stays format 1, lane folders stay under
claims/, and new pool devices are namedagent-env-pool-*andagent-env-emu-*, because 0.2.x boots only emulators with its own prefix. So either version can reap the other's lane once its owner is gone: stop its services, driver and browser, and run its resources' teardowns. - 0.2.x's pool devices stay in the pool. A free one goes to the next lane of either version, and 0.3.0 boots, stops and deletes
agent-env-emu-*emulators as its own.agentlane prune --yesdeletes the free ones along with 0.3.0's, and never one a 0.2.x lane holds. - Moving the folder. Once no project on the Mac runs 0.2.x and
statuslists no lanes, runmv ~/.local/state/agent-env ~/.local/state/agentlane && mv ~/.local/state/agentlane/claims ~/.local/state/agentlane/lanes. 0.3.0 then uses the folder under its own name. Don't run 0.2.x on that Mac afterwards, because it would start a second registry.
New
agentlane prunelists the pool simulators and emulators that no lane holds, andagentlane prune --yesdeletes them to free their disk. It works from the registry, so it covers theagent-env-pool-*andagent-env-emu-*devices 0.2.x made. Each deletion locks the registry and checks again that no lane of either version holds the device, so a lane claimed meanwhile keeps it. A device the registry has no record of is never deleted, even one with a pool name; the listing shows those apart, because a registry in another state folder may hold them.--jsonprints the listing and each result for tools.- Browsers for Intel Macs and Linux. The pinned Chrome for Testing, its headless shell and ffmpeg now cover Intel Macs and Linux on x64 and arm64, so
up --platform webinstalls its browser there withoutAGENTLANE_PLAYWRIGHT_BROWSERS. Linux runs the web half of a project; iOS needs a Mac, and Android on Linux isn't supported yet. - Chrome's system libraries on Linux.
doctorhas abrowser librariescheck that names each library Chrome for Testing needs and the machine lacks, such aslibnss3.so, and gives Playwright'sinstall-deps chromiumcommand as the fix.upstops with the same message before it opens the browser. - Capture hygiene on a simulator has a new
keyboard-introstep. It marks the keyboard's slide-to-type intro as shown (com.apple.keyboard.preferencesDidShowContinuousPathIntroduction= true) and reads it back, so a fresh simulator's first keyboard no longer opens on an intro that covers the app.doctorlists the step with the others. - The
create-verification-skillskill tells a project to clear its app's own first-run sheets (onboarding, what's-new, permission prompts) before capturing, and to name them in its run skill.
Fixed
- On Android, the build hook runs with
JAVA_HOMEset to the JDK the build cache key names:AGENTLANE_JAVA_HOME, elseJAVA_HOME, else the JDK 17 agentlane finds. Before, withJAVA_HOMEunset, Gradle could run a different JDK from the one the cached build was keyed to. - On Linux, hooks run with
LANGandLC_ALLset toC.UTF-8, which glibc always has, instead ofen_US.UTF-8, which many images don't generate.uprefused a web app on such a machine, citing CocoaPods. macOS keepsen_US.UTF-8. - On Linux without
lsoforss, as in thenode:24image,upreads a port's listeners from/proc. Before this, it never found a service's listener and timed out on a server that answered.
0.2.1
Fixes from running setup from scratch on a production app and on the example app, after 0.2.0 reached them. A project that vendors 0.2.0 should move to this one.
maestro testunder a claim keeps a passing run's folder, itstakeScreenshotfiles included, and links every run into Maestro's own folder. 0.2.0 deleted a passing run's folder, so a flow's screenshots were lost and scripts reading~/.maestro/testsfound nothing.- A second
up --platform webon a claim whose browser is open works. 0.2.0 failed with "Tracing has already been started". - A web service started through a package manager (
pnpm exec next dev …) passesup's check that the server on the port is this worktree's, because a listener anywhere below the started process now counts. initwires Claude Code once wherever the plugin loads from, and removes the copies an earlierinitwrote;doctorwarns when both wire it.- Every command the CLI and the skills tell you to run is
node_modules/.bin/agent-env …, which works in every agent's shell. - Simulator hygiene sets the location again, up to 3 times, when a set doesn't read back.
- Claude Code's SessionEnd hook declares a 10 s timeout, so the release isn't cut off by Claude Code's shared 1.5 s budget.
- The skills:
setupruns every committed flow and test suite before and after its changes and lists each one;create-verification-skillpins the device when flows tap by point, writes a precondition per tool, seeds a page per feature the repo's docs list, and treats a wait that never matches in a sign-in flow as a defect.
0.2.0
0.2.0 adds web apps beside mobile apps, per-claim resources, the setup skill and wiring for six agents. A project moving from 0.1.x needs to know the items under "Moving from 0.1.x" first.
Moving from 0.1.x
- Run
initagain after you upgrade. The skill stubs' text changed, sodoctorwarns that a project's stubs are stale untilnode_modules/.bin/agent-env init --agents <list>rewrites them. Warnings don't faildoctor. - Each claim has an evidence folder.
$AGENT_ENV_EVIDENCE(<state dir>/claims/<id>/evidence) is set in every hook and underexec. It survivesreleaseand goes when the claim's files are pruned, seven days after the claim ends.node_modules/.bin/agent-env evidence screenshot | video start|stop | trace start|stop | logs | listwrites there, and a failedrun, or a failed command underexecon a browser claim, keeps its own bundle there. maestro testunder a claim writes into the evidence folder. In 0.1.x, Maestro wrote each run to its own folder,~/.maestro/tests/<run>. The claim'smaestronow passes--debug-output, and each test's output, itstakeScreenshotfiles included, lands in$AGENT_ENV_EVIDENCE/<stamp>-maestro-test-<pid>/.maestro/tests/<run>/<flow>/. The folder name ends in-failedwhen the test failed, which is also the path Maestro prints on a failure.- Each run is also linked into Maestro's own folder (
~/.maestro/tests/<run>, or$XDG_STATE_HOME/maestro/tests/<run>), so a script that reads it keeps working. Maestro's folder holds the runs of every claim on the Mac, so a script that runs under a claim should read$AGENT_ENV_EVIDENCEinstead. - A
--debug-outputor--test-output-diryou pass yourself goes to Maestro unchanged.
- Each run is also linked into Maestro's own folder (
- Printed commands are
node_modules/.bin/agent-env …. Every fix line the CLI prints, and every command in the skills and stubs, is written that way, run from the project root, because a bareagent-envis on the PATH only in Claude Code with the toolkit's plugin. A run skill that says bareagent-envworks only there; write the full path. - The
deviceskill is nowdrive. It drives browsers too. Adeviceskill remains and points todrive, so a run skill that namesdevicestill works. initand the Claude Code plugin. Wherever Claude Code loads the plugin (the project's settings, your local or user settings, or the session runninginit, as--plugin-dirdoes),initwrites none of the plugin's skills, MCP server or hooks for Claude Code, and says where it found the plugin. It removes the copies an earlierinitwrote, backing each file up first in<state dir>/init-backups/. An agent-env server in.mcp.jsonstays for other agents and is turned off for Claude Code withdisabledMcpjsonServers. A project whose only agent is Claude Code through the plugin gets no toolkit stubs in.agents/skills/.doctorwarns when the plugin and the project's own files both wire Claude Code.- The registry format is unchanged. 0.1.3 and 0.2.0 worktrees share a Mac's registry: 0.2.0 adds tables that 0.1.3 doesn't read and keeps the format version 0.1.3 checks.
New
- Web apps.
webinagent-env.jsonnames the service that serves the web app and the page to open.node_modules/.bin/agent-env up --platform webgives the claim its own browser (a profile, a debugging port and a driver session), opens the app, and signs it in through thesigninhook, which writes Playwright storage state to$AGENT_ENV_STORAGE_STATE. The driver is Playwright (playwright-cli) by default, or agent-browser. The toolkit installs Playwright 1.64.0 and agent-browser 0.39.0 with their browsers in its own data folder, so a project's@playwright/testmust be 1.64.x for its tests to find a browser underexec. Browser archives are pinned for Apple silicon Macs only; elsewhere, setAGENT_ENV_PLAYWRIGHT_BROWSERS. One claim can hold a device and a browser. - Service
platforms. A service can be limited to the apps that need it, so a webupdoesn't start Metro. - Resources.
resourcesdeclares data each claim gets its own copy of, such as a database: acreatecommand that exports values to every service, hook andexec, and ateardownthat runs when the claim ends, after a crash too. - Six agents.
node_modules/.bin/agent-env init --agents claude,codex,cursor,copilot,gemini,antigravity(or--all) writes each agent's skill stubs, MCP server and hooks from one source.--checkexits 1 when a file would change. - The setup skill. It takes a project from no toolkit wiring to
doctorready on every platform.upanddoctorname it whenagent-env.jsonis missing or invalid, or no agent is wired.
Fixed
- A service started through a package manager, such as
pnpm exec next dev, is the service's.pnpm execstarts its command in a process group of its own, anduprefused the server as a process the toolkit did not start. A listener below the service's process now counts, and stopping the service stops it too, even when the wrapper passes on no signal. up --platform webruns again on a claim whose browser is open. The second run failed at sign-in with "Tracing has already been started"; it now ends the running trace and starts a new one.- A browser driver error during
uporexecis reported with exit code 1 and a fix that works whendoctorsays ready (close the browser withnode_modules/.bin/agent-env exec -- playwright-cli close, thenupopens a new one), instead of escaping with a stack trace. upsets the simulator's location again, up to three times, when it doesn't read back, as happens on a freshly booted simulator under heavy load.