Hermes Agent の Computer Use を macOS で有効化した記録 — /Applications 書き込みと TCC 権限で詰まった 7 つのポイント
先日書いた macOS と Windows 両対応の Computer Use エージェント選定メモ の続きで、実際に Hermes Agent v0.21.1 の computer_use ツールセットを macOS Tahoe 26.6 の実機上で有効化しました。「インストールは hermes computer-use install の 1 コマンドで済む」と公式ドキュメントには書かれているのですが、実際は cua-driver の macOS 向けインストーラが /Applications への .app 配置を必須にしている点、Jamf 管理端末で当初は admin 権限を持っていなかった点、TCC(Transparency, Consent, and Control)の権限がプロセスの bundle identity に紐づく点が絡み合い、途中で 7 回詰まりました。
この記事は 2026-09-10 時点で Hermes Agent v0.21.1(2026.9.7、upstream 61afcde8)と cua-driver-rs v0.26.0 を使い、Apple Silicon Mac で作業した記録です。同じ環境を組むか、あるいは会社支給の管理端末で似た制約に当たった人の参考になるよう、症状・原因・回避策と、実際に出たコマンドログを合わせて残しておきます。
前提となる環境
作業した端末とバージョンは以下のとおりです。管理端末側の設定に依存する部分もあるので、あわせて明示します。
- macOS: 26.6(Build 25G72、Tahoe 系)
- Mac: Apple Silicon (aarch64)
- Hermes Agent: v0.21.1(2026.9.7、upstream
61afcde8)、~/.hermes/hermes-agentへ git-install - Python: Hermes 同梱の venv、3.11.15
- cua-driver: 0.26.0(Rust 実装、darwin-universal)
- モデル: 途中で Anthropic Claude から OpenAI GPT-5.6 Sol へ切り替え(いずれもツール呼び出しと vision に対応するモデル)
- アカウント: 当初は
staffグループのみで admin 権限なし。Jamf 管理端末で admin グループのメンバーはrootと_jadminのみ - 実行元: ターミナルアプリから Hermes CLI(TUI)
computer_use ツールセットの位置づけ
Hermes Agent の computer_use ツールセットは、trycua/cua の cua-driver を MCP over stdio で呼び出し、macOS のデスクトップを操作するためのツール群です。前回の記事でも触れたように、カーソルとフォーカスを奪わない「no-foreground contract」で動くのが特徴で、ユーザーが同一マシンで別作業を続けたまま背面で電卓や メモ を操作できます。ツール仕様の全体像は Hermes リポジトリの tools/computer_use/schema.py と 公式ドキュメント に整理されています。
アクションの粒度としては、capture でスクリーンショットと Accessibility(AX)ツリー、または番号オーバーレイ付きの SOM 画像を取り、click(element=N) のように要素番号でクリックする流れが基本です。座標指定もできますが、他モデルでも動くように要素番号を先に使うのがスキル側で推奨されています。
このツールセットを実行時に呼び出すためには、cua-driver 本体を macOS 上にインストールし、加えて Accessibility と Screen Recording の TCC 権限を driver 自身の bundle identity に付与する必要があります。ここが本題です。
/Applications への .app 配置が必須である理由
インストールは hermes computer-use install を叩くだけです。中では cua-driver 公式のインストールスクリプト が実行され、GitHub Releases から .tar.gz を取ってきて /Applications/CuaDriver.app に展開し、~/.local/bin/cua-driver を .app 内のバイナリへシンボリックリンクします。
問題は、この /Applications への配置がハードコードされていて環境変数やフラグでは回避できないことです。インストールスクリプトの macOS ブロックには、その理由が明確に書かれています。
- macOS の TCC はアプリの identity(
com.trycua.driverの bundle id と cdhash)に権限を紐づける /Applications/CuaDriver.appを anchor にすることで、LaunchServices がopen -a CuaDriverで.appを発見できる$HOME配下から/Applicationsにシンボリックリンクを張り直すと、cdhash 帰属と LaunchServices 検出の両方が壊れる- ターミナルから素のバイナリを起動すると、権限は「ターミナル」に付与されてしまい、driver 自身の identity には付かない
つまり、ここは「たまたま /Applications に置くだけ」ではなく、TCC の帰属先を driver に固定するための設計上の必須要件です。--bin-dir や CUA_DRIVER_RS_INSTALL_DIR は symlink 先だけを変える環境変数で、.app の配置場所は動かせません。Linux 側は $HOME/.cua-driver/packages/releases/<version>-<target>/ に置く方式が正式なので、この非対称は意図的なものです。
1 回目のインストールは /Applications 書き込みで失敗する
事前状態は以下のようになっていました。ツールセット自体はデフォルトで有効ですが、バックエンドが未インストールなので呼び出しても computer_use backend unavailable が返る状態です。
$ sw_vers
ProductName: macOS
ProductVersion: 26.6
BuildVersion: 25G72
$ hermes computer-use status
cua-driver: not installed
Run: hermes computer-use install
$ hermes tools list | grep -i computer
✓ enabled computer_use 🖱️ Computer Use (macOS)この状態で hermes computer-use install を叩くと、非 admin アカウントでは以下で止まります。
note: installing cua-driver via the Rust implementation.
==> using baked release: cua-driver-rs-v0.26.0
==> downloading https://github.com/trycua/cua/releases/download/cua-driver-rs-v0.26.0/cua-driver-rs-0.26.0-darwin-universal.tar.gz
==> extracting
error: /Applications is not writable. Re-run this installer in a shell where it is, or grant write access.
error: Without the .app bundle, `cua-driver-rs mcp` from an IDE terminal will not auto-relaunch into a TCC-correct daemon.
⚠ cua-driver installing did not complete.
権限まわりは ls -ld /Applications で drwxrwxr-x root admin、id -Gn の結果に admin が含まれない、というごくシンプルな状況でした。Jamf 管理端末の Self Service などで admin 権限に昇格します。
昇格後も既存プロセスからは書けない
ここで最初のつまずきポイントです。管理端末側で admin 権限を得ても、昇格前に起動していた Hermes のシェルからは touch /Applications/.t が Permission denied で失敗します。id -Gn を叩くと admin が出るので一瞬混乱するのですが、Unix のプロセスクレデンシャル(実効 UID・GID・補助グループ)は基本的にプロセス起動時に固定され、後から admin グループに追加されても実行中のプロセスには反映されません。login -f $USER -c などで補助グループを取り直そうとしても、ここでは通りませんでした。
解消は素朴で、新しいターミナルウィンドウを開いてから hermes computer-use install を再実行することです。ここで成功します。
==> stopping any running cua-driver daemons before swap
==> installing /Applications/CuaDriver.app
==> symlinked /Users/<user>/.local/bin/cua-driver -> /Applications/CuaDriver.app/Contents/MacOS/cua-driver
cua-driver-rs 0.26.0 installed.
インストーラはダウンロードした .app に対して codesign --verify --deep --strict を走らせ、既存 .app がある場合は署名 identity の連続性を検証してから差し替えます。連続性が保てなければロールバックする作りで、これも TCC の付与を維持するためです。
インストール完了後の出力には、Claude Code・Codex・Cursor・OpenCode など向けの MCP 設定サンプルも一緒に出ますが、Hermes の場合は computer_use ツールセットが内部で cua-driver を stdio 起動するので、~/.hermes/config.yaml の mcp_servers に追加する必要はありません。
権限の付与先はターミナルではなく CuaDriver.app
Hermes・cua-driver のセットアップで一番混乱しやすいのが、TCC 権限の付与先です。ここで再度、TCC は「アプリの identity」に権限を紐づけるという性質が効いてきます。
インストール直後に cua-driver permissions status を叩いても、以下のように「unknown」を返します。
Accessibility: ❓ unknown
Screen Recording: ❓ unknown
No CuaDriver daemon is running under the driver's own identity (com.trycua.driver), so its real TCC status can't be read.
(A status check from this terminal would report the terminal's grants, not the driver's.)
→ Run `cua-driver permissions grant` to grant + verify, or start the daemon
(`open -n -g -a CuaDriver --args serve`) and re-run this command.
これは、稼働中の daemon に対して直接 TCC 状態を問い合わせる設計になっているためです。daemon がいない状態で status を返すと、ターミナルアプリの権限をそのまま driver の権限と誤認しかねないので、明示的に「unknown」を返しているわけです。
正しい手順は cua-driver permissions grant を叩くことです。このコマンドが LaunchServices 経由で CuaDriver.app を起動し、Accessibility → Screen Recording → Direct Capture 同意の順にダイアログを出します。ダイアログの主体が「CuaDriver」になっていることが重要で、システム設定 → プライバシーとセキュリティ → アクセシビリティ と 画面収録とシステムオーディオ録音 の一覧にも CuaDriver として登録されます。ここが Terminal や Ghostty として登録されてしまうと、driver プロセスには権限が渡らないので永遠に動きません。
permissions grant は対話的にダイアログの応答を待つので、エージェント経由のターミナルツールから叩くとタイムアウトで [Command interrupted](exit 130)に落ちる場合があります。ただしダイアログ自体はすでに出ているので、手元で手動で許可すれば十分です。エージェントから叩くよりは、素直にホストのターミナルウィンドウで直接実行するほうが混乱が少ないと思います。
permissions status が unknown を返し続けるとき
権限を許可した直後、cua-driver permissions status がまだ unknown を返すことがあります。これは、許可前から起動していた daemon プロセスが古い TCC 状態をキャッシュしたまま生き残っているためです。TCC の変更はプロセス再起動で反映されるので、daemon を明示的に叩き直します。
$ pkill -f "CuaDriver.app/Contents/MacOS/cua-driver serve"
$ open -n -g -a CuaDriver --args serve-n は新しいインスタンスを、-g はバックグラウンドで起動して前面に出さないためのフラグです。特に画面収録の許可を出した直後は、macOS 側から「アプリを終了して再起動する必要があります」相当の挙動が発生するので、この再起動をもう 1 回踏む場面がありました。最終的な状態は以下のようになります。
$ cua-driver permissions status
Accessibility: ✅ granted
Screen Recording: ✅ granted
Direct Capture: ❓ not checked (status is read-only; run `cua-driver permissions grant`)
Source: driver-daemon
$ cua-driver call check_permissions '{}'
{
"accessibility": true,
"screen_recording": true,
"source": {
"attribution": "driver-daemon",
"bundle_id": "com.trycua.driver",
"executable": "/Applications/CuaDriver.app/Contents/MacOS/cua-driver",
"note": "These booleans reflect the CuaDriver daemon's own TCC identity (com.trycua.driver) because this process is its own responsible process.",
"pid": 35293,
"responsible_ppid": 1
}
}responsible_ppid: 1(launchd 直下)と attribution: driver-daemon の 2 つが揃っていれば、TCC が driver 自身に帰属している証拠です。ターミナルの子プロセスとして起動していたら、responsible_ppid にターミナルの pid が入ります。
daemon と Hermes セッションの関係
cua-driver の daemon は、open -n -g -a CuaDriver --args serve で ~/Library/Caches/cua-driver/cua-driver.sock にソケットを開いて待機します。ログアウトで止まる作りです。Hermes 側は computer_use を呼び出すタイミングで cua-driver mcp を stdio で起動するので、通常運用では daemon を手動で立ち上げっぱなしにする必要はありません。cua-driver permissions status の確認や、cua-driver call からの疎通テストのために daemon が要る、という位置づけです。
daemon 側にも権限モードがあり、standard がプロンプトなしで通常の自動化、bounded が capability manifest で許可対象を制限、unrestricted は --dangerously-bypass-approvals が必要、という 3 段構えになっています。Hermes 側の approvals とはレイヤーが別なので、両方を意識して設計する必要があります。
Hermes セッションは、TUI 起動時にツールセット構成を固定します(プロンプトキャッシュ保護のため)。したがって、既存セッションで computer_use が表示されない場合は、Hermes をいったん終了して新しいセッションを開く必要があります。~/.hermes/config.yaml の tools.enabled 相当のリストに computer_use が入っていれば、あらためて追加設定は不要でした。
venv から直接呼んで先に疎通を取る
Hermes を再起動する前に、venv から直接 handler を呼ぶことで疎通は先に取れます。
$ cd ~/.hermes/hermes-agent
$ venv/bin/python -c '
from tools.computer_use.tool import handle_computer_use
print(handle_computer_use({"action": "capture", "mode": "ax"}))
'
{"mode": "ax", "width": 1568, "height": 984, "app": "Google Chrome", "window_title": "...", "elements": [...]}ここでシステムの python3 を叩くと、computer_use backend unavailable: No module named 'mcp' になります。mcp パッケージは Hermes venv の computer-use エクストラ(mcp==1.26.0・starlette==1.0.1)にしか入っていないためで、通常運用では発生しませんが、手動検証のときは venv/bin/python を指す必要があります。
キャプチャの返り値には 1568 × 984 という縮小解像度が出ています。これは Retina のネイティブ解像度ではなく、Anthropic のスクリーンショット推奨サイズ に合わせてモデルへ送るための縮小版です。トークン節約のため、Anthropic アダプタは直近 3 枚のみを保持して、それ以前は [screenshot removed to save context] に差し替える設計になっています。
電卓アプリでの動作確認
Hermes を再起動して新しいセッションを開き、テストタスクとして「電卓で 12 × 34 を計算して」を投げました。
結果として、電卓アプリで AC → 1 → 2 → × → 3 → 4 → = の順に押下され、式 12 × 34 と結果 408 の表示まで確認できました。ここで観察できたのは以下です。
- ユーザーのカーソル位置が動かない
- 電卓アプリが前面に出てこない(他アプリのフォーカスを奪わない)
- Space 切り替えも発生しない
背景操作の実体は、cua-driver が SkyLight の SLEventPostToPid / SLPSPostEventRecordTo を使って合成イベントを対象プロセスに直接投げる仕組みで、HID イベントタップやカーソルワープを経由しないためこうなります。前面化が必要なアプリでは fallback する設計なので、常に background で動く保証ではありませんが、電卓のような素朴な AppKit アプリでは想定どおりに背面で動きました。
詰まった 7 つのポイント
上の流れで発生した問題を、症状・原因・対処の順で表にまとめます。次に同じ環境を組む人はここだけ拾えば足りるはずです。
| # | 症状 | 原因 | 対処 |
|---|---|---|---|
| 1 | error: /Applications is not writable | 非 admin アカウント。インストーラは TCC 帰属のため .app を /Applications に置くことを必須にしている | admin 権限を得る。環境変数やフラグでの回避は不可(Linux とは異なる設計) |
| 2 | admin 昇格後も Permission denied | 昇格前に起動したプロセスは古いグループ資格情報を持ち続ける | 新しいターミナルを開いて再実行。Hermes も同時に再起動する |
| 3 | permissions status が unknown | daemon が起動していないか、許可前に起動した daemon が古い TCC 状態を掴んでいる | pkill -f "cua-driver serve" → open -n -g -a CuaDriver --args serve で再起動 |
| 4 | 権限がターミナルに付いてしまう | 素の cua-driver をターミナルから起動するとダイアログの主体がターミナルになる | 必ず cua-driver permissions grant を使い、LaunchServices 経由で .app を起動する |
| 5 | No module named 'mcp' | システム Python で handler を呼び出した | Hermes 同梱の venv/bin/python を使う(通常の Hermes 経由では発生しない) |
| 6 | 既存 Hermes セッションで computer_use が出てこない | ツールセット構成はセッション起動時に固定(プロンプトキャッシュ保護のため) | Hermes をいったん終了して新セッションを開く |
| 7 | permissions grant が [Command interrupted] | 対話的にダイアログを待つコマンドをエージェント経由から叩いた | ダイアログは出ているので手元で手動許可する。ホストのターミナルから直接叩くのが無難 |
このうち 1 と 2 は「会社支給の管理端末で非 admin 運用が既定」という設定に強く依存します。個人 Mac で最初から admin として使っている人はこの 2 つは踏みません。3 から 7 は環境によらず起きうる、TCC の設計と Hermes のセッションモデルに由来する問題です。
セットアップ後に確認する運用設定
日常運用に入る前に、次の 3 点は決めておいたほうが後々混乱しないと思いました。
- 更新:
hermes updateはcua-driverが PATH にあれば upstream のインストーラを自動で再実行します。手動で刺したい場合はhermes computer-use install --upgrade、cua-driver 単体ではcua-driver update --apply、macOS アップデートで SPI が変わった際の保険にはHERMES_CUA_DRIVER_VERSION=0.26.0によるピン留めが使えます - 承認モード:
~/.hermes/config.yamlのapprovals.modeをmanualにすると全アクション確認、cua-driver 側はstandard/bounded/unrestrictedの 3 段。両者は独立した二層で、業務端末ではまず cua-driver 側をboundedにして capability manifest で許可アプリを絞るのが素直です - テレメトリ: cua-driver はデフォルトで匿名の利用統計を送ります。プロンプトや画面内容・パスは送らないと明記されていますが、社内配布を考えるなら
cua-driver telemetry disableで停止したうえで扱いを決めておくのがよいと思います
追加検証: メモアプリ・Direct Capture・ログイン済み Chrome
その後、当初「未検証」と書いていた項目を実機で追試したので、結果を残しておきます。すべて cua-driver 側の permission mode を bounded の範囲内で試した記録です。
まず メモ アプリで日本語入力の挙動を確認しました。type("日本語IME入力テスト") は成功し、AX の値読み戻しでも同じ文字列が得られました。ただしこれは route: accessibility を経由した直接挿入なので、IME コンポジションを通った証拠にはなりません。前景キーストロークで nihongo を打って にほんご へ変換されるかも試しましたが、結果は Nihongo(IME 未経由のプレーンな Latin 入力)のままで、変換は確認できませんでした。したがって「Unicode works」の主張は再現できたものの、日本語 IME のコンポジション経由は引き続き未検証です。テストで作成したメモは削除して、最近削除した項目 へ移動済みです。
Direct Capture については cua-driver permissions grant を完走させたところ、direct_capture_verification が記録され、その後 get_desktop_state で 3024 × 1964 の PNG を実際に取得できました。direct_capture_status 自体は not_checked のままですが、明示的な検証記録と実キャプチャは成功しています。前回書いたとおり som モードのキャプチャは Direct Capture 未確認でも動くのですが、ScreenCaptureKit を通した高解像度パスも実際に開通していることが確認できた形です。
ログイン済み Chrome プロファイルの操作は一部成功しました。ログイン済み Chrome ウィンドウを取得して、プロファイル表示(日本語ラベル)とページ内容の読み取りまではできています。一時的に --grant existing-profile を付けた daemon を立ち上げたうえで試しましたが、browser_prepare は browser_wrong_target_refused(the approved Google Chrome window has no exact New Tab button)で拒否されました。同じウィンドウの AX ツリーには日本語ラベルの 新しいタブ が確実に存在するので、Chrome の UI ローカライズ と照合ロジックの不一致が疑われます。安全機構を迂回してリモートデバッグを有効化するような回避策は取らず、試験用の existing-profile 権限は失効させ、現在は通常の standard daemon に戻しています。
日常的な運用は、次のデイリースタンドアップやチームミーティングでこの結果を共有したうえで、日本語 IME のコンポジション経路・複数モニター・機密画面の 3 点をチームで実測する順序で詰めていくつもりです。
以上、Hermes Agent v0.21.1 の Computer Use を macOS Tahoe で有効化し、/Applications 配置と TCC 帰属をめぐる 7 つの設定上の問題に対処しながら電卓 12 × 34 = 408 まで到達した、現場からお送りしました。
参考情報
- Hermes Agent 公式サイト
- Hermes Agent Computer Use ドキュメント
- NousResearch/hermes-agent GitHub リポジトリ
- trycua/cua GitHub リポジトリ
- cua-driver README
- cua-driver-rs v0.26.0 リリース
- cua macOS 内部実装解説(SkyLight)
- Best-effort background(cua 公式)
- cua-driver permission modes と capability manifest
- Anthropic Claude 公式サイト
- Model Context Protocol 公式サイト
- macOS Accessibility API 公式ドキュメント
- macOS TCC 公式ドキュメント
- macOS ScreenCaptureKit 公式ドキュメント
- macOS アクセシビリティ権限の許可方法(Apple サポート)
- macOS 画面収録権限の許可方法(Apple サポート)
- LaunchServices 概要(Apple Developer アーカイブ)
- Jamf 公式サイト
- 先日書いた選定メモ: macOS と Windows 両対応の Computer Use エージェント