Last reviewed: 2026-08-13
Learning Copilot is a Manifest V3 browser extension that explains text selected on a webpage. It supports Google Gemini, OpenAI, Anthropic, and user-configured local LLM endpoints. Users manage provider credentials, model overrides, and explanation personas on the extension's options page.
Webpage
-> WXT content script detects a text selection
-> Shadow DOM React UI displays the action bar/result window
-> validated runtime port sends an explicit Explain or Cancel request
-> background service worker reads local settings
-> selected provider streams an answer with an abort signal tied to the port
-> runtime port streams chunks back to the webpage UI
Options page
-> React settings/persona editor
-> Test Key sends the current provider, credential, and selected model to the background worker
-> provider model endpoint verifies authentication and model access
-> WXT storage wrapper
-> chrome.storage.local
| Path | Role |
|---|---|
entrypoints/content.tsx |
Runs on matching webpages, detects the exact text selection, mounts the Shadow DOM UI, and opens a streaming runtime port. |
entrypoints/background.ts |
Owns provider generation and key/model-validation requests in the Manifest V3 service worker and returns structured result/error messages. |
entrypoints/options/ |
Provides onboarding, provider configuration, API-key/model testing, debug mode, and custom-persona management. |
| Path | Role |
|---|---|
utils/storage.ts |
Defines typed settings, defaults, and the chrome.storage.local-backed WXT storage item. |
utils/models.ts |
Defines the reviewed low-cost default model for each cloud provider so provider requests and UI hints stay synchronized. |
utils/llm-providers.ts |
Builds prompts and implements generation plus credential/model validation for Gemini, OpenAI, Anthropic, and local providers. |
utils/runtime-messages.ts |
Defines typed runtime contracts, request-size limits, and boundary validators for provider tests and streamed explanations. |
utils/presets.ts |
Defines built-in explanation styles. |
components/ActionBar.tsx |
Renders actions shown beside selected text. |
components/ResultTooltip.tsx |
Renders streamed Markdown output in a draggable, resizable panel. |
assets/style.css |
Supplies Tailwind v4 theme tokens and shared content/options-page styling. |
mainis the accepted Chrome Web Store baseline;devis the integration branch for the next release. Version 0.8.1 remains stable onmainwhile subsequent changes are developed and validated ondev.- A release is promoted from
devtomainonly after its version, documentation, automated checks, manual Chrome smoke test, live-provider checks, Store disclosures, and ZIP artifact have been reviewed together. - WXT generates the Manifest V3 extension from
wxt.config.tsand the files underentrypoints/. npm run compileperforms a TypeScript no-emit check.npm run buildwrites an unpacked Chrome build to.output/chrome-mv3/.npm run zipcreates the Chrome Web Store upload archive.- The package version in
package.jsonbecomes the extension version; keep the root package metadata inpackage-lock.jsonsynchronized.
| Access | Status | Evidence and purpose |
|---|---|---|
storage |
Required | utils/storage.ts stores provider configuration, API keys, prompt preferences, and personas in local extension storage. |
| Provider host permissions | Required and allowlisted | The background worker can reach only the Google Gemini, OpenAI, and Anthropic API origins plus HTTP(S) on localhost and 127.0.0.1. |
Content-script matches: <all_urls> |
Required by the current design | entrypoints/content.tsx must detect a selection on the page where the user is reading. |
scripting |
Removed in v0.8.1 | No chrome.scripting or browser.scripting call exists. WXT declares the content script statically. |
activeTab |
Removed in v0.8.1 | No tab API or action-triggered temporary host access exists. Static content-script access does not use this permission. |
When a selection is made, the content script reads only the exact selection so it can display the action bar. It does not read the page URL, title, surrounding content, cookies, form data, or browsing history. When the user clicks Explain, the selected text and configured prompt instructions are sent through the service worker directly to the chosen model provider. When the user clicks Test Key, only the current credential and selected model identifier are sent to that provider to verify access; no website content or prompt is included. API keys remain in local extension storage unless the user is testing unsaved form values and are sent only as authentication to the cloud provider selected by the user.
- The repository began as a single v0.8.0 commit. It now has runtime-boundary tests and a least-privilege GitHub Actions workflow, but provider parsers still need fixture-based coverage.
- Provider output is streamed over a long-lived extension runtime port. Closing the UI, stopping generation, changing the selection, or replacing a request aborts the active fetch and stale streams are ignored.
- The Settings page can verify the entered cloud key against the effective default or custom model and displays a success state or the provider's error reason. Local mode performs a minimal one-token model request and labels the action Test Connection.
- Gemini, OpenAI, Anthropic, and local-provider streaming parsers are implemented. The reviewed efficiency-first cloud defaults are
gemini-3.5-flash-lite,gpt-5.6-lunawith reasoning disabled, andclaude-haiku-4-5. - Provider host permissions are allowlisted. The local-provider URL is validated at request time and permits only HTTP(S) on
localhostor127.0.0.1without embedded credentials. - The toolbar action opens the options page without requesting an additional permission.
- Production-package verification rejects unexpected API/host permissions, wrong icon dimensions, source maps, starter assets, and common remote/evaluated-code patterns.
- Explanation requests accept at most 20,000 selected characters and a 200-character style identifier; malformed runtime messages fail closed.
- Gemini credentials are sent in the
x-goog-api-keyheader rather than embedded in the request URL. - AI Markdown renders without raw HTML support; generated links open in a separate context with opener access disabled.
- The in-page UI supports Compact, Balanced, and Large scale preferences. The result panel can shrink to 220 pixels and its body typography interpolates with the current width while retaining a 12-pixel floor.
- Chrome's built-in PDF viewer does not expose its selection as a regular webpage DOM, so the content-script workflow supports arXiv HTML pages but not selections made inside Chrome's PDF viewer.
Version 0.8.1 passed Chrome Web Store review and is the stable baseline. Its source and production-package audit included:
npm run compilepassed.npm testpassed eight runtime-boundary and responsive-sizing tests.npm auditreported zero known dependency vulnerabilities after upgrading WXT and the build toolchain.npm run buildproduced.output/chrome-mv3/.- The generated manifest contains only
storageinpermissions; neitherscriptingnoractiveTabis present. npm run zipproduced.output/learning-copilot-0.8.1-chrome.zip.npm run verify:storeenforces the reviewed production-manifest and package constraints.- The options page was rendered at the default desktop viewport and at 390×844; its guide and provider setup remained usable without horizontal overflow.
- The release completed its required package audit, manual Chrome smoke test, live-provider checks, and Chrome Web Store review.
- API keys in
chrome.storage.localare protected by the browser profile boundary, not an encrypted credential vault. - Selected text can contain prompt-injection instructions. The extension isolates code execution and does not enable raw HTML, but it cannot guarantee the factual integrity of provider output.