/horizon-browser
Control, inspect, or audit Horizon browser panels through public browser_* MCP tools.
Claude Code
$ npx -y skills add peters/horizon --skill horizon-browser --agent claude-code
Codex
$ npx skills add peters/horizon --skill horizon-browser -a codex -y
Cursor
$ npx skills add peters/horizon --skill horizon-browser -a cursor -y
Gemini CLI
$ npx skills add peters/horizon --skill horizon-browser -a gemini-cli -y
GitHub Copilot
$ npx skills add peters/horizon --skill horizon-browser -a github-copilot -y
OpenCode
$ npx skills add peters/horizon --skill horizon-browser -a opencode -y
Windsurf
$ npx skills add peters/horizon --skill horizon-browser -a windsurf -y
SKILL.md
horizon-browser.SKILL.mdname: horizon-browser
description: Control, inspect, or audit Horizon browser panels through public browser_* MCP tools.
Horizon browser control
Native VNC Device panels, simulators, and isolated desktop tests use the `horizon-device` skill. The workflow below applies to browser pages.
Use the `browser_*` MCP tools as the only agent-facing browser contract. Do not inspect Horizon runtime files, connect to raw CDP/BiDi/WebDriver endpoints, or invoke a browser-control CLI. If the MCP tools are unavailable, report that the Horizon browser MCP server is not connected.
Start with `browser_list` when the panel id is unknown. If it returns no panels, call `browser_create`; this opens a panel in the current agent's Horizon workspace and returns its ready panel id once the backend is ready and, when you passed a `url`, once that page committed (`navigation: committed`). A `navigation: pending` result means the panel is controllable but the first page had not committed within the bounded startup wait, so use `browser_wait` or `browser_panel` before reading it; `navigation: failed` means that page failed to load (`navigation_error` says why) and you must navigate again or fix the URL; `navigation: superseded` means the user navigated the panel first, so read `panel.url` before acting. If `browser_list` returns a usable panel, reuse that panel for iframe, popup, dialog, and consent interactions. Never create or reveal a helper panel as a workaround. You may hold one panel per browser engine: to run the same check in another engine, call `browser_create` with an explicit `backend` (`chromium`, `firefox` or `safari`) beside your open panel. Only when the user explicitly requests another independent browser session may you call `browser_create` with `allow_additional: true`; a second panel of the same engine, a create without `backend` while you own a panel, and a remote `target` while you own a panel need it. A create that is still pending counts as a panel of its engine. Omit `backend` to use Horizon's configured browser, or select `chromium`, `firefox`, or `safari` when the platform supports it. Read `automation_disclosure` on `browser_list` and `browser_panel`. In the UI, hover the local backend picker or the remote identity header to read the same status. `common_signals_minimized` means the native `navigator.webdriver` getter is still native. On Firefox that result needs `firefox_system_access: true` and geckodriver 0.37 or newer. The option passes geckodriver `--allow-system-access`. Mozilla documents that flag as full system access for any local client that can reach the driver port. Leave it false unless that privilege is acceptable. `preload_fallback` means Firefox installed a script getter that returns false. Sign-in pages can reject that getter. The default minimized Firefox session uses that fallback. Chromium does not install it. A remote Firefox or Chromium session reports `unsupported_by_backend` for minimization. Remote Firefox does not clear the native flag or install the preload. Remote Chromium does not receive the local automation flag. `unreported` means an older manifest omitted the field. That is not an established result. To run at a configured remote target instead of a local browser, pass `target` with its name and omit `backend`; Horizon resolves the provider and credentials from its configuration, and a refusal carries a typed code and at most the target, provider or credential reference name, never a credential value. Such a panel reports `remote_target`, `remote_device` (the model, OS version and hardware evidence the provider itself reported, verified against the target before the panel became ready), classic WebDriver and no network capture. A target that requires a physical device is refused as `remote_device_rejected` unless that evidence confirms it, after Horizon attempts to release the session; a `remote_allocation_unknown` refusal means a device may still be held, so check with the user before creating again; `remote_authentication_failed`, `remote_not_entitled` and `remote_device_unavailable` say which of the credential, the account's automation access or the device request the provider refused, with nothing held. Cite `remote_device`, not the target name, as real-device evidence. Set `visible: false` for background automation; use `browser_visibility` to show or hide the live panel later without stopping its session, capture, ownership, or MCP control. Call `browser_close` on a panel you own when the user is done with it or a remote device session must be released now; it stops the session, releases any remote allocation, and the panel leaves `browser_list`. Read anything you still need from `browser_audit` before closing: it answers only for a live panel. An optional bare-host `url` defaults to HTTPS while explicit HTTP remains available. Use `browser_panel` for a known panel. Discovery and control are scoped to the workspace that contains your agent panel: `browser_list` never shows panels from other workspaces, every other tool rejects their ids, and a panel's `visible` field is host presentation state, not proof that the panel is in your workspace. If nothing usable is listed, create a panel rather than guessing an id. On a cloud worker, your injected actor must match a registered workspace session. For a request addressed to the current worker, an actor outside that workspace receives `panel_outside_workspace` before a browser starts. Use the registered session identity; do not retry an unregistered actor. Before interacting, call `browser_snapshot` or `browser_query` and prefer its short-lived `ref` in `browser_act`. Remote iOS clicks and field entry use synchronous target checks before trusted native input. Verify the visible result after each action. `browser_evaluate` works on a driver that omits its script timeout, and it awaits a returned promise: a rejection is a `javascript_error` and an unsettled promise is an `evaluation_timeout`. Na
Read more
name: horizon-browser description: Control, inspect, or audit Horizon browser panels through public browser_* MCP tools.
Horizon browser control
Native VNC Device panels, simulators, and isolated desktop tests use the `horizon-device` skill. The workflow below applies to browser pages.
Use the `browser_*` MCP tools as the only agent-facing browser contract. Do not inspect Horizon runtime files, connect to raw CDP/BiDi/WebDriver endpoints, or invoke a browser-control CLI. If the MCP tools are unavailable, report that the Horizon browser MCP server is not connected.
Start with `browser_list` when the panel id is unknown. If it returns no panels, call `browser_create`; this opens a panel in the current agent's Horizon workspace and returns its ready panel id once the backend is ready and, when you passed a `url`, once that page committed (`navigation: committed`). A `navigation: pending` result means the panel is controllable but the first page had not committed within the bounded startup wait, so use `browser_wait` or `browser_panel` before reading it; `navigation: failed` means that page failed to load (`navigation_error` says why) and you must navigate again or fix the URL; `navigation: superseded` means the user navigated the panel first, so read `panel.url` before acting. If `browser_list` returns a usable panel, reuse that panel for iframe, popup, dialog, and consent interactions. Never create or reveal a helper panel as a workaround. You may hold one panel per browser engine: to run the same check in another engine, call `browser_create` with an explicit `backend` (`chromium`, `firefox` or `safari`) beside your open panel. Only when the user explicitly requests another independent browser session may you call `browser_create` with `allow_additional: true`; a second panel of the same engine, a create without `backend` while you own a panel, and a remote `target` while you own a panel need it. A create that is still pending counts as a panel of its engine. Omit `backend` to use Horizon's configured browser, or select `chromium`, `firefox`, or `safari` when the platform supports it. Read `automation_disclosure` on `browser_list` and `browser_panel`. In the UI, hover the local backend picker or the remote identity header to read the same status. `common_signals_minimized` means the native `navigator.webdriver` getter is still native. On Firefox that result needs `firefox_system_access: true` and geckodriver 0.37 or newer. The option passes geckodriver `--allow-system-access`. Mozilla documents that flag as full system access for any local client that can reach the driver port. Leave it false unless that privilege is acceptable. `preload_fallback` means Firefox installed a script getter that returns false. Sign-in pages can reject that getter. The default minimized Firefox session uses that fallback. Chromium does not install it. A remote Firefox or Chromium session reports `unsupported_by_backend` for minimization. Remote Firefox does not clear the native flag or install the preload. Remote Chromium does not receive the local automation flag. `unreported` means an older manifest omitted the field. That is not an established result. To run at a configured remote target instead of a local browser, pass `target` with its name and omit `backend`; Horizon resolves the provider and credentials from its configuration, and a refusal carries a typed code and at most the target, provider or credential reference name, never a credential value. Such a panel reports `remote_target`, `remote_device` (the model, OS version and hardware evidence the provider itself reported, verified against the target before the panel became ready), classic WebDriver and no network capture. A target that requires a physical device is refused as `remote_device_rejected` unless that evidence confirms it, after Horizon attempts to release the session; a `remote_allocation_unknown` refusal means a device may still be held, so check with the user before creating again; `remote_authentication_failed`, `remote_not_entitled` and `remote_device_unavailable` say which of the credential, the account's automation access or the device request the provider refused, with nothing held. Cite `remote_device`, not the target name, as real-device evidence. Set `visible: false` for background automation; use `browser_visibility` to show or hide the live panel later without stopping its session, capture, ownership, or MCP control. Call `browser_close` on a panel you own when the user is done with it or a remote device session must be released now; it stops the session, releases any remote allocation, and the panel leaves `browser_list`. Read anything you still need from `browser_audit` before closing: it answers only for a live panel. An optional bare-host `url` defaults to HTTPS while explicit HTTP remains available. Use `browser_panel` for a known panel. Discovery and control are scoped to the workspace that contains your agent panel: `browser_list` never shows panels from other workspaces, every other tool rejects their ids, and a panel's `visible` field is host presentation state, not proof that the panel is in your workspace. If nothing usable is listed, create a panel rather than guessing an id. On a cloud worker, your injected actor must match a registered workspace session. For a request addressed to the current worker, an actor outside that workspace receives `panel_outside_workspace` before a browser starts. Use the registered session identity; do not retry an unregistered actor. Before interacting, call `browser_snapshot` or `browser_query` and prefer its short-lived `ref` in `browser_act`. Remote iOS clicks and field entry use synchronous target checks before trusted native input. Verify the visible result after each action. `browser_evaluate` works on a driver that omits its script timeout, and it awaits a returned promise: a rejection is a `javascript_error` and an unsettled promise is an `evaluation_timeout`. Na
Other skills on horizon.
More skills from other plugins.
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
ask-matt
Ask which skill or flow fits your situation. A router over the skills in this repo.
Questions about horizon-browser.
- Which coding agents can use horizon-browser?
- horizon-browser installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

