Skip to main content
Glama

opencode computer-use (Hyprland foreground operator)

Foreground GUI control for opencode on Arch + Hyprland. Verified against Hyprland 0.56.2, opencode 1.18.30, monitor eDP-1 1920x1080@144 scale 1.25 (logical 1536x864, physical 1920x1080).

Source of truth for behavior: SKILL.md (deploys to /home/cyber/.config/opencode/skills/computer-use/SKILL.md). Constrained executor: agent-computer-operator.md (deploys to /home/cyber/.config/opencode/agents/computer-operator.md). Installer: scripts/install.sh (copies files, never edits JSON for you).

1. Architecture

+---------------------+      ask-per-action      +--------------------------+
| opencode 1.18.30    | -----------------------> | computer-operator        |
| (build/primary)     |      @computer-operator  | (subagent, no bash/edit) |
+----------+----------+                          +------------+-------------+
           | skill load                                       | computer-use_* MCP
           v                                                 v
+---------------------+                          +--------------------------+
| skill: computer-use |                          | computer_use_mcp.py      |
| routing, lease,     |                          | (stdio via hexstrike-env |
| grounding, audit    |                          |  tools: click/type/key..)|
+---------------------+                          +------------+-------------+
                                                              |
            +-------------------------------------------------+-------------+
            | lease /tmp/opencode-computer-use-lease.json                   |
            | audit /tmp/opencode-computer-use-audit.jsonl                  |
            | estop /tmp/opencode-computer-use-estop                        |
            | allow ~/.config/opencode/computer-use.allow.json (deny-first) |
            +-------------------------------+-------------------------------+
                                            v
                       +------------------------------------+
                       | Hyprland 0.56 (eDP-1, fg takeover) |
                       | grim / hyprctl / wtype / dotool    |
                       +------------------------------------+

The subagent cannot touch a shell or the filesystem editor. All desktop effects flow through computer-use_* tools, each gated to ask, one action per approval, with a lease file, an append-only audit log, a kill-switch file, and a deny-by-default allowlist around them.

Related MCP server: hyprland-mcp

2. Codex parity: macOS background vs this foreground-takeover

Dimension

Codex (macOS)

This project (Hyprland)

Session model

Background session, sandboxed

Foreground takeover: user watches, screen is seized

Grounding

Accessibility (AX) tree + screenshot

Screenshot + hyprctl rect only; no AX tree exists

Input path

OS automation API (CUA)

dotool/dotoold mouse (fractions 0-1), wtype keys

Concurrency

Parallel background runs

Forbidden: one lease, one target, one action at a time

Permissions

Per-action macOS consent prompts

computer-use_*=ask + allowlist + lease + estop

Audit

Session transcript

/tmp/opencode-computer-use-audit.jsonl (JSONL)

Credential guard

Sandbox policy

Hard refusal: sudo/polkit/hyprlock/vault surfaces

Net effect: weaker isolation than Codex (foreground by design), compensated by narrower agent capability (no bash/edit), human-in-the-loop approval, and file-based lease/audit/estop that survive agent failure.

3. Install

Prerequisites: Arch, Hyprland 0.56 running, opencode 1.18.30, jq, python3, and one of: fresh python3 -m venv, or the existing /home/cyber/hexstrike-ai/hexstrike-env (verified present; reuse it, do not create a second venv without reason).

  1. Run the installer (idempotent; backs up config; edits nothing): bash /home/cyber/Projects/opencode-computer-use/scripts/install.sh

  2. The installer copies:

    • SKILL.md -> /home/cyber/.config/opencode/skills/computer-use/SKILL.md

    • agent-computer-operator.md -> /home/cyber/.config/opencode/agents/computer-operator.md (rename!)

    • computer-use.allow.json.example -> /home/cyber/.config/opencode/computer-use.allow.json (only if missing)

  3. The installer prints a jq patch command that adds the MCP server block and the permission block to ~/.config/opencode/opencode.jsonc. Review it, back up (done for you: opencode.jsonc.bak.<TIMESTAMP>), apply by hand. It is printed, not applied, because the live config is a 636-line file and scripted rewrites risk corrupting unrelated MCP entries.

  4. MCP server (verified present): computer_use_mcp.py in this repo is a stdio FastMCP server named computer-use (imports cleanly under /home/cyber/hexstrike-ai/hexstrike-env/bin/python, verified 2026-09-09). It exposes observe, focus_window, click, type_text, key, scroll, drag, clipboard, lease, estop (surfaced by opencode as computer-use_*), enforces the same lease/audit paths this skill uses, takes logical coordinates and scales internally. Point the printed mcp block at it verbatim. Until opencode mcp list shows it healthy, the skill refuses with MCP_MISSING.

  5. Start the mouse daemon (user action, needs /dev/uinput): dotoold & (or a user systemd unit with uinput group membership), then verify movement in a scratchpad. As of 2026-09-09 this host reports dotoold inactive, so mouse acts fail until you do this step.

Verify: opencode agent list shows computer-operator; ls /home/cyber/.config/opencode/skills/computer-use/SKILL.md; opencode mcp list shows computer-use healthy.

4. Usage

Normal session (primary agent routes plugin-first; GUI is last resort):

