Skip to content

xiaohuzai/browsa

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

182 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

browsa

browsa = browser side panel AI. Side-panel AI chat for any webpage โ€” talk to your LLM agent about what you're reading.

browsa is a Chrome / Edge extension (Manifest V3) that opens a chat panel next to whatever tab you're on, attaches the page content, and streams replies from any OpenAI-compatible API.

[Web page]  โ†’  [browsa side panel]  โ†’  [your LLM / agent]  โ†’  streaming reply

Install (unpacked)

  1. Clone or download this repo.
  2. Open chrome://extensions (or edge://extensions).
  3. Enable Developer mode.
  4. Click Load unpacked โ†’ select the browsa/ directory.
  5. Press Ctrl+Shift+H (or click the toolbar icon) to open the side panel.
  6. Click โš™ Settings to configure a provider.

Build & package

npm install          # first time only
npm test             # run 460+ unit tests
npm run package      # โ†’ browsa-v<version>.zip

To bump the version before packaging:

npm version patch    # bug fix:      0.24.0 โ†’ 0.24.1
npm version minor    # new feature:  0.24.0 โ†’ 0.25.0
npm run package

npm version automatically syncs the version to both package.json and manifest.json.


Configure a provider

browsa splits providers into two categories:

  • Agent Providers โ€” full agent backend with tool execution (bash, file ops, web search, etc.). The AI can actually do things on the server side.
  • LLM Providers โ€” plain language model endpoint for conversation only. Model ID is required.

Use the Ping button in Settings to verify connectivity and auto-detect capabilities. The provider status (reachable / unreachable) is shown in the sidebar dropdown.


๐Ÿค– Hermes Agent

Hermes is a self-hosted AI agent with built-in tools (web search, terminal, file ops, memory, skills). browsa uses its /v1/runs API โ€” richer than plain chat completions (tool progress, approval/clarification prompts for dangerous actions) โ€” with a stable X-Hermes-Session-Id per conversation so Hermes can maintain session continuity server-side. Falls back to plain /v1/chat/completions automatically if a Hermes deployment doesn't advertise /v1/runs support.

1. Install Hermes

pip install hermes-agent   # or follow the official install guide

2. Enable the API server โ€” add to ~/.hermes/.env:

API_SERVER_ENABLED=true
API_SERVER_KEY=your-secret-key

3. Start Hermes

hermes gateway
# โ†’ [API Server] API server listening on http://127.0.0.1:8642

4. Configure browsa โ€” open โš™ Settings, select the hermes provider:

Field Value
Base URL http://<server-ip>:8642
API Key value of API_SERVER_KEY

5. Ping to verify. /v1/runs support is auto-detected and enabled automatically.


๐Ÿค– Claude Code (via claude-code-openai-wrapper)

This setup runs the real Claude Code CLI on your server โ€” with its full tool suite (bash, file read/write, etc.) โ€” and exposes it as a standard OpenAI-compatible HTTP API.

Prerequisites: claude CLI installed and authenticated on the server (claude auth login or ANTHROPIC_API_KEY set).

1. Install uv (if not already installed)

curl -LsSf https://astral.sh/uv/install.sh | sh

2. Clone and install the wrapper

git clone https://github.com/RichardAtCT/claude-code-openai-wrapper
cd claude-code-openai-wrapper
uv python install 3.11
uv venv --python 3.11
source .venv/bin/activate
uv pip install -e .

3. Configure โ€” create claude-code-openai-wrapper/.env:

# Directory where Claude Code will operate (your project root)
CLAUDE_CWD=/path/to/your/project

# A password you make up โ€” browsa uses this as the API Key
API_KEYS=make-up-any-password-here

# Auth method โ€” pick one:
CLAUDE_AUTH_METHOD=cli          # use existing `claude auth login` session
# ANTHROPIC_API_KEY=sk-ant-...  # or direct API key

IS_SANDBOX=1     # required if running as root
MAX_TURNS=50     # max tool-call turns per request (default 10)

4. Start the wrapper

source .venv/bin/activate
uvicorn src.main:app --host 0.0.0.0 --port 8000

# To keep running in background:
tmux new -s claude-wrapper
# ... start as above, then Ctrl+B D to detach

5. Configure browsa โ€” open โš™ Settings, select the claude-code provider:

Field Value
Base URL http://<server-ip>:8000
API Key value of API_KEYS

Claude Code is an agent provider, so there's no Model ID field to configure โ€” the wrapper picks the model server-side.

Note: Claude Code operates in CLAUDE_CWD. Set it to your project root so Claude can read and write your actual files.


