Roku device harness primitives for package, launch, input, state, and proof loops.
Generic by design: app journeys, credentials, content IDs, and product assertions stay in consumer repos.
Requires Node >=24.14.0; install it in a consumer repo with:
pnpm add -D @putdotio/rokitSet the target Roku in the app repo that consumes rokit:
export ROKIT_TARGET=<roku-ip>
export ROKIT_PASSWORD=<developer-mode-password>Then run the generic device checks and actions you need:
pnpm exec rokit check
pnpm exec rokit package --out artifacts/live/channel.zip
pnpm exec rokit install artifacts/live/channel.zip
pnpm exec rokit launch dev
pnpm exec rokit press Down Select
pnpm exec rokit console artifacts/live/console.log --duration-ms 30000
pnpm exec rokit proof artifacts/live/proof --screenshotROKIT_PASSWORD is required for developer-installer operations such as
install and screenshot. ROKU_DEV_TARGET and ROKU_DEV_PASSWORD are
accepted as optional aliases when the ROKIT_* names are unset.
Prefer JSON when rokit feeds another tool:
pnpm exec rokit describe
pnpm exec rokit --json active-app
pnpm exec rokit --dry-run launch dev
pnpm exec rokit --fields status,data.state media-player
pnpm exec rokit --input-json '{"command":"press","keys":["Down","Select"]}'describe prints the machine-readable command surface, including command
names, parameters, JSON payload fields, global options, and automation feature
flags. When stdout is not a TTY, command output defaults to JSON unless
--output text is explicit.
Common commands:
| Command | Purpose |
|---|---|
describe |
Print the machine-readable command surface |
check |
Confirm ECP and developer-installer reachability |
discover |
Find Roku ECP devices with SSDP |
device-info |
Read Roku device metadata |
active-app |
Read the foreground app |
console <output-path> |
Capture BrightScript console output from 8085 |
debug-command <command> [args...] |
Run an allowlisted Roku debug command |
media-player |
Read parsed /query/media-player state |
snapshot |
Read a compact state snapshot |
proof <output-dir> |
Write reviewable local proof artifacts |
package --out <zip-path> |
Create a sideload ZIP from the current app root |
install <zip-path> |
Publish an existing ZIP to the Roku developer slot |
launch <app-id> |
Launch an app by id with optional params |
press <key...> |
Send Roku remote keys |
query <ecp-path> |
Print a raw ECP response |
sgnodes |
Print the raw SceneGraph tree |
assert-node / wait-node |
Check generic SceneGraph node state |
wait-active / wait-media-player / wait-ready |
Poll generic runtime readiness |
screenshot <output-path> |
Save a timestamped developer screenshot |
Mutating commands support --dry-run where the platform can validate without
changing device or filesystem state. ECP paths reject query strings, fragments,
traversal, backslashes, control characters, and percent-encoded path segments.
Generated output paths must stay within the current working directory.
Screenshots append a timestamp to the requested filename and report the actual
path written, so repeated captures do not reuse cache-prone filenames.
App-specific scenario scripts can import the generic helpers:
import {
assertMediaPlayerContainer,
assertSceneGraphNode,
captureScreenshot,
pressKey,
querySceneGraph,
waitForSceneGraphAssertion,
type RokuContext,
} from "@putdotio/rokit";
const target = process.env.ROKIT_TARGET;
if (!target) {
throw new Error("ROKIT_TARGET is not set");
}
const context: RokuContext = {
target,
timeoutMs: 10_000,
username: "rokudev",
};
await pressKey(context, "Info");
await querySceneGraph(context, { attempts: 3, requireAppNode: true, requireComplete: true });
await assertSceneGraphNode(context, "videoPlayerScreen", { state: "visible" });
await assertMediaPlayerContainer(context, "mp4");
await captureScreenshot(
{ ...context, password: process.env.ROKIT_PASSWORD ?? "" },
"artifacts/player.jpg",
{ attempts: 3 },
);
await waitForSceneGraphAssertion(context, "player ready", (xml) => {
if (!xml.includes("videoPlayerScreen")) {
throw new Error("expected player screen");
}
});rokit owns generic Roku mechanics:
- package, install, launch, deeplink params, and remote keypresses
- raw ECP queries and parsed media-player state
- BrightScript console capture and allowlisted debug-server commands
- SceneGraph state queries and named-node assertions
- timestamped screenshots, snapshots, and proof artifacts
Consumer app repos own product behavior: opening specific routes, asserting playback for real content, checking app-specific UI nodes, and generating review artifacts.
