Agent skill

Horizon Device

by peters in peters/horizon

Manage Horizon native VNC Device panels and drive isolated local desktops for simulators and native application tests through devicepanel and the horizon-device CLI/MCP.

MITAuto-check passed

Install Horizon Device

skills CLI
$ npx skills add peters/horizon --skill horizon-device -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install peters/horizon horizon-device --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/peters/horizon.git skills-src && mkdir -p .claude/skills && cp -r skills-src/assets/plugins/codex/skills/horizon-device .claude/skills/horizon-device && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
horizon-device
GitHub stars
716
Token cost
~4k tokens
SKILL.md length
2,171 words
Files
1
Skills in repo
6
Repo updated
First seen
Licence
MIT

At a glance

Manage Horizon native VNC Device panels and drive isolated local desktops for simulators and native application tests through devicepanel and the horizon-device CLI/MCP.

  • Works in 3 steps: On Unix, run the focused teardown… → Close an owned terminal panel in the… → Record cleanup of the fixture's owned…
  • SKILL.md covers Native VNC Device panel, Isolated desktop input, Horizon terminal close… and Viewer screenshots and video, plus 1 more section
  • Calls cargo and ssh

What it does

Horizon Device is an agent skill from peters/horizon. Manage Horizon native VNC Device panels and drive isolated local desktops for simulators and native application tests through devicepanel and the horizon-device CLI/MCP. Device panels work on every platform; driving an isolated desktop works on Linux with X11 only. Browser pages use horizon-browser.

Its SKILL.md is about 4k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It works with Model Context Protocol and Linux. The repository describes itself as: GPU-accelerated terminal board that puts all your sessions on an infinite canvas. The licence is MIT.

Example prompts

  • “/horizon-device”

Workflow steps

3 steps, taken from the first numbered list in SKILL.md.

  1. On Unix, run the focused teardown regression before native smoke.
  2. Close an owned terminal panel in the isolated candidate with normal UI input.
  3. Record cleanup of the fixture's owned child processes separately from viewer close.

What it can do on your machine

Read from SKILL.md and the folder at commit 39421a4. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • cargo
    • ssh

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md. Its commands use ssh, which can reach the network depending on how they are called.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Horizon Device loads about 4k tokens when it runs. Until then it costs about 79 tokens; SKILL.md has 2,171 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~79
When it runs · the whole SKILL.md, loaded when a task matches
~4k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from peters/horizon at commit 39421a4, republished under its MIT licence (© peters). 2,171 words, ~4,017 tokens.

