# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [0.7.21] - 2026-10-20
### Fixed
- Read WebKitGTK accessibility content through well-known AT-SPI child references and indexed localized action methods. Bound action discovery and revalidation so unresponsive peers do not block later input. Thanks @OnlyHa1bara. (#273)
- Return an error after X11 typing if an XKB layout replacement or a persistent mapping/group change is detected. Detect the reported br-to-us-to-br replacement even when the original layout is restored. Do not replay dispatched input. Preserve xdotool dispatch with an explicit warning when monitoring cannot start. This detects the layout-change case in #272; it does not repair dispatched text, prove field contents, detect every transient remap/group change, or fix the separately reported loss with a stable keymap. Thanks @JADRT22 for the reproduction.
## [0.7.20] - 2026-10-18
### Fixed
- Warn after X11 xdotool text dispatch that non-US or changing XKB layouts can silently substitute symbols. Require inspecting the text before submitting it. Correct the post-action test subprocess selector so its assertions execute. (#267)
## [0.7.19] - 2026-10-17
### Fixed
- MCP hosts that probe with `server/discover` before `initialize` (MCP 2026-07-28) no longer fail with "expect initialized request". The server now uses rmcp 3.5.1, keeps the connection open after an empty probe so the host can initialize, and supports metadata-bearing discovery requests.
## [0.7.18] - 2026-10-17
### Added
- Support opt-in post-action observation (`screenshot_after: true | "screen" | "window"`, `format`, `quality`, `scale`, `max_width`, `max_height`, `max_bytes`, and `include_tree: true`) on mutating tools (`click`, `drag`, `scroll`, `press_key`, `type_text`, `perform_action`, `set_value`, `activate_window`, `move_window`, and `resize_window`) so an action and its verification can complete in one MCP round trip. (#259)
## [0.7.17] - 2026-10-16
### Fixed
- Stabilize Hyprland wtype input for long text in confirmed nonsecret fields. Keep terminal and unknown-field text on private stdin, limited to 100 Unicode characters per call, and reject confirmed password fields. (#256)
- Preserve missing-focus warnings for content trees, including renderer hints computed before tree compaction. Recognize Electron editable states and qualify successful text input as dispatch-only. (#256)
## [0.7.16] - 2026-10-13
### Fixed
- Replace the KWin backend atomic update with stable Rust primitives so source builds work on Rust 1.93.1. (#252)
## [0.7.15] - 2026-10-10
### Fixed
- Treat focused AT-SPI terminals as keyboard targets without requiring an EditableText interface. Keep warnings for other non-editable controls. (#246)
- Send X11 text newlines as Return instead of Linefeed, with one newline per CRLF pair. (#247)
## [0.7.14] - 2026-10-10
### Fixed
- Wait for COSMIC focus state and verify window activation. Report missing initial state as an error, discard closed windows, and wait for complete monitor layouts. (#245)
- Preserve screenshots in native Pi codemode calls with structured results and image blocks accepted by `image()`. Expose MCP tool errors in structured results. (#243)
## [0.7.13] - 2026-10-08
### Fixed
- Remove new portal screenshot files after reading them, including invalid images and cancelled queued reads. Snapshot Pictures filenames before requesting capture, preserve existing names, and hold the returned file open so a replacement cannot reuse its inode.
- Shorten ydotool test directory names so private scratch paths fit Unix socket limits.
## [0.7.12] - 2026-10-07
### Added
- Add a native GNOME Shell activity indicator with cursor motion, click pulses, keycaps, typed-text masking, agent colors and idle fading. The helper preserves shared capture exclusion and rejects captures when hiding is not acknowledged.
- On-screen indicator, on by default: `computer-use-linux-indicator` draws a
software cursor that glides to coordinate pointer targets and ripples on
click, keycaps and a typing line for keyboard input,
an edge glow, and a status pill naming the agent from the MCP `clientInfo`.
Pointer actions wait 350 ms for the cursor to land; AT-SPI actions report
their status without moving it. Screen captures require the capture lock
and a valid hide acknowledgement from a running overlay. `set_value`
values are always masked; keycaps and typed text are masked for password
or unknown focus. Uses `wlr-layer-shell` or the GNOME Shell extension; set
`COMPUTER_USE_LINUX_INDICATOR=0` to turn it off. Installed by `./install.sh`,
`cargo install`, npm, and published as a release asset.
### Fixed
- Reuse desktop session discovery until its environment changes. Process screenshot files and encode images on one blocking worker so large captures keep MCP responsive without multiplying decoded-image memory.
- Refresh already-enabled GNOME extension assets during installation and report the required session restart.
- Mask generic text-box roles, terminal focus and generic enum fallback roles in typed text and keycaps. GTK obscured entries can advertise the same text-box role as public entries.
- `setup-window-targeting` enables the system extension in `/usr/share/gnome-shell/extensions` if a distribution package installed it. It installs the user extension in `~/.local/share/gnome-shell/extensions` only if there is no system extension. If there is a system extension, setup removes the user extension from earlier setups and asks for a GNOME Shell reload. Before, setup always installed the user extension, and GNOME Shell used it instead of the system extension, so package updates had no effect.
- The GNOME Shell extension supports GNOME Shell 51.
- On at-spi2-core 2.62 and later, the doctor check `screen_reader_enabled` failed with "No such property ScreenReaderEnabled", because 2.62 removed that D-Bus property. If the property does not exist, doctor now reads the `org.gnome.desktop.a11y.applications screen-reader-enabled` setting. With older at-spi2-core versions, doctor still reads the property.
- The doctor checks `at_spi_enabled` and `screen_reader_enabled` now show text such as "AT-SPI IsEnabled is false" and "Screen reader is off". Before, they showed raw D-Bus output such as `b false` or `(<false>,)`.
## [0.7.11] - 2026-10-04
### Fixed
- Doctor now separates detected screenshot routes from verified capture. A detected route reports `screenshot_capture_status: "unverified"` and `can_capture_screenshots: false`; use `get_app_state` with a screenshot to obtain `verified` or `failed`. Unverified capture is a setup warning, and callers should not treat the boolean alone as a missing backend.
- GNOME literal text prefers the portal and rejects strings its keymap cannot represent before typing. Wayland coordinate input refuses inaccurate relative-motion fallback. (#226)
- Portal wheel direction matches compositor axis signs on GNOME and KDE. (#226)
- Screenshot errors retain their backend causes, and diagnostic subprocesses have bounded execution and cleanup.
### Changed
- Local development builds keep line information with less debug data, and CI host builds share their cache. Release settings are unchanged. (#225)
- Pi and schema-check dependency lockfiles address audit findings. (#221)
## [0.7.10] - 2026-10-01
### Security
- COSMIC targeted input trusts compositor-reported focus rather than an
activation cache, and no longer writes focus state into a shared temporary
file. GNOME extension calls verify the unique owner of `org.gnome.Shell`. (#215)
- Portal responses are bound to the expected sender and request path.
Screenshot files reject symlinks and non-regular files and enforce byte and
decoded-pixel limits before processing. (#215)
- Automatic ydotool discovery accepts only private, same-user sockets and
no longer falls back to shared `/tmp` sockets. The installer creates a
mode-0600 daemon socket; `YDOTOOL_SOCKET` remains an explicit override. (#215)
- Scroll amounts must be finite and within -100 to 100 before input locks
are taken. Pi executable and PATH overrides must use absolute paths. (#215)
### Fixed
- MCP safety checks recognize npm launcher error output without weakening
the failure assertions. (#214)
## [0.7.9] - 2026-10-01
### Fixed
- Screenshot execution failures return MCP tool results with `isError: true`
and the original error message. Window targeting, capture, crop, and resize
failures no longer surface as JSON-RPC internal errors that some clients
mistake for broken connections. (#210)
- KWin temporary plugin sequences use the current atomic update API so
builds with warnings denied pass on Rust 1.99. (#211)
## [0.7.8] - 2026-10-01
### Added
- Official Claude Code and Codex plugin. The repo is a marketplace for both
hosts: `claude plugin marketplace add agent-sh/computer-use-linux` or
`codex plugin marketplace add agent-sh/computer-use-linux`. The plugin ships
the skill and a launcher that downloads the release binaries pinned to the
plugin version, verifies their sha256, and caches them per version. The
Codex manifest forwards the desktop session variables that Codex strips
from MCP server environments. `COMPUTER_USE_LINUX_BIN` runs a local build. (#202)
### Fixed
- Native X11 queries now enforce one deadline in the transport itself.
Connect, handshake, and every reply share a 2-second bound, so a stalled
X server closes the query connection instead of leaving a blocked worker
running after a timeout. The `doctor` X11 check no longer spawns a
detached thread. Unix sockets, literal IP addresses, and `localhost` need
no resolver; a remote hostname in `DISPLAY` resolves through
`getent ahosts` under the same bound, and a missing or failing lookup
reports the X11 route as unavailable. Fix by Gary Lysenko (ilysenko),
from ilysenko/codex-desktop-linux#1532. (#203)
- Accessibility snapshots stay stable during input. The cached nodes and
the pid that owns them are now one snapshot, and `get_app_state`
publishes a new one only after in-flight input finishes. An index that
passed the owner check can no longer resolve to another app's node
mid-action. `perform_action` and `set_value` now take the input lock that
`click` and `scroll` already held. Fix by Gary Lysenko (ilysenko), from
ilysenko/codex-desktop-linux#1532. (#203)
- PTY metadata alone no longer makes a window a paste-capable terminal. The
paste chord comes only from a known terminal app id or WM_CLASS, so an
IDE with an integrated terminal keeps the standard paste shortcut. PTY
enrichment now also recognizes Ghostty, GNOME Terminal, and KGX by app
id or WM_CLASS, not only by title, which keeps enrichment working for
X11 windows with a custom class and a plain title. This replaces the
earlier rule that defaulted an enriched window with no known identity to
Ctrl+Shift+V. Fix by Gary Lysenko (ilysenko), from
ilysenko/codex-desktop-linux#1532. (#203)
- The bounded process runner no longer sleeps after every chunk while a
command is still producing output. Each drain stays capped and the
deadline is still checked every pass, so continuous output cannot starve
stderr or bypass the output limit. Fix by Gary Lysenko (ilysenko), from
ilysenko/codex-desktop-linux#1532. (#203)
||||||| parent of 1954063 (feat: official Claude Code and Codex plugin)
## [0.7.7] - 2026-09-30
### Added
- Window listing and exact focus on niri through `niri msg`, with direct
JSON IPC as a fallback when the CLI is unavailable. Socket discovery
matches the current Wayland display and refuses ambiguous sessions.
Focus is verified with a fresh window query before targeted input.
Window bounds account for output scaling and window offsets. Missing
positions stay null; unknown or mixed scaling omits bounds. (#192)
## [0.7.6] - 2026-09-29
### Fixed
- Wayland `press_key` on the remote-desktop portal now sends modifiers and
named keys (Enter, arrows, F-keys and the rest) as keysyms, so the
compositor resolves them against the active keymap. With Caps Lock and
Control swapped, `Ctrl+A` used to press the physical Control position,
which toggled Caps Lock and typed `A`. It now selects all. Letters and
digits stay physical keycodes: mutter drops a keysym missing from the
current layout group, so a keysym `a` would vanish under a Hebrew or
Cyrillic layout, and GTK and Qt match shortcuts on those layouts by the
US keycode. KDE Plasma keeps keycodes for now. (#191)
## [0.7.5] - 2026-09-28
### Added
- Opt-in persistence for the Wayland remote-desktop portal. Set
`COMPUTER_USE_LINUX_PERSIST_REMOTE_DESKTOP=1` to send `persist_mode=2`
on `RemoteDesktop.SelectDevices` and reuse the single-use `restore_token`
returned by `Start`. Nothing persistence-related is sent on
`ScreenCast.SelectSources` (that call rejects it for a remote-desktop
session). Pointer and keyboard sessions store separate tokens, mode
`0600`, under `$XDG_STATE_HOME/computer-use-linux/` or
`~/.local/state/computer-use-linux/`. The first grant still shows the
dialog. Later processes restore until the desktop revokes the grant, or
until the token cannot be restored, which falls back to a prompt.
Interface version 2 is required. Unset, behavior is unchanged. (#185)
### Fixed
- X11 `scroll` no longer follows ydotool's absolute move with a single wheel
event. That move warps the pointer through (0, 0). GTK 3 resets its XI2
scroll valuators when the pointer re-enters the window, so the one wheel
event only re-baselines them and the window does not move, while the tool
still returns success. Native X11 now sends the same notch count as XTEST
wheel buttons through xdotool (4 up, 5 down, 6 left, 7 right), which have
no scroll valuators. Wayland portal scroll is unchanged. (#184)
## [0.7.4] - 2026-09-27
### Fixed
- The #167 index check no longer trusts a pid the snapshot did not match.
When `get_app_state` named a pid with no accessibility root plus an app
name, the tree came from the app-name match but was recorded under the
requested pid. An index from that tree then passed a click aimed at the
requested pid and was refused for the app that owns it. The snapshot now
records a pid only when its roots were selected by that pid; otherwise each
node is checked against its owner on the accessibility bus.
## [0.7.3] - 2026-09-26
### Fixed
- `click` and `scroll` by `element_index` or selector now refuse an index from
another app's snapshot. `get_app_state` records the pid it snapshotted;
when the action's target resolves to a different pid, the call fails and
asks for a `get_app_state` of the target, instead of acting on the other
app's node and reporting `ok: true`. An untargeted snapshot mixes apps, so
its node is checked against the pid that owns it on the accessibility bus.
(#167)
- Portal pointer input on scaled GNOME Wayland (for example 125 %) now lands
where it is aimed. mutter maps a stream point to `monitor.x + stream_x /
scale` when its layout mode is logical, which is the GNOME 50 default, so
logical coordinates arrived at 1/scale of the target and still reported
success. The pointer path reads the layout mode from
`org.gnome.Mutter.DisplayConfig` and sends each stream's point multiplied
by its monitor scale. Click, scroll, and drag share the path. Unscaled
monitors, physical layout mode, and other compositors are unchanged. (#169)
- The Pi extension falls back to `computer-use-linux` on `PATH` when neither
`COMPUTER_USE_LINUX_BIN` nor the downloaded package binary is available.
Temporary extensions (`pi -e npm:@agent-sh/computer-use-linux`) are staged
without that binary and warned "binary not found" even with a global
install. The PATH lookup was dropped in the native-tools rewrite. (#170)
- `type_text` and `press_key` no longer warn "no focused element" when the
focus probe merely ran out of budget. The 400-node search now reports when a
node, depth, or read limit stopped it, and the feedback says the input could
not be verified instead. With a target pid, the probe searches only that
app; when no AT-SPI app belongs to it (xterm, Electron without
`--force-renderer-accessibility`), feedback says so instead of warning or
reporting another app's focused widget. (#168)
- KDE Plasma clipboard paste into xterm, uxterm, rxvt, urxvt, and koi8rxterm
now sends Shift+Insert. Those terminals have no Ctrl+Shift+V binding by
default, so the paste was dropped; Klipper sets the selection as well as
the clipboard, so Shift+Insert pastes the new text. When AT-SPI reports a
focused element that is not a terminal (a search field in a terminal
window), paste falls back to Ctrl+V. The check reads the AT-SPI role enum,
not the localized role name. Behavior ported from
ilysenko/codex-desktop-linux#1413.
- Helper spawns (ydotool, wtype, xdotool, gnome-screenshot, and every command
run through the supervised runner) retry a transient `ETXTBSY` ("Text file
busy") for up to 75 ms. The error appears when a helper binary is being
replaced, and it made xdotool fall back to ydotool as if it were missing.
It also made tests that write and exec fake helper scripts fail under the
parallel suite, which failed the first v0.7.2 tag run.
## [0.7.2] - 2026-09-26
### Added
- Native X11 screenshot route: one `GetImage` on the root window over the
X11 connection, used only on a native X11 session (never XWayland) and
tried after GNOME Shell and the portal, before `gnome-screenshot`.
Pixels are device pixels, the space xdotool input and X11 window origins
use. MATE/X11 had no working route: xdg-desktop-portal-gtk has no
Screenshot, and gnome-screenshot 41 blacks out 3/4 of the frame at
window-scaling-factor 2. `doctor` reports the route as
`platform.x11_display` and `capabilities.screenshot` entry `x11`;
`COMPUTER_USE_LINUX_SCREENSHOT_BACKEND=x11` pins it. (#155)
### Fixed
- `doctor` no longer reports the XDG Screenshot, ScreenCast, or InputCapture
portal as available when the portal does not export that interface.
`busctl introspect` exits 0 with only a header line for a missing interface,
so each entry now requires its methods (Screenshot: `Screenshot`). Readiness
gains `can_capture_screenshots` and a blocker when no screenshot route is
detected; this is detection, not a test capture. (#156)
- X11/EWMH window origins now come from the X server
(`TranslateCoordinates` to the root window) instead of `wmctrl -lG`, which
counts the client's offset inside its frame twice. Window-targeted
screenshots cropped the wrong area, relative clicks were offset by the same
amount, off-screen warnings misfired on maximized windows, and
`move_window` reported a mismatch after a correct move. Bounds are the
client area; `move_window` now verifies the frame origin it requested. When
the X server cannot be asked, the origin is reported unknown instead of the
shifted wmctrl value. (#157)
## [0.7.1] - 2026-09-19
### Changed
- `get_app_state` now returns its screenshot as a structured `image` content
block (the same shape as the `screenshot` tool) followed by the JSON report
as text and `structuredContent`. The JSON `screenshot` field keeps the
metadata (dimensions, scale, format, bytes) but no longer embeds the base64
`data_url`, which hosts were counting as ~30K text tokens per call. Callers
that read `screenshot.data_url` from the JSON should read the image block
instead. (#145)
### Fixed
- `type_text` on X11 no longer delivers characters out of order. The xdotool
backend passed `--delay 0`, which lets XTEST key events race each other on
some X servers (seen on Cinnamon / Mint 22). It now uses xdotool's 12ms
per-character default and scales the command timeout with text length.
`COMPUTER_USE_LINUX_XDOTOOL_TYPE_DELAY_MS` overrides the delay. (#147)
- The unscoped-tree warning from `get_app_state` no longer tells a caller that
already passed a `pid` or window target to pass a target. When the target
matched no AT-SPI application root, the warning now points at the app's
missing accessibility support, `list_apps`, and a lower `max_nodes` instead.
## [0.7.0] - 2026-09-16
### Added
- `get_app_state` reports `tree_scoped` and `accessibility_tree_truncated`,
warns in `message` when no app target narrowed the AT-SPI tree to one app,
and documents every scoping parameter in its schema, the server
instructions, the skill, and the Pi guide. Unscoped calls used to return the
whole desktop tree silently and could exhaust a small context window.
### Fixed
- Skill Install section now separates Pi native install from PATH CLI/MCP
install, so `pi install` is not described as sufficient for shell `doctor`
and `setup`.
## [0.6.0] - 2026-09-15
### Added
- GTK4 delivered-event coordinate probe and an opt-in GTK3/MCP semantic-click
regression that verifies actual button activation at scales 1 and 2.
- Explicit foreground `guard-accessibility` command with a passive AT-SPI
listener and verified GNOME toolkit-accessibility reassertion. Ctrl-C or
SIGTERM stops the guard without disabling other accessibility clients or
restoring an old saved setting. Never started automatically by MCP or setup.
- Optional `complete_interaction` MCP notification, enabled by
`COMPUTER_USE_LINUX_NOTIFY_ON_COMPLETE=1`, with bounded notification execution
and graceful handling of unavailable desktop notification services.
### Fixed
- KDE Plasma terminal paste uses terminal shortcuts, including uxterm detection.
- Setup verifies saved GNOME accessibility settings instead of reporting an
unverified write as success.
- Plain left element/selector clicks prefer recognized native AT-SPI activation
actions over toolkit bounds, avoiding GTK3 HiDPI and GTK4 zero-origin pointer
conversion when a matching action is available. Explicit coordinates, right
clicks, and multi-clicks preserve pointer semantics.
- Clarified that relative click/scroll coordinates use the clipped window
screenshot crop origin before preview resizing, not raw surface or widget
coordinates, and require a window target.
## [0.5.0] - 2026-08-31
### Added
- The Pi package now exposes native `computer_use_linux_*` tools without a
separate MCP adapter. One small loader stays active initially, then uses
Pi's additive dynamic-tool loading to expose selected tools with their exact
generated MCP schemas only when desktop control is needed.
- Pi keeps one lazily started, session-scoped computer-use-linux process,
forwards cancellation, serializes desktop actions, preserves image results,
bounds text output, and rejects binary/schema version drift.
### Changed
- Pi installation is now one command (`pi install
npm:@agent-sh/computer-use-linux`) and no longer writes
`~/.pi/agent/mcp.json`. Existing adapter-based entries are detected and
reported for non-destructive manual cleanup.
## [0.4.10] - 2026-08-29
### Added
- An explicitly opt-in `run_shell` MCP tool supports bounded same-user shell
execution for trusted remote MCP deployments. The tool is absent unless
`COMPUTER_USE_LINUX_ENABLE_SHELL=1`, clears ambient credentials, requires
visible environment additions, enforces timeout/output limits and process-
group cleanup, and emits command-digest audit records.
### Fixed
- Wayland literal text now uses `wtype` on compatible compositors when portal
keyboard input is unavailable, preserving Unicode before the ydotool
fallback. Known-incompatible GNOME, KDE/Plasma, and COSMIC sessions do not
advertise or select wtype, and a launched failure never replays the text.
- Absolute uinput pointer axes now end at the final logical desktop pixel, so
edge coordinates are advertised and clamped consistently.
- Capability maps now advertise AT-SPI only when its bus is reachable and a
toolkit accessibility status is actually enabled.
- Buttons outside the absolute uinput device's left, middle, and right set now
fall through to a backend that can synthesize them instead of becoming left clicks.
- Temporary KWin script callbacks now accept one matching response from the
current `org.kde.KWin` bus owner, reject spoofed or replayed responses, and
time out the complete script transaction before cleaning up owned temporary
state without disturbing a colliding callback registration.
- KWin window listings now classify Plasma 6 native Wayland and Xwayland
clients when the legacy client flags are unavailable.
- GNOME extension setup now reports when changed files require an already-active
Shell extension to reload before its newly installed DBus methods are served,
and requires that reload when the previous extension state cannot be read.
## [0.4.9] - 2026-08-12
### Fixed
- Bounded AT-SPI traversals now use concurrent indexed child reads, count both
queued references and failed child lookups against their work budgets, and
enforce a snapshot deadline so wide, malformed, or stalled accessibility
trees cannot allocate or retain unbounded work.
## [0.4.8] - 2026-08-12
### Fixed
- AT-SPI state capture now reaches deeply nested GTK4 controls such as Nautilus
file cells by using a 1,000-node default budget and depth-32 traversal, with
bounded 2,000-node and depth-64 limits shared by the MCP and CLI paths.
- `install.sh` now treats unavailable window-targeting or exact-focus support as
a degraded platform capability when MCP registration, accessibility trees,
and development input are ready, while missing core prerequisites remain hard
failures. The same classification applies when `jq` is unavailable.
## [0.4.7] - 2026-08-09
### Fixed
- `install.sh` now recognizes Artix as pacman-based, chooses an explicitly
requested or unambiguous package manager for unknown distros, treats
ydotool as an optional fallback, installs the required xdotool keyboard
backend on X11, distinguishes pointer-only direct uinput from keyboard-ready
input in `doctor`, reports Wayland RemoteDesktop pointer availability
separately from its required keyboard contract, and skips automatic ydotoold
setup when a systemd user manager is unavailable.
## [0.4.6] - 2026-08-05
### Fixed
- Native X11 coordinate clicks now use one supervised
`xdotool mousemove -- X Y click --repeat N BUTTON` command after the
absolute pointer and eligible portal paths, with `ydotool` fallback only
when `xdotool` cannot be spawned. Standard left, middle, and right buttons
are supported; extended buttons retain the existing fallback path. Set
`COMPUTER_USE_LINUX_FORCE_YDOTOOL_POINTER=1` to skip xdotool.
## [0.4.5] - 2026-08-01
### Fixed
- Stateful ydotool operations now complete while retaining the serialized input
lock after caller cancellation, preventing paired button or key events from
being interrupted. Drag also attempts button release after intermediate
failures.
- Scaled KWin sessions now map logical window geometry through the compositor's
virtual screen geometry while preserving logical portal input coordinates.
- Hyprland window bounds now map against grim's complete global output union,
including negative origins and mixed or fractional scales, and are omitted
when monitor metadata is unavailable or invalid.
- Mirrored KScreen outputs are excluded from the portal monitor layout.
## [0.4.4] - 2026-07-31
### Fixed
- KWin window listing and activation now support both Plasma 6
(`windowList`/`activeWindow`) and Plasma 5 (`clientList`/`activeClient`).
- ydotool is now used only when its CLI, daemon, and socket support the raw
event semantics Computer Use emits. Compatibility probing works without
`XDG_RUNTIME_DIR`, uses an isolated private socket, and rejects CLI errors
that are returned with a successful exit status.
- X11 `xdotool type` now disables per-character delay, and a command that
starts but fails is no longer replayed through ydotool. The ydotool fallback
is limited to failures to launch xdotool, avoiding duplicate partial input.
## [0.4.3] - 2026-07-31
### Fixed
- Hyprland window activation now checks `hyprctl dispatch` stdout instead of
trusting its exit status, so an exit-zero `Invalid dispatcher` response falls
through to the compatible focus dispatcher. (#62)
- Modifier chords sent through the ydotool fallback now include a 100 ms
inter-event delay so applications such as Firefox do not drop simultaneous
modifier and key events. (#63)
## [0.4.2] - 2026-07-25
### Fixed
- X11 keyboard input now goes through `xdotool` (XTEST) instead of ydotool.
ydotool injects raw evdev scancodes into a virtual uinput device, which X11
re-interprets through the active XKB layout — so `press_key "Return"` and
chords like `ctrl+a` landed as stray characters, and `type_text` mangled
symbols and digits (`_` → `%`, `1` → `+`) even on a plain US layout. XTEST
resolves keysyms against the live layout. Wayland behaviour is unchanged, and
the ydotool path remains the fallback when `xdotool` is missing or fails.
`doctor` now reports an `xdotool` input backend on X11. Override with
`COMPUTER_USE_LINUX_FORCE_YDOTOOL_KEYBOARD=1` (opt out) or
`COMPUTER_USE_LINUX_FORCE_XDOTOOL_KEYBOARD=1` (force on). (#58)
- Portal `scroll` direction on KDE Plasma Wayland: vertical discrete axis steps
are inverted for the xdg-desktop-portal-kde discrete path so `direction:
"up"|"down"` matches viewport motion. ydotool / REL_WHEEL polarity is
unchanged. Override with `COMPUTER_USE_LINUX_PORTAL_SCROLL_INVERT=0|1`. (#56)
## [0.4.1] - 2026-07-15
### Fixed
- Targeted `get_app_state` screenshots now crop to the resolved target window,
and refuse the full-desktop fallback when a target was requested but window
bounds cannot be resolved or the window is entirely off-screen. (#48)
- Hyprland window bounds are normalized against each window's monitor origin
and fractional scale so portal screenshot coordinates align on
multi-monitor and scaled (e.g. 1.8x/2.0x) setups. (#48)
- Wayland sessions are recognized via `WAYLAND_DISPLAY` when
`XDG_SESSION_TYPE` is unavailable, so the portal input fallback engages in
environments that don't export the session type. (#48)
- Window focus verification now allows up to one second for compositor
workspace/focus transitions before reporting activation failure. (#48)
## [0.4.0] - 2026-07-15
### Added
- Generic X11/EWMH window backend so `list_windows`, `focused_window`,
`activate_window`, `move_window`, and `resize_window` work on X11 window
managers without a dedicated backend (Cinnamon/Muffin, MATE/Marco,
Xfce/xfwm4, Openbox, and others). (#41)
- Pi coding agent extension package: `pi install npm:@agent-sh/computer-use-linux`
now provides Linux desktop control tools through `pi-mcp-adapter`'s MCP
proxy without a separate pi-specific skill. (#42)
### Fixed
- Hyprland 0.55 exact window focus: `activate_window` now tries the 0.55 Lua
focus dispatcher (`hl.dsp.focus`) first and falls back to the legacy
`focuswindow` dispatcher on older releases. (#45)
- Exported MCP tool schemas no longer carry the non-standard `uint`/`uint8`/
`uint16`/`uint32`/`uint64`/`usize` `format` annotations emitted by
`schemars`, which produced repeated warnings in MCP clients; integer types
and numeric constraints are preserved. (#45)
- GNOME extension package bootstrap on Ubuntu no longer tries to install the
nonexistent `gnome-shell-extension-tool` apt package; `gnome-shell` is
installed only when `gnome-extensions` is missing and apt can provide it. (#40)
## [0.3.1] - 2026-07-03
### Fixed
- A scroll with a window target but no x/y/element_index focused the window and
then scrolled whatever sat under the cursor while reporting success.
Window-targeted scroll now defaults its point to the centre of the resolved
window (and errors with a pass-x/y hint when bounds are unavailable). Scroll
results also gain the same off-screen coordinate warning click already had.
## [0.3.0] - 2026-07-03
### Added
- Exposed a focused Rust library surface for downstream diagnostics,
accessibility snapshots, screenshots, and server integration while preserving
the existing CLI binaries and standalone naming. (#35)
- Input-landing feedback: targeted keyboard input results append
focused-element feedback from AT-SPI and warn when no editable element holds
focus.
- Off-screen detection: screenshot, click, and input results warn when the
target window or coordinate is partially or fully off-screen.
- Window geometry tools: `move_window` and `resize_window` via the GNOME Shell
extension backend.
## [0.2.9] - 2026-06-22
### Fixed
- GTK4 applications (Nautilus, Text Editor, baobab, and others) now return their
full accessibility tree instead of a single `role: "unknown"` root with
`child_count: 0`. Reads were routed through the `atspi` `P2P` trait's
`object_as_accessible`, whose no-peer fallback builds a proxy with a path but
no destination; on the shared a11y bus that fails with `ServiceUnknown` for
any app that does not advertise a peer-to-peer bus address. Modern GTK4 apps
do not implement the legacy `GetApplicationBusAddress`, so they hit the broken
fallback while GTK3/Chromium/Electron apps kept working. Reads now use
`ObjectRefExt::as_accessible_proxy`, which always pins the destination to the
object's bus name. (#31)
## [0.2.8] - 2026-06-17
### Changed
- Published a metadata-only patch release so local and downstream consumers can
pin the already-validated `computer-use-linux` package state.
## [0.2.7] - 2026-06-16
### Fixed
- Window-relative clicks now require a verified target window and resolved
bounds before coordinates are translated, preventing clicks from silently
landing against stale or originless window data.
- Long `ydotool type --file -` input now gets a bounded timeout with both a
fixed process budget and a text-length budget while stdout/stderr are drained
asynchronously.
- KDE clipboard text input now uses the session DBus API directly and waits
long enough for large paste payloads before restoring the previous clipboard;
Klipper proxy creation and method calls share the same bounded DBus timeout.
- Failed accessibility tree extraction clears cached nodes so later
element-targeted actions cannot use stale coordinates.
### Changed
- The COSMIC helper source path and runtime override surface now use standalone
`computer-use-linux` naming only.
## [0.2.6] - 2026-06-06
### Fixed
- Screenshots now work from background processes (systemd user services,
non-interactive parent shells) on GNOME Wayland. The GNOME Shell DBus method
rejects callers that do not own an allowlisted bus name, and the XDG portal
cancels non-interactive requests when there is no foreground window, so both
prior backends failed in that context. `gnome-screenshot` is now a third
capture fallback that works regardless of session context, bounded by a 20s
timeout so a hung capture degrades to a clear error instead of blocking.
### Added
- `COMPUTER_USE_LINUX_SCREENSHOT_BACKEND` to force a single screenshot backend
(`gnome-shell`, `portal`, or `gnome-screenshot`), skipping the fallback chain
for pinned/background deployments and debugging.
- `doctor` now probes `gnome-screenshot` and lists it under
`capabilities.screenshot` when present.
## [0.2.5] - 2026-06-05
### Added
- Added build-time GNOME extension / DBus identity overrides (`CUL_*`) so the
`codex-desktop-linux` embedded copy can share this source while keeping its
Codex extension identity, plus runtime `CODEX_COMPUTER_USE_*` aliases for the
embedded input/backend knobs.
### Documentation
- Cross-referenced the sibling `agent-workspace-linux` project in the README.
### Fixed
- Bounded screenshot payloads by default before returning them to MCP hosts,
while exposing opt-in screenshot sizing controls and coordinate metadata for
downscaled captures.
- Added opt-in JPEG screenshot output with a caller-selected quality so agents
can choose compression before the byte cap forces additional resizing.
- Ported downstream Linux readiness fixes: `doctor` now treats direct
`/dev/uinput` and the XDG RemoteDesktop portal as valid development-input
backends instead of requiring `ydotoold` in every ready setup.
- Ported downstream session hydration fixes for X11 launches by carrying
`XAUTHORITY` through environment hydration and checking the same-user namespace
init process when it owns the graphical session environment.
### Security
- Pinned the release upload GitHub Action to a commit SHA in CI.
## [0.2.4] - 2026-05-25
Primarily a documentation release that refreshes the crates.io and npm README
pages; also bumps the MCP server's advertised version string to match.
### Added
- Documented the `screenshot` MCP tool and the `doctor` capability map, which
were missing from the README tool list and the MCP safety-contract table.
- A new "Environment variables" section covering runtime overrides
(`CU_DISABLE_ABS_POINTER`, the `COMPUTER_USE_LINUX_FORCE_PORTAL` /
`FORCE_YDOTOOL` pointer and keyboard knobs) and the npm wrapper install knobs
(`COMPUTER_USE_LINUX_BIN`, `DOWNLOAD_BASE`, `SKIP_DOWNLOAD`, `LOCAL_*`).
### Changed
- Stopped pinning explicit versions throughout the docs (README, npm README,
Hermes skill). Install commands are now bare and download links use GitHub's
`/releases/latest` redirect, so the docs no longer drift on every release.
- Dropped the `version` field from the Hermes skill frontmatter (optional per
the agentskills.io standard) so it no longer mirrors the tool version.
- Friendlier README opening: warmer tagline and a verb-driven summary, with no
sections removed.
### Fixed
- `install.sh` now reads the current `doctor` readiness schema
(`.readiness.blockers`, empty array means ready) instead of the removed
`.ready` / `.checks` fields, so a fully provisioned system reports ready
instead of always failing the doctor step. Restored the `install.sh`
executable bit. (#9)
## [0.2.3] - 2026-05-22
### Added
- A `sync reminder` CI workflow (`.github/workflows/sync-reminder.yml`) that
opens (or updates) a `codex-sync`-labeled issue when a merge to `main` touches
the crate sources (`src/**`, `Cargo.toml`, `gnome-shell-extension/**`), so the
change can be propagated into the `codex-desktop-linux` embedded copy with its
codex naming re-applied.
### Changed
- Bumped to establish version-enumeration parity with the `codex-desktop-linux`
embedded copy (`0.2.3-linux-alpha1`). The two crates are kept on the same
enumeration on purpose: a mismatch signals that a sync between them is pending.
## [0.2.2] - 2026-05-21
### Added
- Added a uinput absolute pointer (`abs_pointer.rs`) that creates a private
`ABS_X`/`ABS_Y` device mapped to the portal screenshot coordinate space, so
clicks land at the requested pixel on multi-monitor / HiDPI setups instead of
being distorted by pointer acceleration and fractional scaling. Wired into
`click()` with `ydotool` fallback; opt out via `CU_DISABLE_ABS_POINTER`.
- Added a Hermes-compatible skill tap at `skills/computer-use-linux/SKILL.md`
and an `agnix` CI gate for agent-sh skill/config hygiene.
- Added agent-sh project-health files: `CONTRIBUTING.md`, `SECURITY.md`,
`CODE_OF_CONDUCT.md`, and `CODEOWNERS`.
- Synced upstream Linux Computer Use text-input improvements: Wayland remote
desktop portal keyboard sessions, KDE/Plasma clipboard paste fallback for
layout-safe `type_text`, and literal keysym typing on non-KDE Wayland
sessions before falling back to `ydotool`.
- Synced upstream Hyprland/session hydration fixes, including systemd user
environment discovery, common command path hydration, `HYPRLAND_INSTANCE_SIGNATURE`
inference, and rounded window-id disambiguation.
### Fixed
- Omitted the debug-only `received` echo field from the generated MCP
`outputSchema` for `ActionOutput` and `ActivateWindowOutput`. `schemars`
serialized `Option<serde_json::Value>` as the boolean schema `true`, which
strict MCP clients (mcphub, Claude Desktop, `@modelcontextprotocol/sdk`'s
`AssertObjectSchema`) reject, failing the whole `tools/list` response.
Affected `click`, `drag`, `perform_action`, `press_key`, `scroll`,
`set_value`, `type_text`, and `activate_window`. (#1)
### Changed
- Updated repository, release, package, and CI links from `avifenesh` to the
`agent-sh/computer-use-linux` org repo.
- `setup_accessibility` and `doctor` now understand the AT-SPI
`org.a11y.Status IsEnabled` path in addition to GNOME toolkit accessibility.
## [0.2.1] - 2026-05-14
### Added
- npm wrapper package (`@agent-sh/computer-use-linux`) for Node.js users. It
downloads and verifies the matching GitHub release binaries at install time.
- Tag-driven GitHub Actions publishing for crates.io and npm using repository
secrets.
- CI release gates for locked Rust checks, clippy, tests, private rustdoc,
cargo publish dry-run, cargo audit, npm wrapper smoke tests, and an MCP
protocol/safety contract check.
- MCP `ToolAnnotations` that mark read-only observation tools separately from
mutating desktop-control tools.
### Changed
- Switch the COSMIC protocol dependency from a pinned Git revision to the
published `cosmic-protocols` `0.2.0` crate so `computer-use-linux` can be
published on crates.io.
- Ship the `computer-use-linux-cosmic` helper alongside prebuilt release
binaries and install it from `install.sh` so COSMIC window targeting works
outside `cargo install`.
- Keep the MCP `serverInfo.version` aligned with the Cargo package version.
- Remove unused direct `libc` and `png` dependencies from the crate manifest.
### Documentation
- Add Hermes Agent CLI setup commands and clarify the registered MCP tool
names / toolset.
- Add npm install instructions and fix the prebuilt binary install example to
match the release assets, which are raw binaries with `.sha256` files rather
than tar archives.
- Document the mutating-tool safety contract for MCP hosts and npm users.
- Pin README and npm README install examples to the released `0.2.1` packages
and `v0.2.1` GitHub release assets.
## [0.2.0] - 2026-05-14
### Added
- **Multi-compositor window targeting**: native backends for **KWin**
(KDE Plasma), **Hyprland**, **i3**, and **COSMIC** Wayland alongside
the existing GNOME Shell backend. Window listing, focus tracking, and
activation now work across all five compositors with automatic backend
selection at runtime.
- **COSMIC Wayland helper** (`computer-use-linux-cosmic` binary) that
speaks the `zcosmic_toplevel_info_v1` and `zcosmic_toplevel_manager_v1`
protocols, used by the main server when running under COSMIC.
- **`windowing/` crate-internal module** consolidating all backends behind
a uniform `WindowBackend` trait, with a registry that picks the right
backend per session.
- **Datagram ydotool socket support** in addition to the existing stream
sockets. Aligns with `ydotoold`'s newer default and avoids a
reconnection penalty per input event.
- **Raw-keycode keyboard input** path for ydotool, fixing keystroke
delivery on layouts where the symbolic keysym path was unreliable.
- **Compact Linux accessibility trees** in `get_app_state` — deduplicated
redundant container nodes for smaller, more focused snapshots.
- **Enriched AT-SPI state readback** — element states (`focused`,
`selected`, `expanded`, `checked`, …) now flow through to the response
schema for `get_app_state`.
### Changed
- Server-side rejection of empty window-backend results (returns a
structured "no backend available" error instead of an empty list).
- Stale-client eviction in the chrome-extension host path on backend
side (host binary itself not shipped here — see Removed).
### Removed
- **`codex-chrome-extension-host` binary** is intentionally not shipped
in this fork — it is a Chrome native messaging host scoped to Codex
browser automation (`com.openai.codexextension`), unrelated to the
computer-use MCP. The cosmic helper binary is renamed to
`computer-use-linux-cosmic` to match the project naming.
### Synced from upstream
- This release tracks
[`ilysenko/codex-desktop-linux`](https://github.com/ilysenko/codex-desktop-linux)
through commit `4d6fd96` (May 2026), then re-applies the rebrand
(DBus names, env vars, GNOME extension UUID, cache-file prefixes).
Upstream credit goes to ilysenko, mosesmrima, PinguuSS, and the
original Codex contributors.
## [0.1.0] - 2026-05-13
### Added
- Initial public release as a standalone repository, extracted from
[`codex-desktop-linux-local-stack`](https://github.com/avifenesh/codex-desktop-linux).
- Linux Computer Use MCP server (`computer-use-linux` binary) speaking
[rmcp](https://docs.rs/rmcp) over stdio.
- 15 MCP tools: `doctor`, `setup_accessibility`, `setup_window_targeting`,
`list_apps`, `get_app_state`, `list_windows`, `focused_window`,
`activate_window`, `click`, `drag`, `scroll`, `press_key`, `type_text`,
`perform_action`, `set_value`.
- AT-SPI accessibility tree with semantic element selectors (role / name /
text / states) for `click`, `perform_action`, and `set_value`.
- GNOME Shell window targeting via the bundled
`computer-use-linux@avifenesh.dev` Shell extension (DBus service
`dev.avifenesh.ComputerUseLinux.WindowControl`), with automatic fallback to
`org.gnome.Shell.Introspect` when the extension is not installed.
- Screenshot capture through GNOME Shell DBus (preferred) and
`org.freedesktop.portal.Screenshot` (fallback). Supports full-screen,
per-app, per-window, region, and per-element scopes.
- Input synthesis through the Wayland remote-desktop portal when available,
falling back to `ydotool` / `ydotoold` for keystrokes and pointer events.
- Best-effort terminal-window enrichment: maps each terminal window to its
active TTY and foreground process for targeted `type_text` / `press_key`.
- `doctor` subcommand reporting AT-SPI bus health, GNOME Shell introspection
status, extension status, ydotool socket readiness, and portal coverage in
a single JSON document.
### Architecture
- Wayland-first; X11 best-effort through AT-SPI + ydotool.
- Validated against GNOME 50.1 on Wayland (Ubuntu 25.10).
- KDE / Sway / Hyprland untested — see README support matrix.
[Unreleased]: https://github.com/agent-sh/computer-use-linux/compare/v0.7.21...HEAD
[0.7.21]: https://github.com/agent-sh/computer-use-linux/compare/v0.7.20...v0.7.21
[0.7.20]: https://github.com/agent-sh/computer-use-linux/compare/v0.7.19...v0.7.20
[0.7.19]: https://github.com/agent-sh/computer-use-linux/compare/v0.7.18...v0.7.19
[0.7.18]: https://github.com/agent-sh/computer-use-linux/compare/v0.7.17...v0.7.18
[0.7.17]: https://github.com/agent-sh/computer-use-linux/compare/v0.7.16...v0.7.17
[0.7.16]: https://github.com/agent-sh/computer-use-linux/compare/v0.7.15...v0.7.16
[0.7.15]: https://github.com/agent-sh/computer-use-linux/compare/v0.7.14...v0.7.15
[0.7.14]: https://github.com/agent-sh/computer-use-linux/compare/v0.7.13...v0.7.14
[0.7.13]: https://github.com/agent-sh/computer-use-linux/compare/v0.7.12...v0.7.13
[0.7.12]: https://github.com/agent-sh/computer-use-linux/compare/v0.7.11...v0.7.12
[0.7.11]: https://github.com/agent-sh/computer-use-linux/compare/v0.7.10...v0.7.11
[0.7.10]: https://github.com/agent-sh/computer-use-linux/compare/v0.7.9...v0.7.10
[0.7.9]: https://github.com/agent-sh/computer-use-linux/compare/v0.7.8...v0.7.9
[0.7.8]: https://github.com/agent-sh/computer-use-linux/compare/v0.7.7...v0.7.8
[0.7.7]: https://github.com/agent-sh/computer-use-linux/compare/v0.7.6...v0.7.7
[0.7.6]: https://github.com/agent-sh/computer-use-linux/compare/v0.7.5...v0.7.6
[0.7.5]: https://github.com/agent-sh/computer-use-linux/compare/v0.7.4...v0.7.5
[0.7.4]: https://github.com/agent-sh/computer-use-linux/compare/v0.7.3...v0.7.4
[0.7.3]: https://github.com/agent-sh/computer-use-linux/compare/v0.7.2...v0.7.3
[0.7.2]: https://github.com/agent-sh/computer-use-linux/compare/v0.7.1...v0.7.2
[0.7.1]: https://github.com/agent-sh/computer-use-linux/compare/v0.7.0...v0.7.1
[0.7.0]: https://github.com/agent-sh/computer-use-linux/compare/v0.6.0...v0.7.0
[0.6.0]: https://github.com/agent-sh/computer-use-linux/compare/v0.5.0...v0.6.0
[0.5.0]: https://github.com/agent-sh/computer-use-linux/compare/v0.4.10...v0.5.0
[0.4.10]: https://github.com/agent-sh/computer-use-linux/compare/v0.4.9...v0.4.10
[0.4.9]: https://github.com/agent-sh/computer-use-linux/compare/v0.4.8...v0.4.9
[0.4.8]: https://github.com/agent-sh/computer-use-linux/compare/v0.4.7...v0.4.8
[0.4.7]: https://github.com/agent-sh/computer-use-linux/compare/v0.4.6...v0.4.7
[0.4.6]: https://github.com/agent-sh/computer-use-linux/compare/v0.4.5...v0.4.6
[0.4.5]: https://github.com/agent-sh/computer-use-linux/compare/v0.4.4...v0.4.5
[0.4.4]: https://github.com/agent-sh/computer-use-linux/compare/v0.4.3...v0.4.4
[0.4.3]: https://github.com/agent-sh/computer-use-linux/compare/v0.4.2...v0.4.3
[0.4.2]: https://github.com/agent-sh/computer-use-linux/compare/v0.4.1...v0.4.2
[0.4.1]: https://github.com/agent-sh/computer-use-linux/compare/v0.4.0...v0.4.1
[0.4.0]: https://github.com/agent-sh/computer-use-linux/compare/v0.3.1...v0.4.0
[0.3.1]: https://github.com/agent-sh/computer-use-linux/compare/v0.3.0...v0.3.1
[0.3.0]: https://github.com/agent-sh/computer-use-linux/compare/v0.2.9...v0.3.0
[0.2.9]: https://github.com/agent-sh/computer-use-linux/compare/v0.2.8...v0.2.9
[0.2.8]: https://github.com/agent-sh/computer-use-linux/compare/v0.2.7...v0.2.8
[0.2.7]: https://github.com/agent-sh/computer-use-linux/compare/v0.2.6...v0.2.7
[0.2.6]: https://github.com/agent-sh/computer-use-linux/compare/v0.2.5...v0.2.6
[0.2.5]: https://github.com/agent-sh/computer-use-linux/compare/v0.2.4...v0.2.5
[0.2.4]: https://github.com/agent-sh/computer-use-linux/compare/v0.2.3...v0.2.4
[0.2.3]: https://github.com/agent-sh/computer-use-linux/compare/v0.2.2...v0.2.3
[0.2.2]: https://github.com/agent-sh/computer-use-linux/compare/v0.2.1...v0.2.2
[0.2.1]: https://github.com/agent-sh/computer-use-linux/compare/v0.2.0...v0.2.1
[0.2.0]: https://github.com/agent-sh/computer-use-linux/releases/tag/v0.2.0
[0.1.0]: https://github.com/agent-sh/computer-use-linux/releases/tag/v0.1.0