Skip to content

Commit 3355734

Browse files
dadachiclaude
andauthored
Ship the Claude Code plugin (generate-app + walk-app) — 3rd distribution surface (#105)
* feat(plugin): Claude Code plugin skeleton — generate-app orchestration skill (#100) First cut of the Claude Code plugin (ROADMAP Post-v0.1 backlog → in progress on epic/claude-code-plugin). Minimal end-to-end: generate → validate → explain. - plugin/.claude-plugin/plugin.json — manifest (name nativeapptemplate-agent). - plugin/skills/generate-app/SKILL.md — orchestration skill: resolve spec, run the CLI (local dist or npx) with --report-format=both --exit-zero, parse out/<slug>/report.json, and summarize per-platform layer1/2(/3) + reviewer parity + domain mapping; on failure surface the specific findings and the next move (--rename, NATIVEAPPTEMPLATE_REPAIR, NATIVEAPPTEMPLATE_VISUAL). The mobile-mcp home-screen walk-through is explicitly deferred to phase 2. - plugin/.mcp.json — bundles the generator MCP server. - plugin/README.md — local install (claude --plugin-dir ./plugin) + usage. Fix a propagated invocation bug: there is no npm package `nativeapptemplate-agent-mcp` (it's a *bin* of `nativeapptemplate-agent`), so `npx -y nativeapptemplate-agent-mcp` 404s. Correct form, verified against the published 0.2.1 with a real MCP initialize handshake from a clean dir: `npx -y -p nativeapptemplate-agent nativeapptemplate-agent-mcp`. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(plugin): phase 2 — walk-app skill (mobile-mcp UI walkthrough) (#102) Second skill on the plugin epic: launch a generated app on a booted iOS sim / Android emulator and walk its UI conversationally via mobile-mcp — capture the home screen, list elements, tap through a flow, screenshots inline. - plugin/skills/walk-app/SKILL.md — resolve out/<slug> + platform; get the app onto a device (recommended: a NATIVEAPPTEMPLATE_VISUAL=1 generate run does the build+install+launch; manual xcodebuild/gradlew path documented); connect mobile-mcp; capture + walk; stay interactive; diagnose the known device-layer failure modes. Honest about the booted-device + installed-build prerequisites (the flakiest link). - plugin/.mcp.json — bundle @mobilenext/mobile-mcp alongside the generator server. - generate-app SKILL.md — hand-off now points at walk-app instead of "not wired". - plugin/README.md — document both skills + both MCP servers. - plugin.json — 0.1.0 → 0.2.0. Android emulator guidance follows the house rule: boot via Android Studio Device Manager, not CLI `emulator -avd` (Studio owns adb here). Device-dependent paths are untested from here by design — needs a booted sim/emulator on the dev machine. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(plugin): pin generator MCP server to @latest (cwd-shadow resolution bug) (#103) The bundled generator MCP server failed to start with `sh: nativeapptemplate-agent-mcp: command not found` (confirmed in Claude's mcp-logs). MCP servers spawn with cwd = the project root; when that root is the `nativeapptemplate-agent` package's own repo, `npx -p nativeapptemplate-agent` resolves the *local* package and the bin isn't on the path it expects. Pinning `nativeapptemplate-agent@latest` forces registry resolution regardless of cwd — verified with a live MCP initialize handshake from inside the repo. README updated to document why both `-p` and `@latest` are required. Note: the `mobile-mcp` "✘ failed" seen alongside is unrelated — it's the user's identical global mobile-mcp config (a standalone third-party package, no cwd shadowing), whose connection closed during first-run npx download; it stays alive when run standalone. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(plugin): pin bundled mobile-mcp to 0.0.54 (0.0.55+ closes stdio) (#104) The bundled mobile-mcp server (and the user's identical global one) showed ✘ failed in /mcp: mobile-mcp 0.0.55+ closes the stdio connection on startup (observed: "Connection closed" ~6s in, zero output), so `@latest` (now 0.0.56) never completes the MCP handshake. 0.0.54 starts cleanly ("mobile-mcp server running on stdio" + valid initialize response) — verified with a live handshake. This is the same conclusion the agent core already reached: src/mobile.ts pins DEFAULT_ARGS to @mobilenext/mobile-mcp@0.0.54 "(was @latest). mobile-mcp 0.0.55+ closes the stdio …". The plugin now matches that pin. Side benefit: pinning makes the bundled command differ from a typical global `@latest` mobile-mcp config, so Claude won't dedup the broken global over our working bundled one. Note (out of scope, separate): CLAUDE.md's Stack section still lists `npx -y @mobilenext/mobile-mcp@latest`, which is stale/misleading given this pin. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs: flip Claude Code plugin to shipped (3 surfaces) + fix mobile-mcp pin The plugin epic is built and verified end-to-end (generate-app + walk-app), so update the docs from "deferred/planned" to shipped: - README: plugin section now documents both skills + `claude --plugin-dir ./plugin`. - CLAUDE.md: Packaging → three surfaces (CLI + MCP + plugin), with the load-bearing .mcp.json pins noted. Stack: mobile-mcp `@latest` → `@0.0.54` (the stale advice that 0.0.55+ closes stdio — the bug that cost real debugging). - ROADMAP: Track 1 third surface = plugin; Post-v0.1 "Claude Code plugin" section flipped to Status: shipped, recording that the skill carried the value without dispatch() streaming (as predicted). - SPEC addendum: §8 row + structural bullet → CLI + MCP + plugin (three). - walk-app SKILL.md: add the iOS WebDriverAgent (:8100) prerequisite; Android needs none (adb-direct), confirmed on the Pixel emulator walk. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 300696f commit 3355734

9 files changed

Lines changed: 347 additions & 13 deletions

File tree

CLAUDE.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Project-wide Claude Code instructions. Keep this file short — it's loaded into
1818

1919
- **Host language:** TypeScript (Claude Agent SDK `@anthropic-ai/claude-agent-sdk`)
2020
- **Ruby subprocesses** for Rails AST / ERB / migration work (called from TypeScript)
21-
- **External MCP:** [`mobile-next/mobile-mcp`](https://github.com/mobile-next/mobile-mcp) for iOS Simulator + Android Emulator UI automation (`npx -y @mobilenext/mobile-mcp@latest`)
21+
- **External MCP:** [`mobile-next/mobile-mcp`](https://github.com/mobile-next/mobile-mcp) for iOS Simulator + Android Emulator UI automation. **Pin `npx -y @mobilenext/mobile-mcp@0.0.54`** — 0.0.55+ closes the stdio connection on startup (the pin lives in `src/mobile.ts` and the plugin's `.mcp.json`).
2222
- **Node 22+ required.**
2323

2424
## Coding conventions
@@ -110,11 +110,12 @@ Each is an independent, buildable git repo.
110110

111111
## Packaging
112112

113-
Ships as two surfaces today:
113+
Ships as three surfaces today:
114114
- `npx nativeapptemplate-agent "your spec"` — standalone CLI (primary)
115115
- `npx -y -p nativeapptemplate-agent nativeapptemplate-agent-mcp` — stdio MCP server wrapping `dispatch()` as a `generate_app` tool, for any MCP-capable assistant (Claude Code, Cursor, Cline, Goose). The distribution multiplier. (The `-mcp` entry point is a *bin* of the `nativeapptemplate-agent` package, not its own package — hence `-p`; `npx -y nativeapptemplate-agent-mcp` 404s.)
116+
- **Claude Code plugin** in `plugin/``claude --plugin-dir ./plugin` loads two skills: `/nativeapptemplate-agent:generate-app` (generate → validate → explain) and `/nativeapptemplate-agent:walk-app` (drive the running app via `mobile-mcp`). Bundles the generator MCP server + mobile-mcp. See `plugin/README.md`.
116117

117-
A Claude Code plugin (slash command + orchestration skill) is **post-v0.1 backlog**, gated on streaming progress out of `dispatch()` and a skill that chains validation + a `mobile-mcp` walkthrough — against today's single-tool MCP a plugin would be a thin wrapper. See `ROADMAP.md` → Post-v0.1 backlog.
118+
Plugin `.mcp.json` pins are load-bearing: `nativeapptemplate-agent@latest` (MCP servers spawn with cwd = repo root; without `@latest`, `npx -p` resolves the *local* package and fails) and `@mobilenext/mobile-mcp@0.0.54` (0.0.55+ closes stdio).
118119

119120
## Hackathon success criteria (quick reminder — details in docs/SPEC.md section 11)
120121

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ tree ./out/clinic-queue/
126126
# └── validation-report.html ← self-contained visual report (open in a browser)
127127
```
128128

129-
The same generator also ships as an MCP server — `npx -y -p nativeapptemplate-agent nativeapptemplate-agent-mcp` exposes a `generate_app` tool, so any MCP-capable assistant (Claude Code, Cursor, Cline, Goose) can invoke it without leaving the editor. A Claude Code plugin (a discoverable slash command plus an orchestration skill that chains validation and a `mobile-mcp` walkthrough) is planned post-v0.1 — see the [roadmap](./ROADMAP.md#post-v01-backlog).
129+
The same generator also ships as an MCP server — `npx -y -p nativeapptemplate-agent nativeapptemplate-agent-mcp` exposes a `generate_app` tool, so any MCP-capable assistant (Claude Code, Cursor, Cline, Goose) can invoke it without leaving the editor. And a **Claude Code plugin** ships in [`plugin/`](./plugin/)`claude --plugin-dir ./plugin` loads two skills: `/nativeapptemplate-agent:generate-app` (generate → validate → explain) and `/nativeapptemplate-agent:walk-app` (launch the app on a simulator/emulator and walk its UI via `mobile-mcp`, screenshots inline). See [`plugin/README.md`](./plugin/README.md).
130130

131131
## Requirements
132132

ROADMAP.md

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ The strategy is two-track.
3131

3232
### Track 1 — Open source (this repository)
3333

34-
`npx nativeapptemplate-agent "your spec"` — the CLI form of the agent, and the primary surface. A second surface ships alongside it: `npx -y -p nativeapptemplate-agent nativeapptemplate-agent-mcp`, a stdio MCP server exposing a `generate_app` tool so any MCP-capable assistant (Claude Code, Cursor, Cline, Goose) can invoke the agent without a terminal — the distribution multiplier. Both target the free-edition substrate and require an Anthropic API key; every generation run reproduces end-to-end on the reviewer's machine. A Claude Code plugin is a planned third surface — see Post-v0.1 backlog.
34+
`npx nativeapptemplate-agent "your spec"` — the CLI form of the agent, and the primary surface. A second surface ships alongside it: `npx -y -p nativeapptemplate-agent nativeapptemplate-agent-mcp`, a stdio MCP server exposing a `generate_app` tool so any MCP-capable assistant (Claude Code, Cursor, Cline, Goose) can invoke the agent without a terminal — the distribution multiplier. Both target the free-edition substrate and require an Anthropic API key; every generation run reproduces end-to-end on the reviewer's machine. A **Claude Code plugin** is the third surface (in [`plugin/`](plugin/)) — `claude --plugin-dir ./plugin` loads the `generate-app` and `walk-app` skills; see [Claude Code plugin](#claude-code-plugin) below.
3535

3636
This track is permanent. It is not a free trial of a commercial product — it is how we believe a generator like this should ship by default in 2026.
3737

@@ -86,15 +86,14 @@ No interactive prompts — keeps the CLI scriptable and CI-friendly, no TTY assu
8686

8787
### Claude Code plugin
8888

89-
**Status: deferred.** Long named as a packaging surface, not yet built. The shipped MCP server (`nativeapptemplate-agent-mcp`) already covers in-assistant invocation across *every* MCP-capable client — strictly wider reach than a Claude-Code-only plugin. Against today's MCP, which wraps `dispatch()` as a single `generate_app` tool, a plugin would be a thin wrapper: a discoverable slash command plus a one-step install, and little else.
89+
**Status: shipped.** Lives in [`plugin/`](plugin/); load it locally with `claude --plugin-dir ./plugin`. Two skills, bundling two MCP servers (the generator + `mobile-mcp`):
9090

91-
The plugin earns its place once there is depth for it to add — work that doesn't exist yet and that the bare MCP tool can't carry cleanly:
91+
1. **`/nativeapptemplate-agent:generate-app <spec>`** — runs the generator, parses `out/<slug>/report.json`, and explains per-platform / per-layer results, the domain mapping, and any failures with the specific evidence and the next move.
92+
2. **`/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, screenshots inline.
9293

93-
1. **Streaming progress out of `dispatch()`** so a 3–5 min build-mode run isn't a frozen wait. (Flagged non-negotiable for the MCP surface in the monetization notes; the plugin inherits the same need.)
94-
2. **An orchestration skill** that owns the *post*-generation story — chaining a `mobile-mcp` home-screen walkthrough, running the validation layers, and surfacing the report. This is genuinely plugin-shaped (a skill plus bundled MCP wiring), and it's the piece a single `generate_app` tool can't express.
95-
3. **Bundling the generator MCP + `mobile-mcp` pre-wired** so "generate a clinic queue, then walk its home screen" works out of the box.
94+
The original plan gated this on `dispatch()` streaming + an orchestration skill. In practice the skill carries the value without streaming: `generate-app` drives the CLI and narrates around it, delivering the post-generation story (validate → explain; generate → walk) with no streaming needed. Streaming remains a nice-to-have for the single-tool MCP surface, not a blocker for the plugin.
9695

97-
Gate building the plugin on (1) and (2) landing first; until then it adds slash-command discoverability over the MCP and not much more.
96+
Verified end-to-end 2026-05-24: `generate-app` (barbershop-queue, all layers green) and `walk-app` (Android launch + interactive tap-through with inline screenshots on the Pixel emulator).
9897

9998
## What stays out of scope
10099

docs/SPEC.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ This document was originally a **pre-hackathon specification** (v1.0). It's pres
2727
| §6 Layer 2 Stage 1 (boot, build, launch) | **Shipped** | Default behavior. |
2828
| §6 Layer 2 Stage 2 (UI-driven scenario) | **Shipped** | Behind `NATIVEAPPTEMPLATE_VISUAL=2`; see §5 Stage 2 row. The original spec mentioned an HTTP-tail watcher for 4xx/5xx; the actual implementation walks the UI directly and lets the scenario `wait_for_text`/`assert_text` catch error states. |
2929
| §7 Evaluation plan (3 specs × 3 platforms = 9 projects) | **Exceeded** | Validated against 12 PASS combinations (full 6-cell matrix × 2 platforms): free × 3 specs × 2 platforms (6) + paid × 3 specs × 2 platforms (6). Both new paid cells (sushi waitlist, task tracker) passed first-try with no code changes — strong evidence the parameterized scenario is genuinely edition-agnostic. |
30-
| §8 Packaging (CLI + Claude Code plugin) | **Changed** | The planned Claude Code plugin was **not** built. The actually-shipped second surface is the **MCP server** (`nativeapptemplate-agent-mcp`, PR #60) — stdio, wrapping `dispatch()` as a `generate_app` tool, drivable from any MCP-capable assistant (Claude Code, Cursor, Cline, Goose) without the CLI. The §8 prose below still reads "two surfaces (CLI + plugin)" as the frozen pre-hackathon plan; **today's reality is CLI + MCP**, with the plugin deferred to ROADMAP → Post-v0.1 backlog (gated on streaming progress + an orchestration skill, since against the single-tool MCP a plugin would be a thin wrapper). |
30+
| §8 Packaging (CLI + Claude Code plugin) | **Shipped (3 surfaces)** | Shipped surfaces are now **CLI + MCP server + Claude Code plugin**. The MCP server (`nativeapptemplate-agent-mcp`, PR #60) was added as the wide-reach surface. The Claude Code plugin (`plugin/`) was deferred mid-stream, then built post-launch on `epic/claude-code-plugin` — two skills (`generate-app`, `walk-app`) bundling the generator MCP + `mobile-mcp`, both verified end-to-end 2026-05-24. The §8 prose below ("two surfaces (CLI + plugin)") is the frozen pre-hackathon plan; today's reality is **CLI + MCP + plugin**. |
3131
| §8 Packaging — env bridging (new) | **Shipped** | At run time the agent mirrors `NATIVEAPPTEMPLATE_API_*` (HOST/PORT/SCHEME) into renamed-product variants (`<PRODUCT>_API_*`) so the generated Android app picks them up via `~/.gradle/gradle.properties` and the iOS sim launch picks them up via `SIMCTL_CHILD_*` (PR #64). Safety knobs: `NATIVEAPPTEMPLATE_BRIDGE=off` skips the file write; `NATIVEAPPTEMPLATE_BRIDGE_DRY_RUN=1` previews. |
3232
| §9 Non-goals (paid-edition features) | **Stable** | Paid-edition features (multi-tenancy URL routing, invitations, role permissions, org switching) remain out of the rename pipeline by design. The agent operates against paid substrates fine — it just doesn't generate new paid-only features into renamed projects. |
3333
| §11 Hackathon must-haves | **All met** | All Must-have + Stretch criteria green at v0.2.0; see release notes for the post-hackathon delta. |
3434

3535
### What changed structurally since v1.0 of this spec
3636

37-
- **Distribution surfaces: planned CLI + Claude Code plugin → shipped CLI + MCP server.** The MCP server replaced the plugin as the second surface — wider reach (every MCP client, not just Claude Code) for the same `dispatch()` core. The plugin is deferred to the Post-v0.1 backlog.
37+
- **Distribution surfaces: planned CLI + Claude Code plugin → shipped CLI + MCP server + Claude Code plugin** (three). The MCP server was added as the wide-reach surface (every MCP client, same `dispatch()` core); the plugin (two skills, bundling the generator MCP + `mobile-mcp`) shipped post-launch on top.
3838
- **Substrate scope went from "free-only" to "free + paid"** without code changes; same pipeline.
3939
- **Validation went from "9 generated projects, target Layer 1+2 pass + Layer 3 score"** to a concrete 12-cell PASS matrix.
4040
- **Stage 2 went from aspirational ("stretch") to default-when-opted-in** (`NATIVEAPPTEMPLATE_VISUAL=2`).

plugin/.claude-plugin/plugin.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"name": "nativeapptemplate-agent",
3+
"version": "0.2.0",
4+
"description": "Generate a validated three-platform SaaS app (Rails 8.1 API + SwiftUI iOS + Jetpack Compose Android) from a one-sentence spec, explain the validation report, and walk the running app on a simulator/emulator via mobile-mcp — without leaving Claude Code.",
5+
"author": { "name": "Daisuke" },
6+
"homepage": "https://github.com/nativeapptemplate/nativeapptemplate-agent",
7+
"repository": "https://github.com/nativeapptemplate/nativeapptemplate-agent",
8+
"license": "MIT"
9+
}

plugin/.mcp.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"mcpServers": {
3+
"nativeapptemplate-agent": {
4+
"command": "npx",
5+
"args": ["-y", "-p", "nativeapptemplate-agent@latest", "nativeapptemplate-agent-mcp"]
6+
},
7+
"mobile-mcp": {
8+
"command": "npx",
9+
"args": ["-y", "@mobilenext/mobile-mcp@0.0.54"]
10+
}
11+
}
12+
}

plugin/README.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# nativeapptemplate-agent — Claude Code plugin
2+
3+
Drive the [`nativeapptemplate-agent`](https://github.com/nativeapptemplate/nativeapptemplate-agent)
4+
generator from inside Claude Code. Describe an app in one sentence; the plugin
5+
generates a validated three-platform implementation (Rails 8.1 API + SwiftUI iOS
6+
+ Jetpack Compose Android), then reads the validation report back to you in plain
7+
language.
8+
9+
Two skills: **generate → validate → explain**, and an interactive **walk the
10+
running app** layer over `mobile-mcp`.
11+
12+
## What's in here
13+
14+
```
15+
plugin/
16+
├── .claude-plugin/plugin.json # manifest
17+
├── .mcp.json # bundles the generator MCP server + mobile-mcp
18+
├── skills/
19+
│ ├── generate-app/SKILL.md # generate → validate → explain
20+
│ └── walk-app/SKILL.md # launch on a device, walk the UI with mobile-mcp
21+
└── README.md
22+
```
23+
24+
- **`/nativeapptemplate-agent:generate-app <spec>`** — runs the generator on your
25+
spec, parses `out/<slug>/report.json`, and summarizes per-platform / per-layer
26+
results, the domain mapping, and any failures with the specific evidence and the
27+
next move.
28+
- **`/nativeapptemplate-agent:walk-app <slug> ios|android`** — launches a generated
29+
app on a **booted simulator/emulator** and drives `mobile-mcp` to capture the
30+
home screen and walk the UI conversationally, surfacing screenshots inline.
31+
Needs a booted device + an installed build (easiest via a
32+
`NATIVEAPPTEMPLATE_VISUAL=1` generate run — see the skill for details).
33+
- **Bundled MCP servers** (`/mcp` to check): the generator server
34+
(`nativeapptemplate-agent`, wired as
35+
`npx -y -p nativeapptemplate-agent@latest nativeapptemplate-agent-mcp`) and
36+
`mobile-mcp` (`@mobilenext/mobile-mcp@0.0.54`) for device automation.
37+
38+
Two non-obvious bits in that generator command: the MCP entry point is a **bin**
39+
of the `nativeapptemplate-agent` package, not its own package, so `-p` is
40+
required; and the **`@latest`** is load-bearing — without a version spec, `npx`
41+
resolves the *local* package when the server is spawned from inside the agent's
42+
own repo (cwd shadowing) and fails with `command not found`. `@latest` forces
43+
registry resolution regardless of cwd.
44+
45+
`mobile-mcp` is **pinned to 0.0.54** on purpose: 0.0.55+ closes the stdio
46+
connection on startup (`Connection closed` ~6s in), so `@latest` fails. This
47+
matches the agent's own pin in `src/mobile.ts`. If you have a global `mobile-mcp`
48+
config on `@latest`, it'll show ✘ failed in `/mcp` — this bundled, pinned one is
49+
the working copy (different command, so it won't dedup against your global).
50+
51+
## Requirements
52+
53+
- Node.js 22+ and an `ANTHROPIC_API_KEY` with access to `claude-opus-4-7`.
54+
- For the generated apps to validate, the substrate env vars
55+
(`NATIVEAPPTEMPLATE_API` / `_IOS` / `_ANDROID`) must point at the substrate
56+
repos, as documented in the main README. The plugin reads them from your
57+
environment and does not change them.
58+
59+
## Try it locally (no marketplace needed)
60+
61+
```bash
62+
# from the agent repo root
63+
claude --plugin-dir ./plugin
64+
```
65+
66+
Then in the session:
67+
68+
```
69+
/nativeapptemplate-agent:generate-app a walk-in queue for a barbershop
70+
```
71+
72+
After editing plugin files, run `/reload-plugins` to pick up changes. Confirm the
73+
skill is loaded via `/help` and the MCP server via `/mcp`.
74+
75+
## Install from git
76+
77+
```
78+
/plugin install github.com/nativeapptemplate/nativeapptemplate-agent
79+
```
80+
81+
> Note: the plugin lives in the `plugin/` subdirectory of the repo. If installing
82+
> by path, point at `plugin/`, not the repo root.

0 commit comments

Comments
 (0)