← Commit history

Add uninstalling-the-extension skill (background-first; search-filter disambiguates the shared 'Remove' name; confirm-bubble foreground beat; verify by screenshot + dropped profile key). Clipboard-assist uses shell_execute Set-Clipboard (no AD verb yet; filed adom-desktop#23)

John Lauer ·e191dbc73e ·4mo ago ·parent 61e0171
5 files changed +92−2
install.sh+1−1
@@ -3,7 +3,7 @@ # (The extension itself loads into Chrome/Edge via "Load unpacked" from extension/, or the Web Store.) set -e DEST="${HOME}/.claude/skills"-for name in cross-platform-dev driving-the-extension native-browser-safety installing-the-extension native-browser-recording driving-the-extension-demo driving-the-desktop driving-sites driving-gusto reading-google-messages; do+for name in cross-platform-dev driving-the-extension native-browser-safety installing-the-extension uninstalling-the-extension native-browser-recording driving-the-extension-demo driving-the-desktop driving-sites driving-gusto reading-google-messages; do   mkdir -p "$DEST/$name"   cp "skills/$name/SKILL.md" "$DEST/$name/SKILL.md"   echo "installed skill: $name"
package.json+1
@@ -18,6 +18,7 @@     "skills/driving-the-extension/SKILL.md",     "skills/native-browser-safety/SKILL.md",     "skills/installing-the-extension/SKILL.md",+    "skills/uninstalling-the-extension/SKILL.md",     "skills/native-browser-recording/SKILL.md",     "skills/driving-the-extension-demo/SKILL.md",     "skills/driving-the-desktop/SKILL.md",
skills/installing-the-extension/SKILL.md+5
@@ -109,6 +109,11 @@ So prefer the path that keeps the user in control:    absolute path on the clipboard, `desktop_caption {text:"Adom: paste this path (Ctrl+V) into the Folder    box, then click Select Folder"}`, and let the USER do the single paste + click. You stay background;    they finish the one keyboard step. Confirm by screenshot that the card loaded.+   - ⚠️ **AD has no clipboard verb yet**, so set the clipboard via `shell_execute`:+     `powershell -NoProfile -Command "Set-Clipboard -Value '<abs path>'"` (read back with `Get-Clipboard`).+     **Be polite: save the user's current clipboard first (`Get-Clipboard`) and restore it after**, since+     you are overwriting it. (A native `desktop_clipboard_set`/`desktop_clipboard_get` would remove the+     quoting hassle - tracked as an AD request.) 2. **Address bar via SendInput - VERIFIED to work, but it FOREGROUNDS (last resort; user away/consenting).**    First `desktop_caption {text:"Adom: one moment, please don't type"}`, then:    ```
skills/uninstalling-the-extension/SKILL.mdadded+84
@@ -0,0 +1,84 @@+---+name: uninstalling-the-extension+description: How WE (this repo) uninstall the Adom browser extension from the user's real Chrome/Edge, driving adom-desktop's GENERIC OS verbs - BACKGROUND-first, never stealing focus. Covers the critical safety guard (all "Remove" buttons share the same name, so filter the list to the Adom card first or you can remove the WRONG extension), the Remove-confirm bubble (a Chromium owned popup that needs ONE brief foreground beat because it dies on focus loss), verifying removal by screenshot AND by the nbrowser_ profile key dropping, and optional full cleanup (native-messaging host + bridge). Use when the user says "uninstall the extension", "remove the Adom extension", "take it out of my browser", "reinstall it" (uninstall then installing-the-extension). Low-level click mechanics: driving-the-desktop. Safety: native-browser-safety. Part of the adom-browser-extension.+---+Part of **adom-browser-extension**. Install: **installing-the-extension**. Low-level OS mechanics: **driving-the-desktop**. Safety: **native-browser-safety**.++# Uninstalling the extension - the orchestration WE own (background-first)++Like install, this is **our** recipe driving adom-desktop's **generic** OS verbs (`desktop_navigate`,+`desktop_find_control`, `desktop_ui_click`, `desktop_ui_set`, `desktop_screenshot_window`). AD has no+"uninstall extension" feature; we own the sequence and its safety.++## ⛔⛔ Two rules that make or break this+1. **Background-first, never force the foreground.** Focus theft is rude AND corrupts the flow: if the+   user keeps typing, their keystrokes land in the control you focused (the Search box), silently+   changing your filter and **hiding the card you were about to remove** (real case: search became+   `Adoms`, the Adom card vanished). Use background UIA (`desktop_ui_click` Invoke, `desktop_ui_set`+   SetValue), `desktop_navigate`, `desktop_screenshot_window` - none steal focus. There is exactly ONE+   unavoidable foreground beat (the confirm bubble, Step 3); narrate it and keep it to ~1s.+2. **Isolate the target or you may remove the WRONG extension.** On `chrome://extensions` every card's+   Remove button has the **same** accessible name "Remove" and `automationId:"removeButton"` - a blind+   `contains:"Remove"` is ambiguous. **Filter the list to just the Adom card first** (Step 2). Verify by+   screenshot that exactly one card shows before you trigger Remove.++## Step 1 - open chrome://extensions in YOUR OWN background window+```+nbrowser_open_window {profile, url:"about:blank", focused:false}   # your window; find its hwnd via desktop_list_windows (match a unique title)+desktop_navigate {hwnd:<W>, url:"chrome://extensions"}            # edge://extensions for Edge - scheme MUST match the browser+desktop_screenshot_window {hwnd:<W>}                              # read it: is the Adom card present?+```++## Step 2 - ISOLATE the Adom card (the safety guard)+Set the search box to the extension name so only the Adom card (and its Remove button) remains:+```+desktop_ui_set {hwnd:<W>, contains:"Search extensions", text:"Adom"}   # background SetValue; automationId "searchInput", settable+desktop_screenshot_window {hwnd:<W>}                                   # CONFIRM exactly one card shows ("Adom for Chrome & Edge")+```+⚠️ `ui_set` REPLACES the field - re-read the screenshot, because a stray prior value (or a focus-theft+keystroke) can leave junk like `Adoms` that matches nothing ("No search results found"). Fix it (set+again) before proceeding. Do not trigger Remove until the screenshot shows the single Adom card.++## Step 3 - Remove + confirm (the one brief, narrated foreground beat)+The confirm bubble (`Remove "Adom for Chrome & Edge"?`) is a Chromium **owned popup that dies on focus+loss**, so the window must hold focus across the trigger->confirm. This is the one place foreground is+unavoidable - so narrate it and do it fast, atomically, nothing in between:+```+desktop_caption {text:"Adom: removing the extension - one moment, please don't type"}+desktop_bring_to_front {hwnd:<W>}                                       # the ~1s foreground beat (unavoidable for the bubble)+desktop_ui_click {hwnd:<W>, contains:"Remove"}                          # trigger -> opens the bubble (unambiguous now, after Step 2)+# wait ~1s; do NOT insert a screenshot/find_control here - the bubble auto-closes in ~1-2s+desktop_ui_click {hwnd:<W>, scope:"popups", role:"button", name:"Remove"}   # confirm (background Invoke of the owned popup)+desktop_caption {text:""}                                               # clear the caption; return focus to the user+```+- `scope:"popups"` enumerates the window's owned, borderless popups (invisible to `desktop_list_windows`)+  and Invokes the bubble's "Remove". The bubble title is `Remove "<ext>" from <browser>?`.+- If you get `scope:popups found no owned/popup windows`, the bubble already closed (you were too slow or+  inserted a step) - just re-trigger and confirm immediately.+- **To CAPTURE the bubble for docs**, do a SEPARATE pass: trigger Remove, then `desktop_screenshot_window+  {hwnd:<W>}` - the bubble rides back in the response's `screenshots[]` array (saved as+  `popup-<hwnd>-<ts>.png`) since it is an owned popup. Then click Cancel (`scope:"popups"` ... name:"Cancel")+  instead of Remove. Don't try to screenshot mid-removal; the bubble dies before the confirm.++## Step 4 - verify it's gone (screenshot AND state)+1. **Screenshot:** `desktop_screenshot_window {hwnd:<W>}` - the Adom card is gone (the filtered list shows+   "No search results found", or the card is absent when unfiltered).+2. **State:** poll `nbrowser_profiles` / `nbrowser_status` - the `chrome:`/`edge:` profile key **drops**+   within ~1-2s as the service worker dies. (This is the authoritative signal it actually unloaded.)++## Cross-browser (Edge) and full cleanup+- **Edge:** identical, but `edge://extensions` (scheme must match) and verify the `edge:` key drops.+- **Just unloading vs full removal:** removing the card unloads the extension and drops the SW. To fully+  decommission (not just unload), also: remove the HKCU native-messaging host+  (`HKCU\Software\Google\Chrome\NativeMessagingHosts\inc.adom.native_browser`, and the Edge key), and if+  the user wants the bridge gone too, `adom-desktop bridge_uninstall {name:"native-browser"}`. For a plain+  "take it out of my browser," Steps 1-4 are enough.++## Recovery+Reinstall with **installing-the-extension** (dev-mode Load unpacked). Removal + reinstall is also the+clean way to apply an updated `extension/` build.++## The one-line version+Open your own background window, filter to the Adom card so Remove is unambiguous, narrate the one ~1s+foreground beat the confirm bubble forces, atomically trigger->confirm, then verify by BOTH the+screenshot and the dropped `nbrowser_` profile key.
uninstall.sh+1−1
@@ -1,5 +1,5 @@ #!/usr/bin/env bash DEST="${HOME}/.claude/skills"-for name in cross-platform-dev driving-the-extension native-browser-safety installing-the-extension native-browser-recording driving-the-extension-demo driving-the-desktop driving-sites driving-gusto reading-google-messages; do+for name in cross-platform-dev driving-the-extension native-browser-safety installing-the-extension uninstalling-the-extension native-browser-recording driving-the-extension-demo driving-the-desktop driving-sites driving-gusto reading-google-messages; do   rm -rf "$DEST/$name" && echo "removed skill: $name" done