hypruse について
hypruseはHyprland向けのMCP サーバーで、AIエージェントがWayland IPC、アクセシビリティツリー、ネイティブ入力を使ってデスクトップを操作できます。ウィンドウ状態の意味情報と必要に応じたスクリーンショットを組み合わせ、ユーザーの作業を妨げず別のワークスペースで操作できます。
主な機能
- 01ウィンドウ、ワークスペース、モニターの状態取得
- 02アクセシビリティ名によるコントロール操作
- 03画面、ウィンドウ、領域のキャプチャ
- 04ネイティブなマウス、キーボード、ウィンドウ制御
- 05デスクトップイベント待機と操作シーケンス
活用シーン
- 01ワークスペースの切り替えとウィンドウ整理
- 02アプリ内の名前付きコントロールを特定してクリック
- 03アクセシビリティ情報のない画面を画像で操作
- 04バックグラウンドのワークスペースでアプリを起動・操作
MCP 対応
MCP サーバーとして、デスクトップ状態、スクリーンショット、入力、ウィンドウ管理のツールをSTDIO経由でクライアントに提供します。コマンドラインを使うエージェント向けに、各ツールをシェルコマンドとしても利用できます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
uvx hypruseHYPRUSE_SCREENSHOT_MODEHow captures are returned: 'file' writes to XDG_RUNTIME_DIR and returns the path, 'image' returns the image inline. Use 'image' for clients that render MCP images but cannot read files, such as Claude Desktop.HYPRUSE_READONLYSet to 1 to expose only the observation tools (desktop, screenshot, zoom, ui, marks, binds, wait_for). The agent can see and narrate but cannot click, type, or launch.HYPRUSE_CONFINERestrict input to a scope of windows and refuse everything outside it: 'launched' (only windows hypruse opened this session), 'class:firefox,kitty', or 'workspace:3,special:notes'. Unset means no confinement.HYPRUSE_AUTH_GUARDシークレットRefuse to click or type into system authentication dialogs (polkit, keyring prompts). On by default; 'strict' also refuses password fields in ordinary windows; 0 disables it.HYPRUSE_STRICTSet to 1 to refuse to act when the cursor or focused window moved since hypruse's last action, so the agent must re-read the desktop before retrying.HYPRUSE_MARKSet to 1 to make the agent's presence legible: tag every window it opens 'hypruse-owned' and flash an on-screen notice when it opens a window or captures the screen.HYPRUSE_CLIPBOARDSet to 1 to register the opt-in clipboard tool (never in read-only mode). Off by default because clipboards hold passwords.HYPRUSE_JOURNALRecord every tool call, refusals included, as one NDJSON line: 1 writes to XDG_STATE_HOME/hypruse/journal.ndjson, or give a path. Read it back with 'hypruse journal'. Off by default.HYPRUSE_JOURNAL_MAX_BYTESRotate the journal once it reaches this size, keeping one previous generation alongside it. Set 0 to never rotate.HYPRUSE_JOURNAL_TEXTSet to 1 to record typed and copied text in the journal verbatim instead of as a length plus digest. Off by default because keystrokes are passwords; needed only to replay typing.HYPRUSE_DRYRUNSet to 1 for a rehearsal: every acting tool validates its arguments and runs every trust guard, then reports what it would have done and delivers no input.ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
hypruse
Hyprlandでのコンピューター操作。 AI エージェントに Wayland デスクトップをネイティブに操作する手段を提供するMCPサーバーです。ワークスペース、ウィンドウ、マウス、キーボード、スクリーンショットを扱えます。
ydotoolデーモンは不要です。root権限も、ポータルも、X11も不要です。

理由
コンピューター操作機能はmacOSとWindowsにはありますが、ベンダーのLinuxアプリにはいまだに搭載されていません。Claude DesktopのLinux向けドキュメントではコンピューター操作は利用できないとされており、ChatGPTのコンピューター操作機能はmacOSとWindowsのみを対象としています。Anthropicのリファレンス実装はX11コンテナーです。ほかのWaylandツールは、ydotoolやuinput、GNOME専用のポータル、あるいは特定のHyprlandバージョン専用に構築されたコンポジタープラグインに依存しています。
一方、Hyprlandはすでに、アクセシビリティブリッジよりも優れた形でエージェントに必要なすべてを公開しています。状態とウィンドウ管理を網羅するIPCインターフェイスと、入力用の第一級のWaylandプロトコルです。hypruseはそれらをMCPに接続するだけです。
- セマンティックな操作を優先。
desktopは、実際のウィンドウ/ワークスペースツリー(アドレス、クラス、タイトル、ジオメトリ)を1回の呼び出しで返します。エージェントはピクセルを凝視するのではなく、あなたと同じ方法で(IPC経由で瞬時に)ワークスペースを切り替え、ウィンドウにフォーカスします。 - 必要なときに視覚情報を活用。 モニター全体、1つのウィンドウ(Hyprland 0.54以降でgrim 1.5以降を使う場合は、非表示のワークスペース上や別のウィンドウの下にあっても、そのウィンドウ自体をキャプチャします。ただし、非表示のアプリには最後に表示された状態が映ることがあります)、または拡大した領域のスクリーンショットを、任意のピクセルをクリック可能な座標に対応付けるためのジオメトリ/スケールメタデータとともに取得できます。これはGUIエージェント研究に基づく、粗い範囲から細かい範囲へと絞り込むループです。
- ネイティブ入力。 クリックとスクロールはWayland経由で直接送信し(
zwlr_virtual_pointer_v1)、入力は適切なXKBキーマップを備えたwtypeの仮想キーボードを通して行うため、どのレイアウトでもUnicodeに対応します。 - あなたの作業と並行して動作。 あなたが自分のワークスペースで作業している間、エージェントは別のワークスペースにあるアプリで作業できます。アクセシビリティツリー経由でコントロールを操作し、そこから、またはHyprlandの
sendshortcutを使って入力するため、カーソル、キーボードフォーカス、ワークスペースはそのまま維持されます。標準のHyprlandのみで、コンポジタープラグインは不要です。詳しくはバックグラウンドモードをご覧ください。
仕組み
agent (Claude Code, or any MCP client)
│ stdio
▼
hypruse
├── hyprctl -j ········▶ desktop state: monitors, workspaces, windows, layers
├── hyprctl dispatch ··▶ focus / move / close / launch / movecursor,
│ and sendshortcut for keys to a hidden window
├── grim ··············▶ screenshots: monitor, window, region
├── D-Bus (AT-SPI) ····▶ accessibility tree: named controls, current
│ values, exact coords (ui / marks / click_ui),
│ and presses and text in the background
├── wtype ·············▶ keyboard (zwp_virtual_keyboard_v1, real XKB keymap)
└── raw Wayland wire ··▶ click & scroll (zwlr_virtual_pointer_v1)
オプションのバイナリが、さらに2つのツールを利用可能にします。imagemagickはmarks用の番号付きオーバーレイを描画し、wl-clipboardはオプトインのclipboardツールを支えます。
設計上の判断:
- ydotool/uinputは使いません。 この方法ではデーモン、udevルール、またはroot権限が必要で、US配列のスキャンコードを送信するため、ほかのレイアウトでは正常に動作しません。hypruseは、
wlrctlと同じ立場で、コンポジターに接続する単なるWaylandクライアントです。 - ポータルは使いません。
xdg-desktop-portal-hyprlandはRemoteDesktopポータルを実装していません(InputCaptureは入力のキャプチャであり、注入ではありません)。そのため、libei/ポータルを使うものはHyprland上で気づかないうちに機能が低下します。hypruseはその方法を使いません。 - カーソルの位置決めには、コンポジター独自のカーソルディスパッチャーを使用します(グローバルな論理座標を使うため、どのモニター配置でも正確です)。仮想ポインターではボタン/軸イベントのみを送信し、絶対座標による仮想ポインターの移動で知られているマルチモニターの不具合を回避します(hyprwm/Hyprland#6749)。
ツール
| ツール | 機能 |
|---|---|
desktop | 1 回の呼び出しでセマンティックなスナップショットを取得します。モニター、ワークスペース、ウィンドウ(アドレス/クラス/タイトル/ジオメトリ)、アクティブウィンドウ、カーソル、レイヤーサーフェス(ランチャー、バー、通知ポップアップ)を、可能な範囲で種類とジオメトリとともに返します。一覧に表示されるレイヤーは、コンポジターが追跡しているものであり、目に見えるものとは限りません。透明なサーフェスや休止状態のサーフェスも報告されるため、表示状態が重要な場合はスクリーンショットを撮影してください |
screenshot | フォーカス中のモニター、アドレスを指定した 1 つのウィンドウ(Hyprland 0.54 以降で grim 1.5 以降を使用すると、非表示または覆われたウィンドウも対象になります。メタデータの visible はコンポジターがそのウィンドウを描画しているかを示し、source はピクセルがウィンドウ自体のものか画面の切り抜きかを示します。非表示状態でのキャプチャは古い情報の場合があります)、または x,y,WxH で指定した領域を撮影します。画像と座標マッピングのメタデータを返します。デフォルトでは高速な JPEG を使用し(PNG にするには lossless=true)、stable=true を指定するとフレームが落ち着くまで待機します |
zoom | 推定した点の周辺をネイティブ解像度で再キャプチャします(任意でウィンドウの範囲内に制限できます)。小さなコントロールをクリックする前の精密化ステップで、メタデータの仕様は同じです |
ui | ウィンドウのアクセシビリティツリー(AT-SPI。ツリーを公開する GTK/Qt アプリ)を読み取り、正確なグローバル座標付きで、名前からクリック可能な要素を返します。スクリーンショットは不要です。現在の値(入力済みテキスト、スライダーの位置、チェックボックスの状態)も報告します。アプリが何も公開していない場合は、ビジョンベースの処理にフォールバックします |
marks | Set-of-Marks 形式でキャプチャします。ウィンドウのスクリーンショット上に、アクセシビリティ対応のすべてのコントロールを番号付きマークで描画し、JSON 形式の凡例(各番号のロール、名前、現在の値、正確なクリック位置)を返します。描画には ImageMagick が必要です。ImageMagick がない場合は、凡例のみを返します |
click_ui | アクセシブルな名前、または marks の番号を指定して、1 回の呼び出しでコントロールをクリックします。座標はツリーから取得します。現在操作中のウィンドウでは、実際のポインターを使ってクリックします(クリックが目に見え、安全性の保証も同じです)。それ以外のウィンドウでは、バックグラウンドでアクセシビリティアクションを実行してコントロールを押します。名前が曖昧な場合は推測せず、候補を返します |
pointer | グローバル座標での移動/クリック/ドラッグ/スクロール(ホイールの段階的な刻み)を実行します。実際のカーソルを動かすため、デフォルトでは自分以外のウィンドウに入力が届く場合、操作は拒否されます |
keyboard | 文字列をそのまま入力する(Unicode 対応)か、アプリレベルのキーコンビネーション(ctrl+shift+t、esc、F5)を押します。任意の window アドレスを指定すると、キーの送信先を指定できます。現在操作中のウィンドウはフォーカスされて入力され、それ以外のウィンドウにはバックグラウンドでキーを送ります。コンポジターのバインド(super+...)はここではなく、use_bind を使ってください |
hypr | ワークスペースの切り替え、ウィンドウのフォーカス/移動/クローズ、全画面表示、フローティング表示を実行します(純粋な IPC で、ミリ秒単位です。close_window は破棄イベントを最大 1 秒待機するため、結果と then= による観測は競合せず、クローズ後の状態を反映します) |
launch | アプリを起動します。ワークスペースを指定しない場合は、エージェント自身の次のワークスペースで目立たないように起動します(自分のワークスペースで起動するには background=false を指定します)。実際の openwindow イベントが発生するまで待機し、アドレスを返します。ブラウザーなど、ウィンドウが exec ルールを無視するシングルインスタンスアプリを検出し、指定されたワークスペースに移動します |
binds | ユーザー自身のキーバインドをデコードして表示します(SUPER+Q、アクション、説明)。エージェントが実行するには use_bind を使います |
use_bind | キーコンビネーション(SUPER+F)でキーバインドを実行し、割り当てられたアクションを実行します。これにより、エージェントは所有者自身のランチャーやショートカットを操作できます。Lua の hyprland.lua 内のバインドには使用できません。これらは匿名クロージャーであり、Hyprland には呼び出す方法がありません。そのため、binds ではアクションが lua と表示され、use_bind は原因不明のエラーを返す代わりに、その旨を示します |
sequence | アクション(pointer/keyboard/click_ui/hypr/wait_for)の順序付きリストを 1 回の呼び出しで実行します。現在のステップが想定していない形でデスクトップが変化した時点で停止するため、クリック/入力/確定の一連の操作を、複数回ではなく 1 回の往復で実行できます |
wait_for | 実際のコンポジターイベント(ウィンドウのオープン/クローズ、ワークスペースの変更、タイトルの変更、レイヤーサーフェスの表示/クローズ、緊急度、画面共有の開始/停止)を、照合フィルターとタイムアウトを指定して待機します。フィルター付きの待機条件がすでに満たされている場合(ウィンドウがすでに消えている、ワークスペースがすでにアクティブ、レイヤーがすでにマッピング済みなど)は、登録前に発生したイベントを取りこぼさず、already: true を即座に返します。複数ステップの自動化における、スリープして期待するだけの方法に代わるものです |
clipboard | wl-clipboard を使ってテキストクリップボードを読み書きします。明示的なオプトインが必要で、サーバー環境に HYPRUSE_CLIPBOARD=1 が設定されている場合にのみ利用できます |
操作ツール(pointer、keyboard、click_ui、hypr、use_bind、sequence)には省略可能な then 引数があり、結果を同じ呼び出しに追加するため、エージェントは次のラウンドトリップを待たずに効果を確認できます。then='desktop' は最新のセマンティックスナップショット(約20 ms。ウィンドウやフォーカスの変更に最適で、低コスト)を追加し、then='screenshot' は安定したキャプチャ(視覚的な変更に最適)を追加します。then='ui' は操作したウィンドウのコントロールと現在の値を追加します(正確なトークンを数百消費。入力や切り替えの後に最適です。click_ui はクリックによってダイアログにフォーカスが移っても、クリックしたウィンドウを読み取ります。それ以外のツールはフォーカス中のウィンドウを読み取ります)。then='none' は何も追加しません('desktop' が既定値の sequence を除き、すべてのツールで既定値です)。 |
また、すべてのツールはシェル動詞(hypruse desktop、hypruse click_ui Save --window 0x...)としても使用でき、MCP ではなくコマンドを実行するエージェント向けのスキルも用意されています。詳しくはシェル動詞とエージェントスキルをご覧ください。
機能
ツールは5つの機能に分かれており、信頼性と低コストの高い順に並んでいます。この順序で使うエージェントは、より速く、より正確に動作でき、多くのタスクではスクリーンショットさえ必要ありません。
1. セマンティックなデスクトップ操作(まずはここから)
desktop は、すべてのウィンドウとワークスペースのツリーを1回の呼び出しで返します。各ウィンドウのアドレス、クラス、タイトル、ジオメトリ、アクティブなウィンドウ、カーソル、そしてコンポジターが追跡しているレイヤーサーフェス(ランチャー、バー、通知ポップアップ)を確認できます。続いて hypr と launch を使い、IPC 経由でミリ秒単位に操作できます。ワークスペースの切り替え、アドレスを指定したウィンドウのフォーカス、移動、閉じる、全画面表示、フローティング表示、またはアプリの起動が可能です。
**効果的な使い方:**ウィンドウの検索や配置にスクリーンショットを使わないでください。desktop を読み取り、操作したいアドレスを指定します。launch は実際の openwindow イベントを待って、新しいウィンドウのアドレスを返すため、ポーリングしたり推測したりする必要はありません。また、ワークスペースのルールを無視するシングルインスタンスアプリ(ブラウザーなど)の場所も変更できます。
2. ピクセルを使わず、名前でコントロールをクリック
アプリがアクセシビリティツリーを公開している場合(ほとんどの GTK および Qt アプリが該当)、ピクセルではなく名前でコントロールを指定できます。ui はすべてのコントロールを正確なグローバル座標とともに一覧表示し、値を持つコントロールの現在の値も報告します。たとえば、フィールド内のテキスト、スライダーのパーセンテージ、チェックボックスの状態などです。click_ui は名前を解決して1回の呼び出しでクリックします。実際のカーソルを経由するため、ビーコンとすべての安全性保証が適用されます。または、現在表示されていないウィンドウの場合は、カーソルに触れず、コントロール独自のアクセシビリティアクションを使います。marks はスクリーンショット上に番号付きのマークと凡例を描画します。先に選択肢を確認してから click_ui(mark=N) を使いたい場合に便利です。
**効果的な使い方:**ピクセル位置を推測する前に click_ui name="Save" を使ってください。正確で、画像も消費しません。スクリーンショットを撮る代わりに、ui でフォームの状態(チェックボックスが実際にオンになったかなど)を読み取ります。名前が曖昧な場合は推測せず、候補を返します。アプリがツリーを公開していない場合(ターミナル、キャンバスアプリ、--force-renderer-accessibility を指定していない Electron/Chrome など)は、ツールがその旨を伝えるので、ビジョンに切り替えます。
3. 必要なときにビジョンを使う:ズームループ
アクセシビリティツリーでは名前を特定できないものには、screenshot(モニター、ウィンドウ、または領域)と zoom(指定した点の周辺をネイティブ解像度で再キャプチャ)を使います。座標には厳密な契約 global = geometry + pixel / scale が適用され、すべてのモニターと小数スケールで正確さが保たれます。
**効果的な使い方:**全画面画像から小さなコントロールの位置を推測しないでください。粗い確認から細かい確認へ進めます。ウィンドウのスクリーンショットを撮り、対象のおおよその位置を見積もり、そこで zoom を使い、鮮明な切り抜き画像で位置を見積もり直してからクリックします。この2段階のループは、小さな対象を捉える方法として研究に裏付けられています。
4. 往復を減らす:レイテンシーを抑える方法
エージェントでは、タスクのレイテンシーを左右するのはデスクトップではなくモデル呼び出しです。そのため、実際に速度を上げるには構造的な工夫が必要です。sequence は、順序付きの小さな計画(クリック、入力、Enter キーの押下、待機)を単一の呼び出しで実行し、あるステップで意図していない形でデスクトップの構造が変わった瞬間に停止します(ウィンドウの表示、閉じる、移動、予期しないワークスペースの切り替え、または入力を奪うランチャーやオンスクリーンキーボードなどが対象です。フォーカスだけの変化や通知ポップアップは意図的に無視します)。then='desktop' | 'screenshot' | 'ui' を指定すると、操作の呼び出し自体に結果の最新表示を組み込めます。wait_for は、待機して期待するのではなく、実際のコンポジターイベント(ウィンドウやランチャーの表示、タイトルの変更、ワークスペースの切り替え、緊急度の通知、画面共有の開始)を待ちます。
上手な使い方: 既知のクリック/入力/Enter の流れは、ひとつの sequence にまとめます。フォームに入力した後、then='ui' を追加すると、スクリーンショットではなく、数百個の正確なトークンで結果を読み返せます。何かを起動したり、何かを開くショートカットを使ったりした後は、待機するのではなく、wait_for でイベントを待ちます。
5. 安全な委任:信頼レイヤー
hypruse はエージェントに実際の入力権限を渡すため、エージェントができることを制限する制御機能を備えています。常時表示される承認プロンプトと Waybar のアクティビティビーコンに加え、オプトインの環境変数フラグでエージェントが操作できる範囲を狭められます。HYPRUSE_READONLY は観察ツールのみを公開します。HYPRUSE_CONFINE は、エージェントが起動したウィンドウ、またはクラス/ワークスペースの許可リストにあるウィンドウに入力を制限します。HYPRUSE_AUTH_GUARD(デフォルトで有効)は、認証ダイアログの操作を拒否します。HYPRUSE_STRICT は、ユーザーが入力権限を取り戻した場合に操作を拒否します。HYPRUSE_MARK は、エージェント所有のウィンドウにタグを付け、エージェントがウィンドウを開いたり画面をキャプチャしたりすると通知します。さらに、制限ではなく記録を行うフラグが 2 つあります。HYPRUSE_JOURNAL は、拒否を含む各ツール呼び出しを監査可能な NDJSON 行として書き込みます。HYPRUSE_DRYRUN はすべてのチェックを実行しますが、何も実行に移しません。これにより、エージェントがデスクトップに触れる前に、作業の計画を確認できます。
上手な使い方: 最初の 1 週間は読み取り専用で実行してください。ワークフローを信頼できるようになったら、そのツールを許可リストに追加します。また、席を離れる場合は、エージェントの操作範囲を制限し、別のワークスペースにあるパスワードマネージャーにクリックや入力ができないようにしてください。パニック時に使えるバインドを用意しておきましょう(hypruse stop または pkill -f hypruse)。詳しくはセキュリティモデルをご覧ください。
バックグラウンドモード
エージェントは、あなたが自分の作業を続けている間、見ていないワークスペース上のアプリで作業できます。標準の Hyprland では、コンポジタープラグインがなくても、hypruse はそのためにカーソルを動かしたり、キーボードフォーカスを奪ったり、ワークスペースを切り替えたりしません。ただし、エージェントの操作に反応してアプリが独自のウィンドウを前面に表示することはあります。その結果、フォーカス中のウィンドウが変わった場合は、その旨が結果に示されます。
デフォルトでは有効で、自動モードになっています。現在のウィンドウに対する操作は、常にそうであるように、あなたの画面上で実行されます。それ以外のウィンドウに対する操作は、バックグラウンドで実行されます。
click_uiは、アクセシビリティアクションを使ってコントロールを押します。テキストフィールドの場合は、アプリ独自のフォーカスを取得します(これができない GTK 4 を除きます)。名前に一致するボタン、ボックス、フィールドがない場合、click_uiは、Web アプリのリスト内の行など、アクションを持つ別のロールの名前付き要素も操作します。こうしたアクションの中には、要素にフォーカスを当てるだけのものもあります(Qt WebEngine の行では、それ以外の操作はできません)。その場合、結果には要素にフォーカスを当てたことと、アプリがフォーカス中だと報告しているかどうかが示されます。行を開くわけではありません。テストでは、フォーカス中の Qt WebEngine の行に Enter を送っても開きませんでした。window=を指定したkeyboardは、アクセシビリティインターフェースを通じて、そのウィンドウのフォーカス中のテキストフィールド(または唯一のテキストフィールド)に入力します。それ以外の場合は、Hyprland のsendshortcutを使い、キーボードレイアウトに従ってキーを1つずつ、そのウィンドウだけに送ります。改行、タブ、バックスペースは常にキーとして送信されます。キーはアプリ自身がフォーカスしているコントロールに送られるため、テキストが入力されたフィールドと同じとは限りません。そのため、エージェントはキーを送る前にclick_uiでフィールドにフォーカスを当てます。- ワークスペースを指定せずに
launchを実行すると、アプリはエージェント自身のワークスペースのいずれかで開き、あなたからは見えません。 - ポインターはあなたの実際のカーソルなので、バックグラウンドでは動作できません。入力があなた以外のウィンドウに届く場所では操作を拒否し、代わりに
click_uiを使うようエージェントに案内します。
バックグラウンドではできない操作は、理由と代替方法を示して拒否されます。呼び出しで background=false を指定するか、CLI で --foreground を指定すると、あなたの画面上で操作します。
設定
保証はほかのすべてに優先します。保証がなければ、呼び出しごとの background 引数が自動ルールより優先されます。
| 設定 | 内容 |
|---|---|
HYPRUSE_BACKGROUND=1 | 保証です。エージェントは、自身のワークスペース上のウィンドウだけを操作します。ポインター操作、ワークスペースの切り替え、focus_window、fullscreen、対象を指定しない toggle_floating、use_bind は拒否されます。move_window と launch の対象はエージェントのワークスペース(画面に表示されていないものに限ります)だけになり、background=false も拒否されます。 |
background=true または false | 呼び出しごとに、click_ui、keyboard、pointer、launch、sequence で指定します(CLI:--background、--foreground)。true はバックグラウンド操作を強制し、そこで実行できない操作は拒否します。false は画面上での操作を要求します。sequence ではポインター、キーボード、click_ui の各ステップに適用され、true の場合、ワークスペースやフォーカスを切り替える hypr ステップも拒否されます。 |
| 未設定 | 上記のとおり、自動で決まります。 |
HYPRUSE_BACKGROUND=0 | オフです。呼び出しで background=true を渡さない限り、操作は 0.12 と同様に画面上で実行されます(ui は引き続き編集可能なテキストフィールドを一覧表示し、注記を追加します。変更履歴を参照してください)。 |
この保証が制限するのは、hypruse 自身による入力だけです。launch の開始後にプログラムが行うことまでは制限できません。コマンドは指定どおりシェル経由で実行されるため、HYPRUSE_BACKGROUND=1 であっても、クライアントの承認プロンプトを通してから launch を実行してください。
エージェントのワークスペースは HYPRUSE_AGENT_WORKSPACES で指定し、デフォルトは番号の末尾側にある 99 から 90 までです。これにより、使用中のワークスペースと重ならないようにします。A-B はどちらの方向も指定でき、カンマ区切りのリスト(99,98,50)や名前付きワークスペース(name:research)も使用できます。HYPRUSE_AGENT_FILL(デフォルトは 1)は、次のワークスペースを使う前に、エージェントのアプリを 1 つのワークスペースにいくつ配置するかを指定します。1 の場合、各アプリに専用のワークスペースが割り当てられるため、非表示のウィンドウも最大サイズを保てます。範囲内にユーザーのウィンドウがあるワークスペースはスキップされるため、ユーザーとエージェントのウィンドウが混在することはありません。現在表示中のワークスペースもスキップされます。範囲内がすべて埋まっている場合、次のアプリはエージェントのウィンドウが最も少ないワークスペースに配置されます。以前のセッションで開いたウィンドウも、HYPRUSE_MARK によるタグが付いていれば、エージェントのウィンドウとして扱われます。HYPRUSE_CONFINE=workspace:... を指定すると、アプリはその範囲内にあるエージェントのワークスペースだけに開かれます。範囲内に該当するワークスペースがない場合は、これまでどおりユーザーのワークスペースに開かれます。
launch は、起動したプログラム自身のクラスに属するウィンドウ、または指定したワークスペースに開くウィンドウを待ちます。その間にユーザーが別のアプリのウィンドウを開いても、そのウィンドウには手を付けません。同じアプリのウィンドウであれば、起動したプログラムのウィンドウとして扱われることがあります。すでに起動中のアプリ(多くの場合、ブラウザー)は、実行中のプロセスから新しいウィンドウを開きます。このプロセスはワークスペースのルールを無視するため、ウィンドウは画面上に現れ、hypruse が移動するまでフォーカスを奪います。結果にはその旨が記録され、保証が有効な場合は警告も表示されます。これを避けるには、エージェント用に別のインスタンス(ブラウザーの場合は別のプロファイル)を起動してください。
結果の内容
バックグラウンド操作の結果には、実行方法、操作の前後でフォーカス中のウィンドウとワークスペースが同じだったかどうか、値を持つコントロールの場合はアクセシビリティツリーから読み取った値が示されます。
pressed check box 'Agree' through its accessibility action (no pointer, the human's focus untouched) in yad; now: checked=true
typed 12 characters into the text field in yad through the accessibility interface (the human's focus untouched); the field now holds the typed text (12 characters)
sent ctrl+a to 0x5648592451c0 (yad) with sendshortcut, to the control the app has focused (the human's focus untouched)
アプリが無視したチェックボックスやスライダーの操作は、no change seen と表示されます。ボタンの操作、フォーカス中のフィールド、sendshortcut で送信したキーには読み取る値がないため、効果は ui で確認してください。操作中にフォーカス中のウィンドウが変わった場合(アプリがウィンドウを前面に表示した場合、またはワークスペースを切り替えた場合)、結果の末尾に、現在フォーカス中のウィンドウ名を示す WARNING が表示されます。入力した結果にはテキストが繰り返し表示されません。ジャーナルには結果の各行が保持され、入力テキストは長さとダイジェストとしてのみ記録されるためです。スクリーンショットは確認に使用されません。多くのアプリは非表示の間、描画を停止するため、非表示ウィンドウのピクセル情報が古くなっている可能性があります。現在の状態は ui で確認できます。
制限事項
- バックグラウンドで押せるのは、アクセシビリティツリーが公開するコントロールに限られ、実行できる操作もプライマリアクションのみです。右クリックやダブルクリックは拒否されます。非表示のウィンドウ上の任意の位置をクリックするには、コンポジタープラグインか独自の入力シートが必要ですが、この設計ではどちらも使用しません。ツリーのないアプリ(ターミナル、キャンバスアプリ、
--force-renderer-accessibilityを指定していない Electron と Chrome)には、引き続きキーを送信できます。 - アクセシビリティツリーは、タイトルまたはサイズによってアプリのウィンドウを区別します。どちらでも対象を同じアプリの別のウィンドウと区別できない場合(たとえば、同じタイトルとサイズのシングルインスタンスアプリの2つ目のウィンドウ)や、アプリのアクセシビリティ接続がウィンドウとは別のプロセスに属する場合、hypruse はコントロールがどのウィンドウに属するかを特定できません。この場合、
click_uiは拒否され、keyboardはキーを送信します(Hyprland はキーをウィンドウ自体に送ります)。また、uiはコントロールが別のウィンドウにある可能性を示します。 - 非表示のウィンドウの
ui座標は、そのウィンドウ内でコントロールがある位置を示すもので、画面上の位置ではありません。その場所には自分のウィンドウが表示されています。uiはその旨を最後に注記します。これらの座標を使ってpointerでクリックすると、現在見ているウィンドウがクリックされるためです。 - GTK 3 アプリでは、アクセシビリティインターフェースを通じてフィールドにフォーカスすると、ウィンドウが前面に表示されます。Hyprland の
misc:focus_on_activateが有効な場合、ウィンドウに切り替わってしまうため、GTK 3 のフィールドへのフォーカスは拒否されます。ウィンドウごとのfocus_on_activateルールは確認できず、その場合は事後チェックで報告されます。 - キーボードレイアウトに対応するキーがない文字(絵文字や、多くのレイアウトでの CJK 文字など)は、アクセシビリティインターフェース経由でしか入力できません。非表示の GTK ウィンドウでは、複数あるテキストフィールドのどれにフォーカスがあるかを報告しないため、そのようなテキストの入力はキーを送信する前に拒否されます。また、
allow_auth=trueを指定しない限り、複数のフィールドの中にパスワードフィールドがあるフォームへの入力も拒否されます。 sendshortcutは、各キーの送信時に1回のコンポジターステップ内でキーボードフォーカスを対象に移してから戻すため、自分の入力が混ざることはありません。アプリからはフォーカスが離れて戻ったことがわかりますが、ほとんどのアプリはこれを無視します。ただし、開いているメニューを閉じるアプリも一部あります。- 2つのウィンドウがどちらも XWayland の場合、Hyprland はフォーカスされているウィンドウにキーを送信するため、XWayland ウィンドウへの
sendshortcutは拒否されます。 - 複数のキーボードレイアウトがある場合、
sendshortcutが機能するのは、最初のレイアウトを使用しているときだけです。Hyprland は使用中のレイアウトで各キーを見つけますが、アプリはそれを最初のレイアウトで読み取ります。そのため、別のレイアウトでは異なる文字が入力されるため、hypruse は代わりに拒否します。アクセシビリティインターフェース経由のテキスト入力は、レイアウトに依存しません。 - バックグラウンドのウェブページにはブラウザーブリッジが必要ですが、これは後続のリリースで提供されます。
- セッションがロックされている間は、他のすべての入力と同様に、バックグラウンド操作も拒否されます。
すべての信頼レイヤーはバックグラウンド操作にも適用されます。隔離機能は対象ウィンドウを確認し、認証ガードは認証ダイアログ内でのバックグラウンドのクリックやキー入力を拒否します。また、アクセシビリティツリーに表示されるパスワードフィールドへの入力には allow_auth=true が必要です(フォアグラウンドの場合と同様に、ツリーのないアプリは確認できません)。バックグラウンドの作業は見えないため、無人で実行する場合は HYPRUSE_BACKGROUND=1 を設定してください。入力はエージェントのワークスペース内に留まり、hypruse 自身の入力によって画面が奪われることはありません(エージェントが起動したアプリは画面を奪うことがあり、その結果は警告されます)。ジャーナルにはメソッドとともにすべての結果が記録され、エージェントがウィンドウを開いたときには HYPRUSE_MARK が通知します。
シェル動詞とエージェントスキル
すべてのエージェントが MCP に対応しているわけではありません。また、対応しているエージェントもコマンドラインを好む傾向が強まっています。ツールリストは最初の呼び出しより前にセッションあたり数千トークンを消費しますが、シェル動詞は実行するまで何も消費しません。そこで、同じ15個のツールを動詞として利用できます。MCP サーバーが登録するものと同じ関数を通り、同じ信頼ガード、ジャーナル、アクティビティビーコンを使用します。
hypruse desktop # one line per monitor, workspace, window, layer
hypruse launch --workspace 2 -- firefox --new-window https://example.org
hypruse ui --window 0x55a4479a1200 --name Save # [0] push button "Save" @1204,88
hypruse click_ui Save --window 0x55a4479a1200 --then ui
hypruse screenshot --window 0x55a4479a1200 # a file path, then {"geometry":[x,y,w,h],"scale":1.0,...}
hypruse zoom 1180 840 --window 0x55a4479a1200
hypruse keyboard type "hello" --window 0x55a4479a1200
hypruse wait_for title_change --match Inbox --timeout 10
hypruse sequence '[{"op":"click_ui","name":"Search","window":"0x55a4479a1200"},{"op":"keyboard","action":"type","text":"btop","window":"0x55a4479a1200"},{"op":"keyboard","action":"key","keys":"enter","window":"0x55a4479a1200"}]'
この契約は、出力をプログラムが読み取ることを前提に設計されています。動詞はツール名で、ツールの action は位置指定のサブ動詞です(pointer click 800 60、hypr workspace 3、clipboard read)。出力はコンパクトなプレーンテキストで(事実ごとに1行、未加工の結果を1行で表示するには --json を指定)、キャプチャではバイト列ではなくファイルパスと座標メタデータが出力されます。エラーは、意味のある終了コードとともに stderr に1行で出力されます。終了コードは、0 が正常に実行、1 がエラー、2 が使用方法の誤り、3 が信頼レイヤー(または読み取り専用モード)による拒否、4 が実行されたものの操作対象が見つからなかったこと(wait_for のタイムアウト、アクセシビリティツリーがない、名前が曖昧)を表します。hypruse --help にはすべての動詞が、hypruse <verb> --help にはそのフラグが表示されます。--dry-run を指定すると、操作を行う動詞を事前に試せます。動詞は数百ミリ秒で起動し、この経路では MCP スタックは一切インポートされません。
単発のプロセス間で hypruse は、動詞が失うはずの小さな状態を $XDG_RUNTIME_DIR/hypruse/cli-state.json に保持します。状態はコンポジターのインスタンスごとに管理され、marks の番号付け(click_ui --mark N が機能します)、launched の隔離セット、そして本来ならフェイルオープンしてしまう HYPRUSE_STRICT のシート基準値が含まれます。
エージェントに動詞、デスクトップ優先のワークフロー、安全規則を教えるスキルは、パッケージに同梱されています。お使いのマシンにあるエージェント(Claude Code、Codex、Pi、Hermes、OpenClaw、OpenCode、Gemini、Antigravity、Cursor、Copilot)のスキルディレクトリにインストールするか、skills CLI を使ってインストールしてください。
hypruse skill install # ~/.agents/skills/hypruse, linked into each agent that is installed
hypruse skill install --agent codex # one agent, created if absent
npx skills add IlyasKhallouki/hypruse -g
hypruse init からも同じインストールを実行できます。このスキルで事前承認されるのは、観察用の動詞、doctor、--help、キャプチャファイルの読み取りのみです。操作を行う動詞には、エージェント独自の承認プロンプトが必要です。これはセキュリティモデルが依拠する境界です。
インストール
要件:Hyprland(設定マネージャーの両方:hyprland.conf と、0.56 で導入された Lua の hyprland.lua)、grim(Hyprland 0.54 以降では grim 1.5 以降でウィンドウのスクリーンショットをウィンドウ自体からキャプチャでき、hypruse doctor で利用可能か確認できます)、wtype(ほとんどの Hyprland 環境にはこの2つがすでにあります)、および uv です。アクセシビリティツール(ui/marks/click_ui)は、systemd に付属する busctl を使ってアクセシビリティバスを検出し、独自の接続を1つ使って通信します。任意:オプトインのクリップボードツールには wl-clipboard、番号付きの marks キャプチャには imagemagick が必要です。
公式AURから Arch Linux にインストールする場合:
yay -S hypruse # or hypruse-git for main
続いて、自動セットアップと環境の検証を実行します。
hypruse init # detects your MCP clients, registers (asks first), offers the agent skill, runs doctor
hypruse doctor # just the diagnostics
Claude Code に手動で登録する場合:
claude mcp add -s user hypruse -- uvx hypruse
ソースをチェックアウトしたディレクトリから:
claude mcp add -s user hypruse -- uv run --directory /path/to/hypruse hypruse
その他の MCP クライアントでは、stdio サーバーとして uvx hypruse を実行します。hypruse は公式の MCP registry にも io.github.IlyasKhallouki/hypruse として登録されているため、レジストリを参照できるクライアントからインストールできます。
**読み取り専用モード:**サーバー設定で HYPRUSE_READONLY=1 を設定すると、観察用ツール(desktop、screenshot、zoom、ui、marks、binds、wait_for)のみが公開されます。エージェントは画面を確認して説明できますが、クリック、入力、起動はできません。最初の1週間におすすめです。
Claude Desktop(Linux ベータ版)
Linux ベータ版には、Anthropic のファーストパーティー製コンピューター操作機能は含まれていませんが、チャットでは stdio MCP サーバーが動作するため、hypruse が回避策になります。~/.config/Claude/claude_desktop_config.json に次のように設定します。
{
"mcpServers": {
"hypruse": {
"command": "uvx",
"args": ["hypruse"],
"env": { "HYPRUSE_SCREENSHOT_MODE": "image" }
}
}
}
Desktop 固有の注意点が 2 つあります。image モードを使用してください(Desktop は MCP 画像をインラインで表示でき、ファイル読み取りツールはありません)。また、アプリは Hyprland セッション内でネイティブに実行する必要があります。そうすることで、サーバーが WAYLAND_DISPLAY/HYPRLAND_INSTANCE_SIGNATURE を継承します。VM またはコンテナーからは、コンポジターに接続できません。Desktop のインストール環境でツールの承認プロンプトが表示されない場合は、Waybar インジケーター + パニックキー割り当てを任意ではなく必須として扱ってください。
セキュリティモデル
インストールする前に、このセクションをお読みください。hypruse は、エージェントにマウス、キーボード、画面の内容、アプリランチャーを操作できるようにします。 安全性を保つための仕組みは次のとおりです。
- 承認: MCP クライアントはツール呼び出しを制御します。Claude Code では、読み取り専用ツール(
desktop、screenshot)を許可リストに登録し、ワークフローを信頼できるようになるまでは、pointer/keyboard/hypr/launchは毎回確認する設定にしておきます。 - 可視性: サーバーはアクティビティビーコン(
$XDG_RUNTIME_DIR/hypruse/state.json)を管理します。同梱の Waybar module はアイドル時には表示されず、エージェントがデスクトップを操作している間はロボットのインジケーターを表示します。 - 中断: インジケーターをクリックするか、緊急停止用キーを割り当てます。どのインストール方法でも使える形式は次のとおりです:
bind = SUPER SHIFT, BackSpace, exec, pkill -f hypruse。hypruseが PATH 上にある場合(AUR または pipx でのインストール)、bind = SUPER SHIFT, BackSpace, exec, hypruse stopのほうが便利です。サーバーに正常終了を指示し、押したままのポインターボタンを離してビーコンを消去します。uvxでインストールした場合はexec, uvx hypruse stopを使います。ソースをチェックアウトした場合はexec, uv run --directory /path/to/hypruse hypruse stopを使います。いずれの場合も、動作中にプロセスを終了して問題ありません。ボタンの押下と解放が別々のツール呼び出しにまたがることはなく、長いドラッグで押したままのボタンも終了時に解放されます。 - 操作環境は共有されています。 カーソルとキーボードフォーカスはそれぞれ 1 つだけで、Hyprland のフォーカス追従マウス機能により、カーソルを動かすだけでキー入力の送信先が変わることがあります。エージェントがウィンドウを操作している間は入力せず、インジケーターを確認してください。バックグラウンドモードを使うと、エージェントが操作していないすべてのウィンドウで、エージェントが操作環境を占有しなくなります。
- 範囲: stdio のみ(ネットワークリスナーなし)。
$XDG_RUNTIME_DIR(tmpfs、最新 20 件)にビーコンと上限付きスクリーンショットキャッシュを保存する以外、データは永続化されません。また、有効にした場合は、ディスク上の$XDG_STATE_HOMEにアクションジャーナルを保存します(ローテーションあり、世代数 1、デフォルトでテキストを秘匿化)。オプトインしない限りクリップボードにはアクセスしません。HYPRUSE_CLIPBOARD=1を設定するとclipboardツールが登録されます(読み取り専用モードでは登録されません)。クリップボードにはパスワードが含まれることがあるため、ワークフローで必要な場合を除き、無効のままにしてください。スクリーンショットには表示中のものすべてが映ります。また、ウィンドウのスクリーンショットでは、非表示のワークスペース、スクラッチパッド、ほかのウィンドウの背後にあるウィンドウも取得されます。エージェントのセッションは、デスクトップ全体を共有する場合と同じように扱ってください。読み取り専用モードとHYPRUSE_CONFINEが制限するのはエージェントができることであり、見えるものではありません。セッションがロックされている間、ウィンドウのスクリーンショットは拒否されます。 - エージェントが読み取る内容は信頼できません。 ウィンドウタイトル、アクセシビリティ名と値、クリップボードのテキストは、そのままエージェントのコンテキストに渡されます。また、あらゆるウェブページ、ファイル名、ドキュメントに指示を含めることができます(プロンプトインジェクション)。hypruse は意味内容をサニタイズできないため、最後の防波堤となるのは承認レイヤーです。エージェントが信頼できないウィンドウを見る場合は、重要なツール(
launch、keyboard、clipboard)を毎回確認する設定にしてください。承認プロンプトを確認するときは、「画面にそう書いてあった」は攻撃者の入力として扱ってください。 - 入力が、実際には機能しないのに成功したように報告されることはありません。 常時有効の 3 つのチェック(環境変数フラグなし)は、偽の成功を報告する代わりに、入力を拒否または注記します。ランチャーまたはオンスクリーンキーボードのレイヤーサーフェスの下を狙ったクリック(これらはウィンドウより前面にあり、入力を横取りします)、ランチャーがキーボードをグラブしている間の入力、セッションがロック中のすべての入力が対象です。ロック画面は
ext-session-lockクライアントであり、ウィンドウやレイヤーの一覧には表示されません。そのため hypruse は Hyprland 自身に問い合わせます(hyprctl locked)。これにより、hyprlock、swaylock、Omarchy の組み込みロック機能のほか、クラッシュしてセッションをロックしたままにしたロッカーも検出できます。ロック中は、人間がエージェントにロック解除プロンプトを操作させたいことをallow_auth=trueで示した場合を除き(HYPRUSE_CONFINEが設定されている場合は常に)、pointerとウィンドウ指定のないkeyboardは拒否されます。window=を指定したkeyboardとclick_uiは常に拒否されます。ウィンドウを対象とした入力は、ロック画面の背後にあるウィンドウには届かないためです。これらは動作を正しく伝えるための補助であり、サンドボックスではありません。ロックチェックはシステム状態を読み取れない場合に許可するため、一般的なケースを強化するものではありますが、頼れるセキュリティ境界ではありません。(HYPRUSE_AUTH_GUARDが有効な場合、認証プロンプトがないと確認できないため、レイヤー一覧を読み取れないとpointer、click_ui、keyboardは拒否されます。)
任意の制限
7 つのオプトイン環境フラグがあります。最初の 5 つはエージェントが操作できる対象を絞り込み、いずれも動作を減らす方向に機能します。最後の 2 つは制限するのではなく、記録してリハーサルします。すべて上記のレイヤーと組み合わせて使用できます。
- **
HYPRUSE_CONFINE**は、入力をウィンドウのスコープに制限します。launched(このセッションでhypruse自身が開いたウィンドウのみ)、class:firefox,kitty、またはworkspace:3,special:notesを指定できます。キーボード、click_ui、hyprのウィンドウ操作はスコープ外では拒否されます。pointerによるクリックは、ポインターの下にあるウィンドウのいずれかがスコープ外の場合に拒否されます(Hyprlandのウィンドウ一覧はZ順ではないため、hypruseはどのウィンドウが最前面かを推測せず、安全側に倒して操作を拒否します)。これにより、パスワードマネージャーを別のワークスペースに置き、クリックやキー入力(スクリーンショットは対象外)でアクセスできない状態にしたまま、エージェントに作業を続けさせることができます。use_bindは、ウィンドウ単位にスコープを制限できない任意のコンポジター操作をキー割り当てが実行するため、隔離が設定されている間は常に拒否されます。 - **
HYPRUSE_BACKGROUND=1**はバックグラウンド保証です。入力はエージェント自身のワークスペース上のウィンドウに制限され(両方が設定されている場合は、HYPRUSE_CONFINEのスコープにも制限されます)、カーソル、フォーカス、ワークスペースを移動させるhypruseの操作は拒否されます。launchで開始したコマンドの動作は制限できません。 HYPRUSE_AUTH_GUARD(デフォルトは有効)は、システム認証ダイアログ(hyprpolkitagentのようなウィンドウか、Omarchy 4やend-4のドットのようにシェルがレイヤーとして描画するプロンプトかを問わず、polkitエージェント、GNOMEキーリングのプロンプト、Hyprland独自のダイアログ。Hyprlandの権限確認プロンプトと、アプリケーションの応答なし通知およびセーフモード通知は、3つとも同じウィンドウクラスを共有しているため、これらも対象です)へのクリックや入力を拒否し、操作を乗っ取られたエージェントが権限昇格を承認できないようにします。click_uiも、クリック対象のコントロールにそのようなダイアログが重なっている場合は拒否します。レイヤー一覧を読み取れない場合は、推測せずに拒否します。DankMaterialShellのように、シェルが独自のクラスを持つ通常のウィンドウとして開くプロンプトは認識されません。HYPRUSE_AUTH_GUARD=strictを設定すると、アクセシビリティツリーで検出した通常のウィンドウ内のパスワードフィールド(ブラウザーのログイン画面など)への入力も拒否します。pointer/keyboard/click_uiの呼び出しごとにallow_auth=trueを指定すると上書きできます。この指定によってツールの引数が変わるため、上書きは承認プロンプトに明確に表示されます。HYPRUSE_AUTH_GUARD=0を設定すると無効になります。- **
HYPRUSE_STRICT**は、hypruseの最後の操作からカーソルまたはフォーカス中のウィンドウが移動した場合(人間またはポップアップが操作権を取った場合)に、操作を拒否します。エージェントはdesktop/screenshotを読み直して再試行する必要があるため、切り替えたばかりのウィンドウに入力することはありません。 - **
HYPRUSE_MARK**は、デスクトップ上でエージェントの存在を見えるようにします。エージェントが開くすべてのウィンドウにhypruse-ownedのタグを付け、ウィンドウを開いたときや画面をキャプチャしたときに、画面上に通知を表示します。また、そのタグにborder_colorウィンドウルールを設定して、所有するウィンドウを色付きの枠線で囲みます。ただし、実行時ルールが反映されるかどうかは、Hyprlandのバージョンと設定の優先順位によって異なります(環境によっては反映されません)。ルールをまったく設定できない場合、動作していないマーキングレイヤーをひそかに残すのではなく、hypruseが標準エラー出力にその旨を表示します。枠線を確実に表示するには、hypruseのタグ付けと一致するルールを独自の設定に追加してください。hyprland.confではwindowrule = border_color rgb(ff5555), tag hypruse-owned(古いHyprlandではtag:hypruse-owned)、hyprland.luaではhl.window_rule({ match = { tag = "hypruse-owned" }, border_color = "rgb(ff5555)" })を追加します。 - **
HYPRUSE_JOURNAL**は、エージェントの操作を記録します。$XDG_STATE_HOME/hypruse/journal.ndjsonにツール呼び出しごとに1行のNDJSON形式で記録します(HYPRUSE_JOURNAL=1)。または、任意のパスを指定できます。hypruse journalで読み取り、hypruse replayで再実行します。詳しくは、以下の記録をご覧ください。 - **
HYPRUSE_DRYRUN**はリハーサルです。引数チェックと上記のすべてのガードを実行した後、呼び出しで実行されるはずだった内容を報告し、何も実行しません。
記録:ジャーナル、ドライラン、リプレイ
上記のフラグは、その場でエージェントに許可する操作を決めますが、実行後は記録に残りません。HYPRUSE_JOURNAL がメモリーの役割を果たします。1 行につき 1 つの JSON オブジェクトなので、稼働中のファイルに対して tail -f、grep、jq を使えます:
{"v":1,"seq":7,"ts":"2026-08-02T09:12:13.456Z","kind":"act","tool":"pointer",
"args":{"action":"click","x":800,"y":60},"outcome":"ok","ms":37,"result":"click ok"}
kind は、実際によく尋ねられる 2 つの問いを分けます。act はデスクトップに送られた入力、observe はエージェントによる観察です。画面がいつキャプチャされたか、クリップボードがいつ読み取られたかを知りたいプライバシー監査では、後者が重要です。観察の結果は記録されず、観察が行われたことだけが記録されるため、ジャーナルがエージェントの見たものすべての複製になることはありません。拒否も記録されます。ガード自身のメッセージとともに記録されます。信頼レイヤーが機能した履歴が残るのは、ここだけです。
入力およびコピーしたテキストは、テキストそのものではなく、長さと短いダイジェストとして記録されます。キーストロークにはパスワードが含まれるためです。HYPRUSE_JOURNAL_TEXT=1 を設定するとそのまま記録されます。これは入力を再生する場合にのみ必要です。ダイジェストの意味と限界に注意してください。2 つのエントリーに同じ内容が入力されたことは証明できますが、読み手にパスワードを明かすことはありません。ただし、これはソルトなしの SHA-256 の先頭部分であり、正確な文字数も併記されるため、4 桁の PIN は簡単に特定できます。どちらの場合も、ジャーナルは機密情報として扱ってください。0700 のディレクトリー内に 0600 の権限で書き込まれ、HYPRUSE_JOURNAL_MAX_BYTES に達するとローテーションされます(8 MiB、前の世代を .1 として 1 つ保持します。ローテーションしない場合は 0 を設定します)。
ジャーナルはレコーダーであり、ガードではありません。書き込みに失敗しても操作は実行され、hypruse は stderr に一度だけ警告を出します。ログ 1 行のためにデスクトップを止めるのは、正しい判断ではないからです。記録されないのは、then= による観察が独立したエントリーにならないことです。それを伴う操作呼び出しは then=screenshot も含めて記録されますが、キャプチャ自体が別の行に記録されることはありません。
hypruse journal で読み返せます(アクションのみは --acts、ガードによって止められた操作は --refused、末尾から N 件を表示するには -n N、各結果を含めるには -v):
1 09:12:10 session start pid 4211 0.10.0 confine=launched auth_guard=1 strict=True
14 09:12:13 act pointer action=click x=800 y=60
16 09:12:15 act keyboard action=type text=<11 chars>
19 09:12:19 act hypr action=close_window target=0x5f2a10
REFUSED TrustError: 0x5f2a10 (Signal) is outside the agent's confinement scope
312 actions (0 dry), 604 observations, 1 refused by a trust layer, 0 errors
HYPRUSE_DRYRUN=1 を設定すると、同じセッションをリハーサルとして実行できます。すべての操作ツールが引数を検証し、すべての信頼ガードを実行したうえで、実行する代わりに計画を報告します。そのため、ドライランでは実際の実行とまったく同じ操作が拒否されます:
DRY RUN, nothing was delivered: would click push button 'Send' at (1204, 880) in signal
クリックも、キーストロークも、通常は文字入力の前に行われるウィンドウフォーカスの切り替えさえも、デスクトップには届きません。各ツールと入力経路自体の 2 か所で適用されるため、誰も想定していなかったコード経路があっても、シミュレーション中にひそかに動作するのではなく、明確に失敗します。エージェントにはドライラン中であることが伝えられるため、「動作しなかった」操作を再試行せず、計画を報告します。適用範囲はエージェントの操作であり、サーバー自体の起動ではありません。HYPRUSE_MARK を設定している場合、サーバーの起動時にウィンドウルールが引き続き設定されます。
hypruse replay <journal> は、ジャーナルの操作を同じツール関数経由で再実行するため、再生にも同じガードが適用されます。--execute を渡さない限り、計画を表示して停止します。処理を開始する前に、再生が途中で失敗してデスクトップが他人の計画を一部だけ実行した状態になることがないよう、次の場合は最初から拒否します。操作が現在より新しいバージョンの hypruse によって記録されている場合、記録されたウィンドウがもう存在しない場合(--skip-missing を指定すると残りを実行します)、入力テキストがダイジェストとして記録されている場合、セッションとともに番号が失効した click_ui(mark=N) のエントリーである場合、クリップボードへの書き込みエントリーで HYPRUSE_CLIPBOARD が設定されていない場合、または HYPRUSE_READONLY か HYPRUSE_DRYRUN が設定されている場合です。記録されたタイミングに合わせて処理間隔を取り、--max-gap で上限を設定し、--speed で速度を調整します。また、再生自体の操作も記録してマークするため、同じファイルを再び再生しても、元の計画に再生分が加わった内容ではなく、元の計画だけが実行されます。
正直なところ、ウィンドウアドレスには限界があります。これはヒープポインターであるため、昨日のジャーナルにはすでに存在しないウィンドウが大半を占めます。また、後になって別のウィンドウに同じアドレスが再利用されることさえあり、事前チェックでは検出できません。再生は、記録時と同じ状態が保たれているデスクトップでワークフローを再実行するためのものです。
ドライランと再生は自然な順序で組み合わせられます。HYPRUSE_DRYRUN=1 でエージェントに操作させ、ジャーナルを読み、気に入ったプランができたら --execute で再生します。
パフォーマンス
実際のセッション(Hyprland 0.55、1080p、ウィンドウ 20 個)での測定値:desktop
約 20 ms(hyprctl の一括呼び出し 1 回)、ワークスペース/ウィンドウのディスパッチは約 10〜20 ms、モニター全体のスクリーンショットは約 65 ms
(デフォルトの高速な JPEG を使用した場合。可逆 PNG を指定すると約 800 ms
で、grim の zlib 処理が大半を占めます)、領域/ズームのキャプチャはそれより大幅に短時間です。ツールの
呼び出しが遅く感じる場合、原因はほぼ間違いなくサーバーではなく、各呼び出しの前に表示される MCP の承認プロンプトです。
信頼するツールを許可リストに追加すれば、遅延はなくなります。Claude Code(.claude/settings.json):
{
"permissions": {
"allow": [
"mcp__hypruse__desktop",
"mcp__hypruse__screenshot",
"mcp__hypruse__hypr"
// add pointer/keyboard/launch once you trust your workflows
]
}
}
座標
すべて Hyprland のグローバル論理座標を使用します。これは hyprctl cursorpos とウィンドウの at が使用する座標空間です。スクリーンショットはピクセル座標で、各キャプチャは geometry と scale を返すため、global = origin + pixel / scale で変換できます。スケール 1.0 のモニター(多くの環境が該当)では、画像のピクセル座標がそのままグローバル座標になります。
zoom ツールは、エージェントが精密な座標計算を行うためのものです。推定したグローバル座標を渡すと、画面(またはウィンドウ)内に収まるよう調整したうえで、その点を中心にネイティブ解像度の領域をキャプチャし、同じメタデータ形式で返します。全体表示で位置を推定し、ズーム表示でもう一度推定するこの 2 段階の手順は、小さなコントロールを正確に操作するための研究に裏付けられた方法です。
キャプチャはデフォルトで JPEG q90 です。1080p のフレームでは、PNG よりエンコードが約 12 倍速く(キャプチャ時間の大半は grim の zlib 処理で、測定値は約 65 ms 対約 800 ms)、ファイルサイズも 3〜4 倍小さくなります。また、フル解像度の q90 でも UI テキストを十分に読み取れます。ピクセルを正確に保持するには lossless=true を指定してください(PNG)。画像モードでは、ホストの結果サイズ制限(Claude Desktop ではツール結果が 1 MB まで)に収まるよう、解像度を下げる前に画質を下げます。これは grim の縮小フィルターがフル解像度でのキャプチャより遅いためです。また、モデルの代わりにホストが画像を縮小しないよう、長辺を HYPRUSE_MAX_IMAGE_EDGE ピクセル(デフォルトは 1568)に制限します。適用されたスケールは返されるメタデータに反映されるため、座標の変換は正確なままです。HYPRUSE_MAX_IMAGE_BYTES で調整するか、意図的にズームアウトするには scale を指定してください。
デフォルトでは、スクリーンショットツールは $XDG_RUNTIME_DIR/hypruse/ に画像を保存し、そのパスを返します。ファイルリーダー(Claude Code の Read など)を備えた MCP ホストは、画像をネイティブに表示します。一部のホスト(Claude Code 2.1.x を含む)がインライン MCP 画像ブロックを、モデルが認識できない base64 テキストに変換してしまうため、この動作がデフォルトになっています。正しく表示できるホストでは、HYPRUSE_SCREENSHOT_MODE=image を指定すると、画像コンテンツブロックをインラインで使用できます。
開発
uv sync --group dev
uv run pytest # unit tests, no compositor needed
uv run pytest -m e2e --override-ini addopts= # live seat-safe checks
uv run pytest -m background --override-ini addopts= # live: drives yad forms on the agent's workspaces
uv run python scripts/e2e_input.py # supervised: takes the seat ~10s
バックグラウンドテストスイートは、エージェントのワークスペース上で yad フォームを開いてバックグラウンドで操作し、各ステップの後に、アクティブウィンドウ、ワークスペース、カーソルがすべて元の状態のままであることを確認します。実行中はマウスとキーボードに触れないでください。Hyprland 自身のイベントも確認しており、作業中でも、開いたウィンドウがフォーカスを奪うことはなく、エージェントのワークスペースに切り替わることもありません。
入力の E2E テストは、意図的に手動で行います。カーソルとキーボードを使用するため、カウントダウンの後、kitty のリモート制御を使って対象ターミナルの画面を読み取り、クリック、スクロール、文字入力が届いたことを検証し、フォーカスを元に戻します。
ロードマップ
ホットパスのレイテンシーを実測した結果と、コンピューター操作タスクのレイテンシーの76~96%をLLM呼び出しが占めるという知見(OSWorld-Human)に基づいています。そのため、ミリ秒単位の短縮よりもラウンドトリップの削減が効果的です。この方針に基づくラウンドトリップ関連の取り組みは、ほぼ実装済みです。sequence、操作と観測をまとめる then=(then='ui' を含む)、そしてスクリーンショットなしで名前からコントロールを指定するアクセシビリティツリーのツール(ui、marks、click_ui)を提供しています。残る作業は次のとおりです。
高速化
- 生のワイヤーを介したプロセス内の wlr-screencopy(入力ではすでに動作):小さなキャプチャで grim のフォークにかかる最低時間をなくし、ダメージ追跡型の安定待機を追加して、画面が安定した瞬間に返します。
ラウンドトリップの削減
- セマンティックな画面差分:操作後にフレーム全体ではなく、変更された部分だけを返します(イベントストリームから取得するウィンドウ構成、または範囲を限定した変更領域の切り抜き)。
wait_forを支える socket2 のイベント拡張では、構成情報の大部分をすでに追跡しています。残るのは、操作後の差分にこの情報を組み込むことです。
より深い情報の取得
- アクセシビリティ対応範囲の拡大:現在
uiツールとmarksツールが抱える不足を解消します。主な課題は、新しい GTK コンボボックスがテキストも選択状態も公開しないため、ドロップダウンに表示された値を取得するには依然としてスクリーンショットが必要な点です。また、AT-SPI の値変更イベントに対応し、ポーリングせずにコントロールの状態が落ち着いたことをthen='ui'から報告できるようにします。 - 通知:ポップアップの表示を待つだけでなく、最近のデスクトップ通知の内容と履歴を読み取ります(
wait_forはすでに通知名前空間のlayer_openに一致します)。
バックグラウンド
- ブラウザブリッジ(拡張機能とネイティブメッセージングホスト)を介して、バックグラウンドのウェブページに対応します。
信頼性
recordツール:wf-recorder(grim のような wlroots 系のバイナリ)を介して、エージェントがデスクトップを操作する様子を対象範囲を限定した GIF または mp4 で記録します。journal を視覚的に補完するものです。
プラットフォーム
- sway / niri に対応します。ワイヤークライアントはすでに wlr プロトコルを扱えます。残るのは
hyprctl.pyに並ぶ IPC レイヤーです(コントリビューションを歓迎します)。 - CI でのヘッドレスなエンドツーエンドテスト:Hyprland の aquamarine バックエンドには実際の GPU レンダーノードが必要ですが、ホスト型ランナーにはないため、QEMU virtio-gpu VM が必要です。
測定
- ズームループの精度ベンチマーク:既知のターゲットに対する粗密ループのクリック精度を測定します。
- Hyprland でのエンドツーエンドのタスク成功ベンチマーク(OSWorld 形式):ズームループのマイクロベンチマークを拡張した、先送りされている大規模な取り組みです。実際の MCP インターフェースを通じて複数手順からなるタスク全体を評価し、a11y とビジョンの比較やラウンドトリップ削減の成果を、レイテンシーだけでなくタスクの完了度で評価します。
関連プロジェクト
| プロジェクト | アプローチ | Hyprland での状況 |
|---|---|---|
| computer-use-linux | AT-SPI + ポータル、フォールバックとして ydotool | GNOME を優先。優先される RemoteDesktop ポータルは xdg-desktop-portal-hyprland では実装されていません |
| hyprmcp | hyprctl ラッパー | ウィンドウ管理のみ。スクリーンショットや入力には非対応 |
| wayland-mcp | evemu 入力、VLM 分析 | 入力には昇格された権限でのセットアップが必要。Hyprland のセマンティクスには非対応 |
| Anthropic computer-use-demo | Docker 内の X11 + xdotool | 実際のデスクトップではなく、サンドボックス化されたリファレンス環境 |
| Cua (cua-driver) | クロスプラットフォームドライバー。オプションの Hyprland コンポジタープラグインにより、エージェント専用の入力シートを提供 | プラグインはインストール済みの Hyprland の正確なバージョン向けにビルドする必要があり、README では実験的かつ未リリースとされています |
研究
hypruseにはOCRエンジンが同梱されていません。汎用的で高精度な仕組みとして採用しているのは、粗い範囲から細かい範囲へズームするループです。ウィンドウのスクリーンショットを撮り、対象領域をネイティブ解像度で再キャプチャし、正確な座標マッピングを使ってクリックします。この選択は、GUIエージェント分野で確立された方向性に沿っています。Anthropicのcomputer useは生のピクセルからクリック位置を特定し、小さな文字への対処法として、ドキュメントでzoomアクションを提供しています。クリックがわずかにずれる場合のトラブルシューティングでも、OCRではなくズームと領域の切り抜きを推奨しています [1]。OpenAIのCUAも、解像度を適切に管理しながらピクセルのみで位置を特定し、OCRレイヤーは一切ありません [2]。ズームは実測でも有効な手段です。学習不要の反復ズームにより、高解像度での位置特定精度はおよそ2倍になります(OS-Atlas-7BではScreenSpot-Proで18.9から49.7に向上)[3]。ベンチマークの公式ハーネスには、位置特定モデル用のアダプターが12種類と、ズーム/切り抜きの戦略が4種類実装されていますが、OCRベースラインは一つもありません [4]。視覚情報だけを使うエージェントは、HTMLやアクセシビリティツリーも利用するエージェントと同等以上の性能を発揮します [5]。そもそもWaylandでは、これらの情報が保証されているわけでもありません。また、最先端のネイティブエージェントはスクリーンショットだけで動作します [7]。OCRはアイコンを認識できず、アイコンはどの位置特定モデルでも最も苦手とする要素であるため、採用を見送りました(SeeClickではアイコンが30~52%、テキストが56~78%)[6]。現代のスタックでOCRが使われる場合も、テキストを区別するための補助的な機能であり、位置特定の仕組みではありません [8]。
アプリがアクセシビリティツリーを公開している場合、hypruseはこれも読み取ります(uiツール、D-Bus経由のAT-SPI)。スクリーンショットを使わず、正確な座標で名前からコントロールを指定できます。これはLinuxにおける最も有力な先例に沿ったものです。標準的なコンピューター操作ベンチマークであるOSWorldは、デスクトップのアクセシビリティツリー(UbuntuではAT-SPI経由で取得)をスクリーンショットと並ぶ第一級の観測情報として公開し、アクセシビリティツリーとスクリーンショットを組み合わせた構成が最も優れた結果を示すと報告しています [9]。現在のモデルはピクセルだけでは確実に推定できない正確な要素の識別情報と座標を、ツリーから取得できます。Agent-Sは、MLLMには「内部座標系がない」ため、各要素にIDを付けています。これによりOSWorldの成功率が11.2%から20.6%に向上します [10]。MicrosoftのUFOはUI Automationツリーを通じてWindowsを操作し、視覚情報と組み合わせます [11]。ブラウザーエージェントも同じ理由から、ピクセルではなくアクセシビリティツリーを読み取ります。PlaywrightはこれをコンパクトなYAMLにシリアライズします [12]。hypruse独自のWayland向けの工夫は座標マッピングです。アプリは自分のグローバル位置を把握できないため、WaylandではAT-SPIの画面座標が信頼できません。そこでhypruseは、ウィンドウ相対の範囲と、すでにhyprctlから取得しているウィンドウ位置を使います。カバレッジが不均一なのは仕様上避けられません。キャンバス、ゲーム、ターミナル、そしてフラグなしのElectron/Chromeは、公開する情報がほとんどないか、まったくありません [13]。実際のGTKアプリとQtアプリでこの実装をテストしたことで、両方向の特性が明らかになりました。入力欄は内容を正確に読み戻し、スライダーとトグルは位置と状態を報告します。一方、GTKの新しいコンボボックスはテキストも選択項目も公開しないため、描画されたドロップダウンの値を読み取るには、依然としてスクリーンショットが必要です。また、ツールキットは実際にはレイアウトしていないウィジェットについても情報を返します(高さ0のスクロール矢印や、描画されていないタブページが数百万単位の原点を報告するなど)。hypruseはこれらを、hyprctlが確実に把握しているウィンドウ矩形と照合して除外します。優れた視覚的な位置特定器があれば、ツリーを完全に置き換えることも可能です [5]。そのため、アクセシビリティツリーはズームループを補完するものであり、置き換えるものではありません。視覚情報は、常に利用できるフォールバックとして残ります。
- Anthropic、Computer use tool:プラットフォームのドキュメント(
computer_20251124、enable_zoom、解像度に関するガイダンス) - OpenAI、Computer-Using Agentとコンピューター使用ガイド
- DiMo-GUI: Advancing Test-time Scaling in GUI Grounding via Modality-Aware Visual Reasoning、EMNLP 2025。arXiv:2507.00008
- Li ほか、ScreenSpot-Pro: GUI Grounding for Professional High-Resolution Computer Use。arXiv:2504.07981、公式ハーネス
- Gou ほか、Navigating the Digital World as Humans Do: Universal Visual Grounding for GUI Agents(UGround)、ICLR 2025 オーラル発表。arXiv:2410.05243
- Cheng ほか、SeeClick: Harnessing GUI Grounding for Advanced Visual GUI Agents、ACL 2024。arXiv:2401.10935
- Qin ほか、UI-TARS: Pioneering Automated GUI Interaction with Native Agents。arXiv:2501.12326
- Agyeya ほか、Agent S2: A Compositional Generalist-Specialist Framework for Computer Use Agents(テキストによるグラウンディングのサイドカーとしての Tesseract)。arXiv:2504.00906
- Xie ほか、OSWorld: Benchmarking Multimodal Agents for Open-Ended Tasks in Real Computer Environments。arXiv:2404.07972、Ubuntu では AT-SPI を介して a11y ツリーを取得します(コード)
- Agashe ほか、Agent S: An Open Agentic Framework that Uses Computers Like a Human。arXiv:2410.08164
- Zhang ほか、UFO: A UI-Focused Agent for Windows OS Interaction(UI Automation とビジョン)。arXiv:2402.07939
- Playwright、ARIA snapshots:アクセシビリティツリーを簡潔な構造化テキストとして表現
- Wang ほか、GUI Agents: A Survey(アクセシビリティ API の対応範囲の不足、a11y はビジョンを補完)。arXiv:2412.13501
ライセンス
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。