Skip to content

Agent Setup ​

The agent runs on a Mac and streams simulator and emulator screens to the relay. It connects outbound to the relay — no inbound firewall rules needed.

Start the agent ​

When the agent and relay run on the same Mac, no flags are needed — the port is read from tapflow.config.json (default 4000):

sh
tapflow agent start

When the relay runs on a separate machine, pass its URL together with an auth token. 192.168.x.x is the relay machine's LAN IP. See Remote relay authentication for how to create the token:

sh
tapflow agent start --relay ws://192.168.x.x:4000 --token tflw_pat_xxxxxxxx
OptionDefaultDescription
--relayws://localhost:[port]Relay WebSocket URL. Port is read from tapflow.config.json.
--deviceall simulatorsLimit which iOS simulators are exposed to the relay, by name or UDID
--tokennoneToken with the agent scope for remote relay authentication. Can also be passed via the TAPFLOW_AGENT_TOKEN environment variable.

Wired LAN recommended

Keep the agent and relay on the same wired LAN. Wi-Fi works but can stutter on a Mac (AWDL channel hopping), regardless of signal strength — see Stream lag or stuttering for why and how to mitigate.

Remote relay authentication ​

No authentication is needed when the agent connects to a relay on the same machine (localhost). When the relay runs on a different machine, it only accepts agents that present a token with the agent scope. This protects your sessions from an arbitrary device on the same network impersonating an agent and feeding screens into a test session.

The relay requires authentication on every connection except one that reaches the relay port over loopback — this section covers the agent side. Reaching the same Mac by its LAN address counts as remote, and so does a tunnel client, which connects from loopback on someone else's behalf and therefore gets a separate tunnel port where every connection has to authenticate. For how browsers reach the relay from outside the office (tunnels), see External access in Self-Hosting the Relay.

Create a token ​

In the dashboard, go to Settings → Tokens → New token and set the Type to Agent. Only accounts with the Admin role can create agent-scope tokens. The success screen shows a ready-to-run agent command — copy it and run it on the agent machine.

Pass the token ​

Pass it with the --token flag:

sh
tapflow agent start --relay ws://192.168.x.x:4000 --token tflw_pat_xxxxxxxx

If you prefer to keep the token out of your shell history, use the TAPFLOW_AGENT_TOKEN environment variable. When both are set, the flag wins:

sh
export TAPFLOW_AGENT_TOKEN=tflw_pat_xxxxxxxx
tapflow agent start --relay ws://192.168.x.x:4000

Connecting to a remote relay without a token (or with an expired or revoked one) makes the agent print the rejection reason along with the token setup steps, then exit.

iOS ​

Prerequisites ​

  • macOS
  • Xcode with iOS Simulator Runtime installed
  • Node.js ≥ 22

List available simulators ​

sh
tapflow devices

Multiple simulators ​

Each Mac supports 2–4 simultaneous simulators depending on available RAM. The agent reports available slots automatically. See Scaling Mac Resources for details.

Troubleshooting ​

Common
  ✓ Node v22.x

iOS
  ✓ Xcode 26.0
  ✓ xcrun simctl
  ✓ Simulator booted: iPhone 16 Pro

Android ​

Prerequisites ​

  • Android SDK installed (ANDROID_HOME set or adb in $PATH)
  • An AVD using the google_apis/arm64-v8a system image (android-34)

Create an AVD ​

Create an AVD using Android Studio's AVD Manager. See Create and manage virtual devices for a step-by-step guide.

When selecting the system image, note the following:

AVD image matters

Use a google_apis/arm64-v8a image — the tested and recommended configuration. The google_apis_playstore image is not tested and has shown H.264 encoder issues.

The agent boots the emulator automatically, waits for sys.boot_completed, then begins streaming. For emulators on Apple Silicon, the agent encodes H.264 on the Mac host (VideoToolbox), capped at 30 fps — no GPU load on the emulator itself.

Troubleshooting ​

sh
tapflow doctor
# Common
#   ✓ Node v22.x
#
# Android
#   ✓ adb found: /usr/local/bin/adb
#   ✓ AVD: Pixel_8 (android-34 · google_apis/arm64-v8a)

See Troubleshooting for more detailed solutions.

Stream quality ​

Resolution and decoder are chosen automatically per viewer connection — tapflow streams in a Standard, Smooth, or Remote profile depending on how each viewer reaches the relay. See Streaming Quality for the profiles and how to tune them.

Host display and sleep ​

While an agent is connected, it holds a macOS power assertion so the host doesn't sleep mid-session. By default it also keeps the display awake (caffeinate -di): when the display sleeps, macOS parks the GPU and throttles the simulator render and encoding, which shows up as a sluggish stream. Running an agent effectively dedicates the Mac to tapflow, so this is the default.

Set TAPFLOW_ALLOW_DISPLAY_SLEEP=1 to let the display sleep normally (system sleep is still blocked).

Released under the MIT License.