Skip to content

Add Cua to Install > AI - #11342

Draft
spencerbull wants to merge 14 commits into
omacom:quattrofrom
spencerbull:add-cua-ai-menu
Draft

spencerbull wants to merge 14 commits into
omacom:quattrofrom
spencerbull:add-cua-ai-menu

Conversation

@spencerbull

@spencerbull spencerbull commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

Cua Driver lets coding agents inspect and operate desktop applications, but installing the package alone does not surface its agent skills or the optional Hyprland input route. This adds Cua to Install > AI and Remove > AI, and adds Trigger > Toggle > Cua Input when the plugin package is installed.

The installer adds cua-driver-bin, offers the upstream agent skills and an Omarchy companion skill, and installs cua-hyprland-plugin when the channel offers a resolvable package. The companion documents package ownership, the native Wayland environment, targeting and verification, and the plugin's limits. Existing skill directories and foreign symlinks are preserved. Omarchy exports CUA_DRIVER_RS_ENABLE_WAYLAND=1 for the native backend; installation also passes it to the running session's activation environment.

Cua Input checks the installed plugin against the running Hyprland before loading it. It requires cua-hyprland-plugin 0.32.0-3 or newer, supplied by omacom/omarchy-pkgs#772: background agent keyboards own their US keymaps, plain pointer operations do not require a US layout, foreground key operations validate the live mapping and modifier state while preserving compatible Num Lock state, and the module guards Hyprland 0.56.2 against an input-method crash. With input on, fcitx5 requests an input method on every agent seat, and when it exits, which omarchy-restart-xcompose makes it do, Hyprland can dereference an input-method popup whose surface is already gone and restart in safe mode. Earlier packages report the keyboard capabilities but carry no guard, so the toggle requires the package version and an active ime_popup_guard both. The toggle leaves the user's layout, variants, Compose key, Num Lock, and remaps unchanged. Caps Lock, held/latched modifiers, nonzero groups, and keys whose meaning changes remain guarded. Full foreground support for arbitrary layouts and Unicode/IME input remains outside this change. The plugin's application/version qualification restrictions still apply.

A loaded plugin without keyboard_layout_independent, foreground_numlock_compatible and an ime_popup_guard key is left mapped and input is turned off with a logout/login instruction. This detects an older module still running after package installation; it does not claim to identify every future package upgrade. A module reporting ime_popup_guard: false did not install its hooks, so it is refused with its own message instead: logging in again would load the same build. The flag sets plugin.cua.enabled only once hl.get_config sees that option: at login Hyprland reads the configuration before the start hook loads the module, and naming a plugin option earlier is an unknown-key config error. Hyprland reloads its configuration as soon as a plugin loads, so whenever the flag is already on while a module loads, at session start or when turning Cua Input on, the flag is held at enabled = false until the module passes and restored afterwards; both writes use conv=nocreat, so turning Cua Input off during session-start verification still wins. A failed hold, restore or reload removes the flag rather than leaving it reporting on. Log out and back in after updating a loaded plugin. Existing copied toggle flags that contain keyboard overrides are replaced on activation or session startup, and a failed startup check or load removes the flag. Turning Cua Input off removes its flag and reloads configuration without unloading the module.

The plugin remains an explicit opt-in after installation and pins its qualified Hyprland release. An unavailable package or unresolved pin does not undo the driver installation. Removal takes back the driver's own skills, unlinks only the Omarchy companion links it owns, turns off Cua Input before removing the plugin, and removes the driver's own state. The driver retains its upstream content-free telemetry default; cua-driver telemetry disable changes it.

Install > AI with Cua

Trigger > Toggle with Cua Input

Remove > AI listing Cua

This stays a draft until omarchy-pkgs#772 publishes 0.32.0-3: until then the channel's plugin pins the previous Hyprland, so on edge the installer skips it and the toggle refuses it.

🤖 Generated by Codex in T3 Code and Opus 5.5 in Claude Code. Reviewed by Codex XHigh.

@spencerbull

Copy link
Copy Markdown
Contributor Author

Second pass now that the plugin recipe has landed in omarchy-pkgs (#346, builds enabled by #432). Three commits since the PR opened, and the body above now describes the final state.

What the package side looks like today. cua-driver-bin is 0.27.0-1 in all three channel databases; 0.28.1 is merged and waits on a build. cua-hyprland-plugin is not in any channel database yet: its recipe is merged and unquarantined, but nothing has run bin/repo release for it. The plugin pins hyprland=0.56.2-2 exactly. The stable and rc mirrors still serve 0.56.2-2, so it will install there once built; the edge mirror carries 0.56.2-3 (Arch's "rebuild with plugin manager split"), so on edge pacman cannot resolve it until Cua ships a requalified profile.

What changed here.

  • omarchy-install-ai-cua resolves the plugin with pacman -Sp before touching sudo and, when the pin does not match, says which Hyprland the plugin wants and which one is installed, then carries on with the driver.
  • default/hypr/envs.lua exports CUA_DRIVER_RS_ENABLE_WAYLAND=1 to every session, and the install hands it to the running one. Without it the driver an agent starts from its own session uses the X11 backend only.
  • omarchy-toggle-cua-input under Trigger > Toggle > Cua Input is the package README's activation made reversible: consumer check, hyprctl plugin load, and a shipped Hyprland toggle flag holding the exact keymap the plugin admits plus plugin:cua:enabled. It refuses on non-US layouts, reloads the module at session start, and turns itself off if the check stops passing. The remover switches it off before dropping the plugin.

How it was proven. On an omabot worker on stable (Hyprland 0.56.2-2) I built the plugin from the merged recipe with makepkg (all CTests pass) and served it from a local pacman repo so the flow saw it exactly as a channel would. Install > AI > Cua then installed driver 0.27.0-1, both skill sets, and the plugin. Before the toggle, hyprctl -j cua:status reports discovery_only; after omarchy-toggle-cua-input on it reports input_v3_candidate, configured: true, a ready cua-inject-v2.sock transport, and the keymap reads back exactly evdev/pc105/us with empty variant and options. off restores the Omarchy keymap and unsets the plugin config with the module still mapped. A reboot with the flag on loads the module again with no config errors, and the Wayland flag shows in systemctl --user show-environment. cua-driver doctor and health_report are clean on the native Wayland backend. Remove > AI > Cua turned the toggle off first, dropped both packages and the state, and a reinstall through the menu came back clean. Screenshots are in the body.

Worth a product call. The plugin's background input route only admits the exact app versions Cua qualified, which on stable today is Inkscape 1.4.4-6 (the qualified Calc is 26.2.5-3; stable has 26.8.0-2). The toggle is explicit and off by default because of the keymap cost, but if that scope is too narrow to ship a switch for yet, the last commit lifts out cleanly and the install flow still installs the package and points at the README.

spencerbull and others added 8 commits September 25, 2026 21:11
U+E90F is the koala mark from cua.ai, taken from the monochrome
logo_black.svg in the trycua/cua repository. Upstream draws it as seven
paths and omarchy dev font takes exactly one, so cua.svg beside the font
keeps the merged single-path version the glyph was built from, and the
README records both. The charset range menu-test pins moves with it.

Co-Authored-By: Fable 5.1 <noreply@anthropic.com>
omarchy-provision-user links every skill under default/agents/skills into
the agent skill directories for everyone. A skill that only makes sense
once an optional tool is on the machine needs the same directories without
the unconditional provisioning, so this command links one skill directory
into them on demand and takes those links back with --remove.

It never replaces something the user put there: a real directory of the
same name is left alone, and so is a live symlink pointing somewhere else,
the rule cua-driver's own skill installer follows. --remove only deletes
links that resolve to the given skill, so a foreign link of the same name
survives.

Co-Authored-By: Fable 5.1 <noreply@anthropic.com>
The Install > AI entry runs omarchy-install-ai-cua in a floating terminal.
It installs cua-driver-bin, the Cua computer-use driver packaged in
omarchy-pkgs, then offers the Cua agent skills: the upstream pack through
`cua-driver skills install`, which links it into every agent skills
directory that exists, and an Omarchy companion under
default/agents/optional-skills/cua-omarchy covering package identity,
Hyprland geometry and focus, and the plugin, linked with
omarchy-agent-skill-link. The skills are opt-in because a skill is read
into every session of every agent on the machine. When the package channel
carries cua-hyprland-plugin it is installed as well, and its absence is
reported otherwise; the package never loads the module itself and pins the
exact Hyprland release, so the terminal says both.

Remove > AI lets the driver take back its own skill links before the
package goes, unlinks the companion, drops the plugin when present and
then the driver, and deletes the driver's identity, update-check, socket
and log state under ~/.cua-driver, ~/.config/cua and ~/.cache/cua-driver.

Co-Authored-By: Fable 5.1 <noreply@anthropic.com>
cua-hyprland-plugin depends on one exact Hyprland release, and edge moves
past it before the plugin is requalified: today the plugin pins 0.56.2-2
while the edge mirror carries 0.56.2-3. A channel can therefore offer the
package while pacman cannot install it, which used to surface as a failed
sudo pacman transaction followed by a generic message. pacman -Sp resolves
the same transaction without root, so the install now says which Hyprland
the plugin wants and which one is installed, and skips it.

Co-Authored-By: Fable 5.1 <noreply@anthropic.com>
The driver only takes its native Wayland backend when
CUA_DRIVER_RS_ENABLE_WAYLAND=1 reaches whichever process serves the
calls, and an agent following the skill pack starts that process from
its own session without knowing the flag. Omarchy is Wayland-only, so
default/hypr/envs.lua exports it for every session, and the Cua install
hands it to the running one through the user manager and the activation
environment so the first agent session after installing has it too. The
companion skill says where it comes from.

Co-Authored-By: Fable 5.1 <noreply@anthropic.com>
cua-hyprland-plugin ships no hook, autoload, or config edit on purpose:
its README makes activation an explicit step after the package's
compatibility check passes in a fresh session, and its input route only
admits one exact keymap (rules evdev, model pc105, layout us, nothing
else), which drops Omarchy's Compose-on-Caps-Lock while it is on. Left as
a hand ritual, the plugin the install flow adds stays inert.

omarchy-toggle-cua-input is that step made reversible. on refuses without
the package, on any layout other than a plain US one, and when the
package's own profile_verify.py says the module does not match the
running Hyprland; otherwise it loads the module and lands
default/hypr/toggles/cua-input.lua through omarchy-hyprland-toggle, which
sets the admitted keymap and plugin:cua:enabled. off removes the flag and
reloads; the module stays mapped for the session, as the package
requires. The flag runs --load at each session start, since a loaded
module does not outlive the session: the check runs again and a failure
turns the flag off rather than leaving the keymap changed for nothing.
The kit digest the verifier wants is read from the installed
KIT-PROVENANCE.json that pacman already verified, not pinned here where
it would go stale with every requalified profile.

Trigger > Toggle > Cua Input appears once the plugin package is
installed. The Cua install flow points there instead of at the package
README, and the remover switches the toggle off before dropping the
plugin. Verified on an omabot worker on stable (Hyprland 0.56.2-2) with
the plugin built from the merged recipe: on sets the keymap and
cua:status reports configured with a ready transport, off restores both,
and a reboot with the flag on loads the module again.

Co-Authored-By: Fable 5.1 <noreply@anthropic.com>
Require the plugin's independent agent keymaps and remove the toggle's human keyboard overrides. Refresh existing flags without recreating one removed by a concurrent off, and leave older mapped modules disabled until a new session.

Co-Authored-By: Codex XHigh <noreply@openai.com>
spencerbull and others added 5 commits October 3, 2026 21:27
With Cua input on, fcitx5 requests an input method on each agent seat, and when it exits (omarchy-restart-xcompose restarts it) Hyprland 0.56.2 can dereference a destroyed input-method popup surface and crash into safe mode. cua-hyprland-plugin 0.32.0-3 hooks the two methods that reach that surface and reports ime_popup_guard: true; earlier packages report the keyboard capabilities this toggle checked but carry no guard, so it would enable input on exactly the build that crashes. Require 0.32.0-3 and an active guard, treating a module without one like any other stale mapped module.
A loaded module with no ime_popup_guard key was mapped before the update, and logging out loads the new one. A current module reporting false means its hooks did not install; logging out would load the same build and fail the same way, so say that the guard is missing and point at cua:status instead.

Co-Authored-By: Codex XHigh <noreply@openai.com>
Hyprland reloads its configuration as soon as a plugin loads, and the flag already says plugin.cua.enabled = true at login, so the module resumed input before --load had checked it, including a module whose input-method guard failed to install. Rewrite the existing flag to enabled = false before loading and restore it only after the module passes; both writes use conv=nocreat, so a concurrent off still wins.

Co-Authored-By: Codex XHigh <noreply@openai.com>
A failed reload around the held flag ended --load under set -e, and a failed restore only notified, so each left a flag reporting Cua Input on while Hyprland's live configuration still held input off. Turn the toggle off on all three paths, as every other startup failure does.

Co-Authored-By: Codex XHigh <noreply@openai.com>
on with the flag already set and the module not yet loaded hit the same load-triggered reload as session start, so it now holds the flag the same way. A failed reload while landing the flag left it reporting on, and refuse could die on its own failed reload before telling the user; both now remove the flag and notify.

Co-Authored-By: Codex XHigh <noreply@openai.com>
@spencerbull

Copy link
Copy Markdown
Contributor Author

Tested at head 70c99e9f on real hardware, a Dell XPS 16 on Omarchy edge with Hyprland 0.56.2-4 and the cua-hyprland-plugin 0.32.0-3 build from omacom/omarchy-pkgs#772, run by Opus 5.5 in Claude Code. The toggle ran from a separate copy of this branch with OMARCHY_PATH pointed at it. Codex XHigh reviewed each of the four new commits and then the whole range: its findings (a failed guard told to log out, the load-time window at session start and in on, and three failure paths that left a held flag) are fixed with a test and a failing mutant each, and its final pass found nothing left to change.

  • on, off, toggle and --status against the real module: input enabled with ime_popup_guard: true, disabled again with the module still mapped, and no flag left behind.
  • The load-time window, measured with a hyprctl wrapper that reads cua:status 1.5 s after plugin load, in fresh sessions with the flag on and the module not yet loaded: configured=false with this branch, for --load and for on, then configured=true with the guard active once the checks pass; configured=true straight after the load with the previous commit, before any check had run.
  • The published 0.28.2-2 on the same machine reports keyboard_layout_independent and foreground_numlock_compatible but no ime_popup_guard, so this branch now refuses it where the previous head would have enabled input on it.

Still open before this leaves draft: omarchy-pkgs#772 has to publish 0.32.0-3, then Install > AI > Cua end to end against the real edge package and a session start through the installed omarchy-toggle-cua-input.

🤖 Generated by Opus 5.5 in Claude Code. Reviewed by Codex XHigh.

@spencerbull
spencerbull marked this pull request as ready for review October 4, 2026 03:38
@greptile-apps

greptile-apps Bot commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 2/5

[Medium risk] Adds Cua driver installation and Hyprland plugin integration.

The PR does not appear safe to merge while Cua Input can be re-enabled after an off request or remain active during removal or a failed reload.

Findings

  1. P1 Concurrent off is undone ▶
  2. P1 Failed reload leaves input active ▶
  3. P1 Removal skips enabled input ▶

Summary

This PR adds Cua Driver installation and removal, optional agent skills, and an opt-in Hyprland input toggle. Since the previous review, the toggle flag was changed to avoid setting the plugin option before the module loads. No new finding arose from that change; three previously reported issues remain outstanding.

Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Install Cua Driver] --> B[Optionally install skills and plugin]
  B --> C[User enables Cua Input]
  C --> D[Check package and compatibility]
  D --> E[Load module with input held off]
  E --> F[Verify module and guard]
  F --> G[Restore enabled flag and reload]
  G --> H[Turn off or remove: delete flag and reload]
Loading

Reviews (2) · Last reviewed commit: "Set the Cua plugin option only while the..."

refuse "Log out and back in to use the updated Cua plugin, then turn Cua Input on again."
fi
ime_guard_active || refuse "The Cua plugin could not install its input-method crash guard; hyprctl -j cua:status has the details."
omarchy-hyprland-toggle "$FLAG" on >/dev/null || refuse "Hyprland could not reload its configuration; Cua Input stays off."

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Concurrent off is undone

If an on command is still verifying or loading the plugin when the user turns Cua Input off, the off command removes the flag and reloads Hyprland. This final on call then recreates the flag and enables input again. Unlike the startup restore, it does not preserve the user's off request.

Knowledge Base Used: Hyprland configuration and display control

Comment on lines +122 to +124
turn_off() {
omarchy-hyprland-toggle "$FLAG" off >/dev/null
notify "Cua input off" "The plugin stays loaded until you log out."

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Failed reload leaves input active

If hyprctl reload fails while turning Cua Input off, the flag has already been deleted, but the running compositor can retain the enabled setting. This command exits before notifying the user. The refusal path also ignores a failed off reload, so it can say input is off while it remains active.

Knowledge Base Used: Hyprland configuration and display control

Comment thread bin/omarchy-remove-ai-cua
Comment on lines +19 to +23
if omarchy-pkg-present cua-hyprland-plugin; then
# The keymap override and the session-start reload go now; the module
# itself stays mapped for the rest of the session, as the package requires.
if omarchy-hyprland-toggle-enabled cua-input; then
omarchy-toggle-cua-input off

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Removal skips enabled input

If the plugin package was removed separately while its module and input remain enabled in the running session, removing Cua skips the off command because the package is absent. The mapped module can remain active until logout, and the enabled flag survives removal.

Knowledge Base Used: Hyprland configuration and display control

The flag ran hl.config({ plugin = { cua = { enabled = true } } }) whenever Hyprland read its configuration, but at login the module is loaded afterwards, by the hyprland.start hook, so every login with Cua Input on showed "unknown config key 'plugin.cua.enabled'". On an Omabot worker, drawing that error at startup deadlocked Hyprland 0.56.2. hl.get_config returns nil for a key no plugin has registered and a value once the module is loaded, so the flag now checks it first; the reload that follows the load applies the setting, and --load's hold still keeps it off until the module passes.
@spencerbull

Copy link
Copy Markdown
Contributor Author

End-to-end run at head d1b45b13, against the published cua-driver-bin 0.28.2-3 and cua-hyprland-plugin 0.32.0-3 from the edge repository, run by Opus 5.5 in Claude Code on two machines: an Omabot Proxmox worker built from the Omarchy ISO, switched to edge and dev-linked to quattro with this branch merged, and a Dell XPS 16 on edge running the branch from a separate copy. Codex XHigh reviewed the one new commit and found nothing to change.

What the run found. With Cua Input on, every login showed "Your config has errors: … unknown config key 'plugin.cua.enabled'", because the flag set the option when Hyprland read its configuration and the start hook only loads the module after that. On the worker, drawing that error at startup deadlocked Hyprland 0.56.2 (main thread waiting in Hyprgraphics::CAsyncResourceGatherer::await under ErrorOverlay::COverlay::createQueued), and the toggle's start hook then found Hyprland unresponsive and removed its own flag. d1b45b13 sets the option only once hl.get_config("plugin.cua.enabled") returns a value, which it does only while the module is loaded; a real reboot with Cua Input on then came up with no config errors, the plugin loaded by the start hook, input on with ime_popup_guard: true, and the flag intact.

Install and remove. Install > AI > Cua, run through the menu's own action, installed both packages from the signed repository (pacman: validated by checksum and signature), linked the Cua skills into the Claude, Codex, agents and Hermes directories, and set CUA_DRIVER_RS_ENABLE_WAYLAND for the session. Remove > AI > Cua removed both packages, every skill link it added and the driver's state, turned Cua Input off and left the mapped module in place with input disabled.

Computer use, driven by an agent through the installed packages, on both machines:

  • Browser: an isolated driver-owned Chromium bound exactly; example.com read from a semantic snapshot; a Wikipedia search typed through the page route and submitted with a DOM-event click, landing on the article; a local form filled by typing, then checkbox, select, button, slider drag and scroll through the plugin's foreground route, each confirmed by the page; navigation from the address bar.
  • Inkscape 1.4.4-6 in the background with a terminal focused: page fit, rectangle drawn within a pixel of the requested bounds, coloured, saved and found in the SVG.
  • LibreOffice Writer: first-run dialog closed through AT-SPI, a paragraph typed through AT-SPI, then foreground typing with a Ctrl+B bold run and Ctrl+S, all found in the saved file.
  • A terminal: a line containing every printable ASCII class typed in the foreground and written to a file byte for byte; omarchy-restart-xcompose with input on left Hyprland running, and typing continued.

Limits seen, none of them introduced here: the driver's trusted CDP clicks are refused on Hyprland even with the browser focused (its page-route typing and DOM-event clicks work); a GTK popover that holds a grab, such as Nautilus's rename, refuses all plugin input, by design; foreground typing aimed at an unfocused window stops after two or three keys while fcitx5 is running, so the target needs focus first; and background input refuses a window under the user's pointer (primary_target_busy).

This stays a draft until a maintainer reviews it.

🤖 Generated by Opus 5.5 in Claude Code. Reviewed by Codex XHigh.

Before d1b45b13: the config error at login with Cua Input on

After d1b45b13: a clean login with the plugin loaded and input on

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants