agentlaneagentlane

4.3ReferenceMarkdown

agentlane.json

agentlane.json says what a lane of the project holds: the mobile app, the web app, the services and their ports, per-lane resources, hooks, preconditions, capture hygiene, the build cache and the driver. up, doctor and restart read it from the current folder or the ones above it, and agentlane schema prints its JSON Schema.

The setup skill writes this file for you. This page is for reading it and changing it by hand. The site builds each field table from the JSON Schema in the package, so the tables match the version they document.

Point $schema at the copy in node_modules and your editor checks the file as you type:

agentlane.json

{
  "$schema": "node_modules/agentlane/schema/agentlane.schema.json"
}

doctor's config line validates the file and names each field that breaks the schema. npx agentlane schema prints the schema. Every command in the file runs with sh -c in the folder that holds agentlane.json, with the lane's AGENTLANE_* variables, the values of its resources, and LANG and LC_ALL set to a UTF-8 locale: en_US.UTF-8 on macOS and C.UTF-8 on Linux. Environment variables lists what each command gets.

Top level

$schemastring
The path or URL of this schema, for editors.
appobject
The mobile app: what up builds, installs and launches on the claimed simulator or emulator.
webobject
The web app: the service that serves it and the page to open. up --platform web (the default when there is no app) claims ports and no device, starts the services, and ends on doctor with the app's URL, also given to commands as AGENTLANE_WEB_URL.
servicesobject by name
The long-running servers the app needs, by name. Each gets a claimed port in AGENTLANE_<NAME>_PORT (the name upper-cased, dashes as underscores).
resourcesobject by name
What each lane gets of its own besides ports, such as a database, by name. up runs each create once per lane, in this order, after the setup hook and the build preconditions (also under --no-setup). The values a create exports then reach the lane's services, the hooks after setup, and agentlane exec, as AGENTLANE_<NAME>_PORT does; a command never takes an exported variable from the caller's environment. When the lane ends (release, the session-end release, or a reap of a lane whose owner died or was taken over), each teardown runs, last created first.
hooksobject
Fields: setup, build, launch, signin, teardown.
preconditionsarray of object
Checks up runs before any slow step. A failing check refuses with its fix.
hygieneobject
Fields: location, appearance.
buildCacheobject
Lets the toolkit skip the native build when its inputs have not changed. The key also covers the platform, the build variant, the toolchain and the contents of the env file the build uses. The toolchain is the Xcode version for iOS. For Android it is the version of the JDK at AGENTLANE_JAVA_HOME or JAVA_HOME (else the JDK 17 the toolkit finds), which the build hook gets as JAVA_HOME, the Gradle distribution in android/gradle/wrapper/gradle-wrapper.properties when that file is not git-ignored (a generated wrapper follows the inputs that generate it, such as the lockfile), and the revision of every installed Android SDK build-tools, platform, NDK and CMake package.
driverobject
The project drives its app with the toolkit (Maestro flows); up and doctor then check for Java 17.

app

The mobile app: what up builds, installs and launches on the lane's simulator or emulator. app.ios and app.android hold what differs per platform, and replace bundleId, output and device when up runs for that platform.

app.platform"ios" or "android"required
The platform up claims a device for, unless up --platform names another.
app.bundleIdstringrequired
The bundle id or package name.
app.schemestring
A URL scheme the app handles. It is approved on the simulator before it boots, so opening a link never stops at "Open in ...?".
app.launch"dev-client" or "bundler-pin" or "hook"required
How the app is launched. dev-client: an Expo dev client opened on the bundler with --initialUrl. bundler-pin: a React Native app whose bundler location is written to its defaults and read back, then launched. hook: the project's launch hook.
app.bundlerstring
The service the app loads its JavaScript from. Default: the only service of type metro.
app.variantstring
The build variant, given to hooks as AGENTLANE_VARIANT and used by the build cache. Default: "Debug".
app.outputstring
The app the build hook produces (an .app or .apk), relative to this file. The toolkit installs it. Leave it out when the build hook installs the app itself; the installed app is then read back for the cache.
app.deviceobject
Its fields follow.
app.device.typestring
A simulator device type, or an Android device profile such as pixel_8. Default: the newest iPhone the runtime supports, or pixel_8.
app.device.runtimestring
A simulator runtime, or an Android system image (a package id or an API level). Default: the newest installed iOS runtime, or the newest Google APIs image.
app.device.strictboolean
Take only a device of exactly this type and runtime. Without it, when the shared pool is full, a lane takes a free device of another type rather than deleting one to make this type. Default: false.
app.iosobject
What differs on iOS: these replace app.bundleId, app.output and app.device when up runs for iOS.
app.ios.bundleIdstring
The bundle id or package name.
app.ios.outputstring
The app the build hook produces (an .app or .apk), relative to this file. The toolkit installs it. Leave it out when the build hook installs the app itself; the installed app is then read back for the cache.
app.ios.deviceobject
Fields: type, runtime, strict.
app.androidobject
What differs on Android: these replace app.bundleId, app.output and app.device when up runs for Android.
app.android.bundleIdstring
The bundle id or package name.
app.android.outputstring
The app the build hook produces (an .app or .apk), relative to this file. The toolkit installs it. Leave it out when the build hook installs the app itself; the installed app is then read back for the cache.
app.android.deviceobject
Fields: type, runtime, strict.

