Live page
Read-only handle for the active live page tab when the plugin UI is hosted in that context. Prefer hc.livePages for CRUD against saved live page records.
hc.livePage
Available since v2.0.0
Opens or reuses an embedded browser tab and returns a control handle (focus, close, DOM query/evaluate/inject, viewport screenshot).
Requires the browser permission (granted at install/enable). This is independent of Settings → General → Allow script live page access, which only gates request-script hc.livePage. Saving a screenshot with page.screenshot also requires filesystem:write.
Omit url to bind the active browser tab. Pass { reuse: false } to always open a new tab (default reuse is true). New tabs wait for load before the promise resolves.
typescript
export async function activate(hc: PluginContext): Promise<void> {
// Open or reuse a tab at this URL (reuse defaults to true). New tabs wait for load.
const page = await hc.livePage('https://example.com');
// Or always force a fresh tab:
// const page = await hc.livePage('https://example.com', { reuse: false });
// Or bind whatever browser tab is already active (no URL):
// const page = await hc.livePage();
console.log(page.tabId, page.url, page.title, page.canGoBack, page.canGoForward);
await page.focus();
await page.navigate('https://example.com/docs');
await page.reload();
await page.goBack();
await page.goForward();
// Navigation helpers wait for load and refresh url/title/canGoBack/canGoForward.
// First matching element by default; use { all: true } for every match.
const heading = await page.dom.query('h1');
console.log(heading.matchCount, heading.elements);
const links = await page.dom.query('a[href]', { all: true, maxElements: 50 });
console.log(links.elements);
// Expression must return a JSON-serializable value.
const title = await page.dom.evaluate('document.title');
const meta = await page.dom.evaluate(`({
href: location.href,
readyState: document.readyState
})`);
// Inject and run script source in the page main world.
await page.dom.injectScript(`
document.body.dataset.harborProbe = '1';
`);
// Inject CSS; returns an Electron insertion key.
const styleKey = await page.dom.injectStylesheet(`
h1 { outline: 2px solid #32D2E2; }
`);
console.log(styleKey);
// Viewport PNG under the plugin package directory (requires filesystem:write).
const { path } = await page.screenshot('screenshot.png', {});
console.log(path);
// Full-page scroll-and-stitch capture.
const full = await page.screenshot('full.png', { fullPage: true });
console.log(full.path);
// false when the user cancels a leave prompt on a dirty page.
const closed = await page.close();
console.log(closed);
}