Skip to content
bmuxBack

bmux script plugins

Plugins are local folders containing plugin.yaml and scripts in any language. They can contribute actions, automatic hooks, browser operations, and transient prompts. Scripts run as your OS user. Enable only code you trust: host capabilities describe and restrict the host API, but do not sandbox filesystem, network, or other programs the script can access. Pages retain Chromium's sandbox and receive no Node integration or privileged preload.

Install and enable

Copy or symlink a plugin folder under plugins/ beside the active config file, normally ~/.config/bmux/plugins/. Examples live in examples/plugins/ in the checkout and bmux.app/Contents/Resources/plugins/ in packaged builds. There is no automatic download or execution of bundled examples.

Merge these entries into your existing config (preserve your keyboard edits):

keyboard:
  shortcuts:
    Cmd+Shift+L: plugin:experimental.bitwarden/fill
  prefixBindings:
    P: plugins
plugins:
  local.page-tools:
    enabled: true
    hooks: false
  experimental.bitwarden:
    enabled: false

Open plugins in the command prompt to search and run actions. activity shows progress, failures, and cancellation controls. Manifests and config reload live; scripts are read on the next invocation. plugin reload rescans immediately. Invalid manifest edits preserve the last valid definition until corrected or the app restarts. Invalid new plugins appear disabled with an error. Enabled scripts are trusted across updates; bmux does not verify their signatures or contents.

BMUX_CONFIG determines the config and plugin directory. With BMUX_DATA_DIR, the default is that data directory's config and plugins, never personal plugins.

Manifest

schema_version: 1
id: local.example
name: Example
version: 1.0.0
actions:
  - id: run
    title: Run example
    description: Optional explanation
    command: [python3, ./run.py]
    capabilities: [browser.read, browser.write, ui]
    timeout_seconds: 120
    parameters:
      - name: mode
        title: Mode
        kind: choice
        choices: [brief, detailed]
        required: true
hooks:
  - id: page
    title: Prepare page
    event: page-ready
    matches: ["https://example.com/*"]
    command: [sh, ./page.sh]
    capabilities: [browser.write]

Commands are argument arrays, not interpolated shell strings. Paths beginning with . resolve against the plugin directory; executable names use PATH. Invoke sh explicitly for shell scripts. Install required interpreters yourself. Node.js is required by the bmux host CLI, including packaged apps.

Parameters support text, password, boolean, and choice. Interactive runs collect missing parameters with bmux prompts. CLI runs must supply required values through --parameters (use this only for nonsensitive values). Scripts retrieve parameters from the private context host call, not environment variables.

Hooks require both enabled: true and hooks: true in config. startup runs once when enabled or when bmux starts; ordinary reloads do not repeat it. page-ready runs at main-document DOM readiness. url-change runs on same-document navigation (including History API changes). Page hooks require matches: anchored, case-sensitive URL globs where * matches any substring. An optional profiles list filters by profile ID. Hooks cannot collect parameters or open prompts, activate clients, or change selection through the host API.

At most four scripts run concurrently. Manual actions have queue priority. Pending hooks are coalesced by plugin, hook, and tab, and cancelled when their document is superseded. The queue holds up to 256 invocations; excess hooks are dropped. The default timeout is 120 seconds; manifests may choose 1–3600 seconds. Timeouts, cancellation, disablement, and shutdown revoke the invocation and terminate its process group. Scripts must not detach their own daemon processes. Persistent service supervision is not supported.

Host calls

bmux supplies BMUX_CLI, BMUX_PLUGIN_SOCKET, BMUX_PLUGIN_RUN_ID, and BMUX_PLUGIN_TOKEN. Keep invocation credentials private. All host calls use the same JSON envelope as the normal CLI: { "ok": true, "result": ... } or an error with a nonzero exit code. Host calls never start or reconnect to another bmux instance if their invocation has ended.

"$BMUX_CLI" plugin host context
"$BMUX_CLI" plugin host dom
"$BMUX_CLI" plugin host eval '{"expression":"document.title"}'
"$BMUX_CLI" plugin host progress '{"percent":50,"message":"Working"}'
"$BMUX_CLI" plugin host result '{"updated":true}'

