← Commit history
CLAUDE.md+3−2
@@ -35,8 +35,9 @@ will seed/stream the runtime from the release zip via `updateManifestUrl` in `br - `bridge.json` + `BRIDGE_VERSION` — KEEP IN LOCKSTEP (currently 1.2.0). - `adom-bridge-grok-manifest.json` — streaming manifest ab's `updateManifestUrl` points at;   its `url` is the RELEASE download URL of the zip, with matching `sha256`/`size`.-- `SKILL.md` (root) — the main user skill, installed as **`grok`** (not `grok-bridge`).-- `skills/grok-anywhere/SKILL.md` — Grok Bot as an Anywhere character.+- `SKILL.md` (root) — core USER skill, installed as **`grok`** (not `grok-bridge`).+- `skills/grok-anywhere|app-control|chat|record|webhook|account/` — USER sub-skills (in the pkg).+- `dev-skills/grok-dev/` and `dev-skills/grok-publish/` — repo only, not in `files[]`. - `package.json` — wiki skills pkg. Description is the skills-not-runtime sentence. Runtime   files and `*.zip` do **not** belong in `files[]`. 
README.md+22−2
@@ -127,7 +127,7 @@ The other direction — secondary. Grok Bot becomes an Anywhere character so the adom-wiki pkg install adom/grok-bridge ``` -That drops **grok** + **grok-anywhere** into `~/.claude/skills`, `~/.codex/skills` if present, `~/.grok/skills`, and `/home/box/agent-data/workflows` if that parent exists. Skills land where each provider looks; the point is the same EE can work from Grok Bot without leaving Adom.+That drops the USER pack into `~/.claude/skills`, `~/.codex/skills` if present, `~/.grok/skills`, and `/home/box/agent-data/workflows` if that parent exists: **grok** (core), **grok-anywhere**, **grok-app-control**, **grok-chat**, **grok-record**, **grok-webhook**, **grok-account**. DEV/PUBLISH (`grok-dev`, `grok-publish`) stay in the wiki repo under `dev-skills/` and are not in the pkg. Skills land where each provider looks; the point is the same EE can work from Grok Bot without leaving Adom.  From this session, always: @@ -233,6 +233,26 @@ CLI: `adom-bridge --ai-thread "<thread>" [--target NAME] grok_<verb> '<json>'`.  --- +## Skills in this pack++This page ships a **library**, not one file (Bridge SDK: core USER skill + sub-skills by area; DEV/PUBLISH stay in the repo).++| Skill | Kind | What it teaches |+|---|---|---|+| `grok` | USER (pkg) | Cold-start, identity, which verb family to pick |+| `grok-anywhere` | USER (pkg) | Grok Bot as an Adom Anywhere character (drives the PC) |+| `grok-app-control` | USER (pkg) | Open / close / resize / screenshot / list windows |+| `grok-chat` | USER (pkg) | Thinking vs idle, visible transcript, toast + inbox |+| `grok-record` | USER (pkg) | Record the Grok Bot.exe window |+| `grok-webhook` | USER (pkg) | Bind Grok Bridge webhook, fire events, bots/channels |+| `grok-account` | USER (pkg) | Login / logout / plugin install (no passwords) |+| `grok-dev` | DEV (repo) | Architecture, hwnd unwrap, hints-in-output |+| `grok-publish` | PUBLISH (repo) | Zip vs pkg, files[] allowlist, .gitignore trap |++`adom-wiki pkg install adom/grok-bridge` installs SKILLS, not the runtime zip.++---+ ## Install  Skills (this page):@@ -248,7 +268,7 @@ Always `--ai-thread`. `--target` when more than one desktop is connected (`AdomL | | Skills pkg (`adom-wiki pkg`) | Release zip | |---|---|---| | Lands | container `~/.claude/skills/grok` (and Codex / Grok / box workflows) | ab `bridges-cache` on the PC |-| Contains | `SKILL.md`, `skills/grok-anywhere`, `install.sh` | Python HTTP server (`server.py`, `handlers/`, `bridge.json`) |+| Contains | `SKILL.md` + 6 user sub-skills, `install.sh` | Python HTTP server (`server.py`, `handlers/`, `bridge.json`) | | Does not contain | `server.py` / the zip | `SKILL.md` |  `spawn.kind` = python, `port` 0, `healthEndpoint` `/status`, `persistent` true. Binds loopback only.
SKILL.md+33−65
@@ -1,7 +1,7 @@ --- name: grok user-invocable: true-description: "Drive Grok Bot on the user's desktop from the cloud via the grok_* Adom Bridge verbs. Host app is Grok Bot.exe (standalone Electron; Cursor is last-resort fallback only if Grok Bot.exe is missing). Open/close/resize/screenshot/record the app, report thinking vs idle (grok_chat_status), read the visible transcript (grok_chat_read), queue a message (toast + inbox), bind the Grok Bridge webhook and create bots/channels. No public Grok HTTP API — the spawned Python runtime talks back to ab over desktop_* callbacks. Trigger words: grok, grok bot, grok_open, grok_close, grok_chat_status, grok_chat_read, grok_webhook_ensure, grok_webhook_bind, talk to grok, send to grok bot, grok screenshot."+description: "Drive Grok Bot on the user's desktop from the cloud via the grok_* Adom Bridge verbs. Host app is Grok Bot.exe (standalone Electron; Cursor is last-resort fallback only if Grok Bot.exe is missing). Open/close/resize/screenshot/record the app, report thinking vs idle (grok_chat_status), read the visible transcript (grok_chat_read), queue a message (toast + inbox), bind the Grok Bridge webhook and create bots/channels. Sub-skills: grok-app-control, grok-chat, grok-record, grok-webhook, grok-account, grok-anywhere. No public Grok HTTP API — the spawned Python runtime talks back to ab over desktop_* callbacks. Trigger words: grok, grok bot, grok_open, grok_close, grok_chat_status, grok_chat_read, grok_webhook_ensure, grok_webhook_bind, talk to grok, send to grok bot, grok screenshot." ---  # grok — talk to Grok Bot from Adom Bridge@@ -10,17 +10,15 @@ Drive **Grok Bot** (host app: **Grok Bot.exe**, window title **Grok Bot**) on th  `C:\Users\john\AppData\Local\Programs\Grok Bot\Grok Bot.exe` -User data: `%APPDATA%\Grok Bot`. Process name: `Grok Bot.exe`. macOS: `/Applications/Grok Bot.app`. Linux: `grok-bot` / `Grok Bot` on PATH.+User data: `%APPDATA%\Grok Bot`. Process: `Grok Bot.exe`. macOS: `/Applications/Grok Bot.app`. Linux: `grok-bot` / `Grok Bot` on PATH.  **Cursor is a last-resort fallback only if Grok Bot.exe is missing** (`hostAppFallback:"Cursor"`). Never kill Cursor. -The CLI is:- ```bash adom-bridge --ai-thread "<your thread>" grok_<verb> '<json>' ``` -There is no public Grok HTTP API. `ab` spawns a small Python server from the **release zip**; these skills only teach you the verbs. Surface every `_hint` verbatim. Background by default — never steal focus or the keyboard.+There is no public Grok HTTP API. `ab` spawns a small Python server from the **release zip**; this pack only teaches the verbs. Surface every `_hint` verbatim. Background by default — never steal focus or the keyboard.  ## FIRST-TIME / COLD-START @@ -29,87 +27,57 @@ There is no public Grok HTTP API. `ab` spawns a small Python server from the **r | `grok_readiness` `hostAppInstalled:false` / `errorCode: host_app_not_installed` | Grok Bot.exe is not on this PC | **Do not send the user to a download page.** Offer `grok_open`. That verb detects, then asks ab to `launch` / `desktop_open`. | | `hostAppFallback:"Cursor"` | Grok Bot.exe missing; Cursor is last-resort host | Prefer Grok Bot. Drive Cursor only as fallback. **Never kill Cursor.** | | `hostAppInstalled:true`, `hostAppRunning:false` | Grok Bot is on disk, not running | `grok_open {}` — launches in the **background**. |-| `ready:true` / host running | Grok Bot is up | `grok_list_windows` / `grok_chat_status` / `grok_chat_read` / `grok_screenshot` / `grok_send` / `grok_close` / `grok_resize`. |-| `errorCode: webhook_not_bound` | `~/.adom/grok-webhook.json` has no url | `grok_webhook_ensure {}` — scrapes the **Grok Bridge webhook** routine pane (no human copy-paste). Manual fallback: `grok_webhook_bind {url, key}`. Never put the key in a hint or log. |+| `ready:true` / host running | Grok Bot is up | `grok_list_windows` / `grok_chat_status` / `grok_chat_read` / `grok_screenshot` / `grok_send`. |+| `errorCode: webhook_not_bound` | `~/.adom/grok-webhook.json` has no url | `grok_webhook_ensure {}`. Manual fallback: `grok_webhook_bind {url, key}`. Never put the key in a hint or log. | | unknown verb / bridge not spawned | runtime zip not installed on ab yet | `adom-bridge bridge_install` with this page's `updateManifestUrl`. Skills ≠ runtime. | | yellow `/status` chip | bridge is up; Grok Bot isn't (or isn't running) | Not a crash. Read `tooltip` / `_hint`. | -Readiness is layered and **never downloads anything**:- ```bash adom-bridge --ai-thread "<your thread>" grok_readiness '{}' # {ready, hostAppInstalled, hostAppRunning, hostAppFallback?, errorCode?} ``` -## Core verbs--| CLI | Purpose | Key args |-|---|---|---|-| `grok_readiness` | Layered host-app probe. Zero side effects. | — |-| `grok_prewarm` | No-op re-detect. `{wait:true}` just re-detects. | optional `wait` |-| `grok_describe` | Catalog with hint/related/pitfalls. | — |-| `grok_status` | Detect + last send + inbox + webhook bound (host only) | — |-| `grok_open` | Launch Grok Bot in the background; if running, list windows. | optional `foreground` + **required** `foregroundReason` |-| `grok_list_windows` | `desktop_find_window` titleContains exact Grok Bot (preferred; `best.hwnd`) then `desktop_list_windows` + `process_list`. Not bare Grok (Chrome `ai-grok-bot`). | optional `titleContains` |-| `grok_chat_status` | Thinking vs idle. `thinking=true` when UIA exposes `"<agent> is working"` (proven: `"New Bot is working"`). Never steals focus. | — |-| `grok_chat_read` | Visible transcript via `desktop_ui_text {hwnd, role:"Document", range:"all"}` (Document named `"Grok Bot"`). Optional `limit` truncates from the **end** (latest). Never returns webhook keys. | optional `limit` |-| `grok_screenshot` | `desktop_screenshot_window` titleContains Grok Bot | optional `titleContains` |-| `grok_close` | Hide the Grok Bot window (`desktop_set_window_state` hide). Prefer hide over kill. Never kill Cursor. | — |-| `grok_resize` | `desktop_set_window_bounds` on the Grok Bot hwnd. Restores first if maximized. Physical px (same as ab). | `w`, `h`, optional `x`, `y` (omit to keep current origin) |-| `grok_record_start` | `desktop_record_window_start` on the Grok Bot hwnd. | **`reason` required** |-| `grok_record_stop` | `desktop_record_window_stop` wrap. | optional `recordingId` |-| `grok_record_status` | `desktop_record_window_status` wrap. | — |-| `grok_login` | Launch Grok Bot.exe with `grokbot://app/v1/settings?id=theme` as an arg (`desktop_open_url` refuses grokbot://). Does **not** type passwords. | — |-| `grok_logout` | Open settings; try UIA **Sign Out**. Else `needsHuman:true`. | — |-| `grok_plugin_install` | Launch Grok Bot.exe with `grokbot://app/v1/plugin/add?id=<id>` as an arg. Does not confirm install (the app UI does). | **`id` required** |-| `grok_send` | Toast `Grok Bot: {message}` **and** append the durable inbox. Typing is opt-in. | `message`, optional `agent` |-| `grok_uninstall` | Tells you to `bridge_uninstall {"name":"grok"}`. Does **not** kill Grok Bot or Cursor. | — |--## Webhook + bots--A Grok Bot webhook routine named **Grok Bridge webhook** already exists. Call `grok_webhook_ensure {}` to scrape the routine pane (UIA Edit **Webhook URL** / **Webhook key**) and write the json on the PC. Do **not** ask a human to copy the URL or key.--Stored at `%USERPROFILE%\.adom\grok-webhook.json` (Windows) or `~/.adom/grok-webhook.json`:--```json-{"url":"https://...","key":"...","header":"Authorization: Bearer","boundAt":"<iso>"}-```+## Core verbs (80%) -Never log the key. Never put the key in `_hint`. Auth on fire is header `Authorization: Bearer <key>`; a JSON body field named `key` is **wrong**.+| CLI | Purpose | Key args | More |+|---|---|---|---|+| `grok_readiness` | Layered host-app probe. Zero side effects. | — | this skill |+| `grok_prewarm` | No-op re-detect. `{wait:true}` just re-detects. | optional `wait` | this skill |+| `grok_describe` | Catalog with hint/related/pitfalls. | — | this skill |+| `grok_open` / `grok_close` / `grok_resize` / `grok_screenshot` / `grok_list_windows` / `grok_status` | Window + host | see **grok-app-control** | grok-app-control |+| `grok_chat_status` / `grok_chat_read` / `grok_send` | Thinking vs idle, transcript, toast+inbox | see **grok-chat** | grok-chat |+| `grok_record_start` / `stop` / `status` | Window recording | **`reason` required** on start | grok-record |+| `grok_webhook_ensure` / `bind` / `fire` / `status`, `grok_bot_*`, `grok_channel_create` | Wake this session, create bots/channels | never log the key | grok-webhook |+| `grok_login` / `grok_logout` / `grok_plugin_install` | Sign-in UI + plugins | never type passwords | grok-account |+| `grok_uninstall` | Tells you to `bridge_uninstall {"name":"grok"}`. Does **not** kill Grok Bot or Cursor. | — | this skill | -`grok_webhook_ensure` drives the Grok Bot window (never `shell_execute` / `pull_file` / `send_files`):--1. `desktop_ui_click` name exactly `Open routine Grok Bridge webhook` (Button, invokable).-2. If Edits are missing, expand `When a webhook fires` — prefer `desktop_ui_click` the **Button** (invokable); ListItem Invoke is false so the fallback is `desktop_click` at that ListItem's center.-3. Read UIA **Edit** controls (no OCR): name `Webhook URL`, `Webhook key`, `Authorization header`. Also `desktop_ui_get` those names.-4. Write the json on the PC. Settings gear is **not** the Routines list. Do not type into Prompt (if you touch it, set text empty and do not submit).+`grok_describe` is the completeness hatch; the per-call `_hint` is what you read in practice. -| CLI | Purpose | Key args |-|---|---|---|-| `grok_webhook_status` | Whether the json has a url. Returns `bound`, `urlHost` (hostname only). | — |-| `grok_webhook_ensure` | Scrape the routine pane and bind locally. No human copy-paste. | optional `force` |-| `grok_webhook_bind` | Write the json (local FS on the PC). `url` must be **https**. | **`url`**, **`key`** |-| `grok_webhook_fire` | POST `{event, payload, source:"grok-bridge", hostname}`. | **`event`**, optional `payload` |-| `grok_bot_create` | Fire `event=create_bot`. | **`name`**, optional `description` |-| `grok_channel_create` | Fire `event=create_channel`. | **`name`**, optional `member_ids` |-| `grok_bot_list` | Fire `event=list_bots` (cloud agent lists agents). | — |+## Sub-skills in this pack -If unbound: `errorCode: webhook_not_bound` and `_next` is `grok_webhook_ensure {}`.+| Skill | When to load it |+|---|---|+| **grok** (this file) | Cold-start, identity, which verb family to pick |+| **grok-app-control** | Open/close/resize/screenshot/list windows |+| **grok-chat** | Thinking chip, visible transcript, send (toast + inbox) |+| **grok-record** | Record the Grok Bot.exe window (not the agent-box feed) |+| **grok-webhook** | Bind the Grok Bridge webhook, fire events, create bots/channels |+| **grok-account** | Login, logout, plugin install — human clicks, no passwords |+| **grok-anywhere** | The reverse: Grok Bot driving a PC as an Anywhere character | -`grok_describe` is the completeness hatch; the per-call `_hint` is what you read in practice.+DEV and PUBLISH skills (`grok-dev`, `grok-publish`) live in the wiki repo under `dev-skills/` — they are **not** in this pkg.  ## Identity, targeting, etiquette  - Always pass `--ai-thread`. Never `export ADOM_AI_THREAD` (many threads share `$HOME`). Identity is attribution, not authorization. - If more than one desktop is connected, pass `--target NAME` (`adom-bridge targets`).-- Windows open in the **background**. `openedInBackground` / `windowEtiquette:"background"` are the contract. Foreground without `foregroundReason` is refused (`errorCode: foreground_reason_required`).-- `grok_send` does **not** type into the chat widget. It toasts and writes `~/.adom/grok-inbox.jsonl` so the Anywhere character can poll. Desktop typing is opt-in — don't steal the keyboard.-- `grok_login` / `grok_logout` never type passwords. Only UI paths: sidebar account button, **Sign In with Cursor**, **Sign Out**. Only grokbot:// routes: `settings?id=*` and `plugin/add?id=`.+- Windows open in the **background**. Foreground without `foregroundReason` is refused (`errorCode: foreground_reason_required`).+- `ok:true` is not enough — screenshot or read back after a side effect. Branch on `errorCode`, not prose. - This HTTP runtime never calls `shell_execute`, `pull_file`, or `send_files`. Pull screenshots / recordings with the CLI from the container.  ## Two products, one page -1. **Runtime (release zip)** — `server.py` ab spawns on the PC. Keyword **grok**.-2. **This skill pack** — teaches cloud AIs `grok_*` and teaches Grok Bot to act as an Adom Anywhere character (`skills/grok-anywhere`).+1. **Runtime (release zip)** — `server.py` ab spawns on the PC. Keyword **grok**. Version lives in `bridge.json` / `BRIDGE_VERSION`.+2. **This skill pack** — teaches cloud AIs `grok_*` and teaches Grok Bot to act as an Adom Anywhere character.  Wiki: https://wiki.adom.inc/adom/grok-bridge
dev-skills/grok-dev/SKILL.mdadded+55
@@ -0,0 +1,55 @@+---+name: grok-dev+user-invocable: false+description: "DEV skill for editing grok-bridge (not shipped in the pkg). Architecture of the Python grok_* runtime, LINE OF DEMARCATION with ab-core, hwnd unwrap, webhook scrape, and the rich-hints-in-output rule. Trigger words: grok-dev, grok-bridge architecture, grok hwnd unwrap, grok verb contract, grok desktop callbacks."+---++# grok-dev — architecture of grok-bridge++Source of truth: the wiki repo at https://wiki.adom.inc/adom/grok-bridge (`/workspace/grok-bridge` on this box). Cloud-owned. **Do not edit ab-core.** Do not edit pup/nb/kicad/fusion-bridge.++## THE ONE PRINCIPLE (loudest)++The AI almost never reads this file. It **always** reads CLI output. Every `grok_*` response must return `_hint` / `_next` / `related` / `pitfalls`. `{success:true}` with nothing else makes the caller retry-loop. ab relays your fields **verbatim**.++## Three artifacts (do not conflate)++| Artifact | What | Who |+|---|---|---|+| **Skills pkg** `adom/grok-bridge` | USER `SKILL.md` + `skills/*/SKILL.md` | container (`pkg install` / `sync_skills`) |+| **Release zip** `adom-bridge-grok-v*.zip` | Python runtime + `bridge.json` at zip root | ab on the PC (`bridge_install`) |+| **This file + grok-publish** | DEV / PUBLISH | wiki repo only (`dev-skills/`) — **not** in `package.json` `files[]` |++Repo name `grok-bridge` ≠ skill name `grok` ≠ keyword `grok`. Anywhere character is **grok-anywhere** (product 2). Runtime is product 1.++## Runtime layout++- `server.py` — Python HTTP, `spawn.kind=python`, `port` 0, `healthEndpoint` `/status`, `persistent` true, loopback only.+- `bridge.json` — `verbPrefixes: ["grok_"]`, `statusVerb: grok_readiness`.+- `handlers/` — one family per area (window, chat, webhook, account).+- `grok_detect.py` — host app **Grok Bot.exe** first; Cursor last-resort (`hostAppFallback`).+- Talks to ab over **desktop_*** callbacks. No public Grok HTTP API. Never CDP 9222 in shipped code.++## LINE OF DEMARCATION++A bridge NEVER modifies ab. Zero `src-tauri/` or `cli/` changes. If ab would end up knowing `Adom.Grok` AUMID or a `grok_*` router in core, you crossed the line. App-aware window binding stays here; ab gets a resolved HWND.++## hwnd unwrap (live bug class)++`desktop_find_window` returns `best.hwnd` nested under `output`. Flatten before `desktop_list_windows`. TITLE_NEEDLES is `["Grok Bot"]` **only** — not bare `Grok`, not Chrome `ai-grok-bot`.++## Webhook++Routine **Grok Bridge webhook**. `grok_webhook_ensure` scrapes UIA Edit **Webhook URL** / **Webhook key** / **Authorization header**, writes `%USERPROFILE%\.adom\grok-webhook.json`. Never log the key, never put it in `_hint`. Fire: `Authorization: Bearer <key>`, not a JSON `key` field. Issue [adom-bridge #101](https://wiki.adom.inc/adom/adom-bridge/issues/101) is a future Grok Bot-scoped session token — not shipped.++## Test on a desktop++```bash+adom-bridge --ai-thread "Grok Bot" --target AdomLapper grok_readiness '{}'+adom-bridge --ai-thread "Grok Bot" --target AdomLapper grok_list_windows '{}'+adom-bridge --ai-thread "Grok Bot" --target AdomLapper grok_chat_status '{}'+```++Known desktops: `AdomLapper`, `ConfRoomROG`. Never `export ADOM_AI_THREAD`. Never steal focus unless showing the user something. Never kill Cursor.++Ship recipe: **grok-publish**.
dev-skills/grok-publish/SKILL.mdadded+64
@@ -0,0 +1,64 @@+---+name: grok-publish+user-invocable: false+description: "PUBLISH skill for grok-bridge (repo only, not in the pkg). How to cut the runtime zip vs the skills pkg, files[] allowlist, .gitignore trap, install.sh skill list, discovery_triggers, and verify. Trigger words: grok-publish, publish grok-bridge, grok-bridge pkg, grok-bridge release zip, grok skills pack."+---++# grok-publish — shipping grok-bridge++Wiki: https://wiki.adom.inc/adom/grok-bridge. Changelog / `-m` must be ≥10 chars and ≥2 words.++## What goes where++| Artifact | Home | Command | Carries |+|---|---|---|---|+| **Runtime zip** `adom-bridge-grok-vX.Y.Z.zip` | Release | `adom-wiki release upload` | `server.py`, `handlers/`, `bridge.json`, `BRIDGE_VERSION` at zip **root**. No `node_modules`, no hero PNGs, no skills. |+| **Manifest** `adom-bridge-grok-manifest.json` | git repo | `adom-wiki repo push` | zip URL + sha256 + size. `updateManifestUrl` in BOTH zip `bridge.json` and the manifest. |+| **Skills pkg** `adom/grok-bridge` | Package | `adom-wiki pkg pack` then `pkg publish --org adom` | ROOT `SKILL.md` + USER `skills/*/SKILL.md` + `install.sh` + `uninstall.sh` + `package.json`. **No runtime. No `dev-skills/`.** |++`*.zip` / `*.tgz` are gitignored — `repo push` of a zip reports ok and **silently skips**. Binaries go to `release upload`.++## Skills-only vs runtime bump++- Skills library / README / hero: bump **`package.json` version** (pkg). Leave `BRIDGE_VERSION` + `bridge.json` version alone if the Python runtime did not change.+- New/changed `grok_*` verbs: bump **all three** (`BRIDGE_VERSION`, `bridge.json`, `package.json`) in lockstep, rebuild the zip, upload release, rewrite manifest, then pkg publish.++Current runtime: **1.2.0**. Do not republish the zip for a skills-only change.++## Skills pkg allowlist++`package.json` `files[]` lists every USER skill **explicitly** (no globs). Today:++- `SKILL.md`+- `skills/grok-anywhere/SKILL.md`+- `skills/grok-app-control/SKILL.md`+- `skills/grok-chat/SKILL.md`+- `skills/grok-record/SKILL.md`+- `skills/grok-webhook/SKILL.md`+- `skills/grok-account/SKILL.md`+- `install.sh` `uninstall.sh` `package.json` (README.md optional)++`install.sh` has **one** `install_skill <dest> <src>` line per USER skill, kept in sync. Deploys to `~/.claude/skills`, `~/.codex/skills` if present, `~/.grok/skills`, and `/home/box/agent-data/workflows` if that parent exists.++**`.gitignore` trap:** `pkg pack` honors gitignore. `*.png` is ignored with exceptions for `docs/hero.png` and `docs/screenshots/*.png`. Do not gitignore `skills/`. `tar tzf` the tarball — every `skills/<name>/SKILL.md` must be inside, zero zips, zero `dev-skills/`.++## Discovery++`package.json` `discovery_triggers` mix verb names and plain English (`talk to grok`, `is grok thinking`, `grok webhook`). After publish: `adom-wiki discover triggers` and `discover preview "talk to grok"`.++## Hero++Studio-stamped 2000×1250 PNG (`page hero --image`). Familjen Grotesk 700 titles, Satoshi body. Do not PIL-restamp (strips provenance). Path in live `page.json` has been `screenshots/hero.png`.++## Verify++```bash+tar tzf dist/*.tgz | rg 'SKILL.md|dev-skills|server.py'+adom-wiki pkg install adom/grok-bridge   # container+ls ~/.claude/skills/grok ~/.claude/skills/grok-webhook ~/.grok/skills/grok-chat+adom-bridge --ai-thread "Grok Bot" --target AdomLapper grok_readiness '{}'+```++Never paste webhook URL/key, `crsr_` tokens, or Bearer headers into chat, git, `_hint`, or the wiki.++Architecture: **grok-dev**.
install.sh+10−4
@@ -1,7 +1,8 @@ #!/usr/bin/env bash-# Install the grok USER skillpack: main skill `grok` + sub-skill `grok-anywhere`.-# Per the Bridge SDK a pkg ships ONLY user skills. The bridge RUNTIME is not-# here — Adom Bridge loads it from the release zip (adom-bridge-grok-v*.zip).+# Install the grok USER skillpack: core `grok` + area sub-skills.+# Per the Bridge SDK a pkg ships ONLY user skills. DEV/PUBLISH stay in the repo+# (dev-skills/). The bridge RUNTIME is not here — Adom Bridge loads it from+# the release zip (adom-bridge-grok-v*.zip). # Repo name (grok-bridge) != skill name (grok). Don't re-conflate (pup's lesson). set -euo pipefail PKG_DIR="$(cd "$(dirname "$0")" && pwd)"@@ -20,7 +21,12 @@ deploy_into() {   rm -rf "$BASE/grok-bridge"   install_skill grok SKILL.md   install_skill grok-anywhere skills/grok-anywhere/SKILL.md-  echo "  -> $BASE (grok + grok-anywhere)"+  install_skill grok-app-control skills/grok-app-control/SKILL.md+  install_skill grok-chat skills/grok-chat/SKILL.md+  install_skill grok-record skills/grok-record/SKILL.md+  install_skill grok-webhook skills/grok-webhook/SKILL.md+  install_skill grok-account skills/grok-account/SKILL.md+  echo "  -> $BASE (grok + 6 sub-skills)" }  echo "Installing grok-bridge skills:"
package.json+14−5
@@ -1,8 +1,8 @@ {   "slug": "grok-bridge",-  "version": "1.2.0",+  "version": "1.2.1",   "type": "app",-  "description": "Grok Bridge lets Adom talk to Grok Bot. Adom's AI environment is for electrical engineers: any provider (Claude, Codex, Grok, Gemini, …), any desktop power tool, through Adom Bridge. grok_* open/close/resize/screenshot/record the app, read the thread, and create bots/channels via webhook.",+  "description": "Grok Bridge lets Adom talk to Grok Bot. Adom's AI environment is for electrical engineers: any provider (Claude, Codex, Grok, Gemini, \u2026), any desktop power tool, through Adom Bridge. grok_* open/close/resize/screenshot/record the app, read the thread, and create bots/channels via webhook.",   "keywords": [     "grok",     "grok-bot",@@ -25,11 +25,15 @@   "files": [     "SKILL.md",     "skills/grok-anywhere/SKILL.md",+    "skills/grok-app-control/SKILL.md",+    "skills/grok-chat/SKILL.md",+    "skills/grok-record/SKILL.md",+    "skills/grok-webhook/SKILL.md",+    "skills/grok-account/SKILL.md",     "install.sh",     "uninstall.sh",     "README.md",-    "package.json",-    "CLAUDE.md"+    "package.json"   ],   "scripts": {     "install": "./install.sh",@@ -63,7 +67,12 @@     "grok_chat_read",     "is grok thinking",     "read grok chat",-    "grok transcript"+    "grok transcript",+    "install grok plugin",+    "record grok bot",+    "create grok channel",+    "grok_plugin_install",+    "grok_login"   ],   "sample_prompts": [     {
skills/grok-account/SKILL.mdadded+33
@@ -0,0 +1,33 @@+---+name: grok-account+user-invocable: true+description: "Sign in / sign out of Grok Bot and install plugins without typing passwords. grok_login / grok_logout use the app UI (Sign In with Cursor / Sign Out). grok_plugin_install launches grokbot://app/v1/plugin/add?id=<id> as an exe arg because desktop_open_url refuses grokbot://. Trigger words: grok_login, grok_logout, grok_plugin_install, sign in grok bot, sign out grok bot, install grok plugin."+---++# grok-account — login, logout, plugins++Never type passwords, tokens, or 2FA. Human clicks those.++```bash+adom-bridge --ai-thread "<your thread>" grok_login '{}'+adom-bridge --ai-thread "<your thread>" grok_logout '{}'+adom-bridge --ai-thread "<your thread>" grok_plugin_install '{"id":"<plugin id>"}'+```++## Core verbs++| CLI | Purpose | Key args |+|---|---|---|+| `grok_login` | Launch Grok Bot.exe with `grokbot://app/v1/settings?id=theme` as an arg. Does **not** type passwords | — |+| `grok_logout` | Open settings; try UIA **Sign Out**. Else `needsHuman:true` | — |+| `grok_plugin_install` | Launch Grok Bot.exe with `grokbot://app/v1/plugin/add?id=<id>` as an arg. Does not confirm install (the app UI does) | **`id` required** |++## grokbot:// routes++Only these exist: `settings?id=*` and `plugin/add?id=*`. `desktop_open_url` **refuses** `grokbot://` — the runtime launches `Grok Bot.exe` with the URL as an argument.++Do not invent other grokbot:// paths. Do not scrape cookies to mint a session.++`ok:true` means the UI opened, not that the human finished Sign In. If `needsHuman:true`, stop and tell them.++Webhook-driven plugin/login events: **grok-webhook**.
skills/grok-anywhere/SKILL.md+3
@@ -58,3 +58,6 @@ If a *cloud* AI needs to reach **this** Grok session from a Windows ab, that is - Webhook (routine **Grok Bridge webhook**): `grok_webhook_ensure {}` scrapes the pane (Edit **Webhook URL** / **Webhook key**) and stores `~/.adom/grok-webhook.json` (never log the key). Manual fallback `grok_webhook_bind {url, key}`. Then `grok_bot_create` / `grok_channel_create` / `grok_bot_list`.  This anywhere skill is the reverse: Grok Bot driving the PC.++Sibling USER skills in this pack (the other direction, cloud driving Grok Bot): **grok** (core), **grok-app-control**, **grok-chat**, **grok-record**, **grok-webhook**, **grok-account**.+
skills/grok-app-control/SKILL.mdadded+38
@@ -0,0 +1,38 @@+---+name: grok-app-control+user-invocable: true+description: "Open, close, resize, screenshot, and list Grok Bot.exe windows via grok_* Adom Bridge verbs. Host app is Grok Bot (title exact Grok Bot — not Chrome ai-grok-bot, not bare Grok). Background by default; foreground needs foregroundReason. Cursor is last-resort fallback only. Trigger words: grok_open, grok_close, grok_resize, grok_screenshot, grok_list_windows, grok_status, open grok bot, close grok bot, screenshot grok bot, resize grok window."+---++# grok-app-control — window and host++Drive the **Grok Bot.exe** window. Title needle is exactly `Grok Bot`. Do not match Chrome pup sessions named `ai-grok-bot` or a bare `Grok` (that hits the wrong window).++```bash+adom-bridge --ai-thread "<your thread>" grok_<verb> '<json>'+```++`--target NAME` when more than one desktop is connected. Surface `_hint` verbatim. Branch on `errorCode`.++## Core verbs++| CLI | Purpose | Key args |+|---|---|---|+| `grok_status` | Detect + last send + inbox + webhook bound (host only) | — |+| `grok_open` | Launch Grok Bot in the **background**; if running, list windows | optional `foreground` + **required** `foregroundReason` |+| `grok_list_windows` | `desktop_find_window` titleContains `Grok Bot` (preferred; unwrap `output`/`best.hwnd`) then `desktop_list_windows` + `process_list` | optional `titleContains` |+| `grok_screenshot` | `desktop_screenshot_window` of that hwnd | optional `titleContains` |+| `grok_close` | Hide the window (`desktop_set_window_state` hide). Prefer hide over kill. **Never kill Cursor.** | — |+| `grok_resize` | `desktop_set_window_bounds` on the Grok Bot hwnd. Restores first if maximized. Physical px (same as ab) | `w`, `h`, optional `x`, `y` (omit to keep origin) |++## hwnd unwrap++`desktop_find_window` returns `best.hwnd` nested under `output`. A missing unwrap makes `grok_list_windows` look empty even when Grok Bot is up. TITLE_NEEDLES is `["Grok Bot"]` only.++## Etiquette++Windows open in the background. `openedInBackground` / `windowEtiquette:"background"` are the contract. Foreground without `foregroundReason` is refused (`errorCode: foreground_reason_required`). Raise only when the user asked to **watch**.++`ok:true` is not enough — `grok_list_windows` or `grok_screenshot` after open/resize/close.++Cold-start and identity: **grok**. Recording: **grok-record**. Chat: **grok-chat**.
skills/grok-chat/SKILL.mdadded+32
@@ -0,0 +1,32 @@+---+name: grok-chat+user-invocable: true+description: "Read whether Grok Bot is thinking vs idle (grok_chat_status), pull the visible transcript (grok_chat_read), and queue a message via toast + durable inbox (grok_send — does not type into the composer unless opt-in). Capture is the Grok Bot.exe window via UIA, not OCR-first, never webhook keys. Trigger words: grok_chat_status, grok_chat_read, grok_send, is grok thinking, read grok chat, grok transcript, send a message to grok bot."+---++# grok-chat — thinking chip, transcript, send++```bash+adom-bridge --ai-thread "<your thread>" grok_chat_status '{}'+adom-bridge --ai-thread "<your thread>" grok_chat_read '{"limit": 40}'+adom-bridge --ai-thread "<your thread>" grok_send '{"message":"the board is ready for review"}'+```++Never steal focus. Surface `_hint` verbatim.++## Core verbs++| CLI | Purpose | Key args |+|---|---|---|+| `grok_chat_status` | Thinking vs idle. `thinking=true` when UIA exposes `"<agent> is working"` (proven: `"New Bot is working"`) | — |+| `grok_chat_read` | Visible transcript via `desktop_ui_text {hwnd, role:"Document", range:"all"}` (Document named `"Grok Bot"`). Optional `limit` truncates from the **end** (latest). Never returns webhook keys | optional `limit` |+| `grok_send` | Toast `Grok Bot: {message}` **and** append `~/.adom/grok-inbox.jsonl`. Typing into the chat widget is opt-in — default does not steal the keyboard | `message`, optional `agent` |++## Gotchas++- Status and read are the Grok Bot **window**, not this agent's box desktop feed.+- `grok_send` is not a public Grok HTTP API. The Anywhere character (`grok-anywhere`) can poll the inbox.+- If list_windows is empty, fix hwnd unwrap first (**grok-app-control**) — chat verbs need that hwnd.+- `ok:true` is not enough: after send, the toast exists; the composer may be unchanged. Say that honestly.++Window open/screenshot: **grok-app-control**. Webhook bots/channels: **grok-webhook**.
skills/grok-record/SKILL.mdadded+32
@@ -0,0 +1,32 @@+---+name: grok-record+user-invocable: true+description: "Record the Grok Bot.exe window (not the agent-box desktop feed) with grok_record_start / stop / status. grok_record_start requires a reason. Wraps desktop_record_window_* on the Grok Bot hwnd. Trigger words: grok_record_start, grok_record_stop, grok_record_status, record grok bot, grok window recording, demo recording grok."+---++# grok-record — Grok Bot window video++Capture is the **Grok Bot.exe window only**. This is not the agent-box video feed and not a full-desktop recorder.++```bash+adom-bridge --ai-thread "<your thread>" grok_record_start '{"reason":"demo of grok-bridge webhook bind"}'+adom-bridge --ai-thread "<your thread>" grok_record_status '{}'+adom-bridge --ai-thread "<your thread>" grok_record_stop '{}'+```++## Core verbs++| CLI | Purpose | Key args |+|---|---|---|+| `grok_record_start` | `desktop_record_window_start` on the Grok Bot hwnd | **`reason` required** |+| `grok_record_status` | `desktop_record_window_status` wrap | — |+| `grok_record_stop` | `desktop_record_window_stop` wrap | optional `recordingId` |++## Gotchas++- Missing `reason` is refused. Quote what the user asked to show.+- If you need the user to **watch**, raise first (`grok-app-control` / `foregroundReason`). Occluded windows throttle.+- Pull the file with the CLI from the container. This runtime never calls `pull_file` / `send_files`.+- `ok:true` on start is not a finished video — check `grok_record_status`, then stop.++Stills: `grok_screenshot` in **grok-app-control**.
skills/grok-webhook/SKILL.mdadded+55
@@ -0,0 +1,55 @@+---+name: grok-webhook+user-invocable: true+description: "Bind the Grok Bridge webhook without human copy-paste (grok_webhook_ensure scrapes the routine pane), fire events, and create Grok Bot bots/channels. Stores ~/.adom/grok-webhook.json on the PC. Never log or hint the key. Auth on fire is Authorization: Bearer. Trigger words: grok_webhook_ensure, grok_webhook_bind, grok_webhook_fire, grok_webhook_status, grok_bot_create, grok_channel_create, grok_bot_list, grok webhook, create grok bot, create grok channel."+---++# grok-webhook — bind, fire, bots, channels++A Grok Bot webhook routine named **Grok Bridge webhook** already exists. Call `grok_webhook_ensure {}` to scrape the routine pane and write the json on the PC. **Do not ask a human to copy the URL or key.**++Stored at `%USERPROFILE%\.adom\grok-webhook.json` (Windows) or `~/.adom/grok-webhook.json`:++```json+{"url":"https://...","key":"...","header":"Authorization: Bearer","boundAt":"<iso>"}+```++Never log the key. Never put the key in `_hint`. Auth on fire is header `Authorization: Bearer <key>`; a JSON body field named `key` is **wrong**.++## Core verbs++| CLI | Purpose | Key args |+|---|---|---|+| `grok_webhook_status` | Whether the json has a url. Returns `bound`, `urlHost` (hostname only) | — |+| `grok_webhook_ensure` | Scrape the routine pane and bind locally. No human copy-paste | optional `force` |+| `grok_webhook_bind` | Write the json (local FS on the PC). `url` must be **https** | **`url`**, **`key`** |+| `grok_webhook_fire` | POST `{event, payload, source:"grok-bridge", hostname}` | **`event`**, optional `payload` |+| `grok_bot_create` | Fire `event=create_bot` | **`name`**, optional `description` |+| `grok_channel_create` | Fire `event=create_channel` | **`name`**, optional `member_ids` |+| `grok_bot_list` | Fire `event=list_bots` | — |++If unbound: `errorCode: webhook_not_bound` and `_next` is `grok_webhook_ensure {}`.++## How ensure scrapes (no OCR)++`grok_webhook_ensure` drives the Grok Bot window (never `shell_execute` / `pull_file` / `send_files`):++1. `desktop_ui_click` name exactly `Open routine Grok Bridge webhook` (Button, invokable).+2. If Edits are missing, expand `When a webhook fires` — prefer `desktop_ui_click` the **Button** (invokable); ListItem Invoke is false so the fallback is `desktop_click` at that ListItem's center.+3. Read UIA **Edit** controls: name `Webhook URL`, `Webhook key`, `Authorization header`. Also `desktop_ui_get` those names.+4. Write the json on the PC. Settings gear is **not** the Routines list. Do not type into Prompt (if you touch it, set text empty and do not submit).++## Bound events++| Event | What Grok Bot does |+|---|---|+| `ping` | Reply that grok-bridge reached you (include desktop / target name) |+| `create_bot` | Create an agent (`name`, optional `description`) |+| `create_channel` | Create a channel (`name`, optional `member_ids`) |+| `list_bots` | List agents |+| `notify` | Surface a notification |+| `plugin_install` | Open plugin install for `{id}` |+| `login_needed` | Ask the human to sign in |+| `logout_done` | Confirm sign-out |++Smoke: `grok_webhook_fire {"event":"ping"}`. Verify with `grok_webhook_status` (hostname only).
uninstall.sh+2−2
@@ -1,12 +1,12 @@ #!/usr/bin/env bash-# Remove grok + grok-anywhere skills this pack installed (.adom-managed only).+# Remove grok USER skills this pack installed (.adom-managed only). # Does not kill Grok Bot or Cursor and does not uninstall the Windows runtime zip. set -euo pipefail  remove_from() {   local BASE="$1"   [ -d "$BASE" ] || return 0-  for name in grok grok-anywhere grok-bridge adom-bridge-grok; do+  for name in grok grok-anywhere grok-app-control grok-chat grok-record grok-webhook grok-account grok-bridge adom-bridge-grok; do     local dest="$BASE/$name"     if [ -d "$dest" ] && [ -f "$dest/.adom-managed" ]; then       rm -rf "$dest"