Roku certification preflight checker. Runs automatable certification checks against a Roku device and produces a report before you submit to Roku.
npm install @danecodes/roku-cert# Full certification preflight
roku-cert run --device 192.168.0.30 --channel dev
# Single check
roku-cert check app_launch_time --device 192.168.0.30
# List all checks
roku-cert checks# Run all checks
roku-cert run
# Run with options
roku-cert run --device 192.168.0.30 --channel dev
# Run a specific category
roku-cert run --category launch
roku-cert run --category navigation
roku-cert run --category playback
roku-cert run --category stability
# Run a single check
roku-cert check app_launch_time
roku-cert check trick_play
# Skip checks (non-video apps can skip playback)
roku-cert run --skip playback_initiation,trick_play,playback_error_handling
# With deep link config
roku-cert run --deeplinks ./deeplinks.json
# Output formats
roku-cert run --format text # default, colorful terminal output
roku-cert run --format json
roku-cert run --format junit # for CI integration
roku-cert run --format markdown # for PRs / docs
# Save report to file
roku-cert run --output report.json --format json
roku-cert run --output report.xml --format junit
# Quick single-purpose commands
roku-cert launch-time # just test launch time
roku-cert cpu # just sample CPU for 30s
roku-cert stability # rapid input + console checkROKU_DEVICE_IP— device IP (alternative to--device)ROKU_DEV_PASSWORD— dev password for sideloaded channels
import { CertRunner } from '@danecodes/roku-cert';
const runner = new CertRunner('192.168.0.30', {
channelId: 'dev',
deepLinks: './deeplinks.json',
launchTimeout: 15000,
playbackTimeout: 8000,
cpuThreshold: 80,
skip: ['playback_initiation', 'trick_play'],
});
// Run all checks
const report = await runner.runAll();
// Run a specific category
const report = await runner.runCategory('launch');
// Run a single check
const result = await runner.runCheck('app_launch_time');
// List available checks
const checks = runner.listChecks();
// Format report
console.log(runner.formatReport(report)); // terminal text
const json = runner.toJSON(report); // JSON string
const junit = runner.toJUnit(report); // JUnit XML
const md = runner.toMarkdown(report); // Markdown| ID | Check | What it does |
|---|---|---|
app_launch_time |
App launch time | Cold start, measures time to UI render. Must be <15s. |
relaunch_stability |
Relaunch stability | Close and relaunch 3 times. No crashes or console errors. |
cpu_usage |
CPU usage | Samples CPU for 30s during idle. Must stay below threshold. |
memory_baseline |
Memory baseline | Records memAnon/memFile during idle. Warns if high. |
| ID | Check | What it does |
|---|---|---|
back_button |
Back button | Navigate forward 3 screens, back 3 times. Must not crash. |
home_exit |
Home exit | Press Home from various screens. Must exit cleanly. |
focus_visible |
Focus visible | After each nav action, focus must never disappear. |
deep_link_cold |
Deep link cold | Deep link with app not running. Delegates to roku-deeplink. |
deep_link_warm |
Deep link warm | Deep link with app running. Delegates to roku-deeplink. |
| ID | Check | What it does |
|---|---|---|
playback_initiation |
Playback initiation | Verify playback starts within timeout via media player. |
trick_play |
Trick play | Pause, resume, rewind, fast forward. Verify state changes. |
playback_error_handling |
Error handling | Invalid content ID must show error screen, not crash. |
| ID | Check | What it does |
|---|---|---|
console_idle |
No errors idle | Launch, wait 10s, check console for BrightScript errors. |
console_navigation |
No errors nav | Navigate 5 screens, check console after each. |
rapid_input |
Rapid input | Send 20 keys at 100ms intervals. Must not crash. |
| ID | Check | What it does |
|---|---|---|
text_readability |
Text readability | Verify key screens have text elements, not just images. |
The text formatter produces a terminal report:
╔══════════════════════════════════════════════╗
║ Roku Certification Preflight Report ║
╠══════════════════════════════════════════════╣
║ Device: Roku Ultra (4800X) — OS 14.0.2 ║
║ Channel: dev ║
║ Date: 2026-04-15 ║
╚══════════════════════════════════════════════╝
Launch & Performance
────────────────────
✓ App launch time 2.3s (< 15s)
✓ Relaunch stability 3/3 clean
✓ CPU usage avg 34% (< 80%)
⚠ Memory baseline 85MB (high but noted)
═══════════════════════════════════════════════
14/15 PASSED | 1 FAILED | 0 SKIPPED
Total time: 2m 14s
═══════════════════════════════════════════════
Exit codes: 0 = all passed, 1 = failures present.
Deep link checks use a config file compatible with @danecodes/roku-deeplink:
{
"channelId": "dev",
"tests": [
{
"name": "Movie playback",
"contentId": "MOVIE_001",
"mediaType": "movie",
"expect": { "playback": true, "noErrors": true }
}
]
}Skip playback checks for channels without playable content:
roku-cert run --skip playback_initiation,trick_play,playback_error_handlingOr programmatically:
const runner = new CertRunner('192.168.0.30', {
channelId: 'dev',
skip: ['playback_initiation', 'trick_play', 'playback_error_handling'],
});MIT