app
Grok Bot
Public Made by Adomby adom
Grok Bridge lets Adom talk to Grok Bot. Adom's AI environment is for electrical engineers: any provider, any desktop power tool, one place.
← Commit history
grok-bridge 1.3.1: browser windows never count as the host app, grok_settings verb, grok_login presses Sign in, sign-in flow documented
12 files changed
+132−25
BRIDGE_VERSION+1−1@@ -1 +1 @@-1.3.0+1.3.1
CLAUDE.md+5−3@@ -32,7 +32,7 @@ will seed/stream the runtime from the release zip via `updateManifestUrl` in `br `ad_callback`. Never `shell_execute` / `pull_file` / `send_files` from the HTTP path. - `handlers/*.py` — readiness, describe, windows (open/screenshot/list), chat (status/read), send, app (close/resize/record/login/logout/plugin), webhook, bots.-- `bridge.json` + `BRIDGE_VERSION` — KEEP IN LOCKSTEP (currently 1.3.0).+- `bridge.json` + `BRIDGE_VERSION` — KEEP IN LOCKSTEP (currently 1.3.1). - `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) — core USER skill, installed as **`grok`** (not `grok-bridge`).@@ -41,13 +41,15 @@ will seed/stream the runtime from the release zip via `updateManifestUrl` in `br - `package.json` — wiki skills pkg. Description is the skills-not-runtime sentence. Runtime files and `*.zip` do **not** belong in `files[]`. -## Verbs (v1.3.0)+## Verbs (v1.3.1) Existing: `grok_readiness` `grok_prewarm` `grok_describe` `grok_status` `grok_open` `grok_screenshot` `grok_list_windows` `grok_chat_status` `grok_chat_read` `grok_send` `grok_uninstall`. App: `grok_close` `grok_resize` `grok_record_start` `grok_record_stop` `grok_record_status`-`grok_login` `grok_logout` `grok_plugin_install`.+`grok_login` `grok_logout` `grok_settings` `grok_plugin_install`.++Window picking: `_is_host_impostor` rejects ANY browser window (Edge/Chrome/Firefox/...), since sign-in tabs are titled "Sign in to Grok Bot"; exact title "Grok Bot" ranks first. Webhook: `grok_webhook_status` `grok_webhook_ensure` `grok_webhook_bind` `grok_webhook_fire` `grok_bot_create` `grok_channel_create` `grok_bot_list`.
SKILL.md+1−1@@ -50,7 +50,7 @@ adom-bridge --ai-thread "<your thread>" grok_readiness '{}' | `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_computer_screenshot` | Screenshot grok-bridge's computer (the agent box), not Grok Bot.exe. One verb; unique nonce; do not bash-poll | optional `nonce`, `timeoutSeconds` | grok-webhook |-| `grok_login` / `grok_logout` / `grok_plugin_install` | Sign-in UI + plugins | never type passwords | grok-account |+| `grok_login` / `grok_logout` / `grok_settings` / `grok_plugin_install` | Sign-in (presses splash Sign in), plan + billing (`page:usage`), 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_describe` is the completeness hatch; the per-call `_hint` is what you read in practice.
adom-bridge-grok-manifest.json+4−4@@ -1,10 +1,10 @@ { "manifest_version": 1, "name": "grok",- "version": "1.3.0",- "url": "https://wiki.adom.inc/download/adom/grok-bridge/1.3.0/adom-bridge-grok-v1.3.0.zip",- "sha256": "4a2d2172d9987987b4737fb75df0a27a8e230f635608703a65e480787e4e8049",- "size": 48242,+ "version": "1.3.1",+ "url": "https://wiki.adom.inc/download/adom/grok-bridge/1.3.1/adom-bridge-grok-v1.3.1.zip",+ "sha256": "09d480e98a27cec6c3ae6509f7de65de1e910d8165febca6d399e6d33e3df3b5",+ "size": 49640, "verbPrefixes": [ "grok_" ],
bridge.json+3−2@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "grok", "displayName": "Grok Bot",- "version": "1.3.0",+ "version": "1.3.1", "description": "Drive Grok Bot (standalone Electron app, Grok Bot.exe) from Adom Bridge: open/close/resize/screenshot/record the app, read thinking vs idle and the visible transcript of the focused thread, queue messages, bind the Grok Bridge webhook and create bots/channels. No public Grok HTTP API \u2014 the runtime talks back to ab over desktop_* callbacks. Cursor is last-resort fallback only if Grok Bot.exe is missing.", "homepage": "https://wiki.adom.inc/adom/grok-bridge", "author": "Adom Inc.",@@ -49,7 +49,8 @@ "grok_channel_create", "grok_bot_list", "grok_install",- "grok_install_status"+ "grok_install_status",+ "grok_settings" ], "statusVerb": "grok_readiness", "timeouts": {
dev-skills/grok-publish/SKILL.md+1−1@@ -23,7 +23,7 @@ Wiki: https://wiki.adom.inc/adom/grok-bridge. Changelog / `-m` must be ≥10 cha - 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.3.0**. Skills-only bumps `package.json` only; verb changes bump zip + manifest + package.json together.+Current runtime: **1.3.1**. Skills-only bumps `package.json` only; verb changes bump zip + manifest + package.json together. ## Skills pkg allowlist
handlers/app.py+71−5@@ -1,4 +1,4 @@-"""App-window verbs: close / resize / record / login / logout / plugin_install.+"""App-window verbs: close / resize / record / login / logout / settings / plugin_install. All driving is caller_identity.ad_callback (desktop_*). Never shell_execute / pull_file / send_files. Prefer hide over process_kill. Never kill Cursor.@@ -274,12 +274,41 @@ def _open_deeplink(url: str) -> dict: return launch_host([url]) +SIGN_IN_STEPS = (+ "Sign-in is xAI's page ('Log into your Grok Bot account': Google / X / Apple / GitHub / email) in the OS "+ "default browser, then Cursor's 'Enable data sharing' (leave Share Data off, press Continue), then "+ "'Sign in to Grok Bot' with the account (press Sign in), then the browser's 'This site is trying to open "+ "Grok Bot' prompt (press Open). Account-chooser rows are not UIA-invokable: use a foregrounded "+ "desktop_click on the row only when the PC is idle (desktop_user_idle_ms). Never type passwords. "+ "Afterwards the app may say 'Setting up Grok Bot's computer', then 'having trouble connecting' or "+ "'Couldn't load Bots' for several minutes; wait, restart the app once, and only press Recover computer "+ "if the user says the computer's installed apps can go (it removes them)."+)++ def handle_login(_args: dict) -> dict:- """Open Grok Bot settings in the background. Do NOT type passwords."""+ """Start sign-in. Signed-out splash: press its Sign in button (background UIA). Never types passwords."""+ hwnd, _win = grok_hwnd(allow_cursor=False)+ pressed = False+ press_res = None+ if hwnd:+ press_res = _cb("desktop_ui_click", {"hwnd": hwnd, "name": "Sign in"})+ pressed = _callback_ok(press_res) and not (press_res or {}).get("error")+ if pressed:+ return {+ "success": True,+ "pressedSignIn": True,+ "hwnd": hwnd,+ "typedPassword": False,+ "windowEtiquette": "background",+ "_hint": "Pressed Sign in on the Grok Bot splash (background UIA). The app now says 'Continue in your browser'. " + SIGN_IN_STEPS,+ "_next": "desktop_list_windows {} to find the browser tab, then desktop_screenshot_window on it",+ } res = _open_deeplink(SETTINGS_DEEPLINK) ok = _callback_ok(res) return { "success": ok or True, # opening settings is best-effort; the human signs in+ "pressedSignIn": False, "opened": ok, "url": SETTINGS_DEEPLINK, "background": True,@@ -287,10 +316,47 @@ def handle_login(_args: dict) -> dict: "callback": res, "windowEtiquette": "background", "_hint": (- "Launched Grok Bot.exe with grokbot://app/v1/settings?id=theme as an arg in the BACKGROUND (desktop_open_url refuses grokbot://; "- "no password typing). On the account card, the human should click "- "**Sign In with Cursor**. This verb will not type credentials."+ "No signed-out splash found (already signed in, or the window is not up: grok_open first). Opened "+ "Grok Bot settings via grokbot://app/v1/settings?id=theme in the BACKGROUND. " + SIGN_IN_STEPS+ ),+ }+++SETTINGS_PAGES = {"general": "general", "computer": "computer", "usage": "usage", "billing": "usage",+ "updates": "updates", "theme": "theme"}+++def handle_settings(args: dict) -> dict:+ """Open a Grok Bot Settings page (General / Computer / Usage & Billing / Updates) in the background."""+ page = str(args.get("page") or args.get("id") or "usage").strip().lower()+ sid = SETTINGS_PAGES.get(page)+ if sid is None:+ return {+ "success": False,+ "errorCode": "bad_args",+ "error": f"unknown settings page {page!r}",+ "_hint": "page is one of general, computer, usage (Usage & Billing: plan, weekly limit, on-demand cap), updates.",+ "_next": "grok_settings {\"page\":\"usage\"}",+ }+ url = f"grokbot://app/v1/settings?id={sid}"+ res = _open_deeplink(url)+ ok = _callback_ok(res)+ return {+ "success": ok,+ "opened": ok,+ "page": page,+ "url": url,+ "windowEtiquette": "background",+ "callback": res,+ "_hint": (+ (f"Opened Grok Bot Settings > {page} in the background. " if ok else+ f"Could not launch Grok Bot with {url} (see callback); is it installed? grok_readiness. ")+ + "Read it with grok_screenshot. "+ "Usage & Billing shows the plan (e.g. 'Current plan: Pro'), the weekly usage % and reset, and the "+ "on-demand monthly cap billed through Cursor. Close the overlay with its X before typing in the chat." ),+ "_next": "grok_screenshot {}",+ "related": ["grok_screenshot", "grok_login"], }
handlers/describe.py+7@@ -266,6 +266,13 @@ VERB_CATALOG = { "related": ["grok_webhook_ensure", "grok_bot_create"], "pitfalls": ["errorCode webhook_not_bound if unbound"], },+ "settings": {+ "summary": "Open a Grok Bot Settings page: general / computer / usage (plan + limits) / updates. Background.",+ "long": False,+ "hint": "grok_settings {page}. usage answers 'what plan am I on / what am I paying'. Then grok_screenshot.",+ "related": ["grok_screenshot", "grok_login"],+ "pitfalls": ["The overlay covers the chat; close it before typing a prompt."],+ }, "install": { "summary": "Install Grok Bot on this PC from its public update feed. Background job, per-user, no admin, no login.", "long": True,
handlers/windows.py+14−4@@ -196,18 +196,28 @@ def _title_of(win: dict | None) -> str: return str(win.get("title") or win.get("name") or "") +# Browser windows whose tab title mentions Grok Bot (the sign-in pages "Sign in to+# Grok Bot", "Return to Grok Bot", the wiki page) are NOT the host app.+_BROWSER_MARKERS = (+ "google chrome", "microsoft edge", "microsoft\u200b edge", "mozilla firefox",+ "brave", "opera", "vivaldi", "chrome for testing", "ai-grok-bot",+)++ def _is_host_impostor(title: str) -> bool:- """Google Chrome / ai-grok-bot are NOT the Grok Bot host."""+ """Any browser window (Chrome / Edge / Firefox / ...) or ai-grok-bot is NOT the Grok Bot host.""" tl = (title or "").lower()- return "google chrome" in tl or "ai-grok-bot" in tl+ return any(m in tl for m in _BROWSER_MARKERS) def _title_rank(title: str) -> int:- tl = (title or "").lower()+ tl = (title or "").strip().lower() if _is_host_impostor(title): return 9- if "grok bot" in tl:+ if tl == "grok bot": return 0+ if "grok bot" in tl:+ return 1 if "cursor" in tl: return 2 return 9
package.json+6−2@@ -1,6 +1,6 @@ { "slug": "grok-bridge",- "version": "1.3.0",+ "version": "1.3.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.", "keywords": [@@ -93,7 +93,11 @@ "install grok bot", "grok_install", "install grok bot on another pc",- "download grok bot"+ "download grok bot",+ "grok_settings",+ "what plan am i on grok",+ "grok billing",+ "grok bot plan" ], "sample_prompts": [ {
server.py+3@@ -32,6 +32,7 @@ from handlers.app import ( handle_record_status, handle_record_stop, handle_resize,+ handle_settings, ) from handlers.bots import handle_bot_create, handle_bot_list, handle_channel_create from handlers.describe import handle_describe@@ -79,6 +80,7 @@ KNOWN_VERBS = [ "grok_computer_screenshot", "grok_install", "grok_install_status",+ "grok_settings", "grok_run_status", "grok_bot_create", "grok_channel_create",@@ -123,6 +125,7 @@ COMMAND_HANDLERS = { "computer_screenshot": handle_computer_screenshot, "install": handle_install, "install_status": handle_install_status,+ "settings": handle_settings, "run_status": handle_run_status, "bot_create": handle_bot_create, "channel_create": handle_channel_create,
skills/grok-account/SKILL.md+16−2@@ -1,7 +1,7 @@ --- 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."+description: "Sign in / sign out of Grok Bot, read the plan and billing, and install plugins without typing passwords. grok_login presses the splash Sign in (xAI login page in the browser), grok_settings {page:usage} shows the plan, grok_logout uses 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_settings, grok plan, what plan am i on, grok billing, grok usage limit, grok_plugin_install, sign in grok bot, sign out grok bot, install grok plugin." --- Parent skill: **grok** (the core driver). This file is the area split. @@ -20,7 +20,8 @@ adom-bridge --ai-thread "<your thread>" grok_plugin_install '{"id":"<plugin id>" | 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_login` | On the signed-out splash, presses **Sign in** (background UIA) and returns the browser steps. Otherwise opens settings. Never types passwords | — |+| `grok_settings` | Open a Settings page in the background: `general`, `computer`, `usage` (plan, weekly %, on-demand cap), `updates` | `page` | | `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** | @@ -33,3 +34,16 @@ 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**.++## The sign-in flow, as it is today (verified 2026-10-14, app 0.70.2)++1. `grok_login` presses **Sign in** on the splash. The app shows *Continue in your browser · Reopen link · Cancel* and opens the link in the **OS default browser**.+2. xAI's page, **Log into your Grok Bot account**: Google, X, Apple, GitHub or email. Pick the provider the account was made with (find the account first: Grok Bot mail comes from `[email protected]`).+3. Google's account chooser. Its rows are **not** UIA-invokable; a foregrounded `desktop_click` on the row is needed, so only do it when `desktop_user_idle_ms` says nobody is at the PC.+4. Cursor's **Enable data sharing** page: leave Share Data **off**, press **Continue**.+5. **Sign in to Grok Bot** with the account shown: press **Sign in** (only because you just opened it from the app).+6. The browser asks **This site is trying to open Grok Bot**: press **Open**.+7. The app shows *Setting up Grok Bot's computer*. On a new PC it can then say *Grok Bot is having trouble connecting* or *Couldn't load Bots* for 10 to 20 minutes. Wait, restart the app once (process tree of the main `Grok Bot.exe`), and check again. **Recover computer** removes the cloud computer's installed apps and packages for every bot on the account: only with the user's say-so.+8. A first sign-in may show *Introducing your primary Bot*: choose an existing bot (grok-bridge, the webhook mailbox) or create one.++Plan and billing: `grok_settings {"page":"usage"}` then `grok_screenshot`. It shows *Current plan* (Pro, Pro+, ...), the weekly usage limit and reset, and the on-demand monthly cap billed through Cursor.