rk CLI
The rk command is the command-line interface (CLI) for the RSG 2.0 SDK. It provides developer tooling for building, deploying, and debugging Roku apps that use the RSG 2.0 SDK.
Installation
The rk CLI ships in the @roku-sdk/tooling package on npmjs.com, and each RSG 2.0 SDK app declares it in its package.json. Apps created with rk create already list it. To add it to an existing app:
pnpm add @roku-sdk/toolingInside a clone of the SDK repository, the example apps reference it as "workspace:*" instead; therefore, they run against the local source.
Once installed, the rk command becomes available through npx:
npx rk <command> [options]Run rk directly (no npx)
rk directly (no npx)Each call to npx rk or pnpm rk runs a wrapper self-bootstrap step that takes from approximately 350 to 550 ms. The first call in a fresh terminal takes several seconds. Both delays occur before rk starts. To skip that cost, install a one-time launcher:
npx rk setup --install-cli # Writes ~/.local/bin/rkAfter this you can call rk directly from any app directory:
rk <command> [options]The launcher walks up from your current directory to find the nearest project-local rk and runs it directly. If ~/.local/bin is not on your PATH, the installer prints the line to add to your shell profile. You can use rk setup --check to see the launcher and PATH status, and rk setup --uninstall-cli to remove it. The launcher does not support Windows. On Windows, add your app's node_modules\.bin to PATH instead.
Available commands
- mcp — Configure AI assistant integration via the Model Context Protocol (stdio and server mode).
- Debugging with AI — Human-facing recipes: prompts to give your AI for common device debug tasks.
- device — Manage and query Roku devices used by the SDK for sideloading, debugging, and opening the web UI.
- Roku Cloud Emulator devices — Register, start, stop and drive cloud-hosted Roku devices;
rk dev,rk ecp,rk logsand the MCP tools reach them like a Roku on your network. - device lease —
acquire / release / reapa device lease through a configured pool (localor custom). - device pool —
statusof the configured pool's inventory + live state.
- Roku Cloud Emulator devices — Register, start, stop and drive cloud-hosted Roku devices;
- package — Sign, rekey, delete, convert, and list package artifacts on target Roku devices.
- plugins — Add commands and server features to
rkwith installable plugin packages. - dcl — List and delete Downloadable Component Libraries installed on target Roku devices.
- ecp — External Control Protocol commands for querying and controlling Roku devices.
- keysequence — Send an ordered sequence of ECP keypresses from a single CLI call.
- server — Run
rkas a persistent HTTP server for improved performance. - server managed lifecycle (Phase 0) — API contract for managed vs unmanaged server lifecycle with window-based client leases.
- build — Build RSG 2.0 SDK applications for deployment
- dev — Side load your app in development mode, with or without debugging. Add
--no-buildto install an already-built app without rebuilding; it reads<out-dir>/pkg-dir, defaulting todist-dev. Add--no-sideloadfor the inverse — build the dev artifacts and contact no device at all - start-dev — Deprecated alias for
dev; still routes, prints the replacement on stderr - sideload — Deprecated; use
rk dev --no-build. Still works with its existing options - create - Create a new RSG 2.0 SDK application (documentation TBD)
- logs — Start, collect, search, and tail device logs through a server-side log session
- decode-stack — Translate a raw Hermes or JS stack trace back to TypeScript source positions
- gen-types — Generate
.xml.d.tsfor imported XML components without a full build (for freshtype-check) - perfetto — Record and manage Perfetto performance traces on a device
- version — Print the
@roku-sdk/toolingversion (rk version,rk --versionorrk -v);--whereadds how it was installed (npm registry,npx/dlxtemporary copy, or local build) and its path;--jsonprints{"version":"..."}
Extensibility
You can plug in a custom DeviceProvider (for example, a private device farm, a cloud Roku pool, or a custom continuous integration (CI) selection strategy) through the registry exposed by @roku-sdk/tooling. See Extending the device pool for more information.
Usage
Run the rk command with the following syntax:
npx rk <command> [options]You can run npx rk --help to see the global usage and the command list.
You can also run npx rk help <command>, which is equivalent to npx rk <command> --help.
Global behavior:
- The
rkcommand automatically discovers the nearest runningrkserver by walking upward from the current working directory and validating/api/health. - You can use
--localto skip discovery and force local mode for commands that support local execution fallback (build,dev,device,package,dcl,perfetto). - For commands that are server-only (for example,
logs,ecp,server),rkrejects--localas an unknown option.
Startup performance model
The CLI applies several startup optimizations to reduce command latency:
- Lazy command module loading: The CLI imports command modules only for the matched command, instead of eagerly loading all command implementations at startup.
- Lazy fast-path executor loading: The CLI imports the server fast-path executor module (a relatively heavy module) only when it discovers a live
rk server; therefore, non-fast-path invocations never pay its import cost. - Server fast-path (for
build,dev,device,perfetto,package,dcl,cdp): When a liverk serveris discovered and--localis not set, the CLI executes a direct server request before importing local command modules.rk dev --no-buildandrk dev --no-sideloadboth decline the fast path, since the server always builds and always sideloads; they fall back to local execution. - Server endpoint for
dev: The endpoint isPOST /api/dev, withDELETE /api/dev/:sessionIdto stop a watch session. The former names/api/start-devand/api/start-dev/:sessionIdstill route to the same handlers so an older client reaches a newer server, but this repository does not post to them anymore. The internalcommand: "start-dev"discriminator is deliberately not renamed with the route. - Leaf filesystem helpers: Lightweight helpers such as
pathIfExistslive in a dependency-free module (tooling-utils/path-utils); therefore, commands that need only those helpers (for example,sideloadand manifest and version updates) do not transitively pull in the build hub (esbuild,@babel, TypeScript, and sharp).
This design keeps lightweight commands fast and avoids unnecessary local initialization work when server mode is available.
The per-invocation cost described above comes from the npx or pnpm wrapper, not from rk itself. See Run rk directly (no npx) for more information. Only commands that run the build and image pipeline (build, dev, create, and server) load the native image library sharp. Lightweight commands (device, ecp, logs, decode-stack, sideload, and so on) never load it; therefore, it is not a factor in their startup latency.
You can run npx rk <command> --help to see command-specific help.
Updated about 5 hours ago