๐Ÿ’ฌ OpenAI-compatible LLM

Any endpoint that speaks /v1/chat/completions โ€” OpenAI, Anthropic, Ollama, Groq, LiteLLM, etc.

Configure browsa โ€” open โš™ Settings, configure the OpenAI-compatible provider:

Field Value
Base URL e.g. https://api.openai.com
API Key your API key
Model ID required โ€” e.g. gpt-4o, claude-sonnet-4-6

Ping validates connectivity and verifies the model ID is accepted by the server.


Attaching page context

Click ๐Ÿ“Ž in the composer to attach the current page. browsa supports two attachment modes selectable in the composer footer:

Mode What gets sent
Auto Tries Mozilla Readability first (clean article text, ~5โ€“30 KB), falls back to DOM tree, then full body.innerText
๐Ÿ“ท Screenshot PNG of the visible tab โ€” for multimodal models or visual content

Attaching a PDF (or a page that turns out to be one) is automatic โ€” no separate mode to pick. browsa tries pdf-inspector-wasm first (full layout reconstruction โ€” tables, headings, columns โ€” running client-side, nothing uploaded), falls back to plain pdf.js text extraction if that's unavailable or the PDF turns out to be a scanned/image-only page with no text layer, and as a last resort attaches just the PDF's URL so your agent can fetch and read it with its own tools.

For text selection, highlight text on the page and use the floating toolbar or right-click context menu (Ask / Explain / Translate / Summarize). The selection is sent automatically without needing to click ๐Ÿ“Ž.


Supported sites (XHR interception)

For sites where Readability produces poor results, browsa intercepts the browser's own API calls and extracts structured content โ€” no signing, no re-auth, just observing what the page already fetched. Open the page and let it fully load before sending your first message.

Site Content extracted
YouTube Title, transcript, chapters, description, author, view/like counts
Bilibili Title, AI summary, subtitle/transcript, audio URL, video stats
ๅฐ็บขไนฆ Note title, description, tags, images, top comments, stats
ๆŽ˜้‡‘ Full article Markdown source
็ŸฅไนŽ ไธ“ๆ  article or top 3 answers to a question
Twitter / X Tweet text, author, engagement stats
้›ช็ƒ Stock quote or post content
ๅฐๅฎ‡ๅฎ™ Podcast episode title, description, show notes
ๅพ—ๅˆฐ Article text
ๆžๅฎขๆ—ถ้—ด Article text

Features

Chat

  • Streaming replies โ€” tokens appear as they arrive; click โœ• or press Esc to stop
  • Think blocks โ€” <think> / <thinking> content shown in a collapsible block, auto-collapsed after streaming
  • Markdown rendering โ€” full GFM: tables, code blocks, lists, inline formatting
  • Syntax highlighting โ€” 40+ languages via highlight.js
  • LaTeX โ€” inline $...$ and display $$...$$ via KaTeX, offloaded to a Web Worker for formula-heavy messages so the panel doesn't jank
  • Mermaid diagrams โ€” rendered inline with zoom / pan / copy source / export SVG toolbar; sequence diagrams with a semicolon in dialogue text (e.g. embedded SQL) render correctly via an automatic escape-and-retry
  • ECharts charts โ€” ```echarts code blocks rendered inline with a resize-aware toolbar
  • Markmap mind maps โ€” ```markmap code blocks (a plain Markdown heading/list outline) rendered inline as an interactive, zoomable mind map with the same zoom/reset/copy/export toolbar as Mermaid/ECharts; no dedicated button needed โ€” just ask for a mind map/outline and the model knows the format
  • Diff highlighting โ€” diff code blocks color + green and - red
  • Detail thread ("็ป†่Š") โ€” select any text inside a reply to open a scoped side conversation about just that excerpt, without touching the main history. Fully resizable, closes and discards everything on โœ•
  • Edit & resend โ€” click โœ on any user message to edit and re-send
  • Copy response โ€” click โŽ˜ to copy the full raw Markdown
  • Timestamps โ€” hover any message to see send time

History & sessions

  • Session history โ€” save the current conversation as a named session, browse and restore past sessions from the ๐Ÿ• drawer
  • Export โ€” export any session as a Markdown file
  • In-conversation search โ€” Ctrl+F to search across all messages with prev/next navigation
  • Multi-select โ€” select multiple messages for batch deletion
  • Undo clear โ€” clearing history shows an undo option for 5 seconds

