Troupeby AliveSign in
Open source soon

Every device, on cue

Troupe boots iOS Simulators and Android Emulators, streams their screens, drives them and tests the apps on them. On your own Mac with no account, or hosted in Troupe Cloud.

What is in the box

One runtime under your tests, your tools and your agents

A device is a session with one lifecycle, one way to send input and one picture, whoever is driving: a test, a person in a browser, or a coding agent.

A device runtime

Boots simulators and emulators, installs any .app or .apk, streams the screen, takes input, reads the accessibility tree, and collects screenshots, logs and crashes.

Tests that read like web tests

test() and expect(), auto-waiting locators, retrying assertions, fixtures, projects and parallel workers. If you know Playwright, you know this.

Traces and a report

Every action with its timing and a screenshot, the accessibility tree at the failure and the device's logs, in a viewer you can scrub.

Live in a browser

The studio and the React components show a device as live video you can drive. The delay is 17 to 34 ms glass to glass at the median, measured on one Mac.

One contract

Every operation is one of 64 procedures, served over REST, RPC and MCP from a single local listener, with a typed client for your own tools.

A device for your agent

31 curated MCP tools let a coding agent start a device, read the screen, tap, type and take a screenshot of the app it is building.

The test framework

Tests you already know how to write

Specs are *.e2e.ts files. Each worker holds one device and drives it with locators that wait and assertions that retry, so a test says what a person does and nothing about timing.

  • Find things by role, text, label, placeholder or test id
  • Every test starts with the app freshly launched
  • A trace is kept when a test fails
  • One suite, an iOS project and an Android project
Writing tests
1import { expect, test } from '@alivelabs/troupe'
2
3test('signs in', async ({ screen }) => {
4  await screen.getByLabel('Email').fill('ada@example.com')
5  await screen.getByLabel('Password').fill('correct horse')
6  await screen.getByRole('button', { name: 'Sign in' }).tap()
7
8  await expect(screen.getByText('Welcome back')).toBeVisible()
9})
1import { defineConfig } from '@alivelabs/troupe'
2
3export default defineConfig({
4  retries: 1,
5  projects: [
6    {
7      name: 'ios',
8      use: {
9        platform: 'ios',
10        deviceType: 'iPhone 18 Pro',
11        app: './build/Shop.app',
12      },
13    },
14    {
15      name: 'android',
16      use: { platform: 'android', app: './build/shop.apk' },
17    },
18  ],
19})
bunx troupe test

Running 3 tests using 1 worker

  ✓  1 [ios] › e2e/sign-in.e2e.ts:3:1 › signs in
  ✓  2 [ios] › e2e/cart.e2e.ts:3:1 › adds an item to the cart
  ✓  3 [ios] › e2e/cart.e2e.ts:12:1 › checks out

  3 passed

Studio and components

A live device in a browser tab

troupe studio opens a device you can watch and drive, with its accessibility tree and logs beside it. The same pieces ship as React components, so the device can live in your own page.

1import { createClient } from '@alivelabs/troupe-client'
2import {
3  DeviceScreen,
4  TroupeProvider,
5} from '@alivelabs/troupe-react'
6import '@alivelabs/troupe-react/styles.css'
7
8const client = createClient({ baseUrl, token })
9const getTicket = (cap = 'drive') =>
10  client.call('streams.ticket', { sessionId, cap })
11
12<TroupeProvider client={client}>
13  <DeviceScreen stream={{ url, ticket }} getTicket={getTicket} />
14</TroupeProvider>
The React components

MCP

Give your coding agent a device

An agent that can see the app it is building stops guessing. troupe mcp serves the runtime as MCP tools: start a device, install the build, read the screen, tap, type, take a screenshot, read the logs.

bunx troupe mcp install --client claude-code --write

Writes the project's MCP entry for Claude Code, Cursor, VS Code or Codex. Nothing leaves your Mac.

Connecting an agent
Agenttroupe · 31 tools
  1. sessions_createiPhone 18 Pro, ios-simulator
  2. apps_installShop.app
  3. apps_launchcom.example.shop
  4. ui_snapshotthe accessibility tree
  5. input_tapbutton "Add to cart"
  6. media_screenshotwhat the screen shows now

Troupe Cloud

The same runtime, hosted

Devices and builds for a team, without a Mac under anyone's desk. The API is the one you already use locally, with accounts, projects and limits around it.

Platforms

iOS, Android and the Mac, from one suite

Troupe runs on a Mac with Apple silicon and brings its own drivers and media engines for each platform.

iOS Simulator

Any simulator your Xcode offers, with live video and touch.

simctl · XCUITest driver · simcap

Android Emulator

Emulators behind Troupe's own adb server, out of the way of yours.

adb wire client · instrumentation driver · scrcpy

Mac Catalyst

Prebuilt Catalyst apps, driven from inside their own process.

Troupe's host, linked into the app

Open source

On GitHub soon

The runtime, the test framework, the client, the React components, the studio and the report are MIT licensed. The repository opens soon; until then the docs describe everything as it will ship.

  • @alivelabs/troupe
  • @alivelabs/troupe-runtime
  • @alivelabs/troupe-protocol
  • @alivelabs/troupe-client
  • @alivelabs/troupe-react
  • @alivelabs/troupe-report
  • @alivelabs/troupe-platform-ios
  • @alivelabs/troupe-platform-android
  • @alivelabs/troupe-platform-catalyst
  • @alivelabs/troupe-adapter-kit
  • @alivelabs/troupe-preset-expo
esc

    Type to search every page, the protocol reference and the cloud API.