Skip to main content

SDK_README

Constant SDK_README 

Source
const SDK_README: &str = "# @agentmuxai/widget-sdk\n\nThe client for **sandboxed AgentMux widgets**. A widget\'s page runs in a sandboxed iframe inside an AgentMux pane; this SDK connects it to AgentMux and wraps the widget API (protocol 1).\n\nThe full reference is [`docs/specs/SPEC_USER_WIDGETS_AND_WIDGET_API_2026_10_09.md`](../../docs/specs/SPEC_USER_WIDGETS_AND_WIDGET_API_2026_10_09.md) (\u{a7}5 the package, \u{a7}6 the bridge, \u{a7}7 this SDK). Starter widgets are in [`docs/examples/widgets/`](../../docs/examples/widgets).\n\n## Use it without a build step\n\nAgentMux serves the SDK itself, so a plain HTML widget imports it directly:\n\n```html\n<link rel=\"stylesheet\" href=\"/agentmux/widget-sdk/am-widget.css\">\n<script type=\"module\">\n  import { connect } from \"/agentmux/widget-sdk/v1.js\";\n  const am = await connect();\n  await am.ui.setTitle(\"Hello\");\n</script>\n```\n\n## Use it with a bundler\n\n```bash\nnpm install @agentmuxai/widget-sdk\n```\n\n```js\nimport { connect } from \"@agentmuxai/widget-sdk\";\n```\n\nThat bundles a copy into your widget, which works with any AgentMux that speaks protocol 1, and gives you its types. Or keep importing it from `/agentmux/widget-sdk/v1.js`, the copy AgentMux serves, and tell the bundler to leave that import alone (Vite: `build.rollupOptions.external`; see [`docs/examples/widgets/react-vite/`](../../docs/examples/widgets/react-vite)).\n\n## The API\n\n| | |\n|---|---|\n| `connect({ applyTheme?, timeoutMs? })` | The handshake. Resolves to the client; applies the app\'s theme as CSS variables and keeps it current. |\n| `am.info` | The widget\'s id, version and pane; AgentMux\'s version; granted permissions; theme; this pane\'s meta. |\n| `am.on(event, cb)` | `visibility`, `focus`, `theme`, `meta`, `action`, `command` (one of its palette commands or status items, below), `storage` (the widget\'s storage changed, in any of its panes), `dispose`. Returns an unsubscribe. |\n| `am.meta.get()`, `am.meta.set(patch)` | This pane\'s own state, kept with the pane. |\n| `am.ui.setTitle`, `setHeaderActions`, `setContextMenu`, `toast`, `openUrl` | The pane\'s chrome, drawn by AgentMux. |\n| `am.ui.setStatusItem(id, { text, icon, tooltip, tone, hidden })` | Update one of the widget\'s status bar items while this pane is open. |\n| `am.theme.get()` | The current theme. |\n| `am.panes.open(view, meta?, split?)` | Open one of the widget\'s own panes (other views need `panes`). |\n| `am.storage.*` | Per-widget data on this computer (`storage`). |\n| `am.net.fetch(url, init?)` | HTTP to origins the widget declared (`net:<origin>`). |\n| `am.files.pick()`, `am.files.save()` | Files the user picks (`files`). |\n| `am.clipboard.writeText()` | `clipboard:write`. |\n| `am.agents.list()`, `am.agents.send()` | `agents:read`, `agents:send`. |\n| `useVisibility(am, { onActive, onDormant })` | Pause work while the pane is hidden. |\n| `AgentMuxError` | `code`, `name` (`permission_denied`, \u{2026}), `message`, `data`. |\n\nA method a widget wasn\'t granted rejects with `AgentMuxError` named `permission_denied`; `err.data.permission` names what it needs.\n\n## Commands and status bar items\n\nA widget can add entries to the command palette and items to the status bar, declared in its `widget.json` (an AgentMux older than 0.59.19 ignores them):\n\n```json\n\"contributes\": {\n  \"panes\": [{ \"name\": \"main\", \"label\": \"Pull requests\" }],\n  \"commands\": [{ \"id\": \"refresh\", \"title\": \"Refresh pull requests\", \"icon\": \"rotate-right\" }],\n  \"statusItems\": [{ \"id\": \"count\", \"text\": \"PRs\", \"icon\": \"code-pull-request\", \"command\": \"refresh\" }]\n}\n```\n\nRunning a command, from the palette or by clicking a status item that names it, focuses an open pane of the widget in the current tab, or opens one, and sends it the `command` event:\n\n```js\nam.on(\"command\", ({ id }) => id === \"refresh\" && refresh());\nawait am.ui.setStatusItem(\"count\", { text: `${prs.length} PRs`, tone: prs.length ? \"info\" : undefined });\n```\n\nA status item shows its `widget.json` look until a pane of the widget sets another, and again once that pane closes. Its tooltip always starts with the widget\'s name. Up to 20 commands and 4 status items per widget.\n\n## Signing a widget\n\nSigning lets AgentMux\'s install prompt say who published a widget, and warn when a later widget of the same publisher (the part of the id before the dot) is signed by another key. The package\'s `agentmux-widget` command does it with Node\'s own Ed25519:\n\n```bash\nnpx -p @agentmuxai/widget-sdk agentmux-widget keygen ~/.agentmux-widget-key.json   # once; keep it private\nnpx -p @agentmuxai/widget-sdk agentmux-widget sign ./acme.notes --key ~/.agentmux-widget-key.json\nnpx -p @agentmuxai/widget-sdk agentmux-widget verify ./acme.notes\n```\n\n`sign` writes `widget.sig` next to `widget.json`; it covers every other file, so sign last: an edit afterwards makes AgentMux refuse the package until it is signed again. Publish your key\'s fingerprint (`K7Q2-MZ4D-PX3A-9TWE`) where users can check it. A signature names a key, not what the widget does: the permissions in the prompt are still all a sandboxed widget can do.\n";