- Specific hardware, or a device plugged in over USB.
- A licensed desktop app.
- An app that only reaches your internal network.
The runner only makes outbound connections, to the TestDriver API and to Ably for realtime messages. You don’t need to open an inbound port.
Before you begin
The machine needs:- Node.js 18 or newer.
- Python 3 with
pyautoguiandPillow. The runner uses them for the mouse, keyboard, and screenshots. - An unlocked desktop session. The runner drives the real screen, so turn off sleep, screen savers, and lock timers.
- Outbound HTTPS and WebSocket access to
api.testdriver.aiand*.ably.io. curlandjq, to register the machine in step 2.
TD_API_KEY. Copy it from the API keys page.
- macOS
- Linux
- Windows
- Accessibility, so the runner can move the mouse and type.
- Screen Recording, so the runner can take screenshots.
Step 1: Install the runner
testdriver-sandbox-agent command, which connects the machine to a TestDriver session.
Step 2: Register the machine
Ask the API for a session on this machine. Replace192.168.1.50 with the machine’s IP address, and set os to windows on a Windows machine:
agentConfig object with everything the runner needs. Write agentConfig to the runner’s config file, and print the sandbox ID:
/c/Windows/Temp/testdriver-agent.json instead.
Save the sandbox ID, such as sb-69cce96e-1e0, for step 4.
To keep the config file somewhere else, set CONFIG_PATH to its full path before you start the runner.
A registered machine uses one of your plan’s concurrency slots while its session is open.
Step 3: Start the runner
Step 4: Point your test at the machine
Pass the machine’sip and the sandboxId from step 2 to TestDriver(). Setting sandboxId stops TestDriver from creating a cloud sandbox.
tests/my-machine.test.mjs
os: 'windows'.
Run the test from any computer:
Logs
The runner also writes
testdriver-agent-status.json in the same folder, with the sandbox ID, process ID, IP address, and start time.
Security
- Use a dedicated machine or user account. The runner can click anything on the desktop and run shell commands sent by your tests.
- Treat the config file as a secret. It contains your API key and a session token.
- Keep VNC private. If you add a VNC server for debugging, expose it only on localhost or your VPN.
- Rotate your API key on the API keys page when you retire or share a machine.
Troubleshooting
Sandbox has expired and is no longer available
Sandbox has expired and is no longer available
The session ended, which happens after a test disconnects or the session’s
keepAlive runs out. Repeat steps 2 and 3 for a fresh sandbox ID, and use the new ID in your test.The runner connects, but clicks and screenshots do nothing (macOS)
The runner connects, but clicks and screenshots do nothing (macOS)
Accessibility or Screen Recording permission is missing. Add your terminal app to both lists in System Settings → Privacy & Security, then quit and reopen it.
Config file not found after 300s
Config file not found after 300s
The runner couldn’t find the config file. Write it on the same machine, readable by the user who starts the runner, or set
CONFIG_PATH to where it is.The test runs in a cloud sandbox instead
The test runs in a cloud sandbox instead
Check that both
TD_MACHINE_IP and TD_SANDBOX_ID are set when you run the test. If sandboxId is undefined, TestDriver creates a cloud sandbox.Screenshots are blank or frozen (Linux)
Screenshots are blank or frozen (Linux)
DISPLAY points at a display with no desktop, or the screen blanked. Start a desktop on that display and turn off blanking with xset s off && xset s noblank && xset -dpms.Runner environment variables
Next steps
Self-host on AWS
Start a fresh Windows EC2 instance for each test.
Self-hosted
What the Enterprise plan includes.
Locate elements
Describe elements so TestDriver finds them on any screen.
Make assertions
Check that your app reached the right state.