Input

  • Image attachment โ€” drag-and-drop or paste images directly into the composer (for multimodal models)
  • Slash commands โ€” type / to see completions; see list below
  • Quick actions โ€” one-click Summarize / Key Points / Explain / โ†’ ไธญๆ–‡ / Outline buttons above the composer
  • Floating selection toolbar โ€” appears when you highlight text on any page: Ask ยท Explain ยท โ†’ ไธญๆ–‡ ยท Summarize
  • Right-click context menu โ€” browsa โ€บ Ask / Explain / Translate / Summarize on selected text

Settings

  • Domain rules โ€” per-URL-pattern extra system prompt (e.g. always respond in English on github.com)
  • Mask rules โ€” regex-based content redaction before sending to the LLM (e.g. strip phone numbers)
  • Reply language โ€” force replies in a specific language regardless of page language
  • Max text chars โ€” cap how much page content is sent per turn
  • Auto-summarize long attachments โ€” when an attached page or video transcript exceeds the threshold (default: 40,000 chars), browsa chunks it, summarizes each chunk in parallel using the configured provider, and merges the result once in the background โ€” the attachment response returns immediately with no latency, and subsequent turns use the compressed version instead of re-sending the full text every time. Timestamp markers in video transcripts ([mm:ss]) are explicitly preserved so clickable seek links keep working. Fails open: any error silently keeps the original text.
  • llms.txt โ€” optionally fetch <origin>/llms.txt before each chat for site-specific LLM instructions

Slash commands

Type / in the composer to see autocomplete. All commands can be followed by additional instructions:

/summarize focus on the methodology
/translate keep technical terms in English
Command Prompt sent to LLM
/summarize 3โ€“5 bullet summary
/translate Translate to Chinese
/rewrite More concise rewrite, keeping all facts
/explain Explain for a beginner in simple language
/outline Nested outline of headings only
/keypoints Top 5 takeaways
/prompt Show the current active system prompt (not sent to LLM)

Keyboard shortcuts

Shortcut Action
Ctrl+Shift+H Open / close side panel
Enter Send message (configurable in Settings)
Shift+Enter New line
Ctrl+K Clear history (with undo)
Ctrl+/ Cycle context mode (Auto โ†” Screenshot)
Ctrl+F Open in-conversation search
Esc Cancel stream / close search / close drawer

