@ank1015/llm-extension
v0.0.12
Published
Chrome RPC bridge with a Manifest V3 extension, native messaging host, and Node client
Maintainers
Readme
@ank1015/llm-extension
Chrome RPC bridge for automating or inspecting a live Chrome session from Node.js.
This package combines:
- a Manifest V3 Chrome extension that exposes Chrome APIs over RPC
- a native messaging host that bridges Chrome to TCP
- a Node client with
connect(),call(),subscribe(), andgetPageMarkdown()
It is intentionally a low-level Chrome RPC package. It does not ship a higher-level browser automation wrapper.
What You Get
connect(opts?)to attach to the local Chrome bridgeChromeClient.call(method, ...args)for generic Chrome API accessChromeClient.subscribe(event, callback)for Chrome eventsChromeClient.getPageMarkdown(tabId, opts?)as an optional HTML-to-markdown helperChromeServerplus protocol/stdio helpers if you need lower-level integration
Architecture
Node process ── TCP :9224 ──→ native host ── native messaging ──→ Chrome extension- The Chrome extension runs a background service worker.
- Chrome launches the native host through native messaging.
- The native host opens a local TCP server.
- Your Node process connects and sends length-prefixed JSON RPC messages.
Docs:
Install and Setup
pnpm add @ank1015/llm-extensionBuild the package:
pnpm --filter @ank1015/llm-extension buildLoad the unpacked extension from packages/extension/dist/chrome/ in chrome://extensions, then register the native host.
For macOS, use the packaged installer script:
./packages/extension/manifests/install-host.sh <extension-id>The script is macOS-specific. For other environments, use manifests/com.ank1015.llm.json as the template for manual native-host registration.
Usage
import { connect } from '@ank1015/llm-extension';
const chrome = await connect({ launch: true });
const tabs = (await chrome.call('tabs.query', {
active: true,
currentWindow: true,
})) as { id?: number; url?: string }[];
const tabId = tabs[0]?.id;
if (typeof tabId !== 'number') {
throw new Error('No active tab found');
}
const title = await chrome.call('debugger.evaluate', {
tabId,
code: 'document.title',
});
const markdown = await chrome.getPageMarkdown(tabId);Core API
connect(opts?)
Opens a TCP connection to the local Chrome RPC bridge and returns a ready-to-use ChromeClient.
Options:
host: TCP host, default127.0.0.1port: TCP port, default9224launch: auto-open Chrome on connection failurelaunchTimeout: max time to wait for Chrome/native host startup
chrome.call(method, ...args)
Calls Chrome APIs by dot-path. Examples:
tabs.querytabs.getwindows.createcookies.getAllstorage.local.get
Special RPC helpers also exist:
debugger.evaluatedebugger.attachdebugger.sendCommanddebugger.getEventsdebugger.detach
chrome.subscribe(event, callback)
Subscribes to Chrome events such as tabs.onUpdated.
chrome.getPageMarkdown(tabId, opts?)
Reads full page HTML via debugger.evaluate, sends it to a local converter service, and returns markdown.
This helper is optional and non-core:
- it requires a converter service, default
http://localhost:8080/convert - it throws on converter failures instead of returning a fallback string
Commands
pnpm --filter @ank1015/llm-extension build
pnpm --filter @ank1015/llm-extension lint
pnpm --filter @ank1015/llm-extension typecheck
pnpm --filter @ank1015/llm-extension test:unit
pnpm --filter @ank1015/llm-extension test:e2e
pnpm --filter @ank1015/llm-extension test:e2e:page-markdown