SuperAPI AI Directory

hermes-browser-extension

General & other

View repository

Updated 10-16 02:30

About this skill

hermes-browser-extension

Skill by ara.so — Hermes Skills collection.

What it does

Hermes Browser Extension is a Chrome/Edge/Chromium side panel that connects active web page context to a Hermes Agent runtime (local or remote). It is not a standalone chatbot—it's a browser interface for the real Hermes Gateway/API server, accessing your configured models, tools, skills, sessions, memory, and MCP servers.

Key capabilities:

  • Side panel UI powered by Chrome Side Panel API (MV3)
  • Connects to local (http://127.0.0.1:8642) or remote Hermes API server
  • Syncs providers, models, profiles, skills, sessions, and capabilities from Hermes
  • Captures and sends active tab context (title, URL, readable text, selected text, metadata, headings, links, forms, buttons)
  • Supports per-tab or global side panel mode
  • Streams responses from Hermes
  • Voice dictation via Hermes STT or browser speech fallback
  • Read-only context capture (no browser control, no form submission)
  • Multiple themes (Nous, Midnight, Ember, Mono, Cyberpunk, Slate) and light/dark modes

Installation

1. Clone and build

git clone https://github.com/abundantbeing/hermes-browser-extension.git
cd hermes-browser-extension
npm install
npm run build

The extension builds to dist/.

2. Load unpacked in browser

  1. Open chrome://extensions or edge://extensions
  2. Enable Developer mode
  3. Click Load unpacked
  4. Select the dist/ folder (not repo root, not extension/)
  5. Pin the Hermes extension icon and click to open side panel

After code changes, run npm run build and click Reload on the extension card.

3. Verify installation

# Check that dist/ contains manifest.json with version 0.1.6+
cat dist/manifest.json | grep version

Configuration

Local API server (recommended default)

On the machine running Hermes, edit ~/.hermes/.env:

API_SERVER_ENABLED=true
API_SERVER_HOST=127.0.0.1
API_SERVER_PORT=8642
API_SERVER_KEY=your-secret-key-here
API_SERVER_CORS_ORIGINS=chrome-extension://your-extension-id

Find your extension ID at chrome://extensions (looks like abcdefghijklmnopqrstuvwxyz123456).

Start/restart Hermes Gateway:

hermes gateway run

Verify API server is reachable:

curl http://127.0.0.1:8642/health
curl -H "Authorization: Bearer your-secret-key-here" http://127.0.0.1:8642/v1/models

Connect extension to local API

In the extension side panel:

  1. Click Connect to Hermes
  2. If approval flow is available, approve locally in Hermes Desktop/gateway
  3. Otherwise, click Manual setup → Local gateway
  4. Gateway URL: http://127.0.0.1:8642
  5. API Key: paste your API_SERVER_KEY or scoped browser token
  6. Click Test connection, then Save settings
  7. Navigate to a normal webpage and test: Summarize this page in one sentence.

Remote API server

For remote Hermes (same LAN, Tailscale, VPN), bind to reachable interface:

API_SERVER_ENABLED=true
API_SERVER_HOST=0.0.0.0
API_SERVER_PORT=8642
API_SERVER_KEY=your-secret-key-here
API_SERVER_CORS_ORIGINS=chrome-extension://your-extension-id

Security: Use private network/VPN with HTTP, or put behind HTTPS reverse proxy. Never expose Hermes API server naked to public internet.

Example URLs:

http://192.168.1.50:8642
http://hermes-desktop.local:8642
https://hermes.example.com

In extension:

  1. Choose Remote gateway
  2. Paste remote URL (include http:// or https://)
  3. Paste API key/browser token
  4. Click Test connection

Remote dashboard mode (no API server)

If you only expose the OAuth-gated Hermes dashboard (no API server):

  1. Select Remote
  2. Enter dashboard https:// URL
  3. Leave API key blank
  4. Open dashboard URL in normal tab and sign in (keep tab open)
  5. Extension mints WebSocket ticket from signed-in tab
  6. Click Test connection (opens socket and loads models)

Limitations: image attachments inline-only, skills/profiles unavailable (REST-only).

Usage patterns

Basic prompting with page context

# Side panel captures active tab automatically
Summarize this page
Explain the main concept here
What are the key action items on this page?

Quick commands

The extension includes built-in quick commands:

/summarize - Summarize active page
/explain - Explain main concepts
/rewrite - Rewrite or improve content
/tabs - Analyze all open tabs
/action-items - Extract action items

Context scope control

Click the context menu in composer header to choose:

  • Chat only - no browser context attached
  • Follow active tab - context auto-updates when you switch tabs
  • Page only - pin to specific tab
  • Choose tabs - select which open tabs to include

Voice dictation

Click microphone icon in composer:

  • Uses Hermes audio transcription if available
  • Falls back to browser speech recognition otherwise

What Hermes saw

After each turn, expand "What Hermes saw" to inspect:

  • Active tab title, URL
  • Selected text (if any)
  • Readable page text (first N chars)
  • Metadata, headings, links, forms, buttons
  • Open tabs list (if included)

This is the exact context sent to Hermes.

Code examples

Programmatically send message (content script)

// From a content script, send message to background
chrome.runtime.sendMessage({
  type: 'HERMES_PROMPT',
  payload: {
    message: 'Summarize this page',
    context: {
      url: window.location.href,
      title: document.title,
      selectedText: window.getSelection().toString()
    }
  }
});

Access stored settings

// From extension context (popup, side panel, background)
import { getSettings } from './lib/storage';

const settings = await getSettings();
console.log('Gateway URL:', settings.gatewayUrl);
console.log('Theme:', settings.appearance?.theme);
console.log('Context mode:', settings.browserBehavior?.contextScope);

Capture page context

// From content script (extension does this automatically)
const context = {
  url: window.location.href,
  title: document.title,
  selectedText: window.getSelection().toString().trim(),
  readableText: document.body.innerText.slice(0, 50000),
  metadata: {
    description: document.querySelector('meta[name="description"]')?.content,
    author: document.querySelector('meta[name="author"]')?.content
  },
  headings: Array.from(document.querySelectorAll('h1, h2, h3')).map(h => ({
    level: h.tagName,
    text: h.textContent.trim()
  })),
  links: Array.from(document.querySelectorAll('a[href]')).slice(0, 50).map(a => ({
    text: a.textContent.trim(),
    href: a.href
  }))
};

Stream Hermes response

// Extension internal pattern
async function streamHermesResponse(sessionId, messages, signal) {
  const response = await fetch(`${gatewayUrl}/v1/chat/completions`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${apiKey}`
    },
    body: JSON.stringify({
      session_id: sessionId,
      messages,
      stream: true
    }),
    signal
  });

  const reader = response.body.getReader();
  const decoder = new TextDecoder();
  let buffer = '';

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;

    buffer += decoder.decode(value, { stream: true });
    const lines = buffer.split('\n');
    buffer = lines.pop();

    for (const line of lines) {
      if (line.startsWith('data: ') && line !== 'data: [DONE]') {
        const data = JSON.parse(line.slice(6));
        const content = data.choices?.[0]?.delta?.content;
        if (content) {
          // Append to UI
          yield content;
        }
      }
    }
  }
}

Custom theme integration

// Extension appearance settings
const themes = {
  nous: { primary: 'rgb(79, 70, 229)', secondary: 'rgb(99, 102, 241)' },
  midnight: { primary: 'rgb(59, 130, 246)', secondary: 'rgb(96, 165, 250)' },
  ember: { primary: 'rgb(249, 115, 22)', secondary: 'rgb(251, 146, 60)' },
  mono: { primary: 'rgb(71, 85, 105)', secondary: 'rgb(100, 116, 139)' },
  cyberpunk: { primary: 'rgb(236, 72, 153)', secondary: 'rgb(244, 114, 182)' },
  slate: { primary: 'rgb(100, 116, 139)', secondary: 'rgb(148, 163, 184)' }
};

// Apply theme
function applyTheme(themeName, colorMode) {
  const theme = themes[themeName];
  document.documentElement.style.setProperty('--color-primary', theme.primary);
  document.documentElement.style.setProperty('--color-secondary', theme.secondary);
  document.documentElement.classList.toggle('dark', colorMode === 'dark');
}

Environment variables

Extension does not use .env files directly. Configuration is stored in Chrome storage and managed via settings UI.

For Hermes Gateway API server (machine running Hermes):

# ~/.hermes/.env
API_SERVER_ENABLED=true
API_SERVER_HOST=127.0.0.1
API_SERVER_PORT=8642
API_SERVER_KEY=<use-env-var-or-secret-manager>
API_SERVER_CORS_ORIGINS=chrome-extension://<extension-id>

Never commit API keys. Use $(hermes auth token create --scope browser) to generate scoped tokens, or reference secrets from environment/vault.

Troubleshooting

Extension loaded but nothing works

  • Ensure you loaded dist/, not repo root
  • Selected folder must contain manifest.json directly
  • Check chrome://extensions shows version 0.1.6+

Cannot connect to Hermes

# Verify API server is running and reachable
curl http://127.0.0.1:8642/health

# Check models endpoint with auth
curl -H "Authorization: Bearer your-key-here" http://127.0.0.1:8642/v1/models

Common issues:

  • API_SERVER_ENABLED=true not set in ~/.hermes/.env
  • Hermes Gateway not running (hermes gateway run)
  • Wrong API_SERVER_KEY or extension API key
  • CORS origin mismatch (extension ID not in API_SERVER_CORS_ORIGINS)
  • Firewall blocking port 8642

Wrong version after update

Browser cached old unpacked folder:

  1. Run npm run build to generate fresh dist/
  2. Open chrome://extensions
  3. Click Reload on Hermes Browser Extension card
  4. If still wrong, click Remove, then Load unpacked and select fresh dist/
  5. Verify version: click Details → see Version field

No page context captured

Extension cannot read restricted pages:

  • chrome:// or edge:// internal pages
  • chrome-extension:// pages
  • Banking, crypto, password, payment, health, government domains (intentional security restriction)

On normal https:// pages, check:

  • Context scope is not "Chat only"
  • Page has readable text (not just images/video)
  • Click "What Hermes saw" to inspect captured context

Voice dictation not working

  • Check Hermes capabilities: extension queries /v1/capabilities for STT support
  • If Hermes STT unavailable, extension falls back to browser speech recognition
  • Browser speech requires microphone permission (granted on first use)
  • Some browsers/OSes may not support Web Speech API

Computer use / browser automation not working

Hermes Browser Extension is read-only. It does not have browser control permissions (debugger, click, type, form submit).

For native computer use:

# On machine running Hermes
hermes tools list
hermes computer-use status

Computer use comes from Hermes Agent's computer_use toolset via cua-driver, not the browser extension.

CORS errors in console

Extension origin must be allowlisted on Hermes API server:

# ~/.hermes/.env
API_SERVER_CORS_ORIGINS=chrome-extension://your-extension-id-here

Find extension ID at chrome://extensions. Restart hermes gateway run after changing.

Session persistence issues

  • Extension binds one Hermes session per pinned tab
  • Switching tabs creates new sessions (unless "Follow active tab" is enabled)
  • Check /api/sessions in Hermes to see active sessions
  • Clear local history: Settings → Browser behavior → Clear history

Streaming response fails

Extension auto-falls back to non-streaming if:

  • Gateway does not support stream: true
  • Network drops chunks
  • Response is not SSE format

Check gateway logs for streaming errors. Non-streaming mode still works.

Security notes

Extension is intentionally conservative:

  • Read-only: no click, type, form submit, download, or browser control
  • No sensitive permissions: no debugger, nativeMessaging, cookies, history, downloads, bookmarks
  • Content wrapped as untrusted: page text marked as external context before Hermes sees it
  • Local-first default: connects to 127.0.0.1:8642 unless you configure remote
  • Bearer auth required: strong API key for all API access
  • CORS allowlist: extension origin must be explicitly allowed

See repo docs: SECURITY.md, PERMISSIONS.md, DATA-FLOW.md, PRIVACY.md.

Key files

dist/                     # Built extension (load this)
extension/
  manifest.json          # MV3 manifest with side_panel, activeTab, scripting
  background.js          # Service worker, message routing
  sidepanel/
    index.html           # Side panel UI entry
    app.jsx              # Main React app
  content/
    content-script.js    # Page context capture
  lib/
    hermes-client.js     # Hermes API/WebSocket client
    storage.js           # Chrome storage wrapper
    context-capture.js   # DOM scraping logic

Common workflows

Install and connect to local Hermes

git clone https://github.com/abundantbeing/hermes-browser-extension.git
cd hermes-browser-extension
npm install
npm run build

# On Hermes machine, edit ~/.hermes/.env:
# API_SERVER_ENABLED=true
# API_SERVER_HOST=127.0.0.1
# API_SERVER_PORT=8642
# API_SERVER_KEY=<secret>
# API_SERVER_CORS_ORIGINS=chrome-extension://<id>

hermes gateway run

# In browser: chrome://extensions → Load unpacked → select dist/
# In side panel: Connect to Hermes → Local gateway → http://127.0.0.1:8642 → paste key → Test → Save

Switch between multiple local Hermes instances

Settings → Localhost agent picker:

Port 8642 - Default gateway
Port 8643 - Dev gateway
Port 8644 - Testing gateway

Click to switch. Extension stores per-port settings.

Use with remote Hermes on Tailscale

# On remote Hermes machine
API_SERVER_HOST=0.0.0.0
API_SERVER_PORT=8642
API_SERVER_CORS_ORIGINS=chrome-extension://<id>

# In extension
# Remote gateway → http://100.x.y.z:8642 → paste key → Test → Save

Capture and analyze open tabs

In side panel:

/tabs

# Or manually:
List all my open tabs and summarize each one

Extension sends tab list (title, URL) for all open tabs to Hermes.

Pin to specific page for isolated conversation

  1. Open page you want to analyze
  2. Click context menu in composer header → Page only
  3. Panel shows pinned tab indicator
  4. All messages in this panel now tied to that tab, with isolated Hermes session
  5. Switch tabs → panel stays on pinned tab
  6. Click context menu → Follow active tab to resume auto-switching

This skill covers: installation, local/remote configuration, context capture, voice dictation, quick commands, streaming, theming, security model, and troubleshooting for the Hermes Browser Extension.