[ Documentation ]
Nano Simulator JS Client

Nano Simulator JS Client

Remote Simulators are in early access. Access is switched on per customer while we learn how people use it. Email [email protected] and we will turn it on for your account.

Agents and programmatic callers can create and drive a nano simulator directly from JavaScript or TypeScript. There are no CLI child processes to spawn and no shell session to manage. This client targets the Durable Object and Dynamic Worker nano service; rnx ios --remote uses a micro Box instead.

import { readFile } from 'node:fs/promises'
import { createRemoteSimulator, type RemoteSimulator } from 'rnxsim/cloud'
const sim: RemoteSimulator = await createRemoteSimulator({
artifact: new Uint8Array(await readFile('./dist/main.js')),
authorization: 'Bearer sk_rnx_...',
device: 'iphone-16',
})

createRemoteSimulator takes artifact bytes rather than a path or a URL, so fetching and local file access stay under your control. The client verifies the Metro JavaScript and its SHA-256 identity before upload, confirms the initial claim, and keeps the bearer tokens private.

Drive the simulator

Everything that drives the simulator lives on sim.rnx, and the verbs match the CLI one for one:

const tree = await sim.rnx.describe()
await sim.rnx.wait('ready', { maxMs: 20_000 })
await sim.rnx.wait({ type: 'selector', selector: 'loginButton' })
await sim.rnx.do({ type: 'tap', x: 187, y: 406 })
const screenshot = await sim.rnx.screenshot()
const capture = await sim.rnx.capture()
await sim.rnx.reset()

If you know the CLI, you already know this surface. rnx describe is sim.rnx.describe(), and rnx do tap is sim.rnx.do({ type: 'tap', ... }).

Finish

await sim.close()

Closing stops the meter immediately. You do not have to remember to: an idle simulator closes itself, and a simulator whose client stopped reporting is swept closed within five minutes and metered back to its last heartbeat. See Limits & Pricing.

How commands behave

Commands are receipt-backed and serialized per simulator. The client does not arrange that ordering. It falls out of each simulator being a single Durable Object, which is single-threaded and globally unique for its id.

If the execution isolate is replaced mid-session, rnx replays the simulator’s bounded interaction journal into the replacement before running your next command, so the session continues rather than failing.

The same bounded command vocabulary the CLI exposes is available here, including the lower-level command sender for anything without a convenience method. The operations that are supported, and the ones that are not, are listed in the overview.