Skip to content

putdotio/rokit

Repository files navigation

put.io Boncuk logo

rokit

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.

CI npm version License

Install

Requires Node >=24.14.0; install it in a consumer repo with:

pnpm add -D @putdotio/rokit

Quick Start

Set 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 --screenshot

ROKIT_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.

Automation

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.

Command Surface

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.

Library Use

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");
  }
});

Boundaries

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.

Docs

Repo Internals

License

MIT

About

A tiny CLI companion for Roku device harness work.

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Contributors