Skip to content

Extensions

Maho Browser supports Chrome-compatible extensions that use the Manifest V3 standard. In most cases, extensions built for Chrome can run in Maho with minimal or no modification, as long as they depend only on the APIs Maho exposes.

Extensions are loaded from unpacked directories. Maho does not use Chrome Web Store integration. Instead, you point the browser at a local extension directory that contains a valid manifest.json file.

When Maho loads an extension, it validates the manifest and reports errors if the manifest does not meet the supported schema.

Maho supports the following Manifest V3 fields.

FieldRequiredNotes
manifest_versionYesMust be 3
nameYesString
versionYesString in semver format
descriptionNoString
iconsNoIcon map, commonly 16, 48, and 128
actionNoBrowser toolbar button configuration
backgroundNoService worker configuration
content_scriptsNoScript and style injection rules
permissionsNoExtension permissions
host_permissionsNoURL pattern permissions
web_accessible_resourcesNoResources exposed to pages
content_security_policyNoExtension page CSP
options_pageNoExtension options page
options_uiNoOptions UI configuration
devtools_pageNoDevTools integration page

Must be set to 3. Maho only supports Manifest V3 extensions.

The extension name. This field is required and must be a string.

The extension version in semver format. Maho expects a standard version string.

A short human-readable summary of the extension.

Icon paths keyed by size. Common sizes include:

  • 16
  • 48
  • 128

Defines the browser toolbar button. Supported properties include:

  • default_popup
  • default_icon
  • default_title

Declares the background service worker. Maho supports:

  • service_worker
  • type: "module"

Describes scripts and styles injected into matching pages.

Each entry may include:

  • matches
  • js
  • css
  • run_at
  • all_frames

Declares extension permissions such as:

  • storage
  • tabs
  • activeTab
  • scripting

Declares URL patterns the extension can access, such as:

  • *://*.example.com/*

Lists resources that extension pages or content scripts expose to matching web pages.

Defines the extension page content security policy. Maho supports the extension_pages property.

Use these fields to provide settings pages.

  • options_page points to a page path
  • options_ui supports page and open_in_tab

Registers a DevTools page for the extension.

Extensions are installed from unpacked directories only.

  1. Locate the extension directory
  2. Ensure the directory contains manifest.json
  3. Load the directory in Maho
  4. Review validation results if Maho reports manifest errors

Maho does not support installing extensions from the Chrome Web Store.

Maho follows the normal extension lifecycle for unpacked MV3 extensions.

During install, Maho:

  • Parses the manifest
  • Validates supported fields
  • Loads extension resources
  • Starts the background service worker

When enabled, Maho:

  • Injects content scripts into matching pages
  • Shows the extension action button in the toolbar
  • Makes extension APIs available to the extent they are bridged by Maho

When disabled, Maho:

  • Removes content scripts from active use
  • Hides the action button
  • Stops the service worker

When uninstalled, Maho:

  • Clears extension data
  • Wipes extension storage
  • Removes all installed resources for that extension

Content scripts use Chrome-style matching rules.

The matches field supports standard Chrome match patterns, including:

  • <all_urls>
  • *://*.example.com/*

Maho also supports glob patterns for more fine-grained URL matching where applicable.

The run_at field supports the standard MV3 injection times:

  • document_start
  • document_end
  • document_idle

Use all_frames to control whether scripts inject into subframes.

  • true injects into iframes as well as the top-level frame
  • false injects only into the top-level frame

Maho implements chrome.storage.local for extension storage.

MethodBehavior
get(keys)Retrieve stored values
set(items)Store key-value pairs
remove(keys)Delete specific keys
clear()Wipe all storage for the extension

Storage change events fire when values change. Change records include oldValue and newValue.

This lets extensions react to local state updates without polling.

Maho provides bridge APIs for communication between extension scripts and the browser.

  • chrome.tabs.query() for querying open tabs
  • chrome.runtime.sendMessage() and onMessage for extension messaging
  • Tab management APIs for creating, updating, and removing tabs

Only APIs that Maho explicitly bridges are available. Not every Chrome API is exposed.

If an extension depends on an unsupported API, it may install but fail when it tries to call that API.

For best results, keep extensions within the supported MV3 surface area:

  • Use manifest_version: 3
  • Prefer APIs Maho explicitly supports
  • Keep background logic in a service worker
  • Declare all required permissions and host permissions up front

If Maho rejects an extension at load time, check the manifest for:

  • Missing required fields
  • Invalid manifest_version
  • Version strings that do not follow semver format
  • Unsupported field shapes or values

Verify:

  • The matches patterns are correct
  • The page URL is covered by host_permissions where needed
  • run_at is set appropriately
  • all_frames matches the intended injection target

If extension state does not persist as expected, confirm that the extension is using chrome.storage.local and not relying on an unavailable storage API.

Maho’s extension support is centered on unpacked Manifest V3 extensions, Chrome-style content script matching, local storage, and a limited bridge of browser APIs. Extensions that stay within that supported surface can run in Maho with little friction.