qraftai-runner
v0.4.9
Published
QraftAI local device runner — bridge your own Android emulator/phone to a QraftAI workspace.
Maintainers
Readme
QraftAI Runner — bring your own device
Run QraftAI's mobile automation on your own Android emulator or phone, driven by your QraftAI workspace in the cloud. The runner dials out to QraftAI (no inbound ports, firewall-friendly) and executes device actions locally — the AI agent, LLM calls, and billing stay on the QraftAI server. It never sees an API key.
Your browser ──▶ QraftAI (cloud) ──runner tunnel──▶ this runner ──▶ your devicePrerequisites (on this machine)
Same toolchain as a local QraftAI mobile setup:
| Tool | Install (macOS) |
|---|---|
| JDK 17+ | brew install openjdk |
| Android SDK (adb + emulator) | Android Studio — sets ANDROID_HOME |
| Appium 2 | npm i -g appium |
| UiAutomator2 driver | appium driver install uiautomator2 |
| A device | an emulator (AVD) or a USB phone with USB debugging on |
Make sure adb and emulator are on PATH and ANDROID_HOME is set. Verify:
adb devices # your phone/emulator shows "device"
appium --version
emulator -list-avdsRun it
In QraftAI open the Mobile tab → Local → Connect your machine.
Copy the command it shows (it embeds a token scoped to your workspace):
npx qraftai-runner --server wss://app.qraftai.com/runner-stream --token <token>From this repo you can instead run it directly:
node runner/index.js --server wss://<host>/runner-stream --token <token>Leave it running. Your emulators/phones now appear in the Mobile tab's device dropdown. Pick one, choose an app, and Run — the live view, save, replay, and reports all work as usual.
Options
| Flag | Env | Meaning |
|---|---|---|
| --server, -s | QRAFTAI_SERVER | wss://<host>/runner-stream |
| --token, -t | QRAFTAI_TOKEN | org-scoped runner token from the Mobile tab |
| --name, -n | QRAFTAI_RUNNER_NAME | a label for this machine, shown in the app |
The runner auto-reconnects if the connection drops. Stop it with Ctrl-C.
App under test
The app can be:
- an app you upload in QraftAI — it's streamed to the runner and installed for the run,
- an already-installed package on the device, or
- a local
.apkpath on this machine.
Notes
- Android only today (matches the rest of QraftAI mobile).
- The token is a bearer credential for your workspace's device sessions — treat it like a password; regenerate it from the Mobile tab to revoke an old one.
Publishing (maintainers)
The published package is a single self-contained bundle — esbuild inlines the
device layer (../server/mobile/*) at build time, so the tarball has no repo
dependency (only ws, webdriverio, dotenv as normal npm deps). Only dist/ +
README.md are shipped (see files in package.json); dist/ is gitignored and
rebuilt on publish via prepublishOnly.
cd runner
npm install # installs esbuild (build) + declared deps
npm run build # optional: build dist/index.js locally to inspect
npm pack --dry-run # optional: preview the tarball contents
npm login # your npm account/org
npm publish --access publicAfter publishing, npx qraftai-runner … works on any machine with Node 18+.
Troubleshooting
Error: Cannot find module 'readable-stream' (or another sub-dependency of
webdriverio/archiver) on startup. The npx cache installed the runner's
dependency tree incompletely. Fix it with any of:
# 1) Clear the npx/npm cache, then re-run
npm cache clean --force
# Windows: also delete %LocalAppData%\npm-cache\_npx
# macOS/Linux: also delete ~/.npm/_npx
npx qraftai-runner --server <wss…> --token <token>
# 2) Or install globally (resolves the tree more reliably than npx)
npm install -g qraftai-runner
qraftai-runner --server <wss…> --token <token>Prefer Node 20 LTS — webdriverio targets the active LTS lines; very new
Node releases (24+) occasionally hit install/resolution quirks. readable-stream
is now a declared dependency (v0.4.1+), so a clean install pulls it in.
