Mobilerun task runner
Use the repository's runnable
TypeScript task runner as the source
of truth. Resolve this link relative to this SKILL.md, even when the current
working directory is elsewhere. Preserve its server/browser trust boundary and
task lifecycle when adapting it.
Workflow
- Read the example's
README.md,
package.json, and
.env.example.
- Install
@mobilerun/sdk and @mobilerun/react from npm. Do not add local
package overrides. Keep MOBILERUN_CLOUD_API_KEY on the server and use
MOBILERUN_API_URL only to override the default API base.
- Keep SDK calls behind a server adapter. Keep validation and public response
schemas independent from SDK response types.
- Implement the run lifecycle: list eligible devices, start a task, expose
scoped stream credentials, poll task status serially, stop on request, and
remove credentials after a terminal state.
- For offline work, run tests, typechecking, and the production build. Do not
start a real task.
- Only when the user explicitly requests live verification, use a valid key
and an available device to run and, if needed, cancel a real task. Report
that this consumes Mobilerun resources.
Required boundaries
- Never send
MOBILERUN_CLOUD_API_KEY to the browser or expose raw SDK
responses through local routes.
- Accept only the documented public task fields. Keep model selection, output
schema, credentials, and other privileged or expensive SDK options under
server control.
- Validate request bodies, task IDs, task statuses, device summaries, and
outbound response shapes before crossing the browser boundary.
- Return only the fields the UI needs. Convert upstream failures to stable,
non-secret error responses; log enough server-side context to diagnose them
without logging credentials.
- Treat
streamUrl and streamToken as short-lived credentials. Store them in
a bounded, expiring server-side cache keyed by task ID, refresh them from the
task's device when necessary, and delete them for completed, failed, or
cancelled tasks.
- Poll with one request at a time. Abort requests on reset or unmount, apply a
timeout, back off after errors, and keep an active task cancellable when a
poll fails.
- Bind the unauthenticated example server to
127.0.0.1. Require application
authentication, per-user task ownership, authorization, rate limiting, and
auditing before any remote or multi-user deployment.
Architecture
Preserve the example's responsibility split:
src/server/mobilerun-adapter.ts: published SDK calls and server-owned task
options;
src/server/task-service.ts: SDK-independent orchestration and narrow task
views;
src/server/run-session-store.ts: bounded stream-credential lifetime;
src/server/api-app.ts: validation, safe HTTP responses, and route surface;
src/shared/contracts.ts: schemas shared across the trust boundary;
src/client/api-client.ts: same-origin HTTP transport;
src/client/runner-machine.ts and use-task-runner.ts: deterministic UI
lifecycle and non-overlapping polling.
Do not combine trigger workflows with this task-runner lifecycle. Use
mobilerun-webhooks for signed webhook receivers and webhook file downloads.
After changes, run bun run check from the task-runner directory and run the
skill validator when it is available. Never perform live task or device actions
unless the user explicitly requests them.
1---2name: mobilerun-task-runner3description: Build, run, test, or troubleshoot TypeScript task runners that start Mobilerun tasks server-side and render a live device stream with @mobilerun/react. Use for device selection, tasks.run/status/stop flows, short-lived stream credentials, serial polling, cancellation, or the bundled Bun and React task-runner example. Do not use for Python webhook receivers, workflow triggers or actions, or direct browser-side Mobilerun API calls.4---56# Mobilerun task runner78Use the repository's runnable9[TypeScript task runner](../../examples/typescript/task-runner/) as the source10of truth. Resolve this link relative to this `SKILL.md`, even when the current11working directory is elsewhere. Preserve its server/browser trust boundary and12task lifecycle when adapting it.1314## Workflow15161. Read the example's17 [`README.md`](../../examples/typescript/task-runner/README.md),18 [`package.json`](../../examples/typescript/task-runner/package.json), and19 [`.env.example`](../../examples/typescript/task-runner/.env.example).202. Install `@mobilerun/sdk` and `@mobilerun/react` from npm. Do not add local21 package overrides. Keep `MOBILERUN_CLOUD_API_KEY` on the server and use22 `MOBILERUN_API_URL` only to override the default API base.233. Keep SDK calls behind a server adapter. Keep validation and public response24 schemas independent from SDK response types.254. Implement the run lifecycle: list eligible devices, start a task, expose26 scoped stream credentials, poll task status serially, stop on request, and27 remove credentials after a terminal state.285. For offline work, run tests, typechecking, and the production build. Do not29 start a real task.306. Only when the user explicitly requests live verification, use a valid key31 and an available device to run and, if needed, cancel a real task. Report32 that this consumes Mobilerun resources.3334## Required boundaries3536- Never send `MOBILERUN_CLOUD_API_KEY` to the browser or expose raw SDK37 responses through local routes.38- Accept only the documented public task fields. Keep model selection, output39 schema, credentials, and other privileged or expensive SDK options under40 server control.41- Validate request bodies, task IDs, task statuses, device summaries, and42 outbound response shapes before crossing the browser boundary.43- Return only the fields the UI needs. Convert upstream failures to stable,44 non-secret error responses; log enough server-side context to diagnose them45 without logging credentials.46- Treat `streamUrl` and `streamToken` as short-lived credentials. Store them in47 a bounded, expiring server-side cache keyed by task ID, refresh them from the48 task's device when necessary, and delete them for completed, failed, or49 cancelled tasks.50- Poll with one request at a time. Abort requests on reset or unmount, apply a51 timeout, back off after errors, and keep an active task cancellable when a52 poll fails.53- Bind the unauthenticated example server to `127.0.0.1`. Require application54 authentication, per-user task ownership, authorization, rate limiting, and55 auditing before any remote or multi-user deployment.5657## Architecture5859Preserve the example's responsibility split:6061- `src/server/mobilerun-adapter.ts`: published SDK calls and server-owned task62 options;63- `src/server/task-service.ts`: SDK-independent orchestration and narrow task64 views;65- `src/server/run-session-store.ts`: bounded stream-credential lifetime;66- `src/server/api-app.ts`: validation, safe HTTP responses, and route surface;67- `src/shared/contracts.ts`: schemas shared across the trust boundary;68- `src/client/api-client.ts`: same-origin HTTP transport;69- `src/client/runner-machine.ts` and `use-task-runner.ts`: deterministic UI70 lifecycle and non-overlapping polling.7172Do not combine trigger workflows with this task-runner lifecycle. Use73`mobilerun-webhooks` for signed webhook receivers and webhook file downloads.7475After changes, run `bun run check` from the task-runner directory and run the76skill validator when it is available. Never perform live task or device actions77unless the user explicitly requests them.