ADR-0005: A browser extension that talks to portcheck through native messaging¶
- Status: Accepted
- Date: 2026-10-20
Context¶
Developers often meet a port problem in the browser first: localhost:3000 shows
"This site can't be reached", or a page loads from a server they forgot was running.
The browser can't tell which process serves a port, or whether anything listens at
all. ADR-0004 left a browser extension as an optional later phase.
A browser extension can only reach a local program through native messaging: the browser starts a program registered for the extension and exchanges JSON messages with it over stdin/stdout, each prefixed with its length as a 32-bit integer in native byte order. The program is registered with a small manifest file (a registry entry on Windows) that lists which extension IDs may start it.
Decision¶
- Chromium browsers first: Chrome, Edge, Chromium and Brave, with Manifest V3. Firefox uses a different manifest format and can follow later.
- portcheck is the native host. When a browser starts it with an extension origin
(
chrome-extension://<id>/) as its first argument, portcheck serves native messages instead of parsing a command line. No second program is installed. - A fixed allowlist of operations:
version,list(listening sockets),check(one port), andkill(one PID). Each runs the matching portcheck command in-process with--jsonand returns its schema v1 output, so the extension sees exactly what the CLI prints, andkillkeeps all its safety guards. Because the browser is the host's parent process, portcheck refuses to stop the browser itself. Commands that run programs or touch other hosts (run,scan,wait) are not reachable. portcheck browser installwrites the host manifest for the browsers it finds (per user, no administrator rights), allowing only portcheck's extension IDs;uninstallremoves it andstatusreports it.- The extension is a thin client in
extensions/browser/: strict TypeScript, esbuild, Vitest for logic, and an end-to-end test that loads it into a real Chromium with Playwright and checks the badge for a real local server. Its ID is pinned with the manifestkey, so the host manifest can name it.
Consequences¶
- ✅ One implementation of port logic and safety guards for the CLI, the TUI, VS Code and the browser.
- ✅ The browser can't use portcheck for anything beyond the four operations.
- ⚠️ Users run
portcheck browser installonce (the extension tells them to). - ⚠️ Each message starts a short-lived portcheck process. That costs a few milliseconds on macOS (ADR-0003) and is only done for local tabs.
- ⚠️ Extension stores assign their own IDs; each store's ID has to be added to the allowed list when it's published there. The Chrome Web Store also charges a one-time developer fee.