rozenite
Inspect the live Apex Factory app through Rozenite for Agents — network requests, console messages, the React component tree and renders, performance traces, heap snapshots, and the app's own tools —
SKILL.md.agents/skills/rozenite/SKILL.md
GitHubRozenite in this repo
Vendored from callstackincubator/rozenite v2.4.0 (see SOURCE.md) and adapted. Rozenite
for Agents is a JSON CLI over Metro's /rozenite/agent/* routes; there is no MCP server. The
CLI and its plugins are apps/mobile devDependencies, pinned.
It sees only a debug build connected to a Metro started with WITH_ROZENITE=true. A
Release build, the booth binary and OTA bundles contain no Rozenite code, so Rozenite is a
diagnosis tool: the Release run decides pass or fail, a debug run explains a failure.
Set it up on a lane
.agents/scripts/device-lane.sh build ios debug # detached; wait for <log>.exit (needs no lease)
.agents/scripts/device-lane.sh lease ios
.agents/scripts/device-lane.sh install
.agents/scripts/device-lane.sh metro start # this lane's own port, WITH_ROZENITE=true APPDUCT_ENABLED=1
.agents/scripts/device-lane.sh ad open com.callstack.apexfactory --foreground # the lane points the app at its Metro
The loop
.agents/scripts/device-lane.sh rozenite targets # every app on this Metro
.agents/scripts/device-lane.sh rozenite session # creates (once) and prints the lane's session id
.agents/scripts/device-lane.sh rozenite domains # console, network, react, performance, memory, app, controls, …
.agents/scripts/device-lane.sh rozenite network call --tool startRecording
# reproduce the problem with device-lane.sh ad …, then:
.agents/scripts/device-lane.sh rozenite network call --tool listRequests
.agents/scripts/device-lane.sh rozenite console call --tool getMessages
.agents/scripts/device-lane.sh rozenite app call --tool app.app_info # the appduct tools, through Metro
.agents/scripts/device-lane.sh rozenite reset # forget the session (after an app reload)
The lane appends --session <id> and puts --port <metro port> before the subcommand, so do
not pass either. A target is named after its device (simlock-<id> on a leased simulator).
The lane's Metro has a port of its own, so normally its app is the only target; the lane takes
it, and stops when there are several (APEX_ROZENITE_TARGET=<part of a name> picks one).
Another app connected to the same Metro would show up in targets too: check the data
(rozenite app call --tool app.app_info) before trusting a target.
ad open com.callstack.apexfactory on a debug build hands the dev client the lane's Metro and
answers iOS's "Open in" prompt itself. The first load bundles over Metro and shows the splash
screen: device-lane.sh ad wait text "On purpose." 60000 before the next step.
- Calls within a session are serial: never run two Rozenite commands at once.
- A session created before the app (re)loaded misses the plugin domains (
app,controls,network-activity):rozenite reset, thenrozenite sessionagain. session stopcan hang on 2.4.0;resetonly forgets the id, and the session ends with Metro or the app (device-lane.sh releasestops Metro).- An agent session takes the app's one debugger connection, so it disconnects a person's React Native DevTools.
- Traces and heap snapshots are written under
apps/mobile/.rozenite/(gitignored). Name the file in a report; never commit it.
The docs ship with the CLI
The real content is bundled with the installed CLI, so it matches the pinned version. Read it
from apps/mobile (pnpm, never npx):
cd apps/mobile && pnpm exec rozenite skills list # id and one line per doc
cd apps/mobile && pnpm exec rozenite skills show core # ground truths; read this first
cd apps/mobile && pnpm exec rozenite skills show cli # command syntax, sessions, pagination
cd apps/mobile && pnpm exec rozenite skills show network # then the domain you need
Those docs write commands as npx rozenite agent …; here each one is
.agents/scripts/device-lane.sh rozenite … without --port and --session.