Skip to content

@extension-use/host ​

Everything that runs inside your extension: the router, the page actions, the side panel bridge, the control panel, manifest helpers, a CLI, and bundles for extensions with no build step.

bash
npm install @extension-use/host

Entry points ​

ImportRuns inMain export
@extension-use/host/backgroundThe service workerdefineHost(), defineAction(), builtinGroups, allBuiltinGroups, ExtensionUseError
@extension-use/host/contentA content script, in every framestartContentRuntime(), contentGroups, ExtensionUseError
@extension-use/host/frameAn extension page that hosts your web app (side panel, popup)mountFrameBridge()
@extension-use/host/uiAn extension page (options)mountControlPanel()
@extension-use/host/offscreenAn offscreen documentmountOffscreen(), for the opt-in tabCapture group
@extension-use/host/permissionsYour build scriptwithExtensionUse(), permissionsFor(), GROUP_NAMES
@extension-use/host/standalone/*Extensions with no build stepPrebuilt bundles: extension-use-background.js, -content.js, -frame.js, -ui.js, -offscreen.js

The package also installs the extension-use CLI: manifest, codegen and vendor.

defineHost() options ​

ts
import { defineHost } from "@extension-use/host/background";

const router = defineHost({
  id: "my-extension",
  controllers: { frame: { origins: ["https://app.example.com"] } },
});
OptionMeaning
idYour extension's identifier, shown to controllers. Required.
name, versionShown to controllers. version defaults to the manifest's.
controllers.frame{ origins, grants? }: web apps in an iframe inside an extension page.
controllers.page{ origins, grants? }: websites that connect through externally_connectable.
controllers.remote{ grants?, relays? }: scripts and agents through a relay. Needs the storage and alarms permissions. relays defaults to localhost and any https:// relay.
groupsBuilt-in groups to enable. Default allBuiltinGroups (all but the opt-in ones). See permissions.
actionsYour own actions, made with defineAction(). See custom actions.
policy{ blockedSites?, sensitiveFields? }. See security.
contentScriptPath of the bundled content script, such as "content.js". The host injects it into tabs that don't have it yet. Needs scripting.
offscreenPath of a page that calls mountOffscreen(), such as "offscreen.html". Needed by the tabCapture group.
badgeShow control state on the toolbar icon. Default true. Needs an action in the manifest.
defaultTimeoutMsDefault call timeout, when an action has none.
onAudit(entry)Called after every call with { ts, session, transport, origin, action, tabId?, ok, code?, ms }.
debugLog every call.

defineHost() returns the router. router.pause(), router.resume() and router.paused control the kill switch.

startContentRuntime() options ​

OptionMeaning
groupsContent groups to include: contentGroups.page, dom, edit, wait, overlay, picker. Default: all.
handlersHandlers for your own where: "content" actions, by name.
indicatorShow "Controlled by …" on the page during website and remote control. Default true.

It's safe to run twice (manifest and on-demand injection). The second call does nothing.

mountFrameBridge() options ​

See the frame bridge.

mountControlPanel(container, options?) ​

Renders pairing with a relay, the connection state, active sessions, recent actions and Pause all control into container, inside a shadow root.

OptionMeaning
deviceNameThe browser's name offered when pairing.
playgroundAdd a form that runs any action on a tab. For development. Default false.

mountOffscreen() ​

Call it in an offscreen page, and point defineHost({ offscreen }) at that page. It holds tab capture streams for the tabCapture group and for screenshots of background tabs. See recipe 8.

No build step ​

npx extension-use vendor copies the standalone bundles into extension/vendor (and the client into web/vendor). Then:

FileUse it inHow
extension-use-background.jsThe service workerimport { defineHost } from "./vendor/extension-use-background.js" (manifest: "type": "module")
extension-use-content.jsContent scriptsList it in content_scripts[].js. It starts the runtime by itself.
extension-use-frame.jsThe side panel pageimport { mountFrameBridge } from "./vendor/extension-use-frame.js"
extension-use-ui.jsThe control panel pageimport { mountControlPanel } from "./vendor/extension-use-ui.js"
extension-use-offscreen.jsThe offscreen page<script src="vendor/extension-use-offscreen.js"></script>. It mounts by itself.

See the plain JS/TS guide.

Bundle size ​

The router checks input with zod, which adds about 35 KB gzipped to the background script. Content scripts and side panel pages stay small.

The SDK packages are released under the MIT license.