This is the long-form, follow-top-to-bottom guide to the nativeapptemplate-agent
Claude Code plugin: what it is, how to install it, and how to use both of its
skills end-to-end — generating a validated three-platform app and then walking the
running app on a simulator/emulator.
If you just want the short reference card (manifest layout, MCP pins, one-line
install), see plugin/README.md. This document is the
tutorial; that one is the cheat sheet. For the agent's overall design, see
README.md and docs/SPEC.md.
- What the plugin is
- The two skills at a glance
- Prerequisites
- Installing the plugin
- Verifying the install
- Skill 1 —
generate-app, end to end - Skill 2 —
walk-app, end to end - A full session: generate, then walk
- Flags and environment variables — full reference
- Troubleshooting & FAQ
- See also
The plugin drives the
nativeapptemplate-agent
generator from inside Claude Code. You describe an app in one sentence; the
plugin generates a validated three-platform implementation — Rails 8.1 API +
SwiftUI iOS + Jetpack Compose Android — then reads the validation report back to
you in plain language. A second skill puts the generated app on a device and lets
you walk its UI conversationally.
It is one of three ways the same generator ships (the others are the standalone
npx nativeapptemplate-agent CLI and a raw MCP server for non-Claude-Code
assistants). The plugin is the most integrated surface: skills + bundled MCP
servers, no separate terminal.
What's inside the plugin/ directory:
plugin/
├── .claude-plugin/plugin.json # manifest (name, version, author)
├── .mcp.json # bundles the generator MCP server + mobile-mcp
├── skills/
│ ├── generate-app/SKILL.md # generate → validate → explain
│ └── walk-app/SKILL.md # launch on a device, walk the UI with mobile-mcp
└── README.md # the concise reference card
The SKILL.md files are the machine-facing source of truth — the exact
instructions Claude follows. This guide is the human-facing narration of the same
flow; if the two ever drift, the SKILL.md files win.
| Skill | Invoke | What it does |
|---|---|---|
| generate-app | /nativeapptemplate-agent:generate-app <spec> |
Runs the generator on your spec, parses out/<slug>/report.json, and summarizes per-platform / per-layer results, the domain mapping, and any failures with specific evidence and the next move. |
| walk-app | /nativeapptemplate-agent:walk-app <slug> ios|android |
Launches a generated app on a booted simulator/emulator and drives mobile-mcp to capture the home screen and walk the UI conversationally, surfacing screenshots inline. |
They compose: generate an app, then walk what you generated. generate-app is a
self-contained ~3–5 minute run; walk-app is interactive and depends on a live
device — it's the flakiest link in the chain, so §7
is deliberately explicit about its prerequisites.
The plugin also bundles two MCP servers (visible via /mcp): the generator
server (nativeapptemplate-agent) and mobile-mcp for device automation.
- Node.js 22+ — the generator and both MCP servers run on Node. Check with
node -v. - An Anthropic API key with access to
claude-opus-5-5, exported asANTHROPIC_API_KEY(or the dedicatedNATIVEAPPTEMPLATE_AGENT_ANTHROPIC_KEY— see §9):Generation makes real API calls and costs real tokens. Set a spend cap on your workspace as a backstop.export ANTHROPIC_API_KEY="sk-ant-..."
- Local checkouts of the three substrate repos, referenced via environment
variables. The plugin reads these from your environment and never changes them:
All three variables are required (there is no default). The values above point at the public free (MIT) edition repos —
export NATIVEAPPTEMPLATE_API="/path/to/nativeapptemplateapi" export NATIVEAPPTEMPLATE_IOS="/path/to/NativeAppTemplate-Free-iOS" export NATIVEAPPTEMPLATE_ANDROID="/path/to/NativeAppTemplate-Free-Android"
nativeapptemplateapi,NativeAppTemplate-Free-iOS,NativeAppTemplate-Free-Android— for an OSS-reproducible run. Either works — the same pipeline handles both. A starter.env.examplelists every variable in one place.
Tip — where to set these. Claude Code inherits the environment of the shell it was launched from, so export the vars (or load a
.env/direnv) before startingclaude. If you change them mid-session, restart Claude Code so the MCP servers pick up the new values.
walk-app — and any visual (--visual=1 / 2) generate run — puts a real
app on a real device, so it needs the mobile toolchains booted and ready:
- iOS: Xcode 26.3+ with an iPhone 17 Pro simulator on iOS 26.2+, booted.
mobile-mcp's iOS-simulator driver also needs WebDriverAgent listening on
:8100— start it before walking (awda-up-style helper is the convenient way; see §7). - Android: Android SDK with an API 26+ emulator, running. Boot it from
Android Studio's Device Manager (Android Studio owns
adbon a typical dev machine; starting the emulator from the CLI can leaveadbunable to see it). No WebDriverAgent needed — mobile-mcp drives the emulator overadb. - Rails (only if you want live data past the welcome screen): the generated Rails app must be running and the mobile app must be pointed at it. See §7.4.
You do not need any of the mobile toolchains for a plain generate-app run —
the default fast path type-checks/boots rather than doing full device builds.
There are two ways to install the plugin itself, plus a note on using the generator without the plugin.
The repo ships a marketplace manifest
(.claude-plugin/marketplace.json) that
points at the plugin/ directory. Add the marketplace, then install:
/plugin marketplace add nativeapptemplate/nativeapptemplate-agent
/plugin install nativeapptemplate-agent@nativeapptemplate
nativeapptemplateis the marketplace name.nativeapptemplate-agentis the plugin name.
The CLI equivalents (outside an interactive session) are:
claude plugin marketplace add nativeapptemplate/nativeapptemplate-agent
claude plugin install nativeapptemplate-agent@nativeapptemplateFrom the agent repo root, launch Claude Code with the plugin directory loaded — no marketplace needed:
claude --plugin-dir ./pluginThis is the fastest path if you have the repo checked out and want to try or
modify the plugin. After editing any plugin file, run /reload-plugins to
pick up the change without restarting.
If you're not in Claude Code, the same generator is available as a standalone MCP server you can wire into any MCP-capable assistant (Cursor, Cline, Goose, …):
npx -y -p nativeapptemplate-agent@latest nativeapptemplate-agent-mcpIt exposes a single generate_app tool. (The -p matters — the MCP entry point
is a bin of the nativeapptemplate-agent package, not its own package, so
npx -y nativeapptemplate-agent-mcp will 404.) walk-app is Claude-Code-only.
Two quick checks confirm both halves loaded:
- Skills —
/help. You should seenativeapptemplate-agent:generate-appandnativeapptemplate-agent:walk-applisted. - MCP servers —
/mcp. You should see two servers connected:nativeapptemplate-agent— the generator, wired asnpx -y -p nativeapptemplate-agent@latest nativeapptemplate-agent-mcp.mobile-mcp— wired asnpx -y @mobilenext/mobile-mcp@0.0.54.
Two pins in plugin/.mcp.json are load-bearing — if a run
fails at startup, check these first:
nativeapptemplate-agent@latest— the@latestforces registry resolution. Without a version spec, when the MCP server is spawned withcwd= the agent's own repo root,npx -presolves the local package instead of the published one and fails withcommand not found.@latestsidesteps that cwd shadowing.@mobilenext/mobile-mcp@0.0.54— pinned on purpose.0.0.55+closes the stdio connection on startup (Connection closed~6s in), so@latestfails. This matches the agent's own pin insrc/mobile.ts. If you have a globalmobile-mcpconfig on@latest, it'll show ✘ failed in/mcp— this bundled, pinned copy is the working one (its command differs, so it won't dedup against your global).
/nativeapptemplate-agent:generate-app a walk-in queue for a barbershop
The spec is a plain one-sentence description. Specs that work well:
a walk-in queue for a barbershopa restaurant waitlist for casual dininga personal task tracker with due dates
The generator is scoped to the queue / booking / simple-CRUD SaaS family. If you ask for something far outside that (a multiplayer game, a video app), the skill will say so and offer the closest in-scope shape rather than generating something that fails validation.
If you invoke the skill with no spec, it will ask you for a one-sentence description before doing anything.
You can pass these inline; they're forwarded straight to the generator:
| Override | Example | Effect |
|---|---|---|
| Project name | --project-name="Vet Clinic" |
Fixes the display name and the output slug, independent of the domain rename. You can also say it in plain language — "…for household pest detection. project name is Sentova." — and the skill maps it to the same argument. |
| Rename override | --rename Shopkeeper=Vet (repeatable) |
Overrides one of the planner's chosen renames. From must be a substrate token (Shop, Shopkeeper, ItemTag). Only renames the planner already planned are overridable; an override that matches nothing is reported and dropped, and so is one into a reserved name (e.g. Owner, Account, Subscription, Plan, Product, Store, Sentry, Event, Task; full list in the README's "Reserved rename targets"). |
| Domain | --domain=vetclinic.app |
The app's web domain: replaces the template's nativeapptemplate.com (subdomains and emails included) and, reversed, sets the iOS bundle ID (app.vetclinic.VetClinic.ios) and Android applicationId / package (app.vetclinic.vetclinic). Say it in plain language too — "domain is vetclinic.app". Default: <project name>.com. An invalid domain (one label, a URL, a label starting with a digit) stops the run with the reason. |
| Visual level | --visual=2 (0, 1 or 2) |
How much of the UI to validate for this run, overriding NATIVEAPPTEMPLATE_VISUAL without restarting Claude Code. 1 judges the home screens on the booted simulator + emulator; 2 adds the scripted sign-up / sign-in walk (~7–8 min instead of 2–3; needs both devices booted and mise). Say it in plain language too — "visual 2", "check the UI too", "画面も確認して". The skill states time and prerequisites first; the run stops before generating anything (no API call) if a device or mise is missing. |
| Test suites | --tests |
Also run the generated apps' own test suites (bin/rails test, xcodebuild test, ./gradlew testDebugUnitTest) for this run, overriding NATIVEAPPTEMPLATE_TESTS; adds minutes per platform. Plain language: "run the tests", "テストも回して". |
| Japanese name | --rename-ja Shop=動物病院 (repeatable) |
Sets the Japanese noun that replaces the substrate's 店舗 (Shop) or アイテムタグ (ItemTag) in the Rails API's Japanese messages and tests. Overrides the planner's pick; an override for an unplanned rename is reported and dropped. |
Example with both:
/nativeapptemplate-agent:generate-app a walk-in clinic queue --project-name="Vet Clinic" --rename Shopkeeper=Vet
Before it starts, the skill sets expectations: the run makes real Anthropic API
calls and takes ~3–5 minutes (longer with visual validation), output lands in
./out/<slug>/{rails,ios,android}/ in the current directory (each an independent
git-initialized project), and substrate selection comes from your environment.
Under the hood the generator parses the spec into a domain, copies the substrate, renames the skeleton coherently across all three platforms, adapts or replaces the domain module, drives the build, and validates. On completion it prints a line like:
report: file://…/out/<slug>/validation-report.html
Note the <slug> — report.json sits next to that HTML at out/<slug>/report.json.
The skill reads out/<slug>/report.json and narrates it. Its shape:
The validation layers:
- Layer 1 — structural. Leftover domain tokens (ripgrep) + OpenAPI contract parity across Rails ↔ iOS ↔ Android.
- Layer 2 — runtime. Rails boots / iOS builds / Android builds.
mode: "build"means a full build was run (visual mode);mode: "fast"is the default type-check/boot path. - Layer 3 — semantic. Opus 5.5 vision judge scoring the rendered UI against a
rubric. Present only when
visualLevel > 0.
The skill leads with the headline (verdict — PASS / PARTIAL / FAIL — + summary + total time), then a
compact per-platform ✅/❌ table, then the domain mapping the planner chose
(Shop → Clinic, Shopkeeper → Vet, …) and the entities, and finishes with the
path to validation-report.html (and offers to open it on macOS).
The skill pulls the exact evidence and proposes a next move rather than just saying "it failed":
- Layer 1 fail → lists
layer1.findings(leftover substrate tokens). Usually a rename the planner missed; the fix is a targeted re-run with--rename From=To. - Layer 2 fail → shows
layer2.stderrTailfor the failing platform. Jetpack Compose compile + Hilt DI are the known-cryptic ones. Offer of opting into the self-repair loop by re-running withNATIVEAPPTEMPLATE_REPAIR=on. - Reviewer parity fail → lists
reviewer.diffs(Rails ↔ iOS ↔ Android contract drift). - For semantic depth, it offers a re-run with
--visual=1(build + home-screen judge) or--visual=2(full mobile-mcp walk-through).
The generated projects are real, git-initialized, and buildable. Natural
follow-ups: open the report, tweak generated code, commit a project, re-run with
overrides — or see the app running, which hands off to walk-app.
Subscriptions (paid templates). Apps generated from the paid iOS/Android
templates carry the templates' optional RevenueCat subscriptions, off until
you set your own app's RevenueCat key (iOS REVENUECAT_API_KEY in
RevenueCat.xcconfig; Android the Gradle property
<PRODUCT>_REVENUECAT_GOOGLE_API_KEY). The agent never copies the template
developer's key (RevenueCat.local.xcconfig is left out; the env bridge mirrors
only the API settings). The iOS project pulls purchases-ios through Swift
Package Manager, so its first build needs network access.
Error monitoring (paid templates, Rails API). Generated apps carry the
optional Sentry error monitoring, off until you set your own DSN (iOS
SENTRY_DSN in Sentry.xcconfig, included by Project.xcconfig; Android the
Gradle property <PRODUCT>_SENTRY_DSN; Rails SENTRY_DSN, from the Kamal
secret <SERVICE>_SENTRY_DSN in production). The agent never copies the
developer's Sentry.local.xcconfig, .sentryclirc or sentry.properties, and
the dSYM / R8 mapping uploads do nothing without your own Sentry org and project.
The iOS project also pulls sentry-cocoa through Swift Package Manager.
walk-app is the interactive companion to generate-app: it puts a generated app
on screen and lets you explore it — capture the current screen, list its
elements, tap through a flow, screenshots inline. It depends on mobile-mcp
(bundled) plus a real booted device and an installed build. Those parts are
environment-dependent and the flakiest link, so the skill is explicit about what's
required.
/nativeapptemplate-agent:walk-app barbershop-queue ios
- Project (slug): the first argument, e.g.
barbershop-queue. If omitted, the skill uses the most recently modified directory under./out/. It confirmsout/<slug>/exists. - Platform:
iosorandroid. If unspecified, the skill asks — the two need different devices and only one can be driven at a time.
mobile-mcp drives an app that is already installed and running on a booted device. Two routes:
Recommended — let the generator build + install it. A
--visual=1 (home-screen build) or --visual=2 (full scripted walk)
generate run does the full build → install → launch on both platforms and is the
tested path. After it finishes, the app is installed and launched on the booted
device, and you can pick up walk-app for interactive exploration:
/nativeapptemplate-agent:generate-app a walk-in queue for a barbershop --visual=1
/nativeapptemplate-agent:walk-app barbershop-queue ios
Manual — build it yourself from out/<slug>/:
- iOS: the scheme is the project's PascalCase name (run
xcodebuild -listinout/<slug>/ios/to confirm). Build for the iPhone 17 Pro simulator, then install/launch on the booted sim:xcodebuild -scheme <Pascal> -destination 'platform=iOS Simulator,name=iPhone 17 Pro,OS=26.2' build
- Android: from
out/<slug>/android/:./gradlew assembleDebug && ./gradlew installDebug
- iOS: ensure a simulator is booted:
mobile-mcp's iOS-sim driver also needs WebDriverAgent running on
xcrun simctl list devices | grep Booted # boot iPhone 17 Pro + `open -a Simulator` if none
:8100— start it first (awda-up-style helper is the convenient way on a dev machine). - Android: ensure an emulator is running, booted from Android Studio's
Device Manager (not the CLI
emulator -avd, which can leaveadbblind to it). Confirm withadb devices.
If you only want to see the welcome/sign-up screens, the steps above are enough. To get past the welcome screen into real data, two things must both be true — Rails must be running and the app must be pointed at it.
Rails up. From out/<slug>/rails/ (after bundle install +
bin/rails db:prepare + bin/rails db:seed_fu):
mise exec -- bin/devIt binds to the HOST in out/<slug>/rails/.env (a LAN/Wi-Fi IP, not
localhost). The seeded login for these specs is
barber1@example.com / password (renamed per spec).
App → that Rails. This is where the platforms differ:
-
Android bakes the API host in at build time (
<PRODUCT>_API_*gradle properties), so a normal launch reaches it. Nothing extra to do. -
iOS does not. The DEBUG build reads its host from the process environment at launch and otherwise falls back to the nonexistent
https://api.<product>.com. A plainmobile-mcplaunch will render screens but every network call silently fails. To reach a local Rails on iOS, relaunch the app viasimctlwith theSIMCTL_CHILD_passthrough (the same env-bridge the generator's visual mode uses — seesrc/env-bridge.ts):xcrun simctl terminate booted <bundleId> SIMCTL_CHILD_<PRODUCT>_API_SCHEME=http \ SIMCTL_CHILD_<PRODUCT>_API_DOMAIN=<HOST from out/<slug>/rails/.env> \ SIMCTL_CHILD_<PRODUCT>_API_PORT=<PORT from out/<slug>/rails/.env> \ xcrun simctl launch booted <bundleId>
<PRODUCT>is the PascalCase project name upper-cased (e.g.BARBERSHOPQUEUE);SCHEMEishttpfor LAN dev. mobile-mcp still drives the app via WDA regardless of how it was launched, so do this relaunch before you tap into data-backed screens.
The skill uses mobile-mcp to list available devices, select the booted simulator/emulator, list installed apps, and launch the generated one (matching on the display / PascalCase name — launching by name avoids hunting for the bundle id / package name). Then it:
- Takes a screenshot of the current screen and surfaces it inline.
- Lists on-screen elements (mobile-mcp prefers the accessibility tree — more reliable than coordinate taps) so you can both see what's actionable.
- Describes the screen in domain terms (the renamed entities — "Barbershop list", "Add Ticket" — not substrate tokens).
Then it offers to walk a short flow. The sensible default mirrors the validated scenario: Welcome → Sign Up → Sign In → drill into the seeded sample, taking a fresh screenshot after each meaningful step and confirming before any destructive action.
This is exploratory, not a fixed script. After the home-screen capture, you drive: "tap Sign Up", "go back", "what's on this screen?" — the skill runs mobile-mcp per request and returns a screenshot each time. That conversational loop is the whole reason the skill exists.
A complete session, including a custom project name passed in plain language:
/nativeapptemplate-agent:generate-app a two-device home monitor for household pest detection. project name is Sentova.
/nativeapptemplate-agent:walk-app sentova ios
/nativeapptemplate-agent:walk-app sentova android
The project name is Sentova clause sets the display name and output slug
(out/sentova/, Sentova.xcodeproj, Sentova API) independently of the domain
rename the planner chooses. That spec is an adapt of the queue toggle — it
keeps ItemTag and renames it (one run produced Shop → Household,
Shopkeeper → Resident, ItemTag → Sighting, states Idled → Active /
Completed → Resolved); the planner's exact targets vary run to run, so don't
hard-code them.
The barbershop walk-in-queue spec is the canonical demo:
/nativeapptemplate-agent:generate-app a walk-in queue for a barbershop
/nativeapptemplate-agent:walk-app barbershop-queue ios
| Flag | Default | Effect |
|---|---|---|
--project-name="Vet Clinic" |
planner's pick | Names the project. Accepts a human name ("Vet Clinic"), PascalCase (VetClinic), or kebab (vet-clinic); derives the Pascal project name, slug/output dir (out/vet-clinic/), DB prefix + env-bridge token, and display name. Invalid (no derivable slug) is reported and skipped. |
--rename From=To |
planner's pick | Overrides one planner rename target (repeatable). From is a substrate token (Shop, Shopkeeper, ItemTag). An override matching no planned rename is reported and skipped, and so is one into a reserved name (README "Reserved rename targets"). |
--rename-ja From=名前 |
planner's pick | Override the Japanese name of a planned rename (repeatable). From is Shop or ItemTag; the Rails API's Japanese messages (config/locales/ja.yml) and their tests use it in place of the substrate's 店舗 / アイテムタグ. The planner picks one itself (toJa in the rename plan); without one the Japanese is left as is. Example: --rename-ja Shop=動物病院 |
--domain=orangebaton.app |
<project name>.com |
The app's web domain (MCP domain). Replaces nativeapptemplate.com and, reversed, the com.nativeapptemplate prefix: iOS app.orangebaton.OrangeBaton.ios, Android app.orangebaton.orangebaton (applicationId, namespace, packages, source directories). Hyphens become _ and keywords get a trailing _ in the Android package only. See the README's naming flags. |
--visual=0|1|2 |
NATIVEAPPTEMPLATE_VISUAL, else 0 |
Visual validation level for this run (MCP visual); wins over the variable. Levels 1 and 2 check for a booted iOS simulator and an attached Android emulator/device (and, for 2, mise) before generating, and stop with what's missing (exit 2). An invalid value exits 2. See the README's validation flags. |
--tests / --no-tests |
NATIVEAPPTEMPLATE_TESTS, else off |
Run (or skip) the generated apps' test suites for this run (MCP tests); wins over the variable. Implies full builds. |
--report-format=html|json|both |
both |
Which report artifact(s) to write. The skill always uses both so report.json exists to parse. |
--report-embed=true|false |
true |
Embed screenshots as data: URIs (one portable HTML file) vs. copy to report-assets/. |
--report-open |
— | Open the HTML in your browser when the run finishes (macOS). |
--no-report |
— | Skip writing the report entirely. |
--exit-zero |
— | Always exit 0, even on validation FAIL. The skill uses this so a FAIL doesn't abort before it can read and explain the report. |
| Variable | Purpose |
|---|---|
ANTHROPIC_API_KEY |
Your Anthropic key (needs claude-opus-5-5). The only sensitive secret the agent requires. |
NATIVEAPPTEMPLATE_AGENT_ANTHROPIC_KEY |
Optional dedicated workspace key; preferred over ANTHROPIC_API_KEY when set, so a runaway loop hits the workspace cap instead of your tier limit. |
NATIVEAPPTEMPLATE_API / _IOS / _ANDROID |
Paths to the three substrate repos. Required — there is no default. Point at the free repos for an OSS-reproducible run, or at the paid repos if you have them. |
NATIVEAPPTEMPLATE_VISUAL=1 |
Default visual level when --visual isn't given. Stage-1 visual judging: Layer 2 runs in build mode (full xcodebuild build + ./gradlew assembleDebug), installs on the booted sim/emulator, captures the home screen, and judges it with Opus 5.5 vision. Requires a sim/emulator booted per platform. Adds ~60–180s per platform. |
NATIVEAPPTEMPLATE_VISUAL=2 |
Implies =1 and additionally runs Stage 2: boots the generated Rails app, drives a scripted CRUD walk-through via mobile-mcp (Sign Up → email-confirm → Sign In → drill into seeded sample), then judges the post-walk screenshot. Requires both sims/emulators booted + the substrate's mise toolchain. Adds 2–4 min/platform. |
NATIVEAPPTEMPLATE_REPAIR |
Opts into the bounded self-repair loop. on (or a positive integer N, hard-capped at 5). On a code-repairable failure (Layer 1 leftover tokens or Layer 2 build errors) the agent runs a repair pass scoped to the failing project and re-validates, up to the cap. Layer 3 + reviewer misses are surfaced, not auto-repaired. Off by default. |
NATIVEAPPTEMPLATE_BRIDGE=off |
Skip writing <PRODUCT>_API_* into ~/.gradle/gradle.properties (process.env injection still runs for child-spawn paths). |
NATIVEAPPTEMPLATE_BRIDGE_DRY_RUN=1 |
Log what would be written to ~/.gradle/gradle.properties instead of writing it. |
NATIVEAPPTEMPLATE_ADB_SERIAL |
The adb -s target when more than one Android device/emulator is attached (adb devices lists them). Without it the agent prefers an emulator-* serial, then the first device. |
NATIVEAPPTEMPLATE_MOBILE_IOS_DEVICE / _ANDROID_DEVICE |
Pin the device mobile-mcp drives in Stage 2 (device id or exact name) when several are booted. |
NATIVEAPPTEMPLATE_IOS_DESTINATION |
xcodebuild -destination for build mode. Default platform=iOS Simulator,name=iPhone 17 Pro,OS=26.2; set it if you don't have that simulator. |
NATIVEAPPTEMPLATE_API_SCHEME |
http or https for the generated apps' API URL (HOST/PORT come from the substrate Rails .env). |
The agent strips
ANTHROPIC_API_KEY,ANTHROPIC_AUTH_TOKEN, andNATIVEAPPTEMPLATE_AGENT_ANTHROPIC_KEYfrom the environment of every subprocess it spawns — only the Anthropic SDK in the Node process sees the key.
/mcp shows the generator server failed.
Almost always the @latest pin. Confirm
plugin/.mcp.json wires the generator as
npx -y -p nativeapptemplate-agent@latest nativeapptemplate-agent-mcp. Without
@latest, when the server spawns with cwd = the agent repo root, npx -p
resolves the local package and fails with command not found.
/mcp shows mobile-mcp failed (Connection closed ~6s in).
You're on 0.0.55+. Pin to @mobilenext/mobile-mcp@0.0.54. If you also have a
global mobile-mcp on @latest, it'll show ✘ — that's expected; the bundled
pinned copy is the working one.
The skills don't appear in /help.
If you loaded locally, you launched without the plugin dir — start with
claude --plugin-dir ./plugin, or install from the marketplace (§4).
After editing plugin files, run /reload-plugins.
Generation fails immediately on substrate paths.
NATIVEAPPTEMPLATE_API / _IOS / _ANDROID aren't set or don't point at valid
checkouts. Set them before launching Claude Code (it inherits the launching
shell's env); restart if you changed them mid-session. See .env.example.
walk-app: "no device" / mobile-mcp finds nothing.
The sim/emulator isn't booted, or (Android) Studio isn't running and adb sees
no device. Boot it per §7.3.
walk-app: "app not installed."
The build/install step didn't run or failed. Easiest fix is the recommended
--visual=1 route (§7.2),
which builds + installs + launches for you.
walk-app: app launches but data screens are blank / sign-in fails / lists empty.
Rails isn't running, or the app isn't pointed at it. Start Rails
(§7.4); on iOS,
confirm you relaunched with the SIMCTL_CHILD_<PRODUCT>_API_* passthrough — a
plain mobile-mcp launch hits the nonexistent default host, so every call fails
while screens still render.
walk-app: build fails (iOS/Android).
Surface the compiler output; Jetpack Compose + Hilt are the known-cryptic ones.
Offer a repair re-run of generate-app with NATIVEAPPTEMPLATE_REPAIR=on.
How long does a run take / how much does it cost?
A plain generate-app run is ~3–5 minutes of real Anthropic API calls;
--visual=1 adds device builds, --visual=2 the walk too (~7–8 min in all). API cost
is about $0.02 / $0.13 / $0.22 for visual 0 / 1 / 2; each run's own estimate is in
report.json (cost), the HTML report and the CLI's closing summary, and the
skill quotes it. Set a workspace spend cap as a backstop.
Where does output go?
./out/<slug>/{rails,ios,android}/ in the current working directory, plus
out/<slug>/report.json and out/<slug>/validation-report.html. Each platform
dir is an independent, buildable, git-initialized project.
Can I use the generator outside Claude Code?
Yes — the standalone CLI (npx nativeapptemplate-agent "<spec>") and the MCP
server (§4). walk-app is Claude-Code-only.
plugin/README.md— the concise plugin reference card.plugin/skills/generate-app/SKILL.mdandplugin/skills/walk-app/SKILL.md— the machine-facing skill definitions (source of truth).README.md— the agent overall: CLI, MCP, validation, security.docs/SPEC.md— full technical specification.docs/validation-report.md— the report schema.ROADMAP.md— where the project is headed.
{ "meta": { "spec", "slug", "displayName", "visualLevel" /* 0|1|2 */, "durationMs", … }, "overallPass": true, // nothing failed (drives the exit code) "verdict": "pass"|"partial"|"fail", // "partial" = nothing failed, but Layer 3 didn't judge every mobile UI (e.g. visualLevel 0) "summary": "one-line human summary", "platforms": [ { "platform": "rails"|"ios"|"android", "layer1": { "pass": bool, "findings": [ /* leftover-token findings */ ] }, "layer2": { "pass": bool, "command", "mode": "fast"|"build", "exitCode", "stderrTail"? }, "layer3": { /* present only when visualLevel > 0 — vision-judge scores */ } } ], "reviewer": { "contractParity": "pass"|"fail", "diffs": [ /* OpenAPI mismatches */ ] }, "domain": { "renamePlan": [ { "from": "Shop", "to": "…" }, … ], "entities": [ { "name", "replaces", "fields", "states"? }, … ] }, "repairAttempts": [ /* present only if the self-repair loop ran */ ], "cost": { "estimatedUsd", "calls", "byAgent": { "planner", "judge", "repair"? }, … } // this run's API spend, estimated }