Glimpse
Native macOS micro-UI for scripts and agents — sub-50ms WKWebView windows with bidirectional JSON communication
Install / Use
/learn @HazAT/GlimpseREADME
Glimpse
Native micro-UI for scripts and agents. macOS, Linux, and Windows.
https://github.com/user-attachments/assets/57822cd2-4606-4865-a555-d8ccacd31b40
Glimpse opens a native WebView window and speaks a bidirectional JSON Lines protocol over stdin/stdout. No Electron, no browser — just a tiny native binary and a Node.js wrapper.
| Platform | Backend | Requirements | |----------|---------|--------------| | macOS | Swift + WKWebView | Xcode Command Line Tools | | Linux | Rust + GTK4 + WebKitGTK | Rust toolchain, GTK4/WebKitGTK dev packages | | Linux | Chromium CDP (zero-compile) | Any Chromium-based browser | | Windows | .NET 8 + WebView2 | .NET 8 SDK, Edge WebView2 Runtime |
Install
npm install glimpseui
npm install runs a postinstall hook that compiles the native binary for your platform. If the required toolchain isn't found, the build is skipped with a warning — you can compile manually later.
Manual build:
npm run build # auto-detect platform
npm run build:macos # swiftc
npm run build:linux # cargo build --release
npm run build:windows # dotnet publish
Pi Agent Package
pi install npm:glimpseui
Installs the Glimpse skill and companion extension for pi. The companion is a floating status pill that follows your cursor showing what your agents are doing in real-time. It's hidden by default — enable it with the /companion command.
Quick Start
import { open } from 'glimpseui';
const win = open(`
<html>
<body style="font-family: sans-serif; padding: 2rem;">
<h2>Hello from Glimpse</h2>
<button onclick="glimpse.send({ action: 'greet' })">Say hello</button>
</body>
</html>
`, { width: 400, height: 300, title: 'My App' });
win.on('message', (data) => {
console.log('Received:', data); // { action: 'greet' }
win.close();
});
win.on('closed', () => process.exit(0));
Window Modes
Glimpse supports several window style flags that can be combined freely:
| Flag | Effect |
|------|--------|
| frameless | Removes the title bar — use your own HTML chrome |
| floating | Always on top of other windows |
| transparent | Clear window background — HTML body needs background: transparent |
| clickThrough | Window ignores all mouse events |
Common combinations:
- Floating HUD:
floating: true— status panels, agent indicators - Custom dialog:
frameless: true— clean UI with no system chrome - Overlay:
frameless + transparent— shaped widgets that float over content - Companion widget:
frameless + transparent + floating + clickThrough— visual-only overlays that don't interfere with the desktop
Follow Cursor
Attach a window to the cursor. Combined with transparent + frameless + floating + clickThrough, this creates visual companions that follow the mouse without interfering with normal usage.
import { open } from 'glimpseui';
const win = open(`
<body style="background: transparent; margin: 0;">
<svg width="60" height="60" style="filter: drop-shadow(0 0 8px rgba(0,255,200,0.6));">
<circle cx="30" cy="30" r="20" fill="none" stroke="cyan" stroke-width="2">
<animateTransform attributeName="transform" type="rotate"
from="0 30 30" to="360 30 30" dur="1s" repeatCount="indefinite"/>
</circle>
</svg>
</body>
`, {
width: 60, height: 60,
transparent: true,
frameless: true,
followCursor: true,
clickThrough: true,
cursorOffset: { x: 20, y: -20 }
});
The window tracks the cursor in real-time across all screens. followCursor implies floating — the window stays on top automatically.
Platform support: Follow cursor works on macOS and Windows. On Linux with the native backend, it requires Hyprland (via IPC socket). The Chromium CDP backend also supports X11 (via xdotool). Other Wayland compositors without the Chromium backend will emit a warning and silently ignore followCursor.
You can also toggle tracking dynamically after the window is open:
win.followCursor(false); // stop tracking
win.followCursor(true); // resume tracking (snap mode)
win.followCursor(true, undefined, 'spring'); // resume with spring physics
Cursor Anchor Snap Points
Instead of raw pixel offsets, use cursorAnchor to position the window at one of 6 named snap points around the cursor:
top-left top-right
\ /
left -- 🖱️ -- right
/ \
bottom-left bottom-right
A fixed safe zone is automatically applied so the window never overlaps the cursor graphic. cursorOffset can still be used on top of an anchor as a fine-tuning adjustment.
// Window snaps to the right of the cursor with a safe gap
const win = open(html, {
followCursor: true,
cursorAnchor: 'top-right',
transparent: true, frameless: true, clickThrough: true,
});
// Change anchor at runtime
win.followCursor(true, 'bottom-left');
Menu Bar Mode (macOS only)
statusItem() creates a menu bar icon with a popover WebView — click the icon to show/hide your HTML content. The popover auto-closes when clicking outside.
import { statusItem } from 'glimpseui';
const item = statusItem('<h1>Hello from the menu bar</h1>', {
title: '👁',
width: 300,
height: 200,
});
item.on('click', () => console.log('popover toggled'));
// Dynamic updates
item.setTitle('🔴');
item.resize(400, 300);
CLI: glimpse --status-item --title "👁" --width 300 --height 200
Throws on Linux and Windows — menu bar mode is macOS-only.
API Reference
open(html, options?)
Opens a native window and returns a GlimpseWindow. The HTML is displayed once the WebView signals ready.
import { open } from 'glimpseui';
const win = open('<html>...</html>', {
width: 800, // default: 800
height: 600, // default: 600
title: 'App', // default: "Glimpse"
});
All options:
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| width | number | 800 | Window width in pixels |
| height | number | 600 | Window height in pixels |
| title | string | "Glimpse" | Title bar text (ignored when frameless) |
| x | number | — | Horizontal screen position (omit to center) |
| y | number | — | Vertical screen position (omit to center) |
| frameless | boolean | false | Remove the title bar |
| floating | boolean | false | Always on top of other windows |
| transparent | boolean | false | Transparent window background |
| clickThrough | boolean | false | Window ignores all mouse events |
| followCursor | boolean | false | Track cursor position in real-time |
| followMode | string | "snap" | Follow animation: snap (instant) or spring (elastic with overshoot) |
| cursorAnchor | string | — | Snap point around cursor: top-left, top-right, right, bottom-right, bottom-left, left |
| cursorOffset | { x?, y? } | { x: 20, y: -20 } | Pixel offset from cursor (or fine-tuning on top of cursorAnchor) |
| openLinks | boolean | false | Open clicked http/https links in the system browser (macOS only) |
| openLinksApp | string | — | App bundle path for opening links, e.g. "/Applications/Firefox.app" (macOS only) |
| hidden | boolean | false | Start hidden (prewarm mode) — load HTML in the background, reveal with win.show() |
| autoClose | boolean | false | Close automatically after the first message event |
statusItem(html, options?) — macOS only
Creates a menu bar icon with a popover WebView. Returns a GlimpseStatusItem (extends GlimpseWindow).
import { statusItem } from 'glimpseui';
const item = statusItem('<h1>Status</h1>', {
title: '👁', // menu bar icon/text
width: 300,
height: 200,
});
Additional methods:
item.setTitle(title)— Update the menu bar label.item.resize(width, height)— Change the popover dimensions.
Additional events:
click— Emitted when the user clicks the menu bar icon.
Throws Error on Linux and Windows.
prompt(html, options?)
One-shot helper — opens a window, waits for the first message, then closes. Returns Promise<data | null> where data is the first message payload and null means the window was closed without sending.
import { prompt } from 'glimpseui';
const answer = await prompt(`
<h2>Delete this file?</h2>
<button onclick="window.glimpse.send({ok: true})">Yes</button>
<button onclick="window.glimpse.send({ok: false})">No</button>
`, { width: 300, height: 150, title: 'Confirm' });
if (answer?.ok) console.log('Deleted!');
Accepts the same options as open(). Optional options.timeout (ms) rejects the promise if no message arrives in time.
getNativeHostInfo()
Returns the resolved native binary path and platform info:
import { getNativeHostInfo } from 'glimpseui';
const host = getNativeHostInfo();
// { path: '/path/to/glimpse', platform: 'darwin', buildHint: "Run 'npm run build:macos'..." }
supportsFollowCursor() / getFollowCursorSupport()
Runtime capability detection for follow-cursor:
import { supportsFollowCursor, getFollowCursorSupport } from 'glimpseui';
if (supportsFollowCursor()) {
// safe to use followCursor
} else {
const { reason } = getFollowCursorSupport();
console.warn(reason); // e.g. "Wayland follow-cursor is disabled without a compositor-specific backend"
}
GlimpseWindow
GlimpseWindow extends EventEmitter.
Events
| Event | Payload | Description |
|-------|---------|-------------|
| ready | info: object | WebView loaded — includes screen, appearance, and cursor info |
| message | data: object | Message sent from the page via window.glimpse.send(data) |
| info | info: object | Fresh system info (response to .getInfo()) |
| click | — | Menu bar icon clicked (
