Skip to content

simlock run holds a lease around one command, and a detached lease follows the agent process #944

Open

Description

@V3RON

Problem

An agent that uses the CLI runs one shell per tool call. The held form of simlock lease dies with that shell, so the docs steer agents to --detach with a 15 minute default TTL and manual simlock lease renew. In practice the agent copies the lease id and UDID out of the grant JSON by hand, starts a long build or test run, and forgets to renew. The lease ends mid-run and the device is wiped under the test runner.

Today, across several tool calls:

simlock lease --platform ios --device "iPhone 16" --detach --ttl 1h
# copy lease.id and device.driverDeviceId out of the JSON
xcodebuild -scheme MyApp -destination "generic/platform=iOS Simulator" build   # 12 min
simlock simctl install <UDID> build/Debug-iphonesimulator/MyApp.app
maestro test flows/                                                             # 20 min
simlock release <lease.id>

Two things are missing.

1. A command that holds a lease around one child process. The shape of xvfb-run, flock or timeout:

simlock run --platform ios --device "iPhone 16" -- sh -c '
  xcodebuild -scheme MyApp -destination "generic/platform=iOS Simulator" build &&
  simlock simctl install "$SIMLOCK_DEVICE_UDID" build/Debug-iphonesimulator/MyApp.app &&
  maestro test flows/'

run leases with the same options as lease, exports the lease into the child's environment (SIMLOCK_LEASE_ID, SIMLOCK_DEVICE_UDID, ANDROID_SERIAL, plus today's environment), renews every third of the TTL while the child runs, ends the child with a clear message when the lease is lost, releases on exit, and returns the child's exit code.

2. A detached lease that follows the agent's process. --bind-pid already releases a held lease when a named process exits, but it is ignored with --detach (website/src/content/docs/docs/reference/cli.mdx, --bind-pid row). Claude Code exports CLAUDE_PID into every shell it runs. --detach could leave a small keeper behind that renews the lease and releases it when that pid exits, by default when CLAUDE_PID (or an explicit --bind-pid) is present. A closed Claude Code window then frees the device in seconds instead of at the TTL, and nobody has to renew.

Context

Found in the 2026-10-23 product review. Related facts:

  • The grant environment carries no device identifier for virtual devices: only SIMLOCK_IOS_DEVICE_SET (iOS) and ANDROID_ADB_SERVER_PORT (Android). ANDROID_SERIAL is set only for physical phones (src/drivers/android/index.ts, environment block). Omitting -s on the shared adb server is ambiguous with several emulators up.
  • --export-env prints only environment, so the lease id and UDID are lost and the docs send the agent to simlock status, whose human line shows neither.
  • src/leasing/AGENTS.md lists "a SIGKILLed holder keeps its device until the TTL" as a known gap.
  • The MCP server and the held CLI already renew every TTL/3 (src/lease-policy/index.ts); run and the keeper reuse that policy.

Open questions for the spec session: whether run is a new command or a flag on lease; what the keeper does when the daemon restarts; whether run also accepts an existing lease id so a session can reuse a device across several run calls.

Written by an agent.

Activity

  1. added
    request:newInbox. Never picked up, body never edited.
    on Oct 23, 2026
  2. V3RON commented on Oct 23, 2026

    @V3RON
    ContributorAuthor

    When this is specified: #157 adds simlock instructions, the rules text agents follow, with one ## section per surface. The task that ships this request should update the ## simlock CLI section in the same PR, so agents learn the new command.

    Written by an agent.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    request:newInbox. Never picked up, body never edited.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions