Claude Skill

kimi-webbridge

Kimi Browser Extension(Kimi 浏览器扩展,原 Kimi WebBridge)lets AI control the user's real browser — navigate, click, type, read, screenshot, and interact with any website using the user's actual login sessions. Use this skill whenever the user wants to interact with websites, automate b

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download mxyhi-ok-skills-kimi-webbridge-7933c15.zip · 6 KB
mxyhi/ok-skills 490 46 forks Apache-2.0 Updated 5d ago
Part of mxyhi/ok-skills — 37 skills

Install

skills CLI npx skills add https://github.com/mxyhi/ok-skills/tree/main/kimi-webbridge
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install mxyhi-ok-skills@llmmart
Git git clone https://github.com/mxyhi/ok-skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole mxyhi/ok-skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Kimi Browser Extension (formerly Kimi WebBridge)

Control the user's real browser (with their login sessions) via a local daemon at http://127.0.0.1:10086.

Tools

Tool Args Returns Note
navigate url, newTab(bool), group_title {success, url, tabId} First call opens a tab — see Tabs. group_title sets the group's visible label
find_tab url, active(bool) {success, url, tabId, borrowed} Re-select a tab this session opened; active:true borrows the tab the user is viewing — see Tabs
snapshot — {url, title, tree} with @e refs Accessibility tree (text) — use this to read page content and locate elements
click selector (@e ref or CSS) {success, tag, text} Synthetic el.click()
fill selector, value {success, tag, mode} Works on <input>/<textarea> AND [contenteditable] (ProseMirror/Lexical/Slate). mode is "value" or "contenteditable"
evaluate code (supports async/await) {type, value}
cdp method, params raw CDP response Raw chrome.debugger passthrough — what evaluate is to JS, cdp is to CDP. Low-level escape hatch for cases the tools above don't cover
screenshot format(png|jpeg), quality(0-100), optional selector (@e/CSS), optional path {format, path, sizeBytes, mimeType} Returns a file path, not base64 — see Screenshots
network cmd(start|stop|list|detail), filter, requestId request/response data
upload selector, files(string[]) {success, fileCount}
save_as_pdf paper_format, landscape, scale, print_background, optional path {path, sizeBytes, mimeType, pageTitle} Render current page → PDF, returns a file path — see Save as PDF
list_tabs — {success, tabs:[{tabId, url, title, active, groupTitle}]} Inspect tabs in the current session
close_tab — {success, closed: bool} Close the current tab in the session
close_session — {success, closed: int} Close all tabs in the session — closed is the count. See Sessions for when to call

Tabs and the current tab

Single-tab tools (snapshot, click, fill, screenshot, save_as_pdf) act on the current tab — the one you most recently opened with navigate or selected with find_tab.

  • Opening pages: use newTab:true when pages should coexist (comparing, cross-referencing); omit it to send the current tab to a new URL.
  • Going back to an earlier tab: call find_tab to make a tab you opened earlier in this session the current one again. Pass the tab's full URL — take it from list_tabs or the earlier navigate result. A bare root domain (kimi.com) may miss a www.kimi.com tab, so prefer the exact URL. By default find_tab searches only this session's own tabs — it never reaches into the user's other tabs or windows.
  • Acting on a page the user already has open: pass active:true ("use my open X tab" / "the X page I'm viewing"). It borrows the tab the user is currently viewing (returns borrowed:true); the borrowed tab is operated in place — it is not pulled into the session's tab group.
  • If find_tab errors with "no tab matching … in this session", the page isn't open in this session — navigate with newTab:true instead.
curl -s -X POST http://127.0.0.1:10086/command \
  -d '{"action":"find_tab","args":{"url":"https://www.kimi.com","active":true},"session":"k26-research"}'

Call Format

Every command carries a top-level session naming the current task — see Sessions below. The examples in later sections omit it only for brevity; in real calls always include it. The command format depends on the user's OS.

macOS / Linux — inline JSON is fine:

curl -s -X POST http://127.0.0.1:10086/command \
  -H 'Content-Type: application/json' \
  -d '{"action":"navigate","args":{"url":"https://example.com","newTab":true,"group_title":"My task"},"session":"my-task"}'

If the inline call fails — a shell quoting/syntax error from bash, or an HTTP 400 from the daemon — do not retry the same command unchanged. Resend the request as a file body:

  1. Write the JSON body to a uniquely-named temp file with your own file-write tool — never with shell echo/heredoc, which mangles the JSON the same way. Use a fresh name per request (e.g. /tmp/webbridge-req-<random>.json).
  2. POST the file:
curl -s -X POST http://127.0.0.1:10086/command -H 'Content-Type: application/json' --data-binary @/tmp/webbridge-req-<random>.json
  1. Delete the temp file as soon as the request returns.

Windows (PowerShell / cmd) — the shell corrupts non-ASCII characters (Chinese etc.) carried inline in command arguments or pipes; they reach the daemon as ? and the text is unrecoverable. Send every request as a file body instead:

  1. Write the JSON body to a uniquely-named temp file with your own file-write tool — never with shell echo/heredoc, which corrupts non-ASCII the same way. Give every request its own filename with a random suffix (e.g. webbridge-req-<random>.json) so concurrent requests never share a file and overwrite each other.
  2. POST the file with curl.exe — always curl.exe, never bare curl, which Windows PowerShell aliases to Invoke-WebRequest:
curl.exe -s -X POST http://127.0.0.1:10086/command -H "Content-Type: application/json" --data-binary "@$env:TEMP\webbridge-req-<random>.json"
  1. Delete the temp file as soon as the request returns — don't leave request bodies on disk.

Sessions

One task = one session = one tab group. A session collects every tab the task opens into one tab group, so the user sees a single group for "what the agent is doing right now". Pass it as a top-level field of the request body (not inside args).

  • Pick one session name at the task's start, put it on every command, and never switch mid-task — even across different sites. Switching session names per site is the #1 cause of fragmented tab groups.
  • Name it after the task, not the site (camping-research, phone-compare). Use multiple sessions only for genuinely unrelated parallel tasks.
  • group_title is the human-readable group label — write it in the user's language, on the first navigate of the task.
  • When you create the group (the first navigate of a task), tell the user once that this task's pages are collected under group «title», and that you'll close them whenever they ask.
# First tab: set session + a human label (in the user's language)
curl -s -X POST http://127.0.0.1:10086/command \
  -d '{"action":"navigate","args":{"url":"https://www.kimi.com","newTab":true,"group_title":"K2.6 feature research"},"session":"k26-research"}'
# Another site, same task → same session → joins the same group automatically
curl -s -X POST http://127.0.0.1:10086/command \
  -d '{"action":"navigate","args":{"url":"https://www.moonshot.cn","newTab":true},"session":"k26-research"}'

Closing is always user-initiated: call close_session only when the user explicitly asks ("close those", "clear the tabs"). It clears the whole group in one call.

Screenshots

The daemon writes the image to disk and returns {format, path, sizeBytes, mimeType} — never base64, since the model can't read raw image bytes. Take the .path and open it with the Read tool to actually see it.

# Default: PNG of the visible viewport, daemon picks a temp path
curl ... -d '{"action":"screenshot","args":{}}'
# Options (each independent): JPEG quality, element-only via @e/CSS selector, custom output path
curl ... -d '{"action":"screenshot","args":{"format":"jpeg","quality":60}}'
curl ... -d '{"action":"screenshot","args":{"selector":"@e123"}}'

A caller-supplied path is honored verbatim (parent dirs created, existing file overwritten) — use a unique name to avoid clobbering. save_as_pdf follows the same rule.

Prefer snapshot over CSS/JS selectors

snapshot returns interactive elements with @e refs based on semantic role/name. Use them directly with click/fill — they survive CSS class hash changes that break manually-written selectors.

Fall back to evaluate (JS) only when:

  • The target has no @e ref in the snapshot
  • You need attributes not in the snapshot (e.g., href)
  • You need to dispatch complex event sequences, or scroll

Evaluate Tips

  • Always use compact JSON.stringify(data) — never add null, 2 formatting. Indentation and newlines can inflate the response several times over, causing truncation during transmission.
  • evaluate calls share the page's JS realm — re-declaring the same const/let across two calls throws SyntaxError. Wrap in an IIFE for a fresh scope: (() => { const x = ...; return x; })().

Text input — use fill

fill (selector = CSS or @e ref, plus the value) works on <input>/<textarea> (returns mode: "value") and on [contenteditable] rich editors — ProseMirror, TipTap, Lexical, Slate, Quill, etc. (returns mode: "contenteditable"), firing the right input events so the page reacts.

fill is clear-and-insert: existing content is replaced. To append, read the current value via evaluate, concatenate, then fill with the result.

Form submit / special keys

There's no separate "press Enter" tool. To submit a form, click the submit button directly (click on the @e ref or selector). To dispatch a key event programmatically (e.g. Escape to close a modal):

{"action":"evaluate","args":{"code":"document.activeElement.dispatchEvent(new KeyboardEvent('keydown',{key:'Escape',bubbles:true}))"}}

Save the current page as PDF

save_as_pdf renders the current page to PDF and returns the file path. All args optional:

  • paper_format: letter (default) | a4 | legal | a3 | tabloid
  • landscape: false (default)
  • scale: 1.0 (default), range [0.1, 2.0]
  • print_background: true (default) — keep background colors
  • path: caller-supplied output path; if absent, daemon picks a default under OS temp dir using the page title as the filename

path semantics match screenshot: written verbatim, parent dirs auto-created, existing files overwritten.

Decoded PDF cap is 100 MB. Above that the daemon refuses; reduce scale or split the page.

Known limitations

  • Sites that strictly check event.isTrusted (some banking portals, captchas) ignore click / fill because those fire DOM-level synthetic events (isTrusted=false). For these, tell the user the page needs manual interaction. (Trusted input is possible at the protocol level via the cdp escape hatch, but treat that as advanced.)
  • Cross-origin iframes: fill, click, evaluate, and snapshot operate on the top frame. If a target element lives in a same-page iframe from a different origin (e.g. embedded sandbox demos), navigate to the iframe's URL directly instead.

If a tool call fails (daemon or extension not ready)

If a tool call can't reach the daemon (connection refused), start it yourself — don't ask the user. This is safe to run anytime: it no-ops if the daemon is already up.

macOS / Linux:

~/.kimi-webbridge/bin/kimi-webbridge start

Windows (PowerShell):

& "$env:USERPROFILE\.kimi-webbridge\bin\kimi-webbridge.exe" start

Then retry the tool call. If it still fails — or the browser extension won't connect — point the user to the help page instead of deep-troubleshooting:

Never run stop / restart / uninstall automatically — those kill a running daemon. See references/operations.md for anything deeper.

Version mismatches

If a tool returns an error containing "Please update the Kimi Browser Extension", the user's browser extension is older than this skill. Don't try to reconcile versions yourself — just tell the user, in their language, to update the extension and retry:

Files (ok-skills)
  • references
    • operations.md 2 KB
      # Operations: daemon lifecycle and recovery
      
      Read this only when a tool call can't reach the daemon, or the user explicitly asks to install / start / troubleshoot kimi-webbridge.
      
      ## The daemon
      
      The `kimi-webbridge` binary lives at `~/.kimi-webbridge/bin/kimi-webbridge` (Windows: `%USERPROFILE%\.kimi-webbridge\bin\kimi-webbridge.exe`) and serves a local HTTP daemon on `127.0.0.1:10086`. Status, PID, and logs live under `~/.kimi-webbridge/`.
      
      ## Recovery — what to do when a tool call fails
      
      1. **Daemon not reachable (connection refused)** → start it yourself, don't ask the user. `start` is idempotent: it no-ops if the daemon is already up, and concurrent starts converge to a single daemon (the OS lets only one process bind port 10086).
         - macOS / Linux: `~/.kimi-webbridge/bin/kimi-webbridge start`
         - Windows: `& "$env:USERPROFILE\.kimi-webbridge\bin\kimi-webbridge.exe" start`
      
         Then retry the tool call.
      2. **`command not found` / binary missing** → not installed. Point the user to the help page below to install it.
      3. **Extension won't connect, or anything still broken after a `start` + retry** → don't deep-troubleshoot. Point the user to the help page:
         - English: https://www.kimi.com/en/products/kimi-webbridge
         - 中文: https://www.kimi.com/products/kimi-webbridge
      
      ## Do NOT do automatically
      
      Never run `stop` / `restart` / `uninstall` on your own. They kill the running daemon; if the user runs the **Kimi Desktop App** (which manages its own daemon), an external stop/restart also fights the app. If a hard restart is genuinely needed, ask the user to do it themselves — reopen the Kimi Desktop App, or run `kimi-webbridge restart` by hand.
      
      ## /status JSON fields
      
      - `running` (bool) — daemon listening on `:10086`
      - `version` (string) — daemon build version
      - `extension_connected` (bool) — a WebSocket client (the browser extension) is attached
      - `extension_id` (string) — the Chrome/Edge extension ID, empty if none
      - `uptime_seconds` (int)
      
  • SKILL.md 12.8 KB
    ---
    name: kimi-webbridge
    description: |
      Kimi Browser Extension(Kimi 浏览器扩展,原 Kimi WebBridge)lets AI control the user's real browser — navigate, click, type, read, screenshot, and interact with any website using the user's actual login sessions. Use this skill whenever the user wants to interact with websites, automate browser tasks, scrape web content, or perform any action requiring a real browser. Also use when the user mentions "browser", "webpage", "open URL", "screenshot", or asks to read/interact with any website. Use even for simple-sounding browser requests — the daemon handles all complexity.
    metadata:
      version: "2.0.5"
    ---
    
    # Kimi Browser Extension (formerly Kimi WebBridge)
    
    Control the user's real browser (with their login sessions) via a local daemon at `http://127.0.0.1:10086`.
    
    ## Tools
    
    | Tool | Args | Returns | Note |
    |------|------|---------|------|
    | `navigate` | `url`, `newTab`(bool), `group_title` | `{success, url, tabId}` | First call opens a tab — see [Tabs](#tabs-and-the-current-tab). `group_title` sets the group's visible label |
    | `find_tab` | `url`, `active`(bool) | `{success, url, tabId, borrowed}` | Re-select a tab **this session** opened; `active:true` borrows the tab the **user** is viewing — see [Tabs](#tabs-and-the-current-tab) |
    | `snapshot` | — | `{url, title, tree}` with `@e` refs | **Accessibility tree** (text) — use this to read page content and locate elements |
    | `click` | `selector` (@e ref or CSS) | `{success, tag, text}` | Synthetic `el.click()` |
    | `fill` | `selector`, `value` | `{success, tag, mode}` | Works on `<input>`/`<textarea>` AND `[contenteditable]` (ProseMirror/Lexical/Slate). `mode` is `"value"` or `"contenteditable"` |
    | `evaluate` | `code` (supports async/await) | `{type, value}` | |
    | `cdp` | `method`, `params` | raw CDP response | Raw `chrome.debugger` passthrough — what `evaluate` is to JS, `cdp` is to CDP. Low-level escape hatch for cases the tools above don't cover |
    | `screenshot` | `format`(png\|jpeg), `quality`(0-100), optional `selector` (@e/CSS), optional `path` | `{format, path, sizeBytes, mimeType}` | Returns a file path, not base64 — see [Screenshots](#screenshots) |
    | `network` | `cmd`(start\|stop\|list\|detail), `filter`, `requestId` | request/response data | |
    | `upload` | `selector`, `files`(string[]) | `{success, fileCount}` | |
    | `save_as_pdf` | `paper_format`, `landscape`, `scale`, `print_background`, optional `path` | `{path, sizeBytes, mimeType, pageTitle}` | Render current page → PDF, returns a file path — see [Save as PDF](#save-the-current-page-as-pdf) |
    | `list_tabs` | — | `{success, tabs:[{tabId, url, title, active, groupTitle}]}` | Inspect tabs in the current session |
    | `close_tab` | — | `{success, closed: bool}` | Close the current tab in the session |
    | `close_session` | — | `{success, closed: int}` | Close all tabs in the session — `closed` is the count. See [Sessions](#sessions) for when to call |
    
    ### Tabs and the current tab
    
    Single-tab tools (`snapshot`, `click`, `fill`, `screenshot`, `save_as_pdf`) act on the **current tab** — the one you most recently opened with `navigate` or selected with `find_tab`.
    
    - **Opening pages**: use `newTab:true` when pages should coexist (comparing, cross-referencing); omit it to send the current tab to a new URL.
    - **Going back to an earlier tab**: call `find_tab` to make a tab **you opened earlier in this session** the current one again. Pass the tab's **full URL** — take it from `list_tabs` or the earlier `navigate` result. A bare root domain (`kimi.com`) may miss a `www.kimi.com` tab, so prefer the exact URL. By default `find_tab` searches **only this session's own tabs** — it never reaches into the user's other tabs or windows.
    - **Acting on a page the user already has open**: pass `active:true` ("use my open X tab" / "the X page I'm viewing"). It **borrows** the tab the user is currently viewing (returns `borrowed:true`); the borrowed tab is operated in place — it is not pulled into the session's tab group.
    - If `find_tab` errors with "no tab matching … in this session", the page isn't open in this session — `navigate` with `newTab:true` instead.
    
    ```bash
    curl -s -X POST http://127.0.0.1:10086/command \
      -d '{"action":"find_tab","args":{"url":"https://www.kimi.com","active":true},"session":"k26-research"}'
    ```
    
    ### Call Format
    
    Every command carries a top-level `session` naming the current task — see [Sessions](#sessions) below. The examples in later sections omit it only for brevity; in real calls always include it. The command format depends on the user's OS.
    
    **macOS / Linux** — inline JSON is fine:
    
    ```bash
    curl -s -X POST http://127.0.0.1:10086/command \
      -H 'Content-Type: application/json' \
      -d '{"action":"navigate","args":{"url":"https://example.com","newTab":true,"group_title":"My task"},"session":"my-task"}'
    ```
    
    If the inline call fails — a shell quoting/syntax error from bash, or an HTTP 400 from the daemon — do **not** retry the same command unchanged. Resend the request as a file body:
    
    1. Write the JSON body to a **uniquely-named** temp file with your own file-write tool — never with shell `echo`/heredoc, which mangles the JSON the same way. Use a fresh name per request (e.g. `/tmp/webbridge-req-<random>.json`).
    2. POST the file:
    
    ```bash
    curl -s -X POST http://127.0.0.1:10086/command -H 'Content-Type: application/json' --data-binary @/tmp/webbridge-req-<random>.json
    ```
    
    3. Delete the temp file as soon as the request returns.
    
    **Windows (PowerShell / cmd)** — the shell corrupts non-ASCII characters (Chinese etc.) carried inline in command arguments or pipes; they reach the daemon as `?` and the text is unrecoverable. Send **every** request as a file body instead:
    
    1. Write the JSON body to a **uniquely-named** temp file with your own file-write tool — never with shell `echo`/heredoc, which corrupts non-ASCII the same way. Give **every** request its own filename with a random suffix (e.g. `webbridge-req-<random>.json`) so concurrent requests never share a file and overwrite each other.
    2. POST the file with `curl.exe` — always `curl.exe`, never bare `curl`, which Windows PowerShell aliases to `Invoke-WebRequest`:
    
    ```powershell
    curl.exe -s -X POST http://127.0.0.1:10086/command -H "Content-Type: application/json" --data-binary "@$env:TEMP\webbridge-req-<random>.json"
    ```
    
    3. Delete the temp file as soon as the request returns — don't leave request bodies on disk.
    
    ## Sessions
    
    **One task = one session = one tab group.** A `session` collects every tab the task opens into one tab group, so the user sees a single group for "what the agent is doing right now". Pass it as a **top-level field** of the request body (not inside `args`).
    
    - **Pick one session name at the task's start, put it on every command, and never switch mid-task — even across different sites.** Switching session names per site is the #1 cause of fragmented tab groups.
    - Name it after the **task**, not the site (`camping-research`, `phone-compare`). Use multiple sessions only for genuinely unrelated parallel tasks.
    - `group_title` is the human-readable group label — write it in the user's language, on the **first** `navigate` of the task.
    - When you create the group (the first `navigate` of a task), tell the user once that this task's pages are collected under group «title», and that you'll close them whenever they ask.
    
    ```bash
    # First tab: set session + a human label (in the user's language)
    curl -s -X POST http://127.0.0.1:10086/command \
      -d '{"action":"navigate","args":{"url":"https://www.kimi.com","newTab":true,"group_title":"K2.6 feature research"},"session":"k26-research"}'
    # Another site, same task → same session → joins the same group automatically
    curl -s -X POST http://127.0.0.1:10086/command \
      -d '{"action":"navigate","args":{"url":"https://www.moonshot.cn","newTab":true},"session":"k26-research"}'
    ```
    
    Closing is always user-initiated: call `close_session` only when the user explicitly asks ("close those", "clear the tabs"). It clears the whole group in one call.
    
    ## Screenshots
    
    The daemon writes the image to disk and returns `{format, path, sizeBytes, mimeType}` — never base64, since the model can't read raw image bytes. Take the `.path` and open it with the `Read` tool to actually see it.
    
    ```bash
    # Default: PNG of the visible viewport, daemon picks a temp path
    curl ... -d '{"action":"screenshot","args":{}}'
    # Options (each independent): JPEG quality, element-only via @e/CSS selector, custom output path
    curl ... -d '{"action":"screenshot","args":{"format":"jpeg","quality":60}}'
    curl ... -d '{"action":"screenshot","args":{"selector":"@e123"}}'
    ```
    
    A caller-supplied `path` is honored verbatim (parent dirs created, existing file overwritten) — use a unique name to avoid clobbering. `save_as_pdf` follows the same rule.
    
    ## Prefer snapshot over CSS/JS selectors
    
    `snapshot` returns interactive elements with `@e` refs based on semantic role/name. Use them directly with click/fill — they survive CSS class hash changes that break manually-written selectors.
    
    Fall back to `evaluate` (JS) only when:
    - The target has no `@e` ref in the snapshot
    - You need attributes not in the snapshot (e.g., `href`)
    - You need to dispatch complex event sequences, or scroll
    
    ## Evaluate Tips
    
    - Always use compact `JSON.stringify(data)` — never add `null, 2` formatting. Indentation and newlines can inflate the response several times over, causing truncation during transmission.
    - `evaluate` calls share the page's JS realm — re-declaring the same `const`/`let` across two calls throws `SyntaxError`. Wrap in an IIFE for a fresh scope: `(() => { const x = ...; return x; })()`.
    
    ## Text input — use `fill`
    
    `fill` (selector = CSS or `@e` ref, plus the value) works on `<input>`/`<textarea>` (returns `mode: "value"`) and on `[contenteditable]` rich editors — ProseMirror, TipTap, Lexical, Slate, Quill, etc. (returns `mode: "contenteditable"`), firing the right input events so the page reacts.
    
    `fill` is **clear-and-insert**: existing content is replaced. To append, read the current value via `evaluate`, concatenate, then `fill` with the result.
    
    ## Form submit / special keys
    
    There's no separate "press Enter" tool. To submit a form, click the submit button directly (`click` on the @e ref or selector). To dispatch a key event programmatically (e.g. Escape to close a modal):
    
    ```bash
    {"action":"evaluate","args":{"code":"document.activeElement.dispatchEvent(new KeyboardEvent('keydown',{key:'Escape',bubbles:true}))"}}
    ```
    
    ## Save the current page as PDF
    
    `save_as_pdf` renders the current page to PDF and returns the file path. All args optional:
    - `paper_format`: `letter` (default) \| `a4` \| `legal` \| `a3` \| `tabloid`
    - `landscape`: `false` (default)
    - `scale`: `1.0` (default), range `[0.1, 2.0]`
    - `print_background`: `true` (default) — keep background colors
    - `path`: caller-supplied output path; if absent, daemon picks a default under OS temp dir using the page title as the filename
    
    `path` semantics match `screenshot`: written verbatim, parent dirs auto-created, existing files overwritten.
    
    Decoded PDF cap is 100 MB. Above that the daemon refuses; reduce `scale` or split the page.
    
    ## Known limitations
    
    - **Sites that strictly check `event.isTrusted`** (some banking portals, captchas) ignore `click` / `fill` because those fire DOM-level synthetic events (`isTrusted=false`). For these, tell the user the page needs manual interaction. (Trusted input is possible at the protocol level via the `cdp` escape hatch, but treat that as advanced.)
    - **Cross-origin iframes**: `fill`, `click`, `evaluate`, and `snapshot` operate on the top frame. If a target element lives in a same-page iframe from a different origin (e.g. embedded sandbox demos), navigate to the iframe's URL directly instead.
    
    ## If a tool call fails (daemon or extension not ready)
    
    **If a tool call can't reach the daemon (connection refused), start it yourself — don't ask the user. This is safe to run anytime: it no-ops if the daemon is already up.**
    
    **macOS / Linux:**
    
    ```bash
    ~/.kimi-webbridge/bin/kimi-webbridge start
    ```
    
    **Windows (PowerShell):**
    
    ```powershell
    & "$env:USERPROFILE\.kimi-webbridge\bin\kimi-webbridge.exe" start
    ```
    
    Then retry the tool call. If it still fails — or the browser extension won't connect — point the user to the help page instead of deep-troubleshooting:
    
    - English: https://www.kimi.com/en/products/kimi-webbridge
    - 中文: https://www.kimi.com/products/kimi-webbridge
    
    Never run `stop` / `restart` / `uninstall` automatically — those kill a running daemon. See `references/operations.md` for anything deeper.
    
    ## Version mismatches
    
    If a tool returns an error containing **"Please update the Kimi Browser Extension"**, the user's browser extension is older than this skill. Don't try to reconcile versions yourself — just tell the user, in their language, to update the extension and retry:
    
    - English: https://www.kimi.com/en/products/kimi-webbridge
    - 中文: https://www.kimi.com/products/kimi-webbridge
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related