A coding agent can write BrightScript and SceneGraph, but on its own it cannot see the result. There is no Roku on its desk, and a Roku is navigated by focus, so “does the new row work” means knowing what is on screen, where focus landed, and whether the channel printed an error. This guide sets the agent up to answer those questions itself, on real Roku hardware streamed from the cloud.
The fast way: paste this into Claude Code
Open Claude Code in your channel’s project folder and paste the prompt below. The agent installs what is missing, writes vibeview.json, puts the channel on a Roku, checks that it started, and records the workflow in CLAUDE.md so it verifies future changes on its own. The one thing it will ask you to do is log in, because that opens a browser.
Set up VibeView so you can test this Roku channel on a real Roku, then verify it runs.
1. Run `vibeview --version`. If the command is missing, run `npm install -g vibeview`.
2. Run `vibeview whoami`. If I am not logged in, stop and ask me to run `vibeview login` myself (it opens a browser), then continue.
3. Run `vibeview agent-setup --no-mcp` to install the vibeview-agent skill (it teaches you this workflow in future sessions; the CLI is all you need here, so skip the MCP server).
4. Find the channel's `manifest` file. Work out which top-level entries belong in the package: `manifest`, `source/`, `components/`, `images/`, and any other folders the channel loads at runtime, but never `.git`, `node_modules`, `out/`, tests or docs. If the project already has a packaging script (an npm script, a Makefile target), use that instead.
5. Create or update `vibeview.json` in the project root:
{
"defaultPlatform": "roku",
"platforms": {
"roku": {
"build": {
"command": "<a command that deletes out/channel.zip, then zips the entries from step 4 into out/channel.zip with the manifest at the root of the zip>",
"artifact": "out/channel.zip"
}
}
}
}
Add `out/` to `.gitignore`.
6. Run the build command once and check the zip with `unzip -l out/channel.zip`: `manifest` must be at the root, not inside a folder.
7. Start a session: `vibeview dev --platform roku --build --detach --json`. As soon as it prints `session_ready`, give me the `url` so I can watch.
8. Verify the channel started: run `vibeview ui-tree`, `vibeview screenshot --out ./roku-check.png` (look at it) and `vibeview logs`. Tell me what is on screen, which element has focus, and any errors in the log. If the channel failed to start, read the error in `logs`, fix it, run `vibeview dev-reload`, and check again.
9. Add this to CLAUDE.md: "This is a Roku channel. After changing it, run `vibeview dev-reload` and verify the change on the device with `vibeview ui-tree`, `vibeview press`, `vibeview focus` and `vibeview logs` before saying it works. Start a session with `vibeview dev --platform roku --detach --json` if none is running."
10. Leave the session running and tell me that `vibeview dev-stop` ends it.
The rest of this guide explains what that prompt does, step by step, if you would rather set it up by hand or understand what the agent is running.
1. Install the CLI and connect your agent
Log in once yourself; the browser login is the one step the agent should not do for you.
npm install -g vibeview
vibeview login
vibeview agent-setup
agent-setup installs the vibeview-agent skill where Claude Code finds it, offers to register the MCP server, and suggests a line for your CLAUDE.md so the agent verifies changes on a device without being reminded. In Claude Code you can decline the MCP server: the skill teaches the agent the CLI, which does everything here, and MCP is for clients that cannot run a shell (see below). For Cursor, Codex and other agents that install skills from GitHub, npx skills add vibeview/skills does the same job.
2. Tell VibeView how to package the channel
A Roku channel is a zip, not a compiled build. Put the command that makes it in vibeview.json at the root of the channel project, under platforms.roku.build:
{
"defaultPlatform": "roku",
"platforms": {
"roku": {
"build": {
"command": "mkdir -p out && rm -f out/channel.zip && zip -qr -X out/channel.zip manifest source components images",
"artifact": "out/channel.zip"
}
}
}
}
Any command works, npm run package included, as long as it leaves the zip at artifact. If you run vibeview dev --platform roku yourself first, it asks for both values and writes the file for you.
3. The loop the agent runs
With the skill installed, asking Claude Code to “change the detail screen and verify it on the Roku” is enough. Under the hood, the agent works through the same commands you could type:
# start a session on a physical Roku with the channel installed
# (--build on the first run: package and upload the channel before starting)
vibeview dev --platform roku --build --detach --json
# after each edit: re-package, install and restart the channel
vibeview dev-reload
# look
vibeview ui-tree
vibeview screenshot --out ./check.png
vibeview logs
# act
vibeview press down
vibeview focus @e42
vibeview tap-focused @e42
vibeview type "comedy"
vibeview dev-stop
dev --detach --json returns a session page URL. The agent should hand it to you straight away, so you can watch in the browser and take the remote whenever you like.
4. What each tool gives the agent on Roku
ui-treereturns the channel’s elements as text, each with a reference like@e42, and marks which one has focus. The agent reasons about structure, not pixels.presstakes the remote’s names:up,down,left,right,select,back, plusenter,backspaceand the media keys. Home is refused, because the session stays inside your channel.focuswalks the remote to a named element and reports where focus ended up;tap-focuseddoes the same and then selects it.typesends text into a Roku on-screen keyboard, then reads the field back, so a dropped character shows up as a failed step instead of a silent one.logsreturns what your channel printed in this session: its output, the reason it exited, and the error and backtrace when it crashes. Output from earlier sessions is never mixed in.screenshotis for the moments when appearance matters and the tree is not enough.
After a press, focus or tap-focused, the result starts with the element that now has focus, so the agent knows where it is without a second call.
Using MCP instead of the shell
Clients that cannot run shell commands get the same tools from the MCP server: dev_start with platform roku, dev_reload, upload_app for a channel zip, and the verbs above with underscores. In Claude Code:
claude mcp add vibeview -- vibeview mcp
Limits worth knowing
- This is an agent verifying its own changes interactively. To keep a check, record it as a test: recorded tests and AI test runs (beta) work on Roku, and
vibeview run-suites --platform rokuruns them in CI. A channel that draws its own focus highlight replays by element only when built with the VibeView Roku plugin. See Roku test automation for the full walkthrough. - Touch gestures such as swipe and scroll-to have no meaning on a Roku; the agent moves with
pressandfocus. - Roku devices are physical, so a session waits its turn when one is busy.
For a complete run, read how an agent built a Roku channel from an empty repository in 27 minutes of agent time. If you are weighing this against other ways to run a channel, every Roku emulator option is compared in one place.