A library, not an extension
Install the packages into the extension you already have, built with WXT, any bundler, or no build step at all.
Packages you add to your own extension, so a web app, a website, a script or an AI agent can read pages and act on them through a typed, declarative set of actions. Your extension keeps the privileges.
web app (iframe in side panel) ββpostMessageβββΆ frame bridge ββ
website (externally_connectable) ββββββββββββββββββββββββββββββ€βββΆ router (background) βββΆ content runtime (tab)
script / agent (remote) ββrelayβββββββββββββββββββββββ grants Β· policy Β· auditYour extension runs the host: a router in the background, a runtime in each page, and a bridge for your web app. Controllers connect from outside and call actions by name. They can only call the actions you enable, on the sites your policy allows. No controller code ever runs inside the extension, so it stays within Chrome Web Store rules.
// Your extension: background
import { defineHost } from "@extension-use/host/background";
defineHost({
id: "my-extension",
controllers: { frame: { origins: ["https://app.example.com"] } },
contentScript: "content.js",
});// Your web app
import { connect } from "@extension-use/client";
import { frame } from "@extension-use/client/frame";
const ext = await connect(frame());
const { text } = await ext.dom.snapshot({ format: "text" }); // the page as a tree with refs
await ext.dom.click({ locator: { role: "button", name: "Save" } });Not sure which packages you need? The package picker asks three questions and writes the setup for you.