How it works

  • background.js โ€” MV3 service worker. Single handle() message router for all extension messages โ€” still the single dispatcher, but the two biggest cases (CHAT, SUBCHAT) delegate to lib/handlers/. Manages site XHR caches (keyed by tabId), streaming via per-turn browsa-chat/browsa-subchat ports, mid-stream tab switching via streamState (lib/state.js), and fires off a fire-and-forget attachment auto-summarize pass (lib/handlers/attach-summarizer.js) when a page/video attachment exceeds the configured length threshold.
  • sidepanel.js โ€” Chat UI orchestrator: init/send/history/approval-clarify cards/screenshot crop. The Markdown/Mermaid/Markmap/KaTeX/ECharts rendering pipeline, sessions drawer, in-conversation search, multi-select, and detail-thread ("็ป†่Š") side conversations are each their own module under lib/sidepanel/.
  • lib/sidepanel/render.js โ€” marked + DOMPurify + KaTeX + Mermaid + ECharts + Markmap + highlight.js pipeline. Streaming deltas are smoothed via reveal-pacer.js (a thin wrapper around the vendored markstream-core package); KaTeX rendering for the final per-message render offloads formula-heavy messages to a Web Worker (katex-worker-client.js/katex.worker.js), falling back to synchronous rendering below a small-batch threshold or on worker failure; Mermaid's SVG output is sanitized (sanitizeMermaidSvg, from the vendored stream-markdown-parser package) and sequence-diagram parse failures auto-retry with problem semicolons escaped (mermaid-utils.js). All three diagram vendor bundles (Mermaid/ECharts/Markmap) are speculatively preloaded (preloadChartVendors()) the moment a turn starts, so the first diagram in a session doesn't pay a multi-MB cold-load penalty right when it needs to render.
  • lib/page-extractor.js โ€” Injects Readability + Turndown into the page MAIN world for reader mode. For SPA sites, uses the XHR cache from the matching content script.
  • lib/sidepanel/pdf-extractor.js โ€” PDF attachment pipeline: tries pdf-inspector-wasm (full layout/table/heading reconstruction) in a dedicated Worker first, falls back to plain-text pdf.js extraction, and quality-gates both (empty/scanned results don't get treated as success) before the caller falls back further to a plain URL attachment.
  • lib/openai-client.js โ€” Fetch-based SSE streaming client. Supports /v1/chat/completions (all providers) and /v1/runs (Hermes โ€” approval/clarification/tool-progress events, auto-detected).
  • lib/storage.js โ€” chrome.storage.local wrapper. Global flat conversation history (not per-tab), session management, mask rules.
  • Content scripts (lib/content-scripts/) โ€” Run at document_start in MAIN world. Wrap window.fetch and XMLHttpRequest.prototype to observe SPA API calls and forward structured data to the background.

Project structure

browsa/
โ”œโ”€โ”€ manifest.json
โ”œโ”€โ”€ background.js                      # service worker + message router (dispatcher only)
โ”œโ”€โ”€ sidepanel.{html,css,js}            # chat UI orchestrator
โ”œโ”€โ”€ options.{html,css,js}              # settings page
โ”œโ”€โ”€ lib/
โ”‚   โ”œโ”€โ”€ constants.js                   # shared constants (PAGE_CONTEXT_PREFIX, โ€ฆ)
โ”‚   โ”œโ”€โ”€ state.js                       # shared stream/approval state Maps (used by background.js)
โ”‚   โ”œโ”€โ”€ openai-client.js               # SSE streaming client
โ”‚   โ”œโ”€โ”€ page-extractor.js              # content extraction + site synthesizers
โ”‚   โ”œโ”€โ”€ storage.js                     # chrome.storage wrapper + session mgmt
โ”‚   โ”œโ”€โ”€ handlers/
โ”‚   โ”‚   โ”œโ”€โ”€ chat-handler.js            # CHAT case body
โ”‚   โ”‚   โ”œโ”€โ”€ subchat-handler.js         # SUBCHAT / SUBCHAT_ABORT case bodies
โ”‚   โ”‚   โ””โ”€โ”€ attach-summarizer.js       # auto-compress long page/video attachments
โ”‚   โ”œโ”€โ”€ markdown-chunker.js            # structure-aware truncation + chunking (fences/tables never split)
โ”‚   โ”œโ”€โ”€ sidepanel/                     # sidepanel.js's feature modules
โ”‚   โ”‚   โ”œโ”€โ”€ render.js                  # marked+DOMPurify+KaTeX+Mermaid+ECharts pipeline
โ”‚   โ”‚   โ”œโ”€โ”€ reveal-pacer.js            # smooth-reveal wrapper around vendored markstream-core
โ”‚   โ”‚   โ”œโ”€โ”€ katex-threshold.js         # "worth offloading to a worker?" heuristic
โ”‚   โ”‚   โ”œโ”€โ”€ katex-worker-client.js     # batches formulas to katex.worker.js, sync fallback
โ”‚   โ”‚   โ”œโ”€โ”€ katex.worker.js            # dedicated KaTeX rendering Worker
โ”‚   โ”‚   โ”œโ”€โ”€ mermaid-utils.js           # sequence-diagram semicolon fix + preview-height estimate
โ”‚   โ”‚   โ”œโ”€โ”€ pdf-extractor.js           # PDF attach: wasm-primary/pdf.js-fallback orchestration
โ”‚   โ”‚   โ”œโ”€โ”€ pdf-inspector-worker-client.js # pdf-inspector-wasm Worker client (sticky-failure, timeoutโ†’null)
โ”‚   โ”‚   โ”œโ”€โ”€ pdf-inspector.worker.js    # dedicated Worker running pdf-inspector-wasm's processPdf()
โ”‚   โ”‚   โ”œโ”€โ”€ sessions-ui.js             # sessions drawer
โ”‚   โ”‚   โ”œโ”€โ”€ multiselect.js             # bulk-delete mode
โ”‚   โ”‚   โ”œโ”€โ”€ msg-search.js              # Ctrl+F in-conversation search
โ”‚   โ”‚   โ”œโ”€โ”€ detail-thread.js           # "select text โ†’ ็ป†่Š" side conversation
โ”‚   โ”‚   โ”œโ”€โ”€ icons.js                   # ICONS SVG map
โ”‚   โ”‚   โ””โ”€โ”€ ui-utils.js                # $, escM, sendMessage, toast/confirm, card helpers
โ”‚   โ”œโ”€โ”€ content-scripts/               # MAIN-world XHR interceptors + ISOLATED-world toolbar
โ”‚   โ”‚   โ”œโ”€โ”€ selection-toolbar.js       # floating toolbar (Shadow DOM)
โ”‚   โ”‚   โ”œโ”€โ”€ xhs-content-script.js      # ๅฐ็บขไนฆ XHR interceptor
โ”‚   โ”‚   โ”œโ”€โ”€ youtube-content-script.js  # YouTube player API interceptor
โ”‚   โ”‚   โ”œโ”€โ”€ bilibili-content-script.js # Bilibili video API interceptor
โ”‚   โ”‚   โ”œโ”€โ”€ juejin-content-script.js   # ๆŽ˜้‡‘ article interceptor
โ”‚   โ”‚   โ”œโ”€โ”€ zhihu-content-script.js    # ็ŸฅไนŽ article / Q&A interceptor
โ”‚   โ”‚   โ”œโ”€โ”€ twitter-content-script.js  # Twitter/X GraphQL interceptor
โ”‚   โ”‚   โ”œโ”€โ”€ xueqiu-content-script.js   # ้›ช็ƒ stock/post interceptor
โ”‚   โ”‚   โ”œโ”€โ”€ xiaoyuzhou-content-script.js # ๅฐๅฎ‡ๅฎ™ podcast interceptor
โ”‚   โ”‚   โ”œโ”€โ”€ dedao-content-script.js    # ๅพ—ๅˆฐ interceptor
โ”‚   โ”‚   โ””โ”€โ”€ geektime-content-script.js # ๆžๅฎขๆ—ถ้—ด interceptor
โ”‚   โ””โ”€โ”€ vendor/                        # bundled third-party libs
โ”‚       โ”œโ”€โ”€ Readability.iife.js
โ”‚       โ”œโ”€โ”€ Turndown.iife.js
โ”‚       โ”œโ”€โ”€ marked.bundle.js
โ”‚       โ”œโ”€โ”€ purify.bundle.js
โ”‚       โ”œโ”€โ”€ katex.bundle.js
โ”‚       โ”œโ”€โ”€ highlight.bundle.js
โ”‚       โ”œโ”€โ”€ mermaid.bundle.js
โ”‚       โ”œโ”€โ”€ echarts.bundle.js
โ”‚       โ”œโ”€โ”€ markmap-lib.bundle.js       # Markdown โ†’ mind map tree transformer
โ”‚       โ”œโ”€โ”€ markmap-view.bundle.js      # d3-zoom mind map SVG renderer
โ”‚       โ”œโ”€โ”€ markstream-core.bundle.js   # streaming-reveal pacing controller
โ”‚       โ”œโ”€โ”€ stream-markdown-parser.bundle.js # Mermaid SVG sanitizer
โ”‚       โ”œโ”€โ”€ pdf.bundle.js               # pdf.js โ€” fallback PDF text extraction
โ”‚       โ”œโ”€โ”€ pdf.worker.bundle.js        # pdf.js's own Worker
โ”‚       โ”œโ”€โ”€ pdf_inspector_wasm.js       # pdf-inspector-wasm glue (wasm-bindgen)
โ”‚       โ””โ”€โ”€ pdf_inspector_wasm_bg.wasm  # pdf-inspector-wasm binary โ€” primary PDF extraction
โ”œโ”€โ”€ _locales/{en,zh_CN}/
โ”œโ”€โ”€ icons/
โ”œโ”€โ”€ build/
โ”‚   โ”œโ”€โ”€ build.mjs                      # esbuild vendor bundler
โ”‚   โ””โ”€โ”€ package.mjs                    # distribution zip builder
โ”œโ”€โ”€ test/                              # node:test unit tests (576 tests)
โ””โ”€โ”€ check-compat.sh                    # MV3 / static compatibility check

Browser compatibility

Browser Status Notes
Chrome 114+ โœ… Supported Primary target
Edge 114+ โœ… Supported Identical install
Brave 1.56+ โœ… Should work Same Chromium surface
Firefox โŒ Not supported No side_panel API

Security

  • API keys are stored in chrome.storage.local on your machine only โ€” never sent anywhere except your configured baseUrl.
  • PDF attachments are parsed entirely client-side (WebAssembly + pdf.js, both running in the side panel) โ€” the file's bytes are never uploaded anywhere, only the extracted text is sent to your configured provider.
  • LLM replies are sanitized with DOMPurify before rendering, including a hook that blocks data:image/svg+xml sources (which can carry their own <script>/event handlers) while still allowing normal bitmap data: images.
  • Mermaid diagram SVG output is sanitized before insertion (strips <script>, event-handler attributes, and dangerous URLs) โ€” needed because Mermaid's securityLevel:'loose' mode, required for KaTeX math inside diagram labels, otherwise permits arbitrary HTML through.
  • Content scripts only observe network requests; they never modify or block them.

License

MIT

About

No description, website, or topics provided.

Resources

License

Stars

4 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors