@aarwitz/tapp 0.17.0-rc.8 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "tapp",
3
+ "description": "The official Tapp plugin: the agent skill and MCP tools for testing real iOS, Android, and web app surfaces.",
4
+ "owner": {
5
+ "name": "Aaron Horowitz",
6
+ "url": "https://github.com/aarwitz"
7
+ },
8
+ "plugins": [
9
+ {
10
+ "name": "tapp",
11
+ "source": {
12
+ "source": "npm",
13
+ "package": "@aarwitz/tapp"
14
+ },
15
+ "description": "Give Claude hands and eyes on iOS, Android, and web apps, with exploration, replayable flows, evidence, and deterministic CI gates.",
16
+ "author": {
17
+ "name": "Aaron Horowitz",
18
+ "url": "https://github.com/aarwitz"
19
+ },
20
+ "homepage": "https://runtapp.com/",
21
+ "license": "MIT",
22
+ "keywords": [
23
+ "ios",
24
+ "simulator",
25
+ "testing",
26
+ "qa",
27
+ "xcuitest",
28
+ "mcp",
29
+ "agent-skill",
30
+ "copilot"
31
+ ]
32
+ }
33
+ ]
34
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "tapp",
3
+ "description": "Give Claude hands and eyes on iOS, Android, and web apps, with exploration, replayable flows, evidence, and deterministic CI gates.",
4
+ "version": "0.17.0",
5
+ "author": {
6
+ "name": "Aaron Horowitz",
7
+ "url": "https://github.com/aarwitz"
8
+ },
9
+ "homepage": "https://runtapp.com/",
10
+ "repository": "https://github.com/aarwitz/tapp",
11
+ "license": "MIT",
12
+ "keywords": [
13
+ "ios",
14
+ "simulator",
15
+ "testing",
16
+ "qa",
17
+ "xcuitest",
18
+ "mcp",
19
+ "agent-skill",
20
+ "copilot"
21
+ ],
22
+ "mcpServers": {
23
+ "tapp": {
24
+ "command": "npx",
25
+ "args": [
26
+ "-y",
27
+ "@aarwitz/tapp@0.17.0",
28
+ "mcp"
29
+ ],
30
+ "cwd": "${CLAUDE_PROJECT_DIR}"
31
+ }
32
+ }
33
+ }
package/AGENTS.md CHANGED
@@ -1,26 +1,40 @@
1
1
  # Tapp agent playbook
2
2
 
3
- You (the agent) have Tapp: hands, eyes, and judgment on real app surfaces — iOS simulators,
4
- Android emulators/devices, plus (beta) web apps in a real browser.
3
+ You (the agent) have Tapp: hands and eyes on real app surfaces — iOS simulators, Android
4
+ emulators/devices, plus (beta) web apps in a real browser. Release judgment belongs only to Tapp's
5
+ repository-connected deterministic gate.
5
6
 
6
7
  ## No MCP connected? Just run the CLI
7
8
 
8
- Every core capability works as a plain command — no server, no config. `[target]` is
9
+ The core inspect, explore, replay, and gate capabilities work as plain commands — no Tapp account,
10
+ server, or global install. `[target]` is
9
11
  optional: with nothing, tapp finds + builds the Xcode project in the cwd (or falls back to
10
12
  the app already on the simulator); it also accepts a repo dir, a `path/to/App.app`, a
11
13
  bundle id, or (web) an http(s) URL. You never need to know a bundle id up front.
12
14
 