Use plugin host METHOD --stdin with JSON on stdin for sensitive or structured arguments. Do not place secrets in command arguments. For example, Python scripts can use subprocess.run([os.environ['BMUX_CLI'], 'plugin', 'host', method, '--stdin'], input=json.dumps(arguments), capture_output=True, text=True, check=True) and decode stdout. See the page-tools host.py helper.

Methods Capability Arguments and behavior
context None Returns invocation IDs, parameters, URL, document ID, and whether its original client is currently interactive. { "refresh": true } explicitly reacquires the same tab's document.
progress, result None Explicit public output; never include secrets. Progress takes percent and message; result takes a JSON object.
dom browser.read { "html": true } for HTML; otherwise visible text. Returns tab, URL, content.
screenshot browser.read Existing screenshot options, including absolute output path.
wait browser.read selector and optional timeout (maximum 60000 ms). expression waits additionally require browser.write.
eval browser.write expression evaluated in the page's main JavaScript context, including DOM access; returns JSON-compatible value.
click, type, fill browser.write Main-document selectors. Click calls the element's DOM click method; type inserts text into an input/textarea selection. Fill replaces values using fields: [{selector, value}] and requires the current origin. Visible editable fields only. Input/change events are dispatched.
key, navigate, back, forward, reload browser.write Existing browser arguments without a tab override. Navigation starts immediately.
cdp browser.cdp method and params; tab-scoped DOM, Runtime, Page, Input, Network, CSS, Accessibility, Emulation domains. No target/session routing. Raw CDP is an advanced trusted capability; use fill for document-bound credentials.
ui ui kind, title, optional required. Kinds: text, password, confirm, pick. Pickers take items: [{id,label,description?}] and return the selected ID. Confirm returns a boolean; text/password return strings.

browser.manage allows tab.list/create/close/select, profile.list, list-sessions/windows/panes, new-window, split-window, select-pane/window, and activate-client, with the normal CLI RPC argument names and explicit IDs. No other runtime methods are exposed by the plugin host.

Browser calls default to the invocation's captured tab, never the subsequently selected tab. DOM operations reject after URL/document changes until the plugin explicitly calls context with refresh: true. Delayed fill/evaluation uses an object handle in the captured page execution context, which navigation destroys. Waits and script processes do not occupy the browser's per-tab command queue.

Prompts are scoped to the initiating client and selection. Escape, closing the prompt, or changing that selection cancels pending interaction. Background scripts cannot summon an overlay. After an explicitly requested external app interaction, a plugin can wait for context.interactive before requesting the next prompt.

Subprocess stdout/stderr are discarded. Only explicit progress and results are published; invocation tokens, parameters, host requests, and prompt responses are not logged or persisted. Recent run history is bounded and lives in memory. A plugin author can still disclose data through explicit results, DOM changes, or external tools, so this contract is not a sandbox. Filled page values remain accessible to the site and to bmux's existing trusted local automation API.

CLI and authoring examples

bmux plugin list
bmux plugin run local.page-tools/title -t TAB_ID
bmux plugin run local.page-tools/annotate -t TAB_ID --parameters '{"note":"Review this page"}'
bmux plugin runs
bmux plugin cancel RUN_ID
bmux plugin reload

Run returns { "id": "..." } immediately. Poll plugin runs for completion. In the on-screen command prompt, plugin run ID/ACTION uses the current tab and may collect parameters; CLI invocations have no interactive client. Shortcuts use plugin:ID/ACTION, and remain valid configuration even while a plugin is missing.

local.page-tools demonstrates a shell title query, a Python heading picker, parameter collection, and an opt-in page hook scoped to local fixture paths. Bitwarden's experimental plugin demonstrates native desktop communication using the same host API.

Test plugins in a disposable BMUX_DATA_DIR with local fixture pages. Never copy a personal browser profile into a test. Use explicit progress messages for safe diagnostics; raw command output is intentionally not surfaced by bmux.

Bundled browser tools

Saved forms are bundled actions. The browser.forms capability and browser userscript settings are described in Browser tools. Use the plugin panel to enable or disable individual plugins; hooks remain a separate opt-in in config. Bundled IDs take precedence over local plugin folders.

Edit on GitHub