Step 01
Install and initialize
Install the CLI globally and bootstrap your first hunt in one command.
$ npm install -g prowl-tools
$ prowl initProwl CLI · Open source
Prowl is a CLI-first E2E testing tool. Describe a user flow as a short YAML hunt, then run it against a native macOS app — menu bar extras included — through the Accessibility API, or against a browser through Playwright. Deterministic runs, artifacts in your repo, no cloud, no metered pricing.
One hunt format
A hunt describes what a user does, not how a platform is driven. Point target at a native Mac app or a URL and the same steps run against either.
name: save-note
steps:
- fill:
"Title": "Standup notes"
- click: "Save"
- assert:
visible: "Saved"# .prowl/config.yml
target:
type: macos
app: com.example.Notes# .prowl/config.yml
target:
type: web
url: http://localhost:3000Native apps through the Accessibility API — windows, sheets, and menu bar extras. Select by accessibility id, role, or label.
Browsers through Playwright — Chromium, Firefox, and WebKit — with its full selector engine.
The same portable steps on an emulator, a USB device, or the iOS Simulator.
Portable steps — click, fill, type, press, assert, screenshot, if, repeat — run on every target. Web-only steps such as navigate and mockRoute are rejected up front on a native target with a clear error, not ten minutes into a CI run.
Why Prowl
Prowl exists so you can own your own testing — no vendor ecosystem, no metered pricing, no data leaving your repo.
Hunts are deterministic, bounded by guardrails, and reviewable in a pull request — safe to point at agent-generated work, with structured output an agent can branch on.
Hunts, run history, screenshots, and visual baselines live under .prowl/ in your repository. There is no dashboard to sign into and nothing to host.
The AI-assisted steps — like prowl generate — run on your own provider key, paid directly to the provider. No usage caps and no metered pricing from us.
Built in the open by Genkei Labs. Read the code, run it anywhere, and never get locked into a vendor's ecosystem.
Four steps from install to a hunt running in CI.
Step 01
Install the CLI globally and bootstrap your first hunt in one command.
$ npm install -g prowl-tools
$ prowl initStep 02
Login, onboarding, checkout, a menu bar action — human-readable steps that run against a Mac app or a browser.
name: checkout-flow
steps:
- navigate: "/cart"
- click: "Checkout"Step 03
Run hunts from the terminal, then wire the same command into your pull request pipeline.
$ prowl run checkout-flow --json --traceStep 04
Screenshots, logs, and traces land in your repo on every failure, so you fix the bug instead of reproducing it.
PASS checkout-flow (1.2s) 2/2 steps
Artifacts: .prowl/runs/2026-08-29_10-30-45name: login-flowsteps: - navigate: "/login" - fill: "Email": "{{TEST_EMAIL}}" - fill: "Password": "{{TEST_PASSWORD}}" - click: "Sign In" - assert: visible: "Dashboard" ● Running hunt: login-flow ✓ navigate "/login" (120ms) ✓ fill "Email" (85ms) ✓ fill "Password" (62ms) ✓ click "Sign In" (340ms) ✓ assert visible "Dashboard" (15ms) PASS login-flow (622ms) 5/5 stepsAI agents can analyze a page or an app, generate hunts, and execute tests through the CLI or a native MCP server — deterministic results, structured output, no UI reasoning required. Generation runs on your own provider key.
login.yml
name: login
steps:
- navigate: "/login"
- fill: "Email" "{{TEST_EMAIL}}"
- fill: "Password" "{{TEST_PASSWORD}}"
- click: "Sign in"
- assert: visible "Dashboard"terminal output
$ prowl analyze https://app.com/login --json
| prowl generate --intent "test login" --stdout
$ prowl run login --json
PASS login (622ms) 5/5 steps
exitCode: 0Run prowl mcp to expose Prowl to any MCP-capable agent — Claude Desktop, Cursor, OpenClaw — as a small set of named tools. The agent triggers runs and reads structured results; it never needs shell access to your repo.
mcp client config
{
"mcpServers": {
"prowl": {
"command": "prowl",
"args": ["mcp"]
}
}
}exposed tools
prowl analyze <url> --json (or --app <bundle id>) extracts interactive elements with ranked selectors. Agents get a structured map of a page or an app without driving it.
prowl generate turns an analysis and a natural-language intent into a valid, runnable YAML hunt — using the model and key you choose.
Every run returns machine-readable JSON with pass/fail, step timings, and artifact paths. Exit codes let agents branch without parsing.
Import prowl-tools as a Node module. Run hunts programmatically and get typed results — no shell exec needed.
Write tests in readable YAML — no JavaScript, no Swift. Step types cover navigation, forms, assertions, conditionals, mocking, and more.
Accessibility ids, roles, and labels on macOS; the full Playwright selector engine on the web. prowl analyze dumps ranked candidates for either.
Forbidden selectors, allowed domains and apps, and max step limits prevent tests from going off the rails.
Every run saves screenshots, logs, and — on the web — network data and Playwright traces, under .prowl/runs in your repo.
Compare screenshots against baselines to catch unintended visual changes. Pixel-level diff images show exactly what shifted.
On the web target, intercept API requests and return custom responses. Test error, loading, and empty states without touching your backend.
Handle cookie banners, optional modals, and dynamic UI with if/repeat steps. Real-world flows need real-world control flow.
JSON output, JUnit XML reports, structured exit codes, and a native MCP server. Plugs into any CI pipeline or AI agent workflow.
How it compares
Mobile-first and web-only tools each cover part of a Mac developer's app; Prowl covers the native app and the web app with one test format.
| Capability | Prowl | Maestro | Playwright | XCUITest |
|---|---|---|---|---|
| Native macOS apps | Yes — Accessibility API, menu bar extras included | No | Electron apps only (experimental) | Yes — apps built with Xcode |
| Web apps | Yes — Playwright (Chromium, Firefox, WebKit) | Yes | Yes — Chromium, Firefox, WebKit | No |
| Native mobile apps | Android & iOS Simulator — experimental | Yes — iOS and Android | No | iOS |
| Tests are written in | YAML | YAML | JavaScript / TypeScript, Python, Java, .NET | Swift / Objective-C |
| Runs from | One CLI — any terminal or CI | CLI (requires Java) | Test runner / CLI | Xcode / xcodebuild |
Based on each project's public documentation as of August 2026. Maestro, Playwright, and XCUITest are trademarks of their respective owners; Prowl is not affiliated with or endorsed by them.
Four commands to a green web hunt. Testing a Mac app takes one more step today — see below.
Install the CLI
npm install -g prowl-tools
Or with Homebrew:
brew tap prowl-tools/tap && brew install prowl
Install a browser for the web target
npx playwright install chromium
Initialize your project
prowl init
Run the starter hunt
prowl run hello
Testing a native Mac app?
The macOS target ships in the CLI, but its Accessibility helper, prowl-macdriver, is not bundled in the npm package yet — you build it once from the source checkout with the Swift toolchain, then set target.type: macos and grant Accessibility permission to your terminal. A prebuilt, signed helper is the next release milestone.
What people ask before pointing Prowl at their app.
Indie and small-team Mac developers who need end-to-end tests for a desktop app, and web developers who want the same YAML-driven coverage for a browser app — without writing test code in Swift or JavaScript.
Yes. Set target.type to macos and target.app to a bundle id or .app path, and Prowl drives the app through Apple's Accessibility API — windows, sheets, and menu bar extras included, with statusItem and menu= selectors for status menus. The target is labelled experimental: its helper binary is built from source today, and a prebuilt, signed helper is the next milestone.
No. You write hunts in YAML. On the web target Prowl runs Playwright under the hood; on macOS it talks to the Accessibility API. Portable steps run on both, and web-only steps are rejected up front on native targets with a clear error.
Experimental. Prowl 0.1.5 added Android (emulator and USB device) and iOS Simulator targets that run the same portable steps. They are usable today but the selector dialect and step coverage may still change, and real iOS devices are out of scope for now.
Yes. prowl ci runs a suite with deterministic exit codes, JSON and JUnit XML output, and artifacts for the pipeline. Web hunts run on any hosted runner; macOS-app hunts need a runner that has been granted Accessibility permission, which in practice means a self-hosted or MDM-managed Mac.
Yes, two ways. Agents can drive the structured CLI directly — prowl analyze extracts page structure as JSON, prowl generate turns that into a runnable hunt from a natural language intent, and prowl run --json returns structured results with exit codes. Or run prowl mcp to expose Prowl as a native MCP server, so any MCP-capable agent calls it as named tools. You can also import Prowl as a Node library.
Yes. Run prowl mcp to start an MCP server (stdio) that exposes Prowl to any MCP-capable agent — Claude Desktop, Cursor, OpenClaw — as a fixed set of named tools: list_hunts, run_hunt, run_suite, and list_projects. The agent triggers runs and reads structured results without shell access, and your guardrails (allowedDomains, forbiddenSelectors, maxSteps) apply to every run. run_suite also auto-logs failures as deduplicated bug tickets in your backlog, and a project registry lets one server drive multiple repos.
Manual checks miss regressions in large apps. Prowl gives repeatable coverage of critical user journeys on every release.
Visual regression compares screenshots against saved baselines to detect unintended visual changes. Prowl's assertScreenshot step does pixel-level comparison with a configurable threshold. On first run it saves the baseline automatically. Run prowl update-baselines to accept new screenshots as baselines.
Yes. Run prowl analyze <url> --json (or --app <bundle id> for a Mac app) to extract elements and ranked selectors, then pipe the output to prowl generate --intent 'describe the test' to produce a valid hunt file. Generation uses the model and provider key you configure — your key, paid to your provider — and the YAML is validated against Prowl's schema before output.
Yes, on the web target. The mockRoute step intercepts requests matching a URL pattern and returns a custom response — inline JSON or from a file. Use unmockRoute to remove the mock. This lets you test error, loading, and empty states without backend changes.
Start catching regressions today
Deterministic hunts, artifacts in your repo, your own keys — end-to-end coverage without a vendor in the loop.
