Manifest V3 extension that captures llama.cpp-style streaming metrics from browser UIs that call POST /v1/chat/completions over SSE. Docs: https://mwiater.github.io/llamacpp-ui-metrics-extension/
window.fetch() in page context (no DOM scraping for model output)text/event-stream responses and parses data: chunksAllowed domains management in popupExport Permissions status in popup and can request active-site access for PNG exportDebug logging toggle in popupMetrics tab injected on allowlisted hosts)Per-record fields are best effort and include:
req.has_images, req.images_bytes, per-part image info)delta.reasoning_content appears before completionNotes:
choices[0] only.delta.reasoning_content is absent, reasoning split fields are null/zero as expected.A record is emitted when the stream reaches completion with usable timing data:
choices[0].finish_reason and timings[DONE] marker + last timed chunkIf no timed completion chunk is found, no record is emitted.
Export JSONL exports active session onlyExport PNG captures the current dashboard view (including current filters/theme)Clear all removes all stored records and resets active sessionExport filename format:
llamacpp-metrics_<sessionId>.jsonlOn allowlisted hosts, a Metrics button is injected into the page.
EscLight theme example:

Dark theme example:

The dashboard header includes the following controls:
Dark (theme toggle): switches between light and dark dashboard themes (when dark mode is active, the button label changes to Light)Export JSONL: exports the current active session records as JSONLExport PNG: captures the current dashboard view as a stitched PNG imageRefresh: reloads dashboard stats from the extension's stored session dataMinimize: collapses/hides the overlay without closing the injected dashboard entry pointThe popup includes:
example.com, *.example.com, etc.)Export Permissions panel for PNG export:
Grant access to this site button (when requestable)On all sites
Session start: the active session ID (timestamp-based) used for new captures and exportsRecords: count of captured completion records in the active sessionStorage size: estimated local storage size of the active session dataAllowed domains: host allowlist controlling where capture/dashboard injection is enabledexample.com, localhost:8080, or *.example.comAdd button: adds the typed domain pattern to the allowlistRemove (per row): removes that domain pattern from the allowlistExport Permissions panel: status area for current-tab site access required by dashboard PNG exportActive site line: shows the current tab origin permission pattern (for example https://example.com/*) when availablechrome:// pages)Grant access to this site: requests optional host permission for the active tab's originDebug logging toggle: enables verbose logs/probes across background/content/injected layersImport JSONL: imports records from a JSONL file and overwrites current stored data (after confirmation)Clear all: deletes all stored records and resets the active session (after confirmation)Configure in popup (Allowed domains):
example.comlocalhost:8080*.example.comCapture starts only when current page host matches one of these patterns. Refresh open tabs after allowlist changes.
Load unpacked + Developer mode)chrome://extensionsDeveloper mode (top-right)Load unpackedmanifest.json)POST /v1/chat/completions)Allowed domains (for example localhost:8080)Metrics button/tab on the page to view the dashboardExport JSONL, Export PNG) as neededIf PNG export fails with a capture permission error:
Export PermissionsAlternative: set the extension's Chrome Site Access to On all sites in Chrome's extension details.
A lightweight Node test suite covers high-value pure helper functions across the extension scripts (no Chrome runtime or Playwright setup required).
node --test "tests/*.test.cjs"npm testCurrent suite includes helper coverage for background.js (chain heuristics, dashboard aggregation, scenario comparisons), plus pure helper logic in content.js, injected.js, and popup.js.
This repo now includes typedoc, typescript, and @types/chrome as dev dependencies, plus a tsconfig.json configured for JavaScript + JSDoc (allowJs) and Chrome extension typings.
Install dependencies first:
npm install --save-dev typedoc typescript @types/chromepackage.json: npm installTypeDoc command for this project (current layout):
npm run docs:typedoc:currentnpx typedoc --entryPoints background.js --entryPoints content.js --entryPoints injected.js --entryPoints popup.js --excludeInternalWhat the command does:
npx typedoc: runs the local TypeDoc binary from your project dependencies (with TypeScript compiler support from typescript)--entryPoints ...: explicitly documents the extension's top-level JavaScript files as entry points--excludeInternal: hides symbols marked with @internal (used for implementation-only helpers/state)TypeDoc writes HTML output to ./docs by default (unless you pass --out).
Chrome extension API JSDoc references resolve better when @types/chrome is installed and tsconfig.json includes "types": ["chrome"].
Note: file headers use TypeDoc-friendly @module comments (instead of JSDoc @file / @description) to avoid unknown-tag warnings.
Many helper functions and module-scoped state values are intentionally marked @internal so published docs stay focused on the most useful symbols.
Core extension files:
manifest.jsonbackground.jscontent.jsinjected.jspopup.htmlpopup.jspopup.cssDocumentation and assets:
README.md.screens/ (README screenshots)docs/ (generated TypeDoc HTML output, if created)Development files:
package.jsonpackage-lock.jsontsconfig.jsontests/function-loader.cjstests/helpers.test.cjstests/background-aggregation.test.cjsData is stored locally in browser IndexedDB and exported only when user clicks export.
By default, full prompt/output text is not intentionally persisted as primary payload; captured data focuses on metrics, request shape, and timing/token fields.
choices[0] onlycontent-type includes text/event-stream)fetch(..., { body: JSON.stringify(...) })