13
15
  ```bash
14
- npx -y @aarwitz/tapp explore [target] # autonomous exploration → findings + evidence (observation, not a gate; ≈ tapp_explore)
15
- npx -y @aarwitz/tapp open [target] # launch + screen summary + screenshot saved to a file (≈ tapp_open_app)
16
- npx -y @aarwitz/tapp tree [target] # accessibility tree, --json for every element (≈ tapp_ui_tree)
17
- npx -y @aarwitz/tapp shot # screenshot the booted sim file path (≈ tapp_screenshot)
18
- npx -y @aarwitz/tapp apps # what's installed on the simulator, with bundle ids
19
- npx -y @aarwitz/tapp build [dir] # build the app in an Xcode repo + install it (≈ tapp_build)
20
- npx -y @aarwitz/tapp explore app.apk --platform android --app-id com.acme.app
21
- npx -y @aarwitz/tapp flow run .tapp/flows/smoke.yml # committed, keyless E2E replay
16
+ npx -y @aarwitz/tapp@latest explore [target] # autonomous exploration → findings + evidence (observation, not a gate; ≈ tapp_explore)
17
+ npx -y @aarwitz/tapp@latest explore https://your-app.example --watch # web: visibly follow the same exploration
18
+ npx -y @aarwitz/tapp@latest open [target] # launch + screen summary + screenshot saved to a file (≈ tapp_open_app)
19
+ npx -y @aarwitz/tapp@latest tree [target] # accessibility tree, --json for every element (≈ tapp_ui_tree)
20
+ npx -y @aarwitz/tapp@latest shot # screenshot the booted sim file path (≈ tapp_screenshot)
21
+ npx -y @aarwitz/tapp@latest apps # what's installed on the simulator, with bundle ids
22
+ npx -y @aarwitz/tapp@latest build [dir] # build the app in an Xcode repo + install it (≈ tapp_build)
23
+ npx -y @aarwitz/tapp@latest explore app.apk --platform android --app-id com.acme.app
24
+ npx -y @aarwitz/tapp@latest flow run .tapp/flows/smoke.yml # committed, keyless E2E replay
22
25
  ```
23
26
 
27
+ If repository onboarding detects multiple application targets, target detection is deterministic but
28
+ the choice is the user's. Explicit `init --explore` asks even when the model has a saved default; a
29
+ later bare `explore` may consume that default. In a human TTY, Tapp displays a numbered selector and
30
+ continues in the same command. A non-interactive CLI prints the exact choices and exits before
31
+ building. MCP returns
32
+ `reason: "target-selection-required"` with structured `choices[]` (`platform`, `name`, `sourcePath`,
33
+ `selector`, and exact `command`). **Do not pick one yourself.** Present those choices to the user
34
+ with the client's native multiple-choice question UI when available, then rerun using the selected
35
+ `--platform` and `--target`. Plain chat can list the same choices when the client has no question
36
+ widget.
37
+
24
38
  For focused web evidence, `open` and `tree` accept one semantic interaction plus an async content
25
39
  wait: `tapp open https://example.com --tap "Not now" --wait-for "Dashboard"`. Tapp waits for the
26
40
  page to stabilize before capturing it and warns honestly if the bounded wait ends while it is still
@@ -32,7 +46,9 @@ that IS the screen. If you cannot (Cursor, VS Code Copilot), connect the MCP ser
32
46
  instead: its tool results carry the screenshot inline. Screen *recordings* are for the
33
47
  human: on **iOS**, `tapp explore` records the full exploration and embeds it in the report.html
34
48
  evidence page (Android does not currently record video) — tell the user the report path so they can
35
- watch it.
49
+ watch it. On **web**, explicit `--watch` opens the isolated Playwright Chromium window and overlays
50
+ Tapp's current action and pointer; the overlay is omitted from evidence screenshots. It does not
51
+ drive the person's existing/default browser profile.
36
52
 
37
53
  The interactive session/record loop is MCP-only (it needs a long-lived process). Flow replay is
38
54
  also available in the CLI. The rest of this playbook assumes the `tapp_*` MCP tools are connected. With
@@ -43,7 +59,7 @@ installs, returns the bundle id) → `tapp_explore {appBundleId}`.
43
59
 
44
60
  | The user wants… | Use | NOT |
45
61
  |---|---|---|
46
- | "Show me / screenshot a screen" | `tapp_open_app` (launch + screenshot + tree, ~15s) | `tapp_explore` (a full multi-minute QA exploration) |
62
+ | "Show me / screenshot a screen" | `tapp_open_app` (launch + screenshot + tree, ~15s) | `tapp_explore` (a full multi-minute exploration) |
47
63
  | "Tap through / drive / fill a form / log in" | `tapp_session_start` → `session_act` loop | repeated `open_app` calls (cold relaunch each time) |
48
64
  | "Is my app broken? Find bugs" | `tapp_explore` — `appBundleId` for iOS, `androidAppId` for Android, `url` for owned web apps; returns an observation (findings + evidence), not a ship verdict — gate a merge with the CI gate (`tapp ci` CLI / the GitHub Action) + a contract | a manual session (exploration is autonomous) |
49
65
  | "Make this flow a repeatable test" | drive it in a session, then `tapp_flow_save`; replay with `tapp_flow_run` | re-driving it by hand every time |
@@ -53,6 +69,7 @@ installs, returns the bundle id) → `tapp_explore {appBundleId}`.
53
69
 
54
70
  ```
55
71
  tapp_session_start { appBundleId: "com.acme.app" } → fresh launch + initial tree
72
+ tapp_session_act { action: "login", email: "qa@x.com", password: "…" } → atomic fill + submit + verify
56
73
  tapp_session_act { action: "tap", id: "Email" } → tap by a11y id OR visible label
57
74
  tapp_session_act { action: "type", text: "qa@x.com" } → types into the focused field
58
75
  tapp_session_act { action: "tap", id: "Sign In" }
@@ -76,7 +93,8 @@ Rules that prevent 90% of failures:
76
93
  3. **`wait` after anything async** (navigation, network loads): `{action: "wait", id|text, timeoutMs}`.
77
94
  Never assume the next screen is instantly there.
78
95
  4. **Tap the field before typing** — `type` goes to the focused field. Tap email → type email →
79
- tap password → type password.
96
+ tap password → type password. For sign-in, prefer the atomic `login` action: it records a
97
+ secret-templated replay step and avoids native secure-field refocus behavior.
80
98
  5. Tap results: `ok` (landed), `not_hittable` (exists but disabled/covered — the harness
81
99
  auto-dismisses keyboards and retries), `not_found` (nothing matches — re-read the tree).
82
100
  6. One session at a time. `session_start` always begins from a fresh app launch.
@@ -120,6 +138,8 @@ without a coding agent, model, subscription, or API key. AI generation and `asse
120
138
  deterministic assertions, same result every time. A failed assertion is a finding.
121
139
  - **Generate:** `tapp_flow_generate { goal: "log in and add the first item to cart" }` —
122
140
  grounded in the app's actually-explored screens, so it can't invent steps.
141
+ - **Discover the file format without MCP:** `npx -y @aarwitz/tapp@latest flow example` prints a
142
+ complete starter Flow; `tapp flow validate <file>` checks it without launching a target.
123
143
 
124
144
  ## Setup facts (tell the user when relevant)
125
145
 
@@ -765,6 +765,12 @@ class ExplorerTests: XCTestCase {
765
765
  case "type":
766
766
  status = sessionType(value, id: target.isEmpty ? nil : target) ? "pass" : "fail"
767
767
  if status == "fail" { detail = "no field ‘\(target)’ to type into" }
768
+ case "login":
769
+ let email = subst((step["email"] as? String) ?? "$TEST_EMAIL")
770
+ let password = subst((step["password"] as? String) ?? "$TEST_PASSWORD")
771
+ let result = sessionLogin(email: email, password: password)
772
+ status = result.status == "ok" ? "pass" : "fail"
773
+ if status == "fail" { detail = result.detail.isEmpty ? result.status : result.detail }
768
774
  case "swipe":
769
775
  switch target.lowercased() { case "down": app.swipeDown(); case "left": app.swipeLeft(); case "right": app.swipeRight(); default: app.swipeUp() }
770
776
  case "back":
@@ -1029,6 +1035,11 @@ class ExplorerTests: XCTestCase {
1029
1035
 
1030
1036
  let testEmail = resolve("OCQA_TEST_EMAIL")
1031
1037
  let testPassword = resolve("OCQA_TEST_PASSWORD")
1038
+ if resolve("OCQA_CREDENTIALS_EXPLICIT") == "1" {
1039
+ // Presence only: never print, persist, or expose credential values. Report rebuilding
1040
+ // needs this durable marker to distinguish "not supplied" from "supplied but unused".
1041
+ print("OCQA_STATE:credentials_supplied")
1042
+ }
1032
1043
 
1033
1044
  // --- Explicit login replay (config-driven): a recorded type/tap/wait sequence for custom
1034
1045
  // login UIs the heuristic preamble below can't parse. When configured it takes precedence. ---
package/README.md CHANGED
@@ -1,35 +1,76 @@
1
- # tapp — ship with proof
1
+ # Tapp
2
2
 
3
3
  [![CI](https://github.com/aarwitz/tapp/actions/workflows/ci.yml/badge.svg)](https://github.com/aarwitz/tapp/actions/workflows/ci.yml)
4
4
  [![npm](https://img.shields.io/npm/v/%40aarwitz%2Ftapp?color=cb3837&label=npm)](https://www.npmjs.com/package/@aarwitz/tapp)
5
5
  [![npm downloads](https://img.shields.io/npm/dw/%40aarwitz%2Ftapp?label=downloads)](https://www.npmjs.com/package/@aarwitz/tapp)
6
6
  [![license](https://img.shields.io/badge/license-MIT-blue)](./LICENSE)
7
- [![Install in Cursor](https://img.shields.io/badge/Cursor-Install_MCP-000000)](cursor://anysphere.cursor-deeplink/mcp/install?name=tapp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBhYXJ3aXR6L3RhcHAiLCJtY3AiXX0=)
8
- [![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_MCP-0098FF)](https://insiders.vscode.dev/redirect/mcp/install?name=tapp&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40aarwitz%2Ftapp%22%2C%22mcp%22%5D%7D)
9
-
10
- **Tapp is the release-contract and evidence layer for teams shipping agent-authored applications.**
11
- It turns a repository and real product into an observed UI Map, a compact reviewed deterministic
12
- suite, and an inspectable merge decision.
13
-
14
- Coding agents can write the code, and (with Playwright & friends) they can even drive the app.
15
- What nobody gives them is **proof it works**. tapp explores your app like a user — no test code,
16
- no app changes and surfaces what's broken, with evidence. Then a deterministic gate applies
17
- versioned policy to that evidence the findings and coverage, any selected deterministic suites
18
- (Flows/Scenarios/contracts), and, when available, a target-scoped baseline — and returns a merge
19
- decision your queue can trust: `pass`, `fail`, or `inconclusive`. Exploration **observes**; the gate
20
- **judges** — never a soft "ship-ready" guess.
21
-
22
- Three platforms, one observe-and-gate engine:
23
-
24
- - **iOS** the missing Playwright for iOS. tapp is hands *and* eyes: a generic XCUITest
25
- harness drives any app on the simulator via the accessibility surface. Native — no Appium,
26
- no WebDriverAgent.
27
- - **Android** — black-box native driving through ADB + UIAutomator. Install an APK, target its
28
- application id, and run the same exploration, committed Flows, evidence, and regression gate. The
29
- app does not link a Tapp SDK.
30
- - **Web (beta)** — built *on* Playwright. Your agent already has browser hands; tapp adds the
31
- autonomous exploration, the deterministic detectors (uncaught exceptions, failed requests,
32
- dead buttons, broken links, placeholder `href="#"` links, error pages), and the same gate.
7
+ [![Agent Skill](https://img.shields.io/badge/Agent_Skill-install-6b5cff)](https://skills.sh/aarwitz/tapp)
8
+ [![VS Code extension](https://img.shields.io/badge/VS_Code-extension-0098FF)](https://marketplace.visualstudio.com/items?itemName=lidi-solutions.tapp)
9
+ [![Install in Cursor](https://img.shields.io/badge/Cursor-Install_MCP-000000)](cursor://anysphere.cursor-deeplink/mcp/install?name=tapp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBhYXJ3aXR6L3RhcHBAbGF0ZXN0IiwibWNwIl19)
10
+ [![VS Code MCP](https://img.shields.io/badge/VS_Code-Install_MCP-0098FF)](https://insiders.vscode.dev/redirect/mcp/install?name=tapp&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40aarwitz%2Ftapp%40latest%22%2C%22mcp%22%5D%7D)
11
+
12
+ **Tapp gives coding agents hands and eyes on real iOS, Android, and web apps.** It can inspect and
13
+ drive screens, explore for technical failures, save journeys as deterministic tests, and gate
14
+ reviewed behavior in CI.
15
+
16
+ Exploration reports findings, coverage, evidence, and limits. Only the repository-connected gate
17
+ returns `pass`, `fail`, or `inconclusive`. Tapp does not turn an autonomous crawl into a subjective
18
+ "ship-ready" score.
19
+
20
+ Supported targets:
21
+
22
+ | Target app | Runtime |
23
+ |---|---|
24
+ | iOS | Simulator on macOS with Xcode; driven through XCUITest and accessibility |
25
+ | Android | Connected emulator or device with `adb`; driven through UIAutomator |
26
+ | Web (beta) | Owned browser app in Playwright Chromium |
27
+
28
+ Windows can host Android and web testing when their prerequisites are installed. Windows desktop
29
+ UI applications such as WinForms, WPF, and WinUI are not currently Tapp targets.
30
+
31
+ ## Give Tapp to your coding agent
32
+
33
+ After setup, the whole user prompt is:
34
+
35
+ > Use Tapp to test this app.
36
+
37
+ The official skill teaches the agent to choose the smallest useful operation, handle repositories
38
+ with multiple app targets, inspect visual evidence, and keep exploration observations separate from
39
+ gate decisions.
40
+
41
+ **Claude Code, Codex, Cursor, Copilot, and other Agent Skills clients (recommended):**
42
+
43
+ ```bash
44
+ npx -y skills add aarwitz/tapp --skill tapp
45
+ ```
46
+
47
+ This installs the open Agent Skills workflow into the current project and lets the agent run the npm
48
+ CLI directly; no MCP server, plugin, account, API key, global Tapp install, or pasted prompt block is
49
+ required. Add `-g` for a user-wide install, or `--agent claude-code`, `--agent codex`, and similar
50
+ selectors to constrain the clients. Start or restart the agent from the application repository and
51
+ use the short prompt above.
52
+
53
+ **Claude Code — optional enhanced skill and MCP tools:**
54
+
55
+ ```bash
56
+ claude plugin marketplace add aarwitz/tapp
57
+ claude plugin install tapp@tapp
58
+ ```
59
+
60
+ The plugin bundles the same `tapp` Agent Skill with the matching npm-backed MCP server. Use it when
61
+ you want inline screenshot tool results and a persistent interactive tap/read/type session; it is
62
+ not required for the core skill-to-CLI workflow.
63
+
64
+ **No agent integration:** run the npm package directly from an app repository in one line:
65
+
66
+ ```bash
67
+ npx -y @aarwitz/tapp@latest init . --explore
68
+ ```
69
+
70
+ **VS Code:** install [Tapp from the Marketplace](https://marketplace.visualstudio.com/items?itemName=lidi-solutions.tapp).
71
+ It contributes the same cross-platform Agent Skill to Copilot plus focused iOS simulator tools and
72
+ an auto-refreshing screenshot preview. The preview is not an embedded Simulator or video stream.
73
+ Android and web remain available through the skill's CLI/MCP workflow.
33
74
 
34
75
  ```
35
76
  you: "Add a logout button to the settings screen"
@@ -38,7 +79,7 @@ agent: *tapp: builds, opens the app, navigates to Settings, screenshots it*
38
79
  agent: "Done — and here it is working on the simulator: [screenshot]"
39
80
  ```
40
81
 
41
- ## Quickstart for coding agents
82
+ ## npm CLI quickstart
42
83
 
43
84
  Requirements: **Node ≥ 18**. iOS needs **macOS + Xcode**; Android needs `adb` plus a connected
44
85
  emulator/device; web needs Playwright + Chromium.
@@ -46,14 +87,16 @@ emulator/device; web needs Playwright + Chromium.
46
87
  From the app repository, let the agent see the current screen and then explore it:
47
88
 
48
89
  ```bash
49
- npx -y @aarwitz/tapp open # builds/launches as needed; prints a screenshot path + screen summary
50
- npx -y @aarwitz/tapp explore # explores the real app; prints findings + evidence (an observation, not a gate)
90
+ npx -y @aarwitz/tapp@latest open # builds/launches as needed; prints a screenshot path + screen summary
91
+ npx -y @aarwitz/tapp@latest explore # explores the real app; prints findings + evidence (an observation, not a gate)
51
92
  ```
52
93
 
53
94
  Claude Code can read the saved image with its file-reading tool; Codex can open it with
54
95
  `view_image`. The agent should report what the screenshot proves, relay the exploration findings
55
96
  as-is (an observation, not a merge decision — `tapp ci` gates that), and link the HTML evidence
56
- report. No server, account, config file, test code, API key, or bundle id is required for this loop.
97
+ report. No Tapp server, account, global install, API key, or bundle id is required for this loop.
98
+ The platform runtime still needs to be installed, and repository onboarding can write reviewed
99
+ configuration under `.tapp/`.
57
100
 
58
101
  The product, executable, and package leaf are all Tapp: npm distributes it as
59
102
  `@aarwitz/tapp`, while the installed command remains `tapp`.
@@ -62,24 +105,33 @@ To bootstrap maintained release infrastructure, preview the repository model and
62
105
  before Tapp writes anything:
63
106
 
64
107
  ```bash
65
- npx -y @aarwitz/tapp init . --dry-run --json-out /tmp/tapp-init.json
108
+ npx -y @aarwitz/tapp@latest init . --dry-run --json-out /tmp/tapp-init.json
66
109
  # Build/start the detected web target, ground the first UI Map, then stop it.
67
- npx -y @aarwitz/tapp init . --explore --platform web
110
+ npx -y @aarwitz/tapp@latest init . --explore --platform web
68
111
  # Or build/install the detected Xcode target, ground the map, and persist the validated scheme.
69
- npx -y @aarwitz/tapp init . --explore --platform ios --target .
112
+ npx -y @aarwitz/tapp@latest init . --explore --platform ios --target .
70
113
  # Or connect to an already-running owned URL:
71
- npx -y @aarwitz/tapp init . --explore --platform web --url http://127.0.0.1:4173
114
+ npx -y @aarwitz/tapp@latest init . --explore --platform web --url http://127.0.0.1:4173
72
115
  # If the app has roles/accounts, bind names once; values stay in local/CI secrets.
73
- npx -y @aarwitz/tapp actor set alice . --role member --session isolated \
116
+ npx -y @aarwitz/tapp@latest actor set alice . --role member --session isolated \
74
117
  --credential email=ALICE_EMAIL --credential password=ALICE_PASSWORD
75
118
  # Review-only path: tapp init . → tapp plan show → tapp plan review --approve ...
76
119
 
77
120
  # After approved drafts replay and are promoted, establish the selected target's baseline
78
121
  # through the ordinary full gate, then generate the reviewable GitHub workflow.
79
- npx -y @aarwitz/tapp baseline create . --platform web
80
- npx -y @aarwitz/tapp ci install .
122
+ npx -y @aarwitz/tapp@latest baseline create . --platform web
123
+ npx -y @aarwitz/tapp@latest ci install .
81
124
  ```
82
125
 
126
+ In a repository containing multiple apps (for example, iOS plus web),
127
+ `tapp init . --explore` without an explicit target does not guess from detection order—even when a
128
+ prior choice is recorded. A human terminal gets a numbered
129
+ selector; a non-interactive CLI prints exact target-selection commands, while MCP also returns
130
+ structured choices. Neither builds or writes before the choice. After you choose one, the model
131
+ retains every detected target and records the choice as the default for the next bare `tapp explore`;
132
+ explicit `init --explore` continues to ask because it is the onboarding/refresh operation. Setup gaps
133
+ belonging only to unselected targets are shown as informational, not as failures of the selected run.
134
+
83
135
  The baseline command writes only after exploration and every selected deterministic suite pass
84
136
  conclusively. It stores `.tapp/baselines/<platform>/<target-id>.json`; the generated workflow
85
137
  uses that exact target identity so two apps on the same platform never share a baseline. `ci
@@ -92,42 +144,50 @@ Every verb takes whatever you have: nothing (auto-detects the repo you're in, or
92
144
  already on the simulator), a repo directory, a `path/to/App.app`, or a bundle id:
93
145
 
94
146
  ```bash
95
- npx -y @aarwitz/tapp open [target] # launch the app → screen summary + screenshot file
96
- npx -y @aarwitz/tapp tree [target] # accessibility tree of the current screen
97
- npx -y @aarwitz/tapp shot # screenshot the booted simulator
98
- npx -y @aarwitz/tapp apps # what's installed on the simulator (names + bundle ids)
99
- npx -y @aarwitz/tapp build [dir] # just build + install (scheme auto-detected)
147
+ npx -y @aarwitz/tapp@latest open [target] # launch the app → screen summary + screenshot file
148
+ npx -y @aarwitz/tapp@latest tree [target] # accessibility tree of the current screen
149
+ npx -y @aarwitz/tapp@latest shot # screenshot the booted simulator
150
+ npx -y @aarwitz/tapp@latest apps # what's installed on the simulator (names + bundle ids)
151
+ npx -y @aarwitz/tapp@latest build [dir] # just build + install (scheme auto-detected)
100
152
  ```
101
153
 
102
- Web (beta): `npx -y @aarwitz/tapp explore http://localhost:3000` *(one-time setup:
103
- `npm i -g playwright && npx playwright install chromium`)*
154
+ Web (beta): `npx -y @aarwitz/tapp@latest explore http://localhost:3000` *(one-time setup:
155
+ `npm i -g playwright && npx playwright install chromium`)*. Add `--watch` to open Tapp's controlled,
156
+ isolated Chromium window and follow its clicks with an on-page pointer/action label. Tapp hides that
157
+ watch UI from saved evidence screenshots and does not automate your personal/default browser profile.
104
158
 
105
159
  Focused web inspection waits briefly for loading states to settle. If a consent or location modal
106
160
  blocks the screen, dismiss it and wait for the content you care about in the same package-only call:
107
161
 
108
162
  ```bash
109
- npx -y @aarwitz/tapp open https://example.com --tap "Not now" --wait-for "Dashboard"
110
- npx -y @aarwitz/tapp tree https://example.com --tap "Not now" --wait-for "Dashboard" --json
163
+ npx -y @aarwitz/tapp@latest open https://example.com --tap "Not now" --wait-for "Dashboard"
164
+ npx -y @aarwitz/tapp@latest tree https://example.com --tap "Not now" --wait-for "Dashboard" --json
111
165
  ```
112
166
 
113
167
  Android:
114
168
 
115
169
  ```bash
116
- npx -y @aarwitz/tapp explore path/to/app-debug.apk --platform android --app-id com.acme.app
117
- npx -y @aarwitz/tapp open com.acme.app --platform android
170
+ npx -y @aarwitz/tapp@latest explore path/to/app-debug.apk --platform android --app-id com.acme.app
171
+ npx -y @aarwitz/tapp@latest open com.acme.app --platform android
118
172
  ```
119
173
 
120
- Optional but recommended (prebuilds the test harness so the first run is fast):
174
+ Turn a driven journey into a deterministic test, or print the complete Flow format before writing
175
+ one by hand:
176
+
121
177
  ```bash
122
- npx -y @aarwitz/tapp install # ~2 min, one time
123
- npx -y @aarwitz/tapp doctor # verify Xcode / simulators / toolchain
178
+ npx -y @aarwitz/tapp@latest flow example
179
+ npx -y @aarwitz/tapp@latest flow validate .tapp/flows/smoke.yml
180
+ npx -y @aarwitz/tapp@latest flow run .tapp/flows/smoke.yml
124
181
  ```
125
182
 
126
- ### Optional browser workspace
183
+ Flows support an atomic `login` step using `$TEST_EMAIL` / `$TEST_PASSWORD`; Tapp's session recorder
184
+ creates that step without writing credential values into the repository.
127
185
 
128
- `npx -y @aarwitz/tapp app .` opens a local Release Studio for people who want visual repository
129
- onboarding, release-plan review, and CI preparation. It is not required for the coding-agent
130
- `open`/`explore` workflow.
186
+ Optional but recommended (prebuilds the test harness so the first run is fast):
187
+ ```bash
188
+ npx -y @aarwitz/tapp@latest install # ~2 min, one time
189
+ npx -y @aarwitz/tapp@latest doctor # verify Xcode / simulators / toolchain
190
+ ```
131
191
 
132
192
  ### MCP hookup (optional)
133
193
 
@@ -137,14 +197,14 @@ context** (the model literally sees the screen) and the **interactive session lo
137
197
 
138
198
  **Claude Code:**
139
199
  ```bash
140
- claude mcp add tapp -- npx -y @aarwitz/tapp mcp
200
+ claude mcp add tapp -- npx -y @aarwitz/tapp@latest mcp
141
201
  ```
142
202
 
143
203
  **Cursor / VS Code (Copilot)** — add to `~/.cursor/mcp.json` (Cursor) or `.vscode/mcp.json` (VS Code):
144
204
  ```json
145
205
  {
146
206
  "servers": {
147
- "tapp": { "type": "stdio", "command": "npx", "args": ["-y", "@aarwitz/tapp", "mcp"] }
207
+ "tapp": { "type": "stdio", "command": "npx", "args": ["-y", "@aarwitz/tapp@latest", "mcp"] }
148
208
  }
149
209
  }
150
210
  ```
@@ -153,10 +213,10 @@ claude mcp add tapp -- npx -y @aarwitz/tapp mcp
153
213
  ```toml
154
214
  [mcp_servers.tapp]
155
215
  command = "npx"
156
- args = ["-y", "@aarwitz/tapp", "mcp"]
216
+ args = ["-y", "@aarwitz/tapp@latest", "mcp"]
157
217
  ```
158
218
 
159
- **Any other MCP client:** stdio command `npx -y @aarwitz/tapp mcp`.
219
+ **Any other MCP client:** stdio command `npx -y @aarwitz/tapp@latest mcp`.
160
220
 
161
221
  Then ask your agent:
162
222
  > "Explore my app and show me what breaks."
@@ -185,7 +245,9 @@ Then ask your agent:
185
245
  | 📱 | `tapp_list_simulators` / `boot_simulator` / `install_app` | Simulator + app management. |
186
246
  | 🩺 | `tapp_health`, `tapp_capture*`, `tapp_parse_markers` | Diagnostics and capture history. |
187
247
 
188
- Full agent playbook: [AGENTS.md](./AGENTS.md) ships inside the package so agents can read it too.
248
+ Canonical installable skill: [`skills/tapp/SKILL.md`](skills/tapp/SKILL.md). Full low-level tool
249
+ reference: [AGENTS.md](./AGENTS.md). Both ship inside the npm package; installing the Claude plugin
250
+ or Agent Skill is what makes the workflow discoverable without pasting instructions.
189
251
  Application-model and import contract: [`docs/application-model.md`](docs/application-model.md).
190
252
  The desktop Coverage view reads the same `.tapp/application-model.json`,
191
253
  `.tapp/release-plan.json`, and `.tapp/ui-map.json`, including explicit proposal review; it
@@ -297,7 +359,7 @@ accepts that `.app`, detects its bundle id, writes report artifacts, and exits n
297
359
  gate fails:
298
360
 
299
361
  ```bash
300
- npx -y @aarwitz/tapp ci --app path/to/MyApp.app \
362
+ npx -y @aarwitz/tapp@latest ci --app path/to/MyApp.app \
301
363
  --project-dir . --pr-base origin/main --pr-head HEAD \
302
364
  --target-key target_ios_myapp \
303
365
  --pr-plan-out tapp-pr-plan.json \
@@ -331,12 +393,6 @@ environment. Add
331
393
  [`docs/scenarios.md`](docs/scenarios.md). Automatic
332
394
  baselines are isolated by platform and target, so two same-platform apps are never compared.
333
395
 
334
- **The hosted service is under development and is not currently offered for customer repositories.**
335
- Do not upload private code or credentials to an old preview. The retained
336
- cloud prototype is not the production SaaS boundary. Use the local Release Studio and the portable
337
- GitHub Action in infrastructure you control until the new account, tenant authorization, private
338
- evidence, and isolated-worker boundary passes security review.
339
-
340
396
  ## Make your repo agent-verified
341
397
 
342
398
  Drop this into your repo's `AGENTS.md` (read by Codex, Cursor, Copilot, Devin, Zed, …) so
@@ -345,9 +401,9 @@ your agent proves its UI work instead of claiming it:
345
401
  ```markdown
346
402
  ## Verifying UI changes
347
403
  This repo uses tapp (https://github.com/aarwitz/tapp) to verify UI work on a real app surface
348
- (iOS simulator, Android emulator/device, or a browser for web). After any UI change, run `npx -y @aarwitz/tapp open` from the
404
+ (iOS simulator, Android emulator/device, or a browser for web). After any UI change, run `npx -y @aarwitz/tapp@latest open` from the
349
405
  repo root (it finds and builds the Xcode project itself) and look at the screenshot it saves as
350
- proof. Before declaring a feature done, run `npx -y @aarwitz/tapp explore` (or `explore <url>` for web)
406
+ proof. Before declaring a feature done, run `npx -y @aarwitz/tapp@latest explore` (or `explore <url>` for web)
351
407
  and report the findings + evidence. A change is not "done" until it has been seen working.
352
408
  (If the tapp MCP server is connected, the tapp_* tools do the same with inline screenshots —
353
409
  tapp_build builds + installs the app and returns the bundle id for tapp_explore.)
@@ -379,13 +435,6 @@ only an optional authoring/enrichment layer (`tapp_flow_generate`, `assert_ai`,
379
435
  The first tool call builds the harness once (~2 min, cached in `~/.tapp`; rebuilt automatically
380
436
  if you switch simulators). All captures land in `~/.tapp/captures/`.
381
437
 
382
- ## Desktop status
383
-
384
- The macOS cockpit is frozen as a supported native interface and parity floor; it still reads the
385
- canonical Application Model, release plan, and UI Map in Coverage. Its older import/build path is
386
- not yet a thin client of the shared product-operation layer, so new product work is converging in
387
- the browser without deleting or reducing the desktop experience.
388
-
389
438
  ## License
390
439
 
391
440
  [MIT](./LICENSE)