Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .git-hooks/pre-push
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env bash
set -euo pipefail

pnpm verify
28 changes: 28 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
name: Bug report
about: Report a reproducible rokit problem
title: ""
labels: bug
assignees: ""
---

## What Happened

## Expected Behavior

## Reproduction

```bash

```

## Environment

- `rokit` version:
- Node version:
- Roku model or emulator:
- OS:

## Evidence

Add logs, command output, screenshots, or generated artifacts when useful. Do not include device passwords, account tokens, signing keys, private content IDs, or local device identifiers.
23 changes: 23 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
name: Feature request
about: Suggest a generic Roku harness primitive
title: ""
labels: enhancement
assignees: ""
---

## Use Case

## Proposed Command Or API

```bash

```

## Proof Artifact

What should the harness leave behind so a human or agent can verify the behavior?

## Boundaries

What app-specific behavior should stay out of `rokit`?
18 changes: 18 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
day: monday
groups:
actions-patch-minor:
update-types: ["patch", "minor"]
actions-major:
update-types: ["major"]
commit-message:
prefix: "ci"
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
9 changes: 9 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
## Summary

## Changed

## Risks

## Verification

## Follow-Ups
3 changes: 1 addition & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
run: vp run verify

release:
if: github.event_name == 'push' && github.ref == 'refs/heads/main' && !contains(github.event.head_commit.message, '[skip ci]') && vars.PUTIO_RELEASE_BOT_CLIENT_ID != ''
if: github.event_name == 'push' && github.ref == 'refs/heads/main' && !contains(github.event.head_commit.message, '[skip ci]')
name: Release rokit
needs:
- verify
Expand Down Expand Up @@ -74,7 +74,6 @@ jobs:
uses: voidzero-dev/setup-vp@ca1c46663915d6c1042ae23bd39ab85718bfb0fa # v1.10.0
with:
node-version-file: ".node-version"
cache: true

- name: Install dependencies
run: vp install
Expand Down
8 changes: 8 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,18 @@ Keep it platform-focused, typed, and useful for both humans and agents.
## Patterns

- Keep CLI wiring thin: parse/dispatch commands, then call named Roku helpers.
- Keep `src/index.ts` as 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.
- Wrap `roku-deploy` for package publish, screenshots, and device metadata when
it already owns the platform mechanics.
- Use Roku ECP for launch, keypresses, active-app queries, and raw runtime
state.
- 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.
- Keep app journeys, content IDs, account data, and product assertions out of
the generic harness.

Expand All @@ -25,6 +30,8 @@ Keep it platform-focused, typed, and useful for both humans and agents.
primary public contract.
- Avoid sleeps in generic commands. App repos can add meaningful wait/assert
loops around `rokit` primitives.
- Release details live in `docs/DISTRIBUTION.md`; readiness details live in
`docs/READINESS.md`.

## When Contracts Change

Expand Down Expand Up @@ -53,6 +60,7 @@ vp run test
Live Roku checks when a developer-enabled device exists:

```bash
ROKIT_TARGET=<roku-ip> vp run live:smoke
ROKIT_TARGET=<roku-ip> vp exec rokit check
ROKIT_TARGET=<roku-ip> vp exec rokit launch dev
ROKIT_TARGET=<roku-ip> vp exec rokit press Info Back
Expand Down
1 change: 1 addition & 0 deletions CLAUDE.md
27 changes: 24 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,18 @@
vp install
```

## Verify
## Run Locally

Use the built CLI through the package scripts while developing:

```bash
vp run smoke
```

For live Roku checks, set local environment variables in your shell or
`.rokit/.env`.

## Validation

```bash
vp run verify
Expand All @@ -20,12 +31,22 @@ run.
Live checks require a developer-enabled Roku on the same network:

```bash
ROKIT_TARGET=<roku-ip> vp exec rokit check
ROKIT_TARGET=<roku-ip> vp exec rokit launch dev
ROKIT_TARGET=<roku-ip> vp run live:smoke
ROKIT_TARGET=<roku-ip> vp exec rokit press Info Back
```

Screenshots and installs require `ROKIT_PASSWORD`.

Keep local device details in `.rokit/.env` or your shell. Do not commit device
IPs, passwords, signing keys, tokens, or account-specific app data.

## Pull Requests

- Keep changes focused.
- Add or update tests when command behavior, parsing, output, or public exports change.
- Include the most useful verification evidence for the change.
- Keep app-specific journeys out of `rokit`; add those to the consuming app repo instead.

## Distribution

Release and publishing details live in [Distribution](./docs/DISTRIBUTION.md).
40 changes: 38 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,47 @@ Then run:
pnpm exec rokit check
pnpm exec rokit launch dev
pnpm exec rokit press Down Select
pnpm exec rokit press --delay-ms 250 Right Select
pnpm exec rokit query /query/active-app
pnpm exec rokit wait-node videoPlayerScreen visible
pnpm exec rokit screenshot artifacts/live/player.png
```

App-specific scenario scripts can also import the generic helpers:

