Discover and run your tests from a local browser UI or the terminal. Test Studio finds test files and declarations automatically, with built-in support for Bun tests, Maestro flows, Pest tests, and custom adapters.
Quick start · Adapters · Browser UI · Terminal · Configuration · Contributing
From the project you want to test:
npx @kfiros/test-studio
# or
bunx @kfiros/test-studioOpen the printed local URL. Test Studio scans the current directory; pass a path to explore another project:
npx @kfiros/test-studio /path/to/project
npx @kfiros/test-studio /path/to/project --port 4311You need Node.js 22+ with either launcher. Install your project's dependencies and the tools for the tests you want to run: Bun for Bun tests, Maestro for mobile flows, or PHP with Pest in your project for PHP tests. The UI comes compiled in the package, so no frontend setup is needed. Ctrl+C stops the server and active test process.
Prefer a project dependency? Run npm install --save-dev @kfiros/test-studio or bun add --dev @kfiros/test-studio. The installed command is test-studio.
- Browse collapsible folders across a monorepo, filtering by runner, workspace, platform, tags, latest result, or search.
- Run a folder, selected files, or individual statically named Bun and Pest tests.
- Inspect Maestro flow steps and source, and pass a device ID or flow variables.
- Follow live output and per-test results, inspect failed test code, stop a run, or rerun failed files.
- Run the same selections from the terminal with exit codes for scripts and CI.
- Add another test framework through an adapter in your project or an installed package.
Bun and Maestro work out of the box. Adapters let other tools use the same discovery, execution, and results UI.
| Adapter | Discovers | Runs |
|---|---|---|
| Bun | JS/TS test files and static test declarations | Whole files or individual tests |
| Maestro | YAML flows, steps, tags, and platform hints | Complete flows |
| Pest | PHP tests, nested descriptions, and groups | Whole files or static individual tests |
| Your adapter | Any file format you choose | A command that produces normalized results or JUnit |
For a runner that writes JUnit, declare file patterns and a command directly in test-studio.config.json:
{
"adapters": [
"bun",
"maestro",
{
"id": "node-checks",
"label": "Node checks",
"files": ["**/*.check.mjs"],
"executable": "node",
"args": [
"--test",
"--test-reporter=junit",
"--test-reporter-destination={report}",
"{file}"
]
}
]
}That's a complete adapter: Test Studio handles discovery, paths, reports, and process execution. No imports or adapter source file required. You can also export the same object from a local module.
Enable Pest with "adapters": ["pest"], or configure its test paths and PHP working directory with { "use": "pest", "options": { ... } }. Pest discovers nested tests and groups, with individual runs for static names. For projects using Docker Compose, add a docker entry to run inside an existing service and collect the JUnit report. See the Pest and Docker examples.
npx @kfiros/test-studio run --runner node-checks
npx @kfiros/test-studio run --runner pest --file tests/FeatureAdapters can also be installed npm packages. Install them in the project being tested, then add their package names to adapters. Supplying adapters replaces the default list, so include bun and maestro if you still want them.
See Writing adapters for the interface, factory options, TypeScript helpers, and result parsing. Other recognized frameworks, such as Vitest, Jest, and Playwright, are inspectable but need an adapter to run.
- Filter by runner, workspace, platform, tag, or latest result. Press
/to search filenames, test names, or tags. - Expand folders to browse the project. A folder checkbox selects its visible descendants; its play button runs them immediately. Folder actions follow the active filters.
- Open a file to inspect tests, flow steps, or source. Select files or individual Bun/Pest tests, then choose Run selected. Use Run file, Run flow, or a test's play button for an immediate run.
- Watch output and results. Choose Code on a failed test to see its test file with the reported failure line highlighted. When no exact line is reported, Test Studio shows the test declaration or the file source. Stop cancels the active run; Rerun failed retries failed files with their original selections.
Screenshots use a sample project; the test catalog and results come from the running application.
History and the sidebar show recent runs for the current server session. Discovery refreshes every five seconds as files change. Each file runs in a fresh process, one at a time.
For Maestro, open Run settings to choose a device ID and supply NAME=value variables. Start your simulator or device and make sure the target app is ready first. Platform filters narrow the catalog; they do not choose the device.
Add run to execute once without the UI:
# Run all tests with enabled adapters
npx @kfiros/test-studio run
# Run only Bun tests in a package
bunx @kfiros/test-studio run --runner bun --file packages/api
# Select a test by its full name, including its suite name
npx @kfiros/test-studio run --file tests/session.test.ts --test "Session creates a session"
# Run Maestro with a device and flow variables
npx @kfiros/test-studio run --runner maestro --device simulator-id --env APP_ID=com.example.app--no-ui is an alias for run. Add a project path after run to target another directory. --runner and --file can be repeated; all filters combine. --test is a case-sensitive literal substring, and --file takes a file or directory path, not a glob.
Output streams to the terminal and ends with results and a report directory. Exit codes are 0 for passing, 1 for failed tests or setup/selection errors, 130 for Ctrl+C, and 143 for SIGTERM. Empty selections and missing tools fail before execution.
See the CLI reference for complete selection behavior and options.
Start with defaults, or generate a config and ignore file:
npx @kfiros/test-studio initThis creates test-studio.config.json and .teststudioignore, keeping existing files intact. It does not modify package.json.
{
"name": "My project",
"port": 4310,
"adapters": ["bun", "maestro"],
"exclude": ["fixtures/generated/"],
"respectGitignore": true,
"timeoutMs": 1800000
}Every option is optional. Config files also support TypeScript, ESM, and CommonJS. Use --config path/to/config.ts to select one explicitly; the path is relative to the project root. Restart Test Studio after changing config or adapter code.
Add project-specific exclusions to .teststudioignore using Git ignore syntax:
# Generated tests
fixtures/generated/
# Exclude experiments except one smoke test
experiments/*.test.ts
!experiments/smoke.test.tsIgnore rules refresh automatically. Existing .gitignore rules are respected by default. Dependencies, build outputs, symlinks, and nested Git checkouts are skipped.
See configuration, ignore rules, and the JSON schema for the details.
- Discovery reads source without running it. Generated or duplicate test names can require a whole-file run; Maestro steps always run as a complete flow.
- Test Studio uses your project's runner configuration and environment. Start any required services, emulators, or application servers before running tests.
- Run trusted projects: tests, config modules, and adapters execute with your terminal's privileges. The UI server listens only on
127.0.0.1. - Run history lasts for the server session. Reports are stored in the printed temporary directory. Windows process-tree cancellation has not been verified.
The usage reference covers discovery rules, runner configuration, reporting, timeouts, and execution boundaries.
Want to improve the UI, add a framework, or work on the runner? Start with development.md for local setup, the UI workflow, code organization, and checks. Adapter authors can jump straight to Writing adapters.
MIT. Bundled UI dependency licenses are included in dist/web/THIRD_PARTY_NOTICES.txt.

