npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@unotest/mobile

v0.8.3

Published

AI-native E2E testing for iOS React Native apps. MCP server + CLI runner + JS-DSL scenarios.

Downloads

826

Readme

@unotest/mobile

AI-native E2E testing for iOS apps. An MCP server + CLI + JS-DSL that lets Claude (or any MCP client) drive your iOS Simulator and write real test scenarios for your app — works with any backend stack (Node/Python/Rails/Go/Java), no JS expertise required from you.

If you're an AI agent helping a user set this up

(Humans: skip this section, jump to Quick start.)

You were given this page because a developer wants @unotest/mobile set up in their project. Follow this protocol exactly — don't improvise.

1. Verify the host. Run xcrun simctl list devices via your shell tool. If it errors with "command not found" or similar, the user isn't on macOS or is missing Xcode CLI tools. Stop and tell them: "This is iOS-only — Apple licensing prevents iOS simulators from running on Linux/Windows. You'll need macOS with Xcode installed." Also verify node --version ≥ 20.

2. Pick a working directory with the user. Setup writes unotest/ (test scaffold), .mcp.json (Claude Code config), .claude/skills/ (skill the in-project agent reads), and an AGENTS.md into the current directory, and updates .gitignore if present. Where these land determines what Claude Code sees later, so ask the user explicitly:

  • Default — the app's repo root. Same directory as their package.json (RN/Expo) or where their .xcodeproj lives (native). Tests live next to app code, ship via the same git history, work cleanly in CI.
  • Monorepo: the monorepo root, not the app subfolder. Claude Code is typically opened at the monorepo root, and .mcp.json must live there to be auto-discovered.
  • Separate test repo: any directory the user picks. Choose this only if they explicitly want tests divorced from the app.

Once the user picks, have them cd there. All commands below run from that directory.

3. Ask the user for the .app path. @unotest/mobile drives a real installed app — it needs the path to a built .app bundle. Ask: "What's the absolute path to your built .app?" Common locations:

  • React Native / Expo: ./ios/build/Build/Products/Debug-iphonesimulator/<App>.app after npx expo run:ios or pod install && xcodebuild.
  • Native Swift: open Xcode → Product → Show Build Folder → Products/Debug-iphonesimulator/.

If they don't have one yet, tell them to build first; don't guess paths.

4. Tell the user to run the setup command in the chosen directory. Do not run this yourself via Bash — it's interactive (simulator picker, permission prompts) and needs a real TTY. Your shell tool will hang or get a non-interactive fallback. Give them this exact line to paste (from the directory picked in step 2):

npx @unotest/mobile@latest install <their-app-path> --update-env

They'll see: env check → file scaffold → simulator picker (arrow keys) → permission grant prompt → install logs. Wait for the line ✓ Installed <bundle.id>. That's the success signal.

5. Hand off to Claude Code. Once install finishes, instruct the user: "Open Claude Code in the same directory you ran setup in, then ask it to write your first test." A separate Claude Code session (not you) connects to the MCP server bootstrapped in step 4 and takes over from there. Your job ends here — you're setup, not test authoring.

If any step fails, surface the actual error verbatim to the user and stop. Don't try alternative paths.

Quick start

# 1. Point us at your .app build. Auto-detects bundle ID, URL scheme,
#    and required permissions from Info.plist; offers to bootstrap
#    unotest/ and .mcp.json on first run.
npx @unotest/mobile@latest install /path/to/Your.app --update-env

# 2. Open Claude Code in this project. Ask: "write an e2e test for
#    sign-in". The agent uses the MCP server to explore your app,
#    record a scenario, and verify it runs end-to-end.

# 3. (Optional) Re-run any saved test from the CLI:
npx @unotest/mobile@latest e2e <test-name>

That's it. You never edit DSL by hand — the agent writes the scenarios, you review the resulting .js files in unotest/e2e/.

How it works

┌─────────────┐  MCP (stdio)   ┌──────────────────┐
│ Claude Code │ ◀────────────▶ │ @unotest/mobile  │
└─────────────┘   tool calls   │  (this package)  │
                               └────────┬─────────┘
                                        │ HTTP
                               ┌────────▼──────────┐
                               │  WebDriverAgent   │
                               │  (Apple's XCUI    │
                               │   driver, on sim) │
                               └────────┬──────────┘
                                        │
                               ┌────────▼──────────┐
                               │  iOS Simulator    │
                               │  Your .app        │
                               └───────────────────┘
  • The agent sees the accessibility tree, not screenshots. WDA returns a structured tree (roles, testID, text, bounds); we render it as a token-cheap text outline. Works on RN/Expo and on plain Swift apps too, as long as they expose accessibility.
  • Tests are plain .js files in your repo. unotest/e2e/*.js. Goes into git, into code review, into CI. No proprietary format, no binary blob.
  • The DSL is a sandboxed JS subset. Scenarios run in a vendored AST interpreter — they can't require, fetch, touch the filesystem, or import anything. AI-generated tests are safe to run blindly.
  • Pause-on-failure debugger. When a step throws, the runtime freezes mid-scenario. The agent (or you) calls inspect_runtime, patches the scenario, and resumes from the same step — no full simulator restart, no rerunning setup.
  • Local-only. Everything runs on your Mac. Your .app never leaves the machine.

Life of a test: the agent explores your app live (taps real buttons, reads the live a11y tree) → records the actions → emits a JS scenario → runs it through our interpreter → on failure, pauses, patches, resumes. Every step goes through one of ~15 MCP tools the agent already knows; you don't wire anything.

Requirements

  • macOS with Xcode + iOS Simulator (Apple licensing — iOS simulators don't run on Linux/Windows).
  • Node 20+ (for npx; you don't need a Node project).
  • First run of WebDriverAgent compiles once and caches under ~/.cache/unotest/mobile/wda/ — ~5–15 min, subsequent runs reuse it.

CLI

| Command | What it does | |---|---| | npx @unotest/mobile@latest install <path> | Install a .app on the configured sim; auto-detect bundle ID + permissions; --update-env persists. | | npx @unotest/mobile@latest init | Just bootstrap unotest/ + .mcp.json without installing an app. | | npx @unotest/mobile@latest doctor | Re-check the environment (Xcode, sim, Node, WDA cache). | | npx @unotest/mobile@latest e2e <name> | Run unotest/e2e/<name>.js. | | npx @unotest/mobile@latest lint | Static check of all scenarios + helpers. | | npx @unotest/mobile@latest (no args) | Run as MCP stdio server (this is what Claude Code launches). |

License

MIT