Download SKILL.mdSave it as .claude/skills/horizon-device/SKILL.md (or your agent's skills folder).
name
horizon-device
description
Manage Horizon native VNC Device panels and drive isolated local desktops for simulators and native application tests through device_panel and the horizon-device CLI/MCP. Device panels work on every platform; driving an isolated desktop works on Linux with X11 only. Browser pages use horizon-browser.

Horizon native VNC and device control

Use this skill for Horizon VNC Device panels, simulators, and isolated native application tests. Browser pages use the horizon-browser skill and browser_* tools. Never drive a browser with device input.

Native VNC Device panel

Always observe interactive native tests live through a Horizon native VNC Device panel in the user's current workspace. Use a task-owned isolated desktop and private application state. Do not use noVNC or a browser viewer, or substitute screenshots or recordings for the live panel.

device_panel operations are create, list, inspect, screenshot, video, visibility, reveal, reconnect, and close. Use the public device_panel MCP tool for viewer lifecycle. Call operation: "list" to discover panels in the caller's workspace. Create a task-owned viewer with operation: "create" and the fixture's numeric loopback endpoint (IP and nonzero port); retain its returned panel_id. This requires a Horizon-launched agent and a supporting host. The tool does not provision a desktop or forward input. The source checkout's scripts/device-smoke/README.md describes the isolated fixture; launch it with --native-view and use its vnc_address, not a browser URL.

A VNC server on another machine's loopback is reached with optional ssh in create: { "host": "lab", "user": "deploy", "port": 2222 } (user and port optional). endpoint is then the address as seen from that SSH host, typically 127.0.0.1:5900. Horizon runs ssh -W with its own SSH configuration and keys, with strict host-key checking pinned regardless of ssh_config, so the host must already be trusted in known_hosts (open it over SSH once); never pass credentials, key paths or ssh options. Labels may only contain letters, digits, ., _, - (and : in an IPv6 host), at most 253 characters for the host and 64 for the user, and are refused otherwise, so nothing reaches ssh as an option or a shell fragment. Inspect and list report ssh for tunnelled viewers, and connection_error carries ssh's last lines when the tunnel fails.

When known, include optional identity in create: machine_name, hostname, ip_addresses (numeric IPv4/IPv6 list), and tailscale_name. These are labels supplied by the session creator, not verified identity. Use details for the actual target machine; never substitute the local tunnel endpoint or the viewer's own hostname. Omit unknown fields. Inspect/list return these labels.

Creation returns immediately. Use operation: "inspect" and the returned id to check connection: "connected". For a visible, on-screen viewer, also verify image_received, image_displayed and an advancing frame_sequence while target output changes. visible is only a presentation setting; an image can be off canvas or clipped. Current hosts keep uploading about once a second while a viewer is not drawn, so frame_sequence keeps advancing off canvas; older hosts pause uploads there, so also accept an advancing received_frame_sequence while target output changes as reception evidence. That counter tracks received image updates independently of the uploaded-image frame_sequence. Establish live presentation once per connection (image_displayed with advancing frames). If the viewer later reports not_rendered with outside_canvas while last_displayed_age_millis is present, the person navigated away: keep testing and recording, do not pause the lane, and do not reveal again just to advance counters. Both counters reset on reconnect and neither is a heartbeat: a stationary desktop is not a connection failure. Older hosts may omit reception progress; do not interpret a missing/default-zero counter as a failure. Set operation: "visibility", visible: true for a hidden owned viewer, then verify actual presentation. Never claim that a separate isolated viewer is visible to the user merely because its screenshot is available.

Check this automatically; never ask a human to confirm visibility or advancing frames. Save at least three timestamped public inspections, two seconds apart. The current frame_sequence counts uploaded images, not independent transport heartbeats. An unchanged sequence on a static or unknown target does not prove a stalled connection. A displayed static image proves presentation only; changing target output and sequence advancement are needed for live-motion evidence.

Recover only the task-owned viewer, with at most one visibility request when hidden and one reconnect when stopped or disconnected. Inspect again after each request; do not reconnect a healthy connection merely because its image is not displayed. Do not close/recreate viewers in a loop. Retain the attempt budget across retries for the same incident. For a viewer that has never presented an image, a connected, visible, unpresented viewer requires operation: "reveal" on hosts advertising it. Current hosts return navigation_preserved once this viewer has presented a non-discarded image, including after reconnect or ownership transfer. Restored viewers also preserve the saved canvas when their previous display history is unavailable; reconnect grants transport ownership, never navigation permission. Keep background testing, recording and inspection running; use the UI to return to the viewer when needed. Never close/recreate it to bypass this protection. Reveal an owned viewer at most once; it changes the viewport without reconnecting and answers once the host has drawn the viewer, or after at most three seconds with the presentation reason and host exclusion that kept it off screen (a host running no UI frames cannot draw it and answers when that bound expires). In the reveal answer, image_displayed is true only for a draw after the reveal applied. A drawn image is not live-motion proof. When diagnostics are present, record connection generation, decoded-frame sequence and age, sampling pause, last displayed age and presentation reason. Current hosts keep reception and bounded uploads active while hidden or off canvas; older hosts may pause them. Neither not_rendered nor a legacy sampling pause proves a transport failure; awaiting_frame differs from clipped. Decoded pixels alone do not prove display. Older hosts may lack reveal or diagnostics: record presentation_unverified and the missing capability instead of asking the user to move or watch the panel. Continue non-interactive checks. Never restart the user's Horizon to upgrade these capabilities without authorization.

operation: "reconnect" explicitly connects and acquires an unowned/restored viewer; do not take another owner's panel. Restored viewers stay stopped until reconnected. operation: "close" closes an owned viewer without terminating its target. On host_timeout, list before retrying a mutation because it may have completed. If the tool, supporting host or visible native viewer is unavailable, report the blocked lane. Do not fall back to noVNC, edit private runtime files, restart active sessions, or automate the developer's desktop.

Isolated desktop input

Drive the isolated target with explicitly configured device CLI/MCP tools: use device_doctor, then device_screenshot, then bounded device_act input with fresh geometry. Observe the result after each action. A dispatched receipt confirms input delivery, not application success. On stale geometry take another screenshot. On indeterminate input observe before deciding whether another action is appropriate; never replay blindly. The native Device panel is read-only for agents: a person may turn its Interact toggle on in the UI, but no tool operation can.

The local CLI has the same contract: horizon-device --target <private-target.json> doctor|screenshot|act|resize <JSON>. For screenshots an optional output path writes a new private file instead of base64 JSON. Optional --options JSON (or --options - for stdin) accepts region: {x,y,width,height}, output: {width,height}, format: png|jpeg, and JPEG-only quality: 1..100. MCP screenshot accepts the same options directly. Omitting options preserves full-resolution PNG; JPEG defaults to quality 85. act - reads JSON from stdin. Use this to avoid putting entered text in shell history. The MCP server uses --target <file> mcp and stays bound to that configured target. Read --help if the executable/target was not supplied.

device_act operations are click, drag, scroll, type, and key. Action fields: click (at, button), drag (from, to, duration_ms), scroll (at, vertical_notches, horizontal_notches), type (text), key (key, modifiers). Coordinates are original surface pixels. When a screenshot is cropped/scaled, map image pixels through source_region and image_dimensions before input: origin + floor((pixel + 0.5) * source_size / image_size) per axis. Keep the returned original geometry unchanged. Touch and accessibility are not implemented. Each type action accepts at most 256 Unicode scalars and 4096 UTF-8 bytes, without NUL. Text input is paced to let the application consume X11 key mappings; split longer text into bounded actions and verify the displayed result. Only control the explicitly authorized display; no implicit desktop fallback.

The caller owns the isolated display, application startup and cleanup. Independent fixtures need separate unused displays, private configuration/home, expiring targets, loopback VNC ports and owned process trees. Bind each agent to its exact target; do not share screenshot geometry across fixtures. Never control the developer's desktop, change production configuration, or stop a pre-existing application. When a target expires, stop; do not recreate it from a saved display number.

Finish the intended build, copy executables to a new task-owned directory, and record their hashes before launch. Keep build caches separate across source checkouts during qualification. Verify the running application's executable/hash against that frozen copy, following the actual child rather than a sandbox launcher such as bwrap. Close only the owned candidate normally when replacing it; a rebuild does not change a running process. Native View controls change local rendering, not target desktop geometry or VNC compression. Device screenshot crop/output options are separate controls.

For nested Device-panel tests, view the isolated Horizon containing that panel through a native panel in the user's workspace; keep each target and its geometry distinct.

Show full SKILL.md (686 more words)Show less

Horizon terminal close regression

Use docs/testing/procedures/terminal-close.md in the Horizon source checkout for task IDs, native response and owned cleanup.

When testing terminal close in Horizon, use this sequence:

  1. On Unix, run the focused teardown regression before native smoke.

    bash
    cargo test -p horizon-core terminal::lifecycle::tests::dropping_a_finished_event_loop_does_not_wait_for_its_live_child -- --exact

    Result: The caller returns before the live PTY child exits. Background cleanup then completes after the child exits.

  2. Close an owned terminal panel in the isolated candidate with normal UI input.

    Result: The candidate remains responsive while a helper thread joins the event loop and destroys its PTY.

  3. Record cleanup of the fixture's owned child processes separately from viewer close.

    Result: The evidence distinguishes responsive UI behavior from completed process cleanup.

A finished thread handle can still own a returned PTY that waits for its child. Do not replace this regression with a larger timeout or remove its live-child condition.

Viewer screenshots and video

Use device_panel with operation: screenshot and the owned panel_id to get full connected desktop pixels as a private PNG with dimensions. Local crop and scale controls do not affect this capture. Optional copy_to_clipboard defaults false; clipboard_requested proves native host dispatch, not OS acknowledgement. Stopped, disconnected, or no-frame viewers refuse capture. Capture changes no visibility, focus, canvas, or Interact state. Only eight exports remain until panel close or normal host exit. A screenshot does not replace live-motion evidence.

device_panel video operations are start, status, and stop. For feature evidence, use device_panel with operation: video, the owned panel_id, and action: start|status|stop. Start before the flow. It records the full VNC desktop as private WebM without audio and continues offscreen. Every action requires the exact owning agent. It stops on disconnect, after five minutes, or at 256 MiB. Stop is asynchronous: read status at a bounded interval until recording.capture.active and recording.finalizing are both false. Examine encoder_failed and frames_encoded, then decode representative frames. The file path is on the Horizon host. Copy it before panel close or four subsequent recordings. Browser pages use browser_video; native provider sessions use app_video through horizon-app-testing.

On older hosts without viewer video, use a recorder explicitly scoped to the owned isolated display. If recording is unavailable or stalls, report that lane; still images do not replace motion evidence. Keep finalized evidence private. Public demonstrations use generic fixtures and synthetic content only. Client-side scaling does not reduce VNC wire bandwidth.

Close only task-owned viewers and application/display fixtures, then verify children exited and target configuration expired. Horizon injects device_panel on the browser MCP; this skill does not start a viewer or register the input server. Callers must still supply the horizon-device executable and target for input, or register --target <file> mcp.

Desktop resizing

Owner permission is separate from server support. Enable desktop_resize.policy.enabled only for the owned container session, with max_width, max_height and max_pixels limits. An optional adapter uses the explicit desktop_resize.vnc_address; existing X11 users need no VNC dependency.

Check doctor, then call resize '{"width":1920,"height":1080}' or MCP device_resize with the same dimensions. A confirmed result includes requested and applied dimensions and current surface geometry. Capture a fresh screenshot before input. Pre-resize coordinates remain stale after a grow/shrink round trip. Screenshot crop/output dimensions and viewer Fit do not resize the desktop.

The CLI/MCP runner serializes commands and writes a target.json.resize-pending journal before dispatch. After a timeout, disconnect or process exit during mutation, the owner must reconcile the same session before removing that journal. device_resize cannot enable permission or clear uncertainty. A separate target.json.resize-observe marker blocks input until a successful fresh screenshot. A bounded operation already in progress finishes even if its MCP caller cancels.

Target filenames must not end in .lock, .resize-pending or .resize-observe.

CLI/MCP errors include resize_uncertain: true means a resize may have been applied and requires owner reconciliation before retrying.

To change permission during a running session, call device_set_resize_enabled with {"enabled":true} or {"enabled":false}, or use horizon-device --target <file> --resize-enabled true|false from another CLI. The next operation reloads the saved setting; no MCP restart is needed. Limits, endpoint and pending journals are preserved. A busy result means retry the permission change after the current operation finishes; disabling cannot cancel an already dispatched resize or reconcile uncertainty.

© peters, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in assets/plugins/codex/skills/horizon-device of peters/horizon.

Open the folder on GitHubat commit 39421a4

Compare with similar skills

Horizon Device next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Horizon Device compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Horizon Device this skillpeters/horizon716—~4kAutomated safety check: PassMIT
Open Computer UseiFurySt/open-codex-computer-use2.4k—~1.5kAutomated safety check: PassMIT
Youtubeeat-pray-ai/yutu699—~1.1kAutomated safety check: PassMIT
Linux Desktop Controlagent-sh/computer-use-linux675—~2.8kAutomated safety check: PassMIT
Gearcoleco Debuggingdrhelius/Gearcoleco142—~3.5kAutomated safety check: PassGPL-3.0
Cortex Mem MCPsopaco/cortex-mem313—~2.8kAutomated safety check: PassMIT

Similar skills

  • Open Computer Use

    iFurySt/open-codex-computer-use

    Platform-neutral guidance for using Open Computer Use, the open-source Computer Use MCP server and CLI for macOS, Linux, and Windows.

    2.4k GitHub stars~1.5k tokensUpdated today
    Productivity & AutomationAuto-check passed
  • Youtube

    eat-pray-ai/yutu

    A skill your agent uses whenever the user mentions YouTube, video uploads, channel management, playlists, video SEO, or any YouTube Data API operation.

    699 GitHub stars~1.1k tokensUpdated 2 days ago
    DevOps & CloudAuto-check passed
  • Linux Desktop Control

    agent-sh/computer-use-linux

    Lets an agent observe and operate a local Linux desktop through the computer-use-linux MCP server or Pi tools: accessibility trees, screenshots, windows and input.

    675 GitHub stars~2.8k tokensUpdated yesterday
    Productivity & AutomationAuto-check passed
  • Gearcoleco Debugging

    drhelius/Gearcoleco

    Debug and trace ColecoVision and Super Game Module games using the Gearcoleco emulator MCP server.

    142 GitHub stars~3.5k tokensUpdated yesterday
    DevelopmentAuto-check passed
  • Cortex Mem MCP

    sopaco/cortex-mem

    Persistent memory enhancement for AI agents. An agent skill from sopaco/cortex-mem.

    313 GitHub stars~2.8k tokensUpdated 2 mo ago
    Agent WorkflowsAuto-check passed
  • Delive Transcript Analyzer

    XimilalaXiang/DeLive

    Analyze, summarize, and extract insights from DeLive transcription sessions.

    270 GitHub stars~1.4k tokensUpdated today
    Media & CreativeAuto-check passed

More from peters/horizon

  • Horizon Speech

    peters/horizon

    Check that a microphone is usable for Horizon dictation and report which layer is at fault — no signal, bad level, or a genuine model/accent limit.

    716 GitHub stars~1.8k tokensUpdated today
    Auto-check passed
  • Horizon App Testing

    peters/horizon

    Run or inspect declared iOS and Android native app tests through Horizon devicetestrun and app MCP tools.

    716 GitHub stars~277 tokensUpdated today
    Auto-check passed
  • Horizon Cast

    peters/horizon

    Cast Horizon panels, workspaces, cloud cards, or its main window to Apple TV through the public cast MCP tool.

    716 GitHub stars~227 tokensUpdated today
    Auto-check passed
  • Horizon Browser

    peters/horizon

    Control, inspect, or audit Horizon browser panels through public browser MCP tools.

    716 GitHub stars~4.8k tokensUpdated today
    Auto-check passed
  • Horizon Cloud

    peters/horizon

    Inspect Horizon cloud offers and companions, control explicitly authorized companion workers, use a worker Local Network Bridge, or ask for GitHub access from a cloud worker through public MCP tools.

    716 GitHub stars~311 tokensUpdated today
    Auto-check passed

Questions about Horizon Device

What does Horizon Device do?

Manage Horizon native VNC Device panels and drive isolated local desktops for simulators and native application tests through devicepanel and the horizon-device CLI/MCP. Horizon Device is an agent skill from peters/horizon. Manage Horizon native VNC Device panels and drive isolated local desktops for simulators and native application tests through devicepanel and the horizon-device CLI/MCP.

How do I install Horizon Device in Claude Code?

Run `npx skills add peters/horizon --skill horizon-device -a claude-code`. Or copy the skill folder (assets/plugins/codex/skills/horizon-device in peters/horizon) into .claude/skills/horizon-device in your project. Claude Code loads it when a task matches its description.

How do I install Horizon Device in Codex?

Run `npx skills add peters/horizon --skill horizon-device -a codex`. Or copy the skill folder (assets/plugins/codex/skills/horizon-device in peters/horizon) into .agents/skills/horizon-device in your project. Codex loads it when a task matches its description.

Can I use Horizon Device in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add peters/horizon --skill horizon-device -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/horizon-device, .gemini/skills/horizon-device, .github/skills/horizon-device and .opencode/skills/horizon-device in your project.

What does Horizon Device need to run?

Going by SKILL.md and its folder, Horizon Device needs the command-line tools its instructions call (cargo and ssh).

Does Horizon Device access the network?

SKILL.md contains no URLs. Its commands use ssh, which can reach the network depending on how they are called. This is read from the text; nothing was executed.

Is Horizon Device safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Horizon Device use?

Horizon Device is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Horizon Device use?

About 4k tokens (SKILL.md is roughly 16k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Horizon Device?

Skills that share tags, products or a category with Horizon Device: Open Computer Use (iFurySt/open-codex-computer-use, 2.4k stars), Youtube (eat-pray-ai/yutu, 699 stars), Linux Desktop Control (agent-sh/computer-use-linux, 675 stars) and Gearcoleco Debugging (drhelius/Gearcoleco, 142 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Horizon Device?

peters (a GitHub user) maintains it in peters/horizon, which has 716 GitHub stars. The repository holds 6 skills in this directory. The repository was last updated on October 10, 2026.

Source: peters/horizon on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.