Skip to content

Tap

rozenite agent tap connects to a device and prints Rozenite plugin messages as they flow, in both directions, without opening a browser or React Native DevTools.

The full loop for checking that a plugin’s native side behaves — Metro, a simulator, the app, a browser running React Native DevTools, the shell, and the panel — is a lot of overhead just to watch a handful of messages when the thing you’re testing lives on the device. tap skips the browser half entirely.

Terminal window
npx rozenite agent tap --session <id> --plugin @acme/sqlite-plugin
← 12:04:31.220 sqlite:list-tables-request {"requestId":"a1"}
→ 12:04:31.244 sqlite:list-tables-response {"requestId":"a1","tables":["users","posts"]}

Each line is a direction arrow, a local timestamp, the message type, and the JSON payload:

  • ← — received from the device.
  • → — sent to the device.

Omit --plugin to watch every plugin’s traffic on the session. tap keeps running until you stop it with Ctrl-C, closing the underlying connection cleanly.

Because the stream is bidirectional, tap doubles as a minimal stand-in for DevTools: send one message from the terminal, then keep watching for whatever comes back.

Terminal window
npx rozenite agent tap --session <id> --plugin @acme/sqlite-plugin --type sqlite:query --payload '{"sql":"select 1"}'

--plugin, --type, and --payload map directly onto the three fields of the message sent to the device (pluginId, type, payload). --payload defaults to {} and is validated as JSON on its own, so a malformed payload is reported against --payload, not against a blended argument. --type requires --plugin, since a message needs to know which plugin it’s addressed to.

--plugin also filters the stream — --type does not, since filtering on it would hide the very response your poke is meant to surface.

Pass --json for newline-delimited JSON, one message per line, so another program or agent can consume the stream directly instead of screenshotting a terminal:

Terminal window
npx rozenite agent tap --session <id> --json
{
"direction": "in",
"timestamp": 1700000000000,
"pluginId": "@acme/sqlite-plugin",
"type": "list-tables-request",
"payload": { "requestId": "a1" }
}

Each line has this shape:

Field Description
direction "in" (received from the device) or "out" (sent to the device).
timestamp Milliseconds since the Unix epoch.
pluginId The plugin the message belongs to.
type The message type.
payload The message payload, unmodified.
  • -s, --session <id> — target Agent session ID (required). Create one with npx rozenite agent session create.
  • -p, --plugin <id> — filter the stream to this plugin ID; required together with --type.
  • -t, --type <name> — send one message of this type before watching. Requires --plugin.
  • -a, --payload <json> — JSON payload for the sent message. Defaults to {}.
  • --json — newline-delimited JSON output instead of the human-readable format.
  • --host <host> / --port <port> — Metro host and port, inherited from rozenite agent, so they go before tap: npx rozenite agent --host 192.168.1.10 --port 8082 tap --session <id> (defaults to 127.0.0.1:8081).

tap rides the same connection rozenite agent uses, and neither disconnects React Native DevTools. You can keep a plugin’s panel open in DevTools and watch the same messages in the terminal. Stop the tap with Ctrl-C when you’re done.

  • Rozenite for Agents — the wider agent-facing workflow tap is part of.
  • Agent SDK — build custom tooling on top of the same session tap uses.