opencode run "@computer-operator click the New Tab button in zen"

What happens: primary delegates; subagent loads the computer-use skill, checks the allowlist for class zen, acquires the lease, proposes exactly one click with coordinate math, waits for your approval, acts, screenshots to verify, releases the lease, and reports screenshot paths.

Emergency stop at any time: touch /tmp/opencode-computer-use-estop. The operator halts before its next act and releases the lease. Resume only with a fresh explicit message.

Inspect a run: tail -f /tmp/opencode-computer-use-audit.jsonl cat /tmp/opencode-computer-use-lease.json

5. Safety model

  • Lease (/tmp/opencode-computer-use-lease.json, TTL 300 s, heartbeat <=120 s): mutual exclusion across sessions. Atomic acquire, never steal.

  • Approval: computer-use_*=ask in the agent definition. One approval covers exactly one act. The subagent has no bash/edit to route around it.

  • Allowlist (~/.config/opencode/computer-use.allow.json): default deny; entries match window class + optional title substring. Edits are user-only. always_allow_expiry_hours: 24 bounds re-approval lifetime.

  • Audit (/tmp/opencode-computer-use-audit.jsonl): append-only JSONL; unwritable log means no acts.

  • Estop (/tmp/opencode-computer-use-estop): presence halts all acts.

  • Refusals: opencode self-window, sudo/polkit/hyprlock/admin-auth, password-manager/vault exfiltration, non-allowlisted targets, and screen-content-as-instruction (prompt injection) all abort the run.

6. Limitations (factual, verified where stated)

  • No background operation: Hyprland has no off-screen session like macOS; every run seizes the visible desktop. Do not start one while presenting or while another person uses the machine.

  • No AX tree: Wayland exposes no accessibility hierarchy to clients, so grounding is vision + hyprctl window rects. Small/overlapping controls and popovers are the main mis-click source; the inside-focused-rect rule exists for exactly this.

  • HiDPI math is load-bearing: grim = physical 1920x1080, hyprctl = logical 1536x864 (scale 1.25), dotool = 0.0-1.0 fractions of the physical raster. A dropped x1.25 clicks 20% off-target. The skill requires the full chain in every audit entry.

  • ydotool/dotool daemon gap: verified 2026-09-09 that dotoold is inactive on this host; mouse is dead until the user starts the daemon with working /dev/uinput access. wtype (typing) needs no daemon.

  • slurp in interactive form blocks forever waiting for a manual drag; agents must never invoke it bare. Region capture uses grim -g with a computed geometry or grim -o eDP-1.

  • 144 Hz + screenshots: allow one settle frame after focus changes before grim; tearing/animating windows are a GROUNDING_STALE retry, not a click-spam license.

  • Without a healthy server everything degrades to a clean MCP_MISSING refusal (section 3.4), never a bash workaround.

  • Known server bug (dotool backend, computer_use_mcp.py click path): the dotool mouseto fraction is computed as logical-x / monitor-width, but hyprctl monitors reports width in physical pixels (1920), so under the dotool backend the cursor lands ~20% up-left of the intended logical point. The ydotool path (logical_to_physical) is correct. Workaround: prefer the ydotool backend (ydotoold running) and treat any consistently up-left click offset as this bug, not as agent mis-grounding (verify-fix in the server, not in agent prompts).

7. Troubleshooting (per error code)

  • OS_PERMISSION: run systemctl --user status dotoold; start it (dotoold & or user unit); check /dev/uinput group/permissions; test wtype in a scratch editor. The agent cannot and must not sudo.

  • MCP_MISSING: opencode mcp list; confirm the computer-use entry from section 3 is present and healthy; restart opencode after config change; re-run scripts/install.sh to re-verify file deployment.

  • APP_DENIED: confirm the window class with hyprctl activewindow -j; add/fix the entry in ~/.config/opencode/computer-use.allow.json yourself; check always_allow_expiry_hours has not lapsed.

  • LEASE_HELD: cat /tmp/opencode-computer-use-lease.json for holder and expiry; wait or ask the holder's user. Deleting a live foreign lease is forbidden. Remove only a provably stale one (holder session dead) and say so in chat.

  • GROUNDING_STALE: check focus (hyprctl activewindow -j), compare the last two screenshots, re-observe; after 3 failed grounds the run aborts and you should shrink the goal (larger control, settled window).

  • Skill/agent not discovered: filenames must be exact (SKILL.md caps; agent file deployed as computer-operator.md, not the draft name); skill dir must equal skill name (computer-use); check skill: deny permission overrides in opencode.jsonc.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables AI agents to control a Hyprland Wayland desktop by listing windows, capturing screenshots, and sending input to a dedicated agent workspace without disrupting the user's screen.
    -
  • A
    license
    A
    quality
    C
    maintenance
    Enables AI agents to operate a real GNOME Wayland desktop through accessibility-tree widget actions, pointer/keyboard input, OCR, window management, and screen capture, optionally on a private headless session.
    33
    8
    Apache 2.0
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables an AI agent to see and control a Linux desktop via Wayland/Hyprland, providing screenshots, structured desktop state, pointer/keyboard input, semantic window/workspace tools, and a policy engine for safe execution.
    Apache 2.0