web

The web app: the service that serves it and the page to open. up --platform web claims ports and a browser, no device, starts the services and opens the page.

web.servicestring
The service that serves the web app. Default: the only service of type web.
web.pathstring
The page to open, on the service's port. Default: "/".
web.browserobject
The lane's own browser, which up opens on the web app. Each lane gets its own profile folder, debugging port and driver session, released with the lane. The toolkit installs the driver and its browser at pinned versions in its own data folder (agentlane browser install). Drive it with the driver's own CLI under agentlane exec, which sets the driver's session, the web app's URL and the lane's saved login. The signin hook writes that saved login, in Playwright's storage-state format, to the file named by $AGENTLANE_STORAGE_STATE, and the browser starts with it.

web.browser

The lane's own browser. Browsers for web apps explains the drivers.

web.browser.driver"playwright" or "agent-browser"
playwright: Playwright's own CLI, playwright-cli, and Playwright tests run with exec -- npx playwright test. agent-browser: Vercel's agent-browser CLI, headless. Both drive the toolkit's pinned Chrome for Testing. Default: "playwright".
web.browser.headedboolean
Show the browser window, so a person can watch it. Default: headless. Playwright only: agent-browser runs headless, on the headless shell of Chrome for Testing. Default: false.

services

The long-running servers the apps need, by name. A name is lowercase letters, digits and dashes, and it becomes the port variable: api-v2 gets AGENTLANE_API_V2_PORT. Ports and dev servers shows them in use.

services.<name>.typestringrequired
The port block the service's port comes from: metro, api, web, or a name of your own with ports.
services.<name>.ports[integer, integer]
[first, last]: the port block for a type of your own. The Mac's own blocks (metro, api, web, and any in its registry config) take precedence.
services.<name>.startstringrequired
The command that runs the server in the foreground on $AGENTLANE_<NAME>_PORT. It is started in its own process group and logged to a file per lane.
services.<name>.cwdstring
The directory to start it in, relative to this file.
services.<name>.platformsarray of "ios" or "android" or "web"
The platforms that need it, such as ["ios", "android"] for a bundler the web app does not use. up, doctor and restart for another platform leave it out. Leave it out to run it for every platform.
services.<name>.readyhttpReady or tcpReadyrequired
services.<name>.timeoutSecondsnumber
How long to wait for the readiness check. Default: 60.
services.<name>.dialobject
The app dials this service: launch it with this argument, so it talks to this lane's server.
services.<name>.dial.argumentstringrequired
The launch argument, such as -apiBaseUrl.
services.<name>.dial.valuestring
The argument's value; {port} is the service's port. Default: "http://localhost:{port}".

ready

ready is one of two checks. An HTTP check:

ready.kind"http"required
ready.pathstringrequired
The path to GET.
ready.statusinteger
The status that means ready. Default: 200.
ready.bodystring
Text the response body must contain.
ready.hoststring
The host the readiness check connects to. Default: "127.0.0.1".

Or a TCP check, which passes when the port accepts a connection:

ready.kind"tcp"required
ready.hoststring
The host the readiness check connects to. Default: "127.0.0.1".

resources

Data each lane gets its own copy of, such as a database, by name. up runs each create once per lane, in the order listed, after the setup hook. Teardowns run when the lane ends, last created first. A database per lane walks through one.

resources.<name>.createstringrequired
A shell command that makes the resource for this lane. It writes each value it exports as a NAME=value line (quotes around the value are removed) to the file named by $AGENTLANE_EXPORTS. Its output goes to its log, and a failing create stops up with it. It runs again at the next up when it failed or never finished, so it must cope with what a partial run left.
resources.<name>.exportsarray of string
The variables create writes, such as DATABASE_URL. Create must write each of them and no other. Names starting with AGENTLANE_, and LANG and LC_ALL, are the toolkit's.
resources.<name>.teardownstringrequired
A shell command that removes the resource when the lane ends. What it runs is recorded when create starts: this command, its folder and its variables (the lane's, plus the values create exported), so it runs even after this file changes and after the session that made the lane died. When the folder is gone (the worktree was deleted), it runs in the lane's log folder. A failed teardown is kept and tried again at the next release or reap, so it must cope with a resource that is already gone.
resources.<name>.cwdstring
The directory create and teardown run in, relative to this file.
resources.<name>.teardownTimeoutSecondsnumber
How long teardown may run before it is stopped and counted as failed. Default: 120.

hooks

Shell commands the project owns. Each one reads the lane from the environment, runs without asking anything, and exits non-zero when it didn't do its job. up writes each hook's output to hooks/<name>.log in the lane's folder.

hooks.setupstring
A shell command run with sh -c first, to install dependencies.
hooks.buildstring
A shell command run with sh -c to build the app for the claimed device.
hooks.launchstring
A shell command run with sh -c to launch the app when app.launch is "hook"; AGENTLANE_LAUNCH_ARGS holds the dial arguments.
hooks.signinstring
A shell command run with sh -c after launch, to sign in; for the web app it writes the lane's saved login, in Playwright's storage-state format, to $AGENTLANE_STORAGE_STATE.
hooks.teardownstring
A shell command run with sh -c by agentlane release, after the services stop and before the resources' teardowns.

preconditions

Checks up runs before a slow step, each with the fix to print when it fails. Use one per tool a hook calls that the project doesn't install, one for the dependency install, and one per env file a hook needs.

preconditions[].namestringrequired
What is checked, as a short phrase.
preconditions[].runstringrequired
A shell command that exits 0 when the precondition holds.
preconditions[].fixstringrequired
What to do when it fails.
preconditions[].before"claim" or "build"
claim: checked before anything is claimed. build: checked after the setup hook, before the build. Default: "claim".
preconditions[].platformsarray of "ios" or "android" or "web"
The platforms it applies to. Leave it out to check it for every platform.

agentlane.json

{
  "preconditions": [
    { "name": "CocoaPods is installed", "run": "command -v pod", "fix": "brew install cocoapods", "platforms": ["ios"] },
    { "name": "node_modules is installed", "run": "test -d node_modules", "fix": "run pnpm install", "before": "build" }
  ]
}

hygiene

What capture hygiene sets on the lane's device. Leave it out for the defaults: the location 37.3349, -122.009, and light appearance. Simulators and emulators lists every step.

hygiene.locationobject
Its fields follow.
hygiene.location.latitudenumberrequired
hygiene.location.longitudenumberrequired
hygiene.appearance"light" or "dark"

buildCache

Lets up skip the native build when its inputs haven't changed. The build cache explains the key.

buildCache.inputsarray of object or objectrequired
buildCache.cacheableVariantsarray of stringrequired
The build variants whose output may be stored and served. Leave out any variant that embeds its JS bundle, such as a Release build.
buildCache.envFilestring
An env file the build bakes in, relative to the config file's directory. Its contents enter the key; a missing file counts as absent. Use this for files git ignores, which a files input never sees.
buildCache.maxAgeDaysnumber
An entry unused for longer than this is pruned. Default: 14.
buildCache.maxEntriesinteger
Only the most recently used entries up to this count are kept. Default: 6.

A files input

buildCache.inputs[].kind"files"required
buildCache.inputs[].pathsarray of stringrequired
Files, directories or globs (*, **), relative to the directory holding the config file. Matched as git glob pathspecs over tracked files and untracked files git does not ignore; each enters the key by path, mode and content.
buildCache.inputs[].excludearray of string
Files, directories or globs to leave out of paths.
buildCache.inputs[].platformsarray of "ios" or "android"
The platforms whose key includes this input. Leave it out to include it for every platform.

A command input

buildCache.inputs[].kind"command"required
buildCache.inputs[].runstringrequired
A shell command run with sh -c in the config file's directory, with the lane's environment. Its stdout enters the key; a non-zero exit means no key, so the build runs uncached.
buildCache.inputs[].platformsarray of "ios" or "android"
The platforms whose key includes this input. Leave it out to include it for every platform.

driver

driver.flowsstring
The folder of committed flows, relative to this file.

With a driver block, up and doctor check for Java 17, and maestro under exec is agentlane's Maestro build on the lane's device.