Skip to main content

Site Plugins

Every website MonoSurf can access is defined by a single JSON file. Adding a new site means creating one file — no Rust code, no rebuilding, no deploying. Standalone monosurf and kernel-cli websurf enter through the same lib-monosurf facade and load the same plugins through lib-monosurf-core. Verified against monosurf 0.11.3, OpenCLIs build 2026-07-19-222928.

Plugin Location

Plugin Structure

Fields

Top Level

Command Fields

Actions (Write Operations)

Accessing Accessibility Tree in JS Actions

For sites that strip CSS selectors (like Meta’s Threads), use ARIA roles in JS:
Use js, click, type, and wait for current CDP workflows. Legacy plugin JSON can still contain a pw action and monosurf sites help currently lists that compatibility shape, but execution fails closed with conversion guidance.

Display Templates

Templates use {field} to reference fields from extracted JSON objects:

Domain Security

The filename IS the identity. MonoSurf enforces:
  1. Filename = domain: x.com.json can only define base_url for x.com
  2. URL validation: Relative URLs are prepended with base_url
  3. Mismatch = rejection: If base_url domain doesn’t match filename, plugin is refused
This prevents a malicious plugin from masquerading as another domain.

Variable Substitution

URLs and type actions support {variable} syntax:
Variables come from CLI positional arguments:
  • First arg after command → {query}, {id}, {text}
  • Unresolved variables are silently removed

Shared Extraction via $ref

Commands can reuse extraction logic from other commands:
$ref:top copies the extract_js from the top command. Avoids duplicating long JavaScript strings.

Plugin Integrity

Site plugins contain JavaScript that runs in the browser. MonoSurf protects against tampering with a checksum system.

Signing

Signing computes a checksum of all extract_js and actions in the plugin and writes it to the JSON:

Verification

Runtime Enforcement

Every plugin execution checks integrity before running:
  • OK — executes normally
  • UNSIGNEDblocked. Must be signed before first use.
  • TAMPEREDblocked. Execution refused until reviewed and re-signed.
Execution also uses the 0.11.3 exact-port ownership guard. New profiles skip active unregistered ports; after selecting a profile, MonoSurf verifies that the exact chosen CDP listener carries that profile’s --user-data-dir. A known foreign listener blocks immediately, and temporarily unknown ownership gets only a bounded settle interval before failure. The command stops before the plugin can navigate, read cookies, or run actions. This protects unattended site commands and batch work as well as direct profile browsing. If the live domain jar is empty and a gated bridge/login snapshot exists, hydration happens before plugin navigation. Every cookie scope is validated, an explicit HTTP(S) origin is supplied, attributes are preserved, and any CDP error fails the command. A non-empty live jar always wins.

Workflow

  1. Create or modify a plugin JSON
  2. monosurf sites sign — seal it
  3. Plugin runs normally
  4. If JSON is modified externally → checksum breaks → execution blocked
  5. Review the change → monosurf sites sign to re-seal

Plugin Registry

Official plugins are distributed through api.openclis.com. Users can pull plugins from the server, and authorized developers can push updates.

Source Levels

Source is determined server-side from the developer’s JWT org membership. It cannot be self-asserted by the client.

Publishing

Installing

Reset to Official

If AI modifies a plugin locally (source changes to local), reset restores the official version from backup.

Server Endpoints

The index enables AI to discover which sites are available:

Existing Plugins