open-computer-use
Desktop app control over MCP on macOS, Linux and Windows through each system's accessibility APIs
Linux desktop control over MCP: accessibility trees, screenshots, clicks and typing on Wayland and X11
By agent-sh Rust Local · stdio Browser automationDeveloper tools
74 popularity score ★ 824 ↓ 4.4k/wk
Opens the app, which asks before it adds the server.
npm install -g @agent-sh/computer-use-linux
computer-use-linux setupclaude mcp add computer-use-linux -- computer-use-linux mcp{
"mcpServers": {
"computer-use-linux": {
"command": "computer-use-linux",
"args": [
"mcp"
]
}
}
}{
"mcpServers": {
"computer-use-linux": {
"command": "computer-use-linux",
"args": [
"mcp"
]
}
}
}{
"servers": {
"computer-use-linux": {
"type": "stdio",
"command": "computer-use-linux",
"args": [
"mcp"
]
}
}
}[mcp_servers.computer-use-linux]
command = "computer-use-linux"
args = ["mcp"]gemini mcp add --scope user computer-use-linux computer-use-linux -- mcpOpens the app, which asks before it adds the server. Then replace each <NAME> in its settings with your value.
git clone https://github.com/agent-sh/computer-use-linux
cd computer-use-linux
./install.shclaude mcp add computer-use-linux -- '<ABSOLUTE_PATH_TO_HOME>/.local/bin/computer-use-linux' mcp{
"mcpServers": {
"computer-use-linux": {
"command": "<ABSOLUTE_PATH_TO_HOME>/.local/bin/computer-use-linux",
"args": [
"mcp"
]
}
}
}{
"mcpServers": {
"computer-use-linux": {
"command": "<ABSOLUTE_PATH_TO_HOME>/.local/bin/computer-use-linux",
"args": [
"mcp"
]
}
}
}{
"servers": {
"computer-use-linux": {
"type": "stdio",
"command": "<ABSOLUTE_PATH_TO_HOME>/.local/bin/computer-use-linux",
"args": [
"mcp"
]
}
}
}[mcp_servers.computer-use-linux]
command = "<ABSOLUTE_PATH_TO_HOME>/.local/bin/computer-use-linux"
args = ["mcp"]gemini mcp add --scope user computer-use-linux '<ABSOLUTE_PATH_TO_HOME>/.local/bin/computer-use-linux' -- mcp| Set together: opt-in tools | |
|---|---|
COMPUTER_USE_LINUX_ENABLE_SHELL |
Optional: Set exactly to 1 to register the run_shell tool. |
COMPUTER_USE_LINUX_NOTIFY_ON_COMPLETE |
Optional: Set exactly to 1 to register complete_interaction, which needs notify-send. |
| Set together: indicator | |
COMPUTER_USE_LINUX_INDICATOR |
Optional: Set to 0, false, off or no to turn off the on-screen overlay. |
COMPUTER_USE_LINUX_INDICATOR_HIDE_TEXT |
Optional: Set exactly to 1 to mask typed text and keycaps in the overlay. |
COMPUTER_USE_LINUX_AGENT_NAME |
Optional: Name shown in the overlay in place of the MCP client's name. |
COMPUTER_USE_LINUX_INDICATOR_BIN |
Optional: Path to computer-use-linux-indicator when it is not beside the server binary or on PATH. |
| Set together: input | |
COMPUTER_USE_LINUX_PERSIST_REMOTE_DESKTOP |
Optional: Set exactly to 1 to keep RemoteDesktop portal grants across processes through a stored token. |
COMPUTER_USE_LINUX_PORTAL_SCROLL_INVERT |
Optional: Set to 1 to reverse vertical scrolling sent through the RemoteDesktop portal. |
COMPUTER_USE_LINUX_FORCE_PORTAL_POINTER |
Optional: Prefer the RemoteDesktop portal for pointer input on Wayland. |
COMPUTER_USE_LINUX_FORCE_YDOTOOL_KEYBOARD |
Optional: Always send keyboard input through ydotool. |
YDOTOOL_SOCKET |
Optional: Explicit ydotool socket path; when unset only the owner-only socket in the user runtime dir is used. |
| Set together: capture | |
COMPUTER_USE_LINUX_SCREENSHOT_BACKEND |
Optional: Force one screenshot backend: gnome-shell, portal, x11 or gnome-screenshot. |
computer-use-linux is a Rust program that gives an agent control of the Linux desktop it runs on. Started with the `mcp` argument it is a stdio MCP server. It reads application accessibility trees through AT-SPI, lists and focuses windows, takes screenshots, and sends clicks, drags, scrolls, key chords and text. You can point at a control by its element index from a `get_app_state` snapshot or by a role/name/text selector. Pixel coordinates work for canvases, and each action can return a fresh screenshot or tree in the same call.
Wayland is the main target. Window lookup tries backends in turn and reports which answered: a bundled GNOME Shell extension or GNOME Introspect, KWin scripting on Plasma, hyprctl, niri IPC, i3 IPC (which also covers Sway), a COSMIC helper, the labwc socket from the Selkies patch, the wlr-foreign-toplevel-management protocol for stock labwc and other wlroots compositors, and finally wmctrl/xprop on X11. Input goes through the RemoteDesktop portal, uinput, ydotool, wtype or xdotool, depending on the session. A `doctor` tool returns a JSON readiness report that names what is missing.
Three binaries ship together: the server/CLI, the `computer-use-linux-cosmic` helper and `computer-use-linux-indicator`, an overlay that shows the agent's cursor and keys and hides itself during captures. Besides npm, crates.io and the source install there are Claude Code and Codex plugins that fetch pinned release binaries on first start. Pi and Hermes have their own setups.
In src/server.rs, 19 tools are registered by default. Two more appear only when set in the environment: `run_shell` with COMPUTER_USE_LINUX_ENABLE_SHELL=1 and `complete_interaction` with COMPUTER_USE_LINUX_NOTIFY_ON_COMPLETE=1. The same file has `get_app_state` read 1000 accessibility nodes and 32 levels by default. `max_nodes` and `max_depth` raise that to hard caps of 10000 and 64. Trees too large to return inline are written to a private file, and `get_tree_page` pages through them.
| Runtime | A prebuilt binaryNode.js 18+ |
|---|---|
| Runs on | Linux |
| Also |
|
Node.js is only for the npm wrapper, which fetches the x86_64 or aarch64 binaries at install. Those prebuilt binaries need glibc 2.28 or newer (RHEL 8, Debian 10, Ubuntu 20.04 and later). On older systems build it with `cargo install computer-use-linux`, which needs Rust. `./install.sh` installs Rust and system packages itself. Run `computer-use-linux setup` (or the `setup_accessibility` tool) to turn on AT-SPI. Exact window focus on GNOME Wayland needs the bundled Shell extension: run `setup-window-targeting`, then log out and in. Pi's native-tools mode needs Pi 0.84.4+ on Node.js 22.19+. Plugin and Pi installs keep binaries in a private cache and don't put `computer-use-linux` on PATH.
Only GNOME Shell 50.1 on Ubuntu 25.10 Wayland (and niri window listing) was tested by hand. Other desktops rest on parser tests. Sway is reached through its i3 IPC. When the window backend gives no pid (i3, Sway, COSMIC), a targeted click or action needs a snapshot taken for that window. ydotool text accepts printable ASCII, tab and newline only and can mistype under non-US layouts. `move_window` and `resize_window` need the GNOME Shell extension or the generic X11 backend. Screenshots are cut to 1920 px and 2 MiB by default, and screenshot portals may ask for consent.
Suits someone who wants an agent to operate their own Linux desktop apps, especially on GNOME Wayland, and is willing to enable AT-SPI and set up a portal or ydotool. It drives the live session with the user's full desktop reach, so it fits supervised use better than unattended agents. For a desktop the agent does not share with you, its makers point to agent-workspace-linux as the sibling project for an isolated workspace. Claude Code, Codex and Pi users get the quickest setup through the plugins or `pi install`. On macOS or Windows it does not apply.
6 only read, 14 change things, 1 can delete or overwrite. A ? marks an optional parameter.
doctorsetup_accessibility changessetup_window_targeting changeslist_appsget_tree_pageoffset?: integerlist_windowsfocused_windowactivate_window changeswindow_id?: integerpid?: integerapp_id?: stringwm_class?: stringtitle?: stringtty?: stringterminal_pid?: integerterminal_command?: stringterminal_cwd?: stringscreenshot_after?: anyinclude_tree?: booleanget_app_stateapp_name_or_bundle_identifier?: stringwindow_id?: integerpid?: integerapp_id?: stringwm_class?: stringtitle?: stringmax_nodes?: integermax_depth?: integerinclude_screenshot?: booleanmax_width?: integermax_height?: integermax_bytes?: integerformat?: enumverbose?: booleanscreenshot changeswindow_id?: integerpid?: integerapp_id?: stringwm_class?: stringtitle?: stringraise_window?: booleanfull_screen?: booleanmax_width?: integermax_height?: integermax_bytes?: integerscale?: numberformat?: enumquality?: integerclick changeselement_index?: integerrole?: stringname?: stringtext?: stringstates?: arrayx?: integery?: integercoordinate_space?: enumbutton?: stringclick_count?: integerwindow_id?: integerapp_id?: stringwindow_title?: stringrelative?: booleanscreenshot_after?: anyinclude_tree?: booleandrag changesstart_x: integerstart_y: integerend_x: integerend_y: integerscreenshot_after?: anyinclude_tree?: booleanscroll changesdirection: stringpages?: numberelement_index?: integerx?: integery?: integerwindow_id?: integerapp_id?: stringwindow_title?: stringrelative?: booleanscreenshot_after?: anyinclude_tree?: booleanpress_key changeskey: stringwindow_id?: integerpid?: integerapp_id?: stringwm_class?: stringtitle?: stringtty?: stringterminal_pid?: integerterminal_command?: stringterminal_cwd?: stringscreenshot_after?: anyinclude_tree?: booleantype_text changestext: stringwindow_id?: integerpid?: integerapp_id?: stringwm_class?: stringtitle?: stringtty?: stringterminal_pid?: integerterminal_command?: stringterminal_cwd?: stringscreenshot_after?: anyinclude_tree?: booleanperform_action changeselement_index?: integerrole?: stringname?: stringtext?: stringstates?: arrayelement_identifier?: stringaction?: stringscreenshot_after?: anyinclude_tree?: booleanset_value changeselement_index?: integerrole?: stringname?: stringtext?: stringstates?: arrayelement_identifier?: stringvalue: stringscreenshot_after?: anyinclude_tree?: booleanmove_window changeswindow_id?: integerpid?: integerapp_id?: stringwm_class?: stringtitle?: stringx: integery: integerscreenshot_after?: anyinclude_tree?: booleanresize_window changeswindow_id?: integerpid?: integerapp_id?: stringwm_class?: stringtitle?: stringwidth: integerheight: integerscreenshot_after?: anyinclude_tree?: booleanrun_shell deletescommand: stringcwd?: stringenv?: objecttimeout_seconds?: integercomplete_interaction changes