app
Adom Bridge (macOS)
Public Made by Adomby adom
Adom Bridge is a small operating system for AI on your Mac: it gives an AI real hands on your native desktop, including your signed-in browser, KiCad, Fusion 360, the shell, files, windows and screenshots. It provisions its own Node and Python so bridges run without touching your setup, and it talks straight to your machine. It ships with Adom Hydrogen and installs standalone too, so if you drive your Mac with Claude Desktop or another AI, this is what gives that AI hands.
← Commit history
Delete skills/adom-desktop-permissions
2 files changed
−239
skills/adom-desktop-permissions/._SKILL.mddeleted⋯ 1 unchanged line ⋯
skills/adom-desktop-permissions/SKILL.mddeleted−239@@ -1,239 +0,0 @@-name: adom-desktop-permissions-description: >- How the Adom Bridge human-approval permission gate works for an AI caller.- Read this when a verb refuses with errorCode needs_approval or reason_required,- when you need shell approval / bypass permissions on a machine, when you must- call request_shell_approval to surface the human approval dialog, when a call- demands a reason arg, or before an unattended run that touches shell_execute,- run_script, write_file, or any other gated verb. Covers the human approval- gate, the Approve 1 hr / 24 hr / Bypass Permissions buttons, why grants are- human-only, and the macOS TCC permissions (Screen Recording, Accessibility)- that sit underneath Bridge's own gate.--# Adom Bridge permissions: the human approval gate for AI callers--## The trust model in one paragraph--Bridge binds `127.0.0.1` only, and installing Bridge (or a bridge plugin) is-the user's consent to be driven, so every LOCAL caller (the CLI on the same-box, Adom Hydrogen, and bridges on the loopback direct API) is trusted by-transport and never gated. The approval gate applies to exactly one origin:-the remote relay / cloud-AI path (`via_relay`), a thread driving the machine-from off-box that the user may not be watching. If you are calling over the-relay, the gated verbs below require a human grant. Read-only verbs-(screenshots, status, window and UI reads, discovery) are never gated.--## Which verbs gate--The gated class is "runs code / writes / deletes / kills processes /-synthesizes input":--- **Arbitrary code execution:** `shell_execute`, `run_script` (bash / zsh /- sh), `launch_process`, `wiki_exec`-- **Filesystem:** `write_file`, `delete_file`-- **Process control:** `process_kill`-- **Synthetic input** (drive the machine as the user): `desktop_click` /- `desktop_type` / `desktop_press_key` and the Accessibility (AX) action- verbs; these ride the SAME grant window as shell--One human grant covers the whole class. A bridge's own exec verbs-(`browser_evaluate`, `nbrowser_eval`, `blender_run_python`,-`fusion_run_modeling_script`, ...) gate per the bridge's declared `risk`-field, independently of this class; check that bridge's describe output, not-this doc.--## The `reason` requirement: every gated call must explain itself--Every permission-class verb sent over the relay MUST carry a `reason` arg:-one plain sentence saying WHY you need this. The human sees it verbatim in-the approval prompt, attributed as "The AI says: ..." (omitting it shows-"(no reason given)", which a cautious user should decline). It also lands in-Bridge's activity log.--```bash-adom-desktop shell_execute '{"command":"brew install kicad",- "reason":"Installing KiCad so I can export your gerbers"}'-```--Write the reason for the human, not for the log: say what you are trying to-accomplish, not what the command does. Good: "Installing the KiCad CLI so I-can export your gerbers". Weak: "running npm install" (that is just the-command again). The reason is capped at 300 chars and never replaces the-command preview; the human always sees both.--A permission-class call with NO reason is refused before any approval path:--```json-{- "success": false,- "errorCode": "reason_required",- "error": "'write_file' needs human permission, so it REQUIRES a `reason`. Retry the SAME call with reason:\"...\".",- "retryWith": { "reason": "<why you need this, in one plain sentence>" },- "appliesTo": ["shell_execute", "run_script", "launch_process", "wiki_exec", "write_file", "delete_file", "process_kill"]-}-```--The rule is class-based and flat: the verbs in `appliesTo` ALWAYS carry a-reason (whether or not a grant is currently active); verbs not in that list-never need one. Learn it once: do not pay the round-trip again, and do not-add `reason` to ungated verbs.--## What a refusal looks like--When no grant is active, a gated relay call refuses with-`errorCode: "needs_approval"` plus a structured `approval` block; you never-need to read `~/.adom/config.json`:--```json-{- "success": false,- "errorCode": "needs_approval",- "error": "'write_file' needs shell approval - it runs code / writes / deletes / kills a process (a Tier-2 verb, as dangerous as shell_execute).",- "approval": {- "required": true,- "granted": false,- "class": "shell",- "verb": "write_file",- "grantedBy": "human-only",- "grantVerb": "request_shell_approval",- "howToGrant": ["Ask the user to click Approve (1 hr / 24 hr) or Bypass Permissions ...",- "Call request_shell_approval to re-surface the prompt ...",- "The user can tick Settings > Shell Commands > Bypass Permissions ..."]- }-}-```--The refusal itself already surfaced a human-facing prompt on the machine: the-Bridge window SUMMONS ITSELF to show the approval dialog (Bridge is normally a-menu-bar agent with no window; an approval flips it from Accessory to Regular,-shows the window, and activates it), and a Notification Center notification-fires as well. If the human actively clicks Deny (embedded mode), you get-`errorCode: "denied_by_user"` instead; do NOT auto-retry that one, ask the-user what they want.--## The correct AI flow on a gate hit--1. **Surface the prompt** (the gate already did once; re-surface on demand):-- ```bash- adom-desktop request_shell_approval- ```-- This is ungated; it only SURFACES, never grants. It re-shows the approval- dialog and brings the Bridge window to the front, so "there is nothing to- click" is never true.--2. **Ask the human** (in your conversation) to click **Approve 1 hr**,- **Approve 24 hr**, or **Bypass Permissions** in the Adom Bridge window.--3. **RETRY the original verb unchanged** (with its `reason`). One grant- covers the whole exec/write/kill/input class for the granted window.--## Grants are HUMAN-ONLY: you cannot self-grant--Granting is permanently human-only. The only grant paths are a human clicking-in Bridge: the approval dialog's Approve buttons and the Settings checkbox. A-GRANT attempt via `shell_auto_approve` / `set_shell_auto_approve` from a relay-(cloud-AI) caller is refused with `errorCode: "human_only"` and auto-surfaces-the human prompt instead. Your only lever is `request_shell_approval`; it-TRIGGERS the human decision, it does not perform it.--The one exception: a REVOKE is allowed for any caller (de-escalation is-always safe):--```bash-adom-desktop shell_auto_approve '{"duration_secs":0}' # clears the checkbox AND the timer-```--Do not look for a workaround. `launch_process` is not a bypass of-`shell_execute` (it gates identically), and synthetic input (clicking the-Approve button yourself) rides the same grant. If the AI could grant, the-gate would be theater.--## The durable Settings checkbox--**Settings > Shell Commands > Bypass Permissions** (config-`shell_auto_approve_permanent`, default OFF) is the durable indefinite grant,-for machines the user fully trusts. The timed buttons (1 hr / 24 hr) set an-in-memory window instead. Unticking the checkbox, or-`shell_auto_approve {"duration_secs":0}`, returns to per-command approval-instantly.--## Embedded mode: Adom Hydrogen owns the decision--When Bridge runs embedded under Adom Hydrogen (Hydrogen passed `auto_approve`-in `POST /embedded/enter`), the human's app is Hydrogen and Bridge shows no UI-of its own. Each gated relay command is FORWARDED to Hydrogen's-`/permission/request`; Hydrogen renders the prompt (with your `reason` and a-decoded command preview) and returns the decision:--- `allow_once`: run this one command, no window-- `allow_1h` / `allow_24h`: set a timed grant window and run-- `bypass_while_running`: session-length grant (clears on restart)-- `deny`: you get `errorCode: "denied_by_user"`; do not auto-retry--While forwarding is active, a standing grant (flag / checkbox / timer) does-NOT suppress the forward; Hydrogen decides every time. If Hydrogen is-unreachable, Bridge falls back to its own dialog. `auto_approve: true` means-the user opted in to auto-approval.--## macOS TCC permissions (underneath Bridge's gate)--Bridge's approval gate governs WHO may drive the machine; macOS's own TCC-privacy system separately governs what the Bridge PROCESS may do, and no-Bridge grant can override it. In System Settings > Privacy & Security the app-appears as **Adom Bridge**:--- **Screen Recording**: required for window and screen screenshots. Without- it, captures come back blank or fail.-- **Accessibility**: required for synthetic input (CGEvent mouse/keyboard)- and the AX read/action verbs. Without it, gated input verbs fail with a- clear error naming the missing grant (macOS silently ignores CGEvent- posting otherwise, so Bridge checks `AXIsProcessTrusted` first and refuses- loudly).--If a verb says the Accessibility or Screen Recording permission is missing,-that is a one-time human toggle in System Settings, not something-`request_shell_approval` can grant.--## Check state up front with `status`--Before an unattended run, read `status.permissions.shell` so you know whether-you will stall on a human gate:--```bash-adom-desktop status-```--```json-"permissions": {- "shell": {- "autoApproved": false,- "willPrompt": true,- "source": "none", // "permanent" | "timed" | "none"- "expiresInSec": null,- "grantedBy": "human-only",- "grantVerb": "request_shell_approval",- "gatedFor": "relay (cloud-AI) callers only",- "embeddedPolicy": "standalone" // "forward-to-hd" | "auto-approve" | "standalone"- },- "bridgeExec": { "note": "bridge exec verbs gate per the bridge's declared risk field" }-}-```--If `willPrompt` is true and no human is at the machine, get the grant FIRST-(`request_shell_approval` plus asking the user) before starting the run.--## Quick reference--| Situation | What you do |-|---|---|-| `errorCode: reason_required` | Resend the SAME call plus `reason:"<one plain sentence>"` |-| `errorCode: needs_approval` | `request_shell_approval`, ask the human to click Approve, retry |-| `errorCode: human_only` | You tried to self-grant. Ask the human instead |-| `errorCode: denied_by_user` | The human said no. Do not auto-retry; ask them |-| A capture/input verb reports a missing macOS permission | Ask the user to enable Adom Bridge under System Settings > Privacy & Security (Screen Recording or Accessibility) |-| Planning an unattended run | Check `status.permissions.shell.willPrompt` first |-| Need to drop a grant | `shell_auto_approve {"duration_secs":0}` (allowed for any caller) |