Show native UI from scripts and agents — dialogs, forms, visualizations, floating widgets, cursor companions. Supports macOS, Linux, and Windows. Use when you need to display HTML to the user, collect input, show a chart, render markdown, or create any visual interaction without a browser.
Show native UI from scripts and agents — dialogs, forms, visualizations, floating widgets, cursor companions. Supports macOS, Linux, and Windows. Use when you need to display HTML to the user, collect input, show a chart, render markdown, or create any visual interaction without a browser.
Glimpse — Native Micro-UI
Glimpse opens a native window with a webview in under 50ms. You write HTML, the user sees it instantly. Bidirectional communication via window.glimpse.send() (webview → Node) and .send(js) (Node → webview). Works on macOS (WKWebView), Linux (WebKitGTK), and Windows (WebView2).
When to use Glimpse:
You need user input beyond yes/no (forms, selections, text input)
You want to show something visual (charts, markdown, images, diffs)
You want to confirm a destructive action with a proper dialog
You want a floating indicator, notification, or companion widget
You need the user to interact with rich content
Import: Always use the absolute path to glimpse.mjs within the installed package — the bare 'glimpseui' specifier fails when scripts run from /tmp or anywhere without node_modules. Resolve ../../src/glimpse.mjs relative to this skill file's directory.
// e.g. import { open, prompt } from 'file:///C:/Users/me/.pi/agent/.../glimpseui/src/glimpse.mjs';
Quick Reference
One-Shot Dialog (prompt)
import { prompt } from'<RESOLVED_PATH>/src/glimpse.mjs';
const answer = awaitprompt(html, {
width: 400, height: 300, // window sizetitle: 'My Dialog', // title bar textframeless: true, // no title bartransparent: true, // see-through background
});
// answer = data from window.glimpse.send(), or null if user closed window
Persistent Window (open)
import { open } from'<RESOLVED_PATH>/src/glimpse.mjs';
const win = open(html, options);
win.on('ready', (info) => {}); // HTML loaded — info has screen, appearance, cursor
win.on('message', data => {}); // user interaction
win.on('info', info => {}); // fresh system info (after getInfo())
win.on('closed', () => {}); // window gone
win.send('document.title = "Hi"'); // eval JS in webview
win.setHTML('<h1>New content</h1>'); // replace HTML
win.info; // last-known system info
win.getInfo(); // request fresh info
win.close(); // close window
All Options
{
width, height, // pixels (default: 800×600)
title, // window title (default: "Glimpse")frameless: true, // no title bar, draggable by backgroundfloating: true, // always on toptransparent: true, // transparent window backgroundclickThrough: true, // mouse passes through windowfollowCursor: true, // window follows mouse cursorfollowMode: 'spring', // 'snap' (instant, default) or 'spring' (elastic)cursorAnchor: 'top-right', // snap point: top-left, top-right, right, bottom-right, bottom-left, leftcursorOffset: {x, y}, // offset from cursor (default: 20, -20)openLinks: true, // open clicked http/https links in default browseropenLinksApp: '/Applications/Google Chrome.app', // optional app bundle pathautoClose: true, // close after first messagenoDock: true, // no dock icon or app switcher entry (macOS)
x, y, // exact screen position
timeout, // for prompt() only — ms before rejecting
}
Fullscreen overlay — Use win.info.screen for exact dimensions, frameless + transparent
Adaptive theming — Read win.info.appearance.darkMode and style to match the OS
Multi-monitor aware — Use win.info.screens to position windows on specific displays
Tips
Always set cursor: pointer on clickable elements
Use autofocus on the primary input field
Add keyboard shortcuts — Enter to confirm, Escape to cancel
For transparent windows, set background: transparent !important on <body> and use a styled container with border-radius for rounded corners
Backdrop blur (backdrop-filter: blur(20px)) makes transparent windows look native and polished
.send() accepts any JS — use it to push live data into the webview (progress, streaming text, state changes)
prompt() returns null when the user closes without sending — always handle this case
Be generous with window height — Content clips without scrollbars if the window is too short. Add 20–30% more height than you think you need. Padding, margins, and button rows add up fast. A form with 2 inputs + buttons needs ~300px minimum, not 200px
Keep windows small — Glimpse is for focused interactions, not full apps
Windows-Specific Tips
Use file:/// for ESM imports — On Windows, Node.js ESM requires file:///C:/... URLs for absolute paths. Bare paths like C:/... fail with ERR_UNSUPPORTED_ESM_URL_SCHEME
Use addEventListener instead of inline onclick — Inline event handlers (onclick="...") can be unreliable in WebView2. Always use document.getElementById('x').addEventListener('click', fn) instead
Use floating: true for sequential prompts — When opening multiple prompt() calls in sequence, subsequent windows may appear behind other windows. Setting floating: true ensures they stay on top