No description
  • Rust 78.8%
  • JavaScript 12.7%
  • Shell 5%
  • Python 2.5%
  • HTML 0.9%
  • Other 0.1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Satya Benson b30f6c8ebe sign_in: only list and fill the signing-in tab's logins
Bitwarden computes its inline menu's logins for the active tab of the
window Chrome last focused, not for the focused field's tab, and keeps
the old list when focus moves between two sites' login fields. deskd
focused the window with the browser seat only, but a window seat0 still
focuses (the one shown last) stays activated, so Chrome never took it as
focused: its menu listed the previous sign-in's site (seen live: USAA's
menu listing Capital One's logins). The site check on the focused field's
tab passed in that case.

Now sign_in focuses the window on both seats, and checks with Bitwarden's
service worker that its focused field is in this tab, this tab's window
is Chrome's focused one, every menu entry is a saved login for the tab's
URL, and the buttons show those entries; until then it refocuses and has
Bitwarden recompute, or clicks the field again (blurred first, since any
navigation in any tab clears Bitwarden's focused field). It checks again
right before clicking, and after filling confirms the chosen login's
last-used date moved, clearing the form otherwise. Switching, closing and
removing tabs wait for a sign-in in progress.

tests/signin_cross_site.sh: 3x4 7/12 -> 12/12, 5x4 18/20 -> 20/20; with
other agents' focus stolen every 2 s 12/12. No run filled a wrong login.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-06 10:20:15 -04:00
crates sign_in: only list and fill the signing-in tab's logins 2026-10-06 10:20:15 -04:00
docs sign_in: only list and fill the signing-in tab's logins 2026-10-06 10:20:15 -04:00
patches/sway Add sign_in via Bitwarden autofill and sway seat focus patch 2026-09-26 10:18:30 -04:00
scripts Initial commit: deskhand phase 0 spikes and phase 1 core 2026-09-25 23:19:39 +02:00
spikes Add a cross-site concurrent sign_in test and Bitwarden focus spikes 2026-10-06 10:20:15 -04:00
tests Add a cross-site concurrent sign_in test and Bitwarden focus spikes 2026-10-06 10:20:15 -04:00
.gitignore Initial commit: deskhand phase 0 spikes and phase 1 core 2026-09-25 23:19:39 +02:00
Cargo.lock Recover Linux runtime directory for MCP launches without session environment 2026-10-01 10:32:17 -04:00
Cargo.toml Add deskview take-over viewer 2026-09-28 09:01:57 -04:00
LICENSE Add README and MIT license 2026-10-05 15:27:49 -04:00
PLAN.md Add deskview take-over viewer 2026-09-28 09:01:57 -04:00
README.md Add README and MIT license 2026-10-05 15:27:49 -04:00

deskhand

Gives AI agents (Claude Code and other MCP clients) their own desks on a Linux desktop without interfering with the user's session or with each other.

Agents run in "agentland", a headless nested sway with one seat and one output per agent. A single shared browser process (Helium, driven over the Chrome DevTools Protocol) lives in agentland; each agent's tabs are windows on its own workspace. Logins go through the Bitwarden browser extension's autofill, so passwords never enter the model's context. The user can take over any desk in a viewer window and hand it back.

This is not a security sandbox: the aim is no interference by default, not containment.

Status: the browser side works. Native desktop apps and desktop notifications are planned (see PLAN.md).

Components

Crate What
crates/deskd Daemon: starts agentland and the browser, serves a JSON-RPC control socket
crates/deskhand-mcp stdio MCP server, one per agent session; starts deskd if needed
crates/deskctl CLI: status, stop, run a tool as an agent, open the viewer
crates/deskview Take-over viewer: shows an agent's desk and forwards your input to it
crates/proto Shared protocol types

Agent tools include browser_open, navigate, click, type, key, scroll, tabs, select_tab, close_tab, screenshot, ui_tree, wait_for, run_script, desk_size and sign_in.

agentland needs a patched sway (patches/sway/, six patches on sway 1.12) that adds per-seat client binding and a few seat commands; see docs/sway-patch.md.

Build

Needs Rust, and for the patched sway: meson, ninja, a C compiler, and the sway/wlroots 0.20 development headers.

scripts/build-sway.sh        # fetches sway 1.12, applies patches/sway, installs it
cargo build --release        # deskd, deskhand-mcp, deskctl, deskview
cargo test

Register with an MCP client by pointing it at target/release/deskhand-mcp.

Documentation

License

MIT; see LICENSE. The sway patches in patches/sway/ are derived from sway and, like sway, are under the MIT license.