```ts
import { assertSceneGraphNode, pressKey, querySceneGraph, 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,
Comment on lines +53 to +59
timeoutMs: 10_000,
username: "rokudev",
};

await pressKey(context, "Info");
await assertSceneGraphNode(context, "videoPlayerScreen", { state: "visible" });
await querySceneGraph(context);
```

## Commands

```bash
rokit check
rokit device-info
rokit active-app
rokit wait-active <app-id> [--timeout-ms <ms>]
rokit launch <app-id> [--param key=value]
rokit press <key> [key...]
rokit press [--delay-ms <ms>] <key> [key...]
rokit query <ecp-path>
rokit sgnodes
rokit assert-node <node-name> <visible|hidden|absent|text|attr> [value]
rokit wait-node <node-name> <visible|hidden|absent|text|attr> [value] [--timeout-ms <ms>]
rokit screenshot <output-path>
rokit install <zip-path>
rokit --version
Expand All @@ -60,10 +88,15 @@ rokit --version
is reachable.
- `device-info` prints enhanced Roku device metadata as JSON.
- `active-app` prints the foreground app.
- `wait-active` waits until the requested app is foregrounded.
- `launch` opens an app and waits until it is active. Use repeated `--param`
values for deeplink parameters.
- `press` sends Roku remote keys through ECP.
- `press` sends Roku remote keys through ECP. Use `--delay-ms` for navigation
sequences that need a stable gap between keys.
- `query` prints a raw ECP response such as `/query/sgnodes/all`.
- `sgnodes` prints the raw SceneGraph tree from `/query/sgnodes/all`.
- `assert-node` checks a named SceneGraph node once.
- `wait-node` polls SceneGraph until a named node condition matches.
- `screenshot` saves a developer screenshot. It requires `ROKIT_PASSWORD`.
- `install` publishes an existing ZIP through `roku-deploy`. It requires
`ROKIT_PASSWORD`.
Expand Down Expand Up @@ -92,6 +125,7 @@ tokens, and app-specific media identifiers do not belong in git.
- launch and deeplink parameters
- remote keypresses
- raw ECP queries
- SceneGraph state queries and named-node assertions
- screenshots

App repositories should keep their own scenario commands for product behavior,
Expand All @@ -101,6 +135,8 @@ HTML, or checking app-specific UI nodes.
## Docs

- [Contributing](./CONTRIBUTING.md)
- [Distribution](./docs/DISTRIBUTION.md)
- [Agent readiness](./docs/READINESS.md)
- [Security](./SECURITY.md)

## Repo Internals
Expand Down
40 changes: 35 additions & 5 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,38 @@
# Security

Report security issues privately through GitHub Security Advisories for this
repository.
If you believe you have found a security or privacy issue in this project,
please report it privately.

Do not include device passwords, signing keys, account tokens, private content
IDs, or local device identifiers in public issues, pull requests, examples, or
logs.
## Contact

- email: devs@put.io

Private reports are preferred for security and privacy issues.

If you are unsure whether something is sensitive, email first instead of opening
a public issue.

## Scope

Useful reports usually include issues involving:

- token, secret, or credential exposure
- unsafe handling of device passwords or signing keys
- command injection through CLI arguments, env values, or device responses
- publishing, release, or package integrity problems
- private device, account, or media identifier exposure

## Guidelines

- test only against devices, accounts, environments, and data you control
- keep testing non-destructive, low-volume, and service-safe
- do not include device passwords, signing keys, account tokens, private content IDs, or local device identifiers in public issues, pull requests, examples, or logs

## Supported Versions

Only the latest published version receives routine fixes.

## Disclosure

Please allow a reasonable amount of time to investigate and fix the issue before
sharing details publicly.
49 changes: 49 additions & 0 deletions docs/DISTRIBUTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Distribution

`rokit` is a public npm package published as `@putdotio/rokit`.

## Local Contract

The release path starts with the repo-local verification command:

```bash
pnpm verify
```

`verify` runs formatting/lint checks, TypeScript, package bundling, tests, and an npm pack dry run. GitHub Actions calls this same command before release.

## Continuous Release

Merges to `main` are considered publishable. The CI workflow runs:

1. `verify` on pull requests and `main` pushes.
2. semantic-release on `main` after `verify` passes.

semantic-release analyzes conventional commits, publishes to npm, creates GitHub Releases, and writes release metadata when needed.

## Release Credentials

The release job uses the `release` GitHub Environment with `deployment: false`.

Required protected inputs:

- `PUTIO_RELEASE_BOT_CLIENT_ID` as a repository or Environment variable
- `PUTIO_RELEASE_BOT_PRIVATE_KEY` as an Environment secret
- `NPM_TOKEN` as an Environment secret

Release writes use the `putio-release-bot` installation token. The default `GITHUB_TOKEN` remains read-only.

## Release Smoke

After a release, confirm the tag and package are visible:

```bash
gh release list --repo putdotio/rokit --limit 5
npm view @putdotio/rokit version
```

Live Roku behavior is not required for npm release. Real-device checks are local/manual because they require a developer-enabled Roku:

```bash
ROKIT_TARGET=<roku-ip> pnpm live:smoke
```
Loading