rokit is a small Node CLI that wraps generic Roku device harness primitives.
Keep it platform-focused, typed, and useful for both humans and agents.
- README.md: install, command surface, env contract, quick start.
- docs/debugging.md: Roku debug surfaces, console capture, crash-proof workflow.
- docs/distribution.md: release path, semantic-release wiring, credentials.
- skills/rokit/: consumer skill and its command references.
- Merging publishes. A
feat,fix,perf, revert or breaking commit onmainpublishes@putdotio/rokitto npm, and a published version number can never be reused, so the commit type is the release decision. - Taking over someone's Roku. A Roku holds one sideloaded developer app,
and the target may be a TV someone is watching.
installandlive:probereplace that app;launchandpresschange what is on screen.check,device-info,active-appand the other reads leave it alone, and--dry-runvalidates a mutating command without side effects.
- Keep
rokitfree of put.io product behavior. Do not add put.io app IDs, deep links, content IDs, account data, credentials, journeys, UI node names, or product assertions. @putdotio/rokit,putdotio/rokit, release-bot wiring, copyright, and security contacts are ownership/publishing metadata only; do not treat them as permission to add product-specific fixtures.- Use neutral examples such as
dev,Example Channel,videoPlayerScreen, and synthetic SceneGraph/XML data when docs or tests need sample app data. - Consumer app repos own product scenario scripts, app-specific selectors, playback/content assertions, and review artifacts.
- Use Effect at the runtime boundary and for reusable effectful operations. Keep errors schema-backed and render them without stack traces in CLI output.
- Use
effect/cliArgumentandFlagprimitives for command grammar before adding custom argv parsing. - Keep CLI wiring thin: parse/dispatch commands, then call named Roku helpers.
- Keep
src/roku.tsas a public compatibility barrel. Put implementation in focused modules such asapp-control,device,media-player-query,scenegraph-query, androku-context. - Keep human output stable;
--json/--output jsonshould wrap every command result and error in a deterministic object for agents. - Keep
src/index.tsas the public library surface for app-specific scenario scripts. Export generic Roku/SceneGraph primitives only. - Treat
process.cwd()as the consumer app root. - Keep
.rokit/consumer-local; it can hold env, generated artifacts, and transient device state. - Keep
skills/rokit/SKILL.mdaligned with agent-facing command and safety guardrails. - Keep
examples/live-probe-channelgeneric. It exists only to prove package, install, launch, input, SceneGraph, screenshot, and proof mechanics. - Use native developer-installer, screenshot, device-info, and package-ZIP
helpers where rokit owns the platform mechanics. Keep
roku-deployonly for package-command compatibility with existingrokudeploy.jsonfile rules until native glob parity replaces that adapter. - Use Roku ECP for launch, keypresses, active-app queries, and raw runtime state.
- Media-player helpers can parse and wait on Roku
/query/media-playerstate, but app repos own expectations about specific content, playback URLs, and containers. - Keep SceneGraph helpers generic: node state, text, attributes, focus/state waits, and raw tree output are okay; product-specific screen contracts stay in app repos.
This repository uses the Effect TypeScript library. The installed version's own
guide is node_modules/effect/AGENTS.md; consult it for the APIs the change
touches, and search node_modules/effect/src for anything it does not cover.
- Missing config/env and child-command failures should not print stack traces.
- CLI tests default to in-process entry points (
mainEffectfromsrc/cli.tsor the command effects) so V8 coverage attributes them. Spawndist/rokit.mjsonly when the process boundary itself is under test; those runs are not attributed to coverage (seevite.config.ts). ROKU_DEV_TARGETandROKU_DEV_PASSWORDare optional fallback aliases, not the primary public contract; the env contract is in README.md.- Avoid sleeps in generic commands. App repos can add meaningful wait/assert
loops around
rokitprimitives.
- Command, env, or output changes: update
README.mdand CLI tests. - CI/release/publishing changes: update workflow docs or release config in the same change.
CLAUDE.mdis a one-line@AGENTS.mdimport of this file; keep it that way.
.worktreeinclude carries local env files into managed worktrees. Run the
Checks setup commands. If device config is missing, copy
.env.example to .env or .rokit/.env.
Vite+ is the pinned vite-plus devDependency, so run it as pnpm exec vp; no
global install is needed.
pnpm install
pnpm exec vp run hooks:install
pnpm exec vp run verifyFast loops:
pnpm exec vp run check
pnpm exec vp run typecheck
pnpm exec vp run smoke
pnpm exec vp run testLive Roku checks when a developer-enabled device exists; node dist/rokit.mjs
is the CLI that live:smoke builds:
ROKIT_TARGET=<roku-ip> pnpm exec vp run live:smoke
ROKIT_TARGET=<roku-ip> ROKIT_PASSWORD=<password> pnpm exec vp run live:probe
ROKIT_TARGET=<roku-ip> node dist/rokit.mjs check
ROKIT_TARGET=<roku-ip> node dist/rokit.mjs launch dev
ROKIT_TARGET=<roku-ip> node dist/rokit.mjs press Info BackWhich proof a change needs:
- Docs only:
pnpm exec vp run check, pluspnpm exec vp run skills:lintforskills/; no device run. - Source, command, env, output or export changes:
pnpm exec vp run verify. - Device-facing behavior:
verify, thenlive:smoke(read-only) orlive:probe(installs the generic probe channel).
Open a pull request; CI runs vp run verify on pull requests and on main.
On main, semantic-release publishes releasable commits to npm and GitHub
Releases. Credentials and release smoke: Distribution.