Skip to content

feat(tool-server): add start-metro tool#370

Open
hubgan wants to merge 2 commits into
mainfrom
feat/start-metro-tool
Open

feat(tool-server): add start-metro tool#370
hubgan wants to merge 2 commits into
mainfrom
feat/start-metro-tool

Conversation

@hubgan

@hubgan hubgan commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator

Add start-metro tool for React Native Metro bundler startup

Summary

Adds a start-metro tool that starts a Metro bundler for a React Native project, or reuses an instance already running on the target port — complementing the existing stop-metro. Until now agents had to instruct users to run Metro manually (npx react-native start), which made fully automated RN app startup impossible. With this tool the start→run→debug loop can run end-to-end without a human in the loop.

What it does

start-metro returns { port, pid, status } where status is "started" or "reused":

  • Reuse by default — probes the port's /status endpoint for the packager-status:running marker; if Metro is already up, returns status: "reused" without spawning a second server.
  • reuseExisting: false — forces a fresh instance; errors instead of reusing a running Metro.
  • Port conflict detection — if the port is held by a non-Metro process, fails fast with the offending PID(s) and tells the caller to free it with stop-metro, rather than spawning a Metro that would just fail to bind.
  • Default & custom commands — runs npx react-native start --port <port> detached by default; pass command/args (e.g. "npm" + ["run", "start:local"]) to run a project's own start script verbatim (no flag injection — the caller owns its flags). Supports cache-reset via custom args.
  • projectRoot — sets the working directory (and --projectRoot for the default command) for monorepos where the tool-server cwd isn't the app root.
  • Readiness wait — polls /status until Metro is ready (60s timeout) before returning, folding boot-time error/exit listeners into the readiness race so a later natural exit can't crash the tool-server.

Implementation notes

  • The detached + unref'd child outlives the tool-server (same pattern as simulator-server); stop-metro terminates it by port later.
  • Accurate PID reporting: findListeningPids uses lsof -ti tcp:<port> -sTCP:LISTEN. The -sTCP:LISTEN filter is essential — a bare query also matches established client sockets (including the tool-server's own keep-alive to Metro), which would return the wrong PID. For wrapper commands (npx/npm run) the reported PID is the descendant that actually bound the port, not the wrapper.
  • All process spawning uses spawn/execFileSync with no shell, so port and other inputs can never be shell-interpreted.

Files

  • packages/tool-server/src/tools/simulator/start-metro.ts — the tool
  • packages/tool-server/src/utils/setup-registry.ts — registration
  • packages/tool-server/test/start-metro.test.ts — unit tests covering reuse, fresh start, custom command verbatim, LISTEN-only PID lookup, non-Metro port conflict, and reuseExisting: false
  • Skill/docs updates (argent.md rule, argent-react-native-app-workflow SKILL, argent-metro-debugger failure-scenarios) to route agents to start-metro instead of shelling out to npx react-native start

Scope note

The optional --public-base-url flag for remote-agent workflows from the original scope is not included in this change. The reuse/fresh-start parameter is implemented as a boolean reuseExisting (default true) rather than a --no-reuse-existing flag.

@hubgan hubgan marked this pull request as ready for review June 18, 2026 12:42
Comment thread packages/tool-server/src/tools/simulator/start-metro.ts Outdated

@filip131311 filip131311 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expo will not work after this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants