macOS 権限のセットアップ
Zanei が要求する TCC 権限の一覧、付与手順、zanei doctor による recorder 状態の確認。
capture.sources と 2 つの content opt-in に応じて、Zanei は最大 3 種類の macOS 権限(TCC)を使います。画面収録は含まれません。
必要な権限
| 権限 | System Settings 上の項目 | 何のために使うか | 関係するイベント型 |
|---|---|---|---|
| アクセシビリティ | Accessibility | 共有する前面ウィンドウ識別、ウィンドウタイトル・フォーカス・UI 要素・可視 content snapshot の取得 | window.* ui.* input.* clipboard.* browser.navigate content.snapshot |
| 入力監視 | Input Monitoring | キー・スクロール・クリックの検知 | input.* ui.click clipboard.* |
| オートメーション | Automation(対象アプリごと) | Chrome/SafariのURLとwindow eligibility を取得し、URL 捕捉と content 抑止に使用 | browser.navigate、browserの ui.value/input.key/clipboard 本文と content.snapshot |
次の性質があります。
- アプリの起動・終了・前面切替(
app.*)は権限なしで記録できます。何も付与しなくても、アプリ単位の行動履歴は記録されます。 inputとbrowserは、event を app と window に結び付ける単一の前面ウィンドウ識別に Accessibility を使います。event の検出自体には、それぞれ入力監視と Automation も使います。- 権限が必須になるのは、それを必要とする機能が有効な場合だけです。
capture.content_snapshotはcapture.sourcesから独立しており、windowがなくても Accessibility が必要です。snapshot 単独では入力監視は不要です。 browserがない場合も、対象browserがtext-content scopeで許可され、text_contentとui/inputが有効な場合、または有効なcontent-snapshot scopeで許可される場合は、そのbrowserへのAutomation権限が必要です。関連scopeがすべて除外するbrowserでは不要です。
初回セットアップ
署名済み app bundle の TCC identity は dev.zanei.recorder です。権限ダイアログは Zanei 名義で表示されます。アクセシビリティには Zanei の行が自動追加されますが、入力監視はダイアログでの付与が有効でも行が自動追加されないことがあります。次の順で設定します。
zanei startを実行します。まっさらな環境での通常のダイアログ表示順は、アクセシビリティ → 許可 → 入力監視です。recorder はアクセシビリティが付与されるまで最長 2 分待ち、その間は入力監視を要求しません。アクセシビリティが付与されるか 2 分の上限に達すると入力監視を要求します。この上限は、アクセシビリティを拒否したユーザーにも入力監視を付与する機会を残すための意図的な挙動です。続けて入力監視のダイアログが表示されることもありますが、表示されない環境もよくあります。表示されない場合は手順 3 に進み、zanei doctor --fixから app を手動で追加してください。各権限を要求するのは、その起動中に 1 回だけです。startが終了コード 3 を返した場合も、デーモンは起動済みで、heartbeat が権限不足を報告しています。デーモンは動作を継続します。初回の権限ダイアログが応答待ちの間は、zanei doctorがオートメーションをnot_determinedと報告することがあるため、ダイアログに応答してからもう一度実行してください。- 下表のペインを開きます。自動追加されたアクセシビリティの行を ON にします。入力監視に
Zaneiがあればその行を ON にしますが、行がないことだけではダイアログでの付与失敗を意味しません。 - 一覧から入力監視の権限を操作する場合は、
+でインストール済みのZanei.appを選択します。まだ権限不足と報告されている間は、zanei doctor --fixがペインを開き、symlink 解決後の正確なZanei.appのルート path をコピーして、同じ app を Finder に表示します。ファイル選択ダイアログで Command-Shift-G を押してその path を貼り付けます。手動追加した bundle の行は定着します。 zanei stop && zanei startを実行し、付与結果を recorder に反映します。zanei doctorを実行し、recorder 自身に適用されている状態を確認します。入力監視に行がなくても、recorder 由来の結果を正とします。
| 権限 | 場所 |
|---|---|
| アクセシビリティ | Privacy & Security → Accessibility |
| 入力監視 | Privacy & Security → Input Monitoring |
| オートメーション | Privacy & Security → Automation(初回の実 Apple Event 時に macOS が確認。起動時には要求しない) |
付与操作は必ずユーザーが行います。zanei doctor --fix は必要なペインを開き、権限ごとの操作を案内します。正確な挙動は次節に書いています。
doctor で確認する
zanei doctor
recorder の heartbeat が新鮮な間は、recorder 自身が報告した権限状態を表示します。それ以外では doctor プロセスから probe し、人間向け出力に「recorder 自身の権限を見るには起動する」旨を注記します。不足があれば付与手順を案内し、終了コード 3 で終了します。
zanei doctor --fix
--fix は不足している必要権限のペインを 1 つずつ開きます。複数のペインが必要な場合は
ペイン間で Return キー入力を待ち、最後のペイン後には待機しません。--json --fix も指定でき、
最初に JSON report を出力した後、必要権限が不足していれば同じ対話フローを実行します。
この場合の stdout は JSON のみではありません。アクセシビリティまたは入力監視が不足している
場合は、symlink 解決後の Zanei.app のルート、またはバンドル外の実行ファイルをコピーし、
同じ対象を Finder に表示します。オートメーションでは、recorder を実行している app/executable
の Google Chrome または Safari トグルを有効にするよう案内します。診断コマンドと recorder
は異なる実行ファイルの場合があります。オートメーションだけが不足している場合は path のコピーや
Finder 表示を行わず、拒否後の再起動で許可ダイアログが再表示されるとも案内しません。
不足がなければ --json --fix は JSON だけを出力します。
agent・スクリプト向け:--json
zanei doctor --json
{
"ok": false,
"reported_by_recorder": true,
"capture_sources": ["app", "window", "ui", "input", "browser"],
"capabilities": {
"read_accessibility_tree": {
"state": "available", "required": true,
"required_for": ["window.focus", "window.title", "ui.focus", "ui.click", "ui.value", "content.snapshot"],
"detail": { "platform": "macos", "permission": "accessibility", "status": "granted", "settings_url": "x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility" }
},
"observe_input": {
"state": "action_required", "required": true,
"required_for": ["input.key", "input.scroll", "clipboard.copy", "clipboard.paste", "ui.click"],
"detail": { "platform": "macos", "permission": "input_monitoring", "status": "denied", "settings_url": "x-apple.systempreferences:com.apple.preference.security?Privacy_ListenEvent" }
},
"automate_browser": {
"state": "deferred", "required": true,
"detail": { "platform": "macos", "permission": "automation", "status": "not_determined", "settings_url": "x-apple.systempreferences:com.apple.preference.security?Privacy_Automation", "target_bundle_id": "com.google.Chrome" }
}
}
}
capability の state は available / action_required / deferred です。内側の macOS detail がネイティブな permission 名と status、System Settings URL、必要な場合は target bundle ID を持ちます。reported_by_recorder で recorder heartbeat とローカルプロセスの probe を区別できます。権限不足は専用の終了コード 3 で通知されるため、agent やスクリプトは出力を解析せずに権限の問題を判定できます(終了コード)。
権限を解除・リセットする
ペインに Zanei の行があれば、削除するとその権限を解除できます。または Zanei を停止し、消去する判断に対応する service の reset を実行してから再起動します。
zanei stop
tccutil reset Accessibility dev.zanei.recorder
tccutil reset ListenEvent dev.zanei.recorder
zanei start
bundle ID を指定する reset は、Zanei がまだインストールされている間に実行します。tccutil が解決できるのは LaunchServices に登録済みの bundle だけなので、アンインストール後は dev.zanei.recorder に適用できません。bundle を持たない素の cargo install 実行ファイルにも適用されません。
権限とコード署名
macOS の権限は署名済み app の identity に紐づきます。リリース成果物には署名・notarize・staple 済みの Zanei.app が入り、Homebrew Formula も同じ app を libexec に配置して CLI symlink を公開します。どちらも Zanei.app/Contents/MacOS/zanei を実行するため、アップグレード後も TCC は dev.zanei.recorder に帰属します。
範囲
- Zanei はアクセシビリティと入力監視の判断を macOS に要求しますが、権限の付与や TCC データベースの操作は行いません。上の reset コマンドはユーザーが明示的に実行する操作です。オートメーションは初回の実 Apple Event 時に確認されます。
- recorder は起動時に、必要かつ未付与の権限だけを 1 回要求します。同じ起動中に繰り返し要求しません。
- バックグラウンド
startは recorder の権限不足報告後に終了コード 3 を返しますが、デーモンは degraded 状態で動作を継続します。付与後はzanei stop && zanei startで再起動します。