Turn your Mac into a simulator cloud that manages itself.

Simlock leases, serves and manages iOS and Android devices for your coding agents. Start on one Mac, then add machines behind a gateway when you need more. Free and open source.

One machine. Your agents lease its devices three ways:
the simlock CLI, agent-device, or HTTP.

Works with iOS simulators, Android emulators, Physical iPhones, Physical Android phones, macOS workers, Linux workers, CLI, MCP, HTTP API, agent-device.

[01] How it works

Start on one Mac. Grow into a fleet.

  1. 01

    Install

    Install the CLI. The daemon starts on demand, so there is no setup step.

    $ npm i -g simlock
  2. 02

    Lease

    Ask for a platform and a model. You get a booted, checked device no other agent will touch.

    $ simlock lease --platform ios --device "iPhone 16"
  3. 03

    Add machines

    Run one daemon as a gateway, mint a join token, and point each Mac or Linux worker at it.

    $ simlock --gateway token create --role worker
Simlockzsh
simlock lease --platform ios --device "iPhone 16"
simlock simctl install <device.address> ./MyApp.app
simlock release <lease.id>





simlockFor agents on the machine itself. Lease results are one JSON line on stdout.Set up CLI

[02] Fleet

One URL in front of every machine you own.

A gateway owns no devices. Workers dial out to it, so a Mac behind NAT joins with a URL and a token, and each request goes to a warm device first, then to the machine with the most room.

Set up a gateway
Simlockzsh
# on the gateway
simlock --gateway daemon start
simlock --gateway token create --role worker

# on each worker, Mac or Linux
simlock config set gateway '{"url":"wss://gw.example","token":"slk_..."}'
simlock daemon stop
simlock daemon start

[03] Console

Open one page. See who holds what.

The daemon serves the console itself once HTTP is on. Sign in with an operator token, or through the sign-in proxy you already run, and watch every worker, lease and request on the gateway update within about a second.

Read about the console

[04] What you get

Devices that manage themselves, for agents that don’t wait.

[05] Safe by default

It only touches what it made.

Your devices stay yours

Simlock only shuts down, erases or deletes devices it created. Everything else is read-only to it.

Loopback only by default

The HTTP API and the console listen on loopback only, and both ask for a token. Nothing is reachable from another machine until you change http.host.

Tokens with roles

Agents, operators and workers get their own tokens, hashed at rest and revocable.

Passthrough with limits

simlock simctl and simlock adb refuse verbs that would change a device behind its lease.

[06] FAQ

Frequently asked questions

Does Simlock sandbox my agents?
No. It is advisory: agents are told to use only devices a lease hands them, and Simlock does not intercept simctl or avdmanager. What it does enforce is its own reach: it only shuts down, erases or deletes devices it created.
What happens when an agent dies holding a device?
Every lease has a TTL and lives only while it is renewed. simlock lease renews on a timer and releases when it exits, so a killed holder frees its device at once, and one that vanishes costs the device only until the TTL runs out.
What if every device is busy?
Simlock creates another one, up to a capacity it derives from the machine’s CPU and RAM. After that the request waits in a fair queue, with --timeout and --no-wait for callers that want something else.
Does a worker need an open port to join a fleet?
No. A worker dials out to the gateway over one WebSocket, with the gateway URL and a join token from simlock --gateway token create --role worker, so a Mac behind NAT joins without an inbound port.
Can a Linux machine be a worker?
Yes, for Android. Emulators run headless with android.emulator.headless, as on a Linux CI runner. iOS simulators need a Mac with Xcode.
How do agents on other machines reach it?
Over the HTTP API, with a token: POST /v1/lease-requests on the gateway, then POST /v1/leases/{id}/exec to run simctl or adb on whichever worker holds the device. agent-device can use the gateway as its proxy too.
Get started