Muxy

Get started

This page builds a working extension in a few minutes: a panel you toggle from the top bar or a shortcut.

1. Create the files

An extension is a folder with a package.json. Muxy loads the folder's dist/ build output when it has one, otherwise the folder itself, so a plain HTML page needs no build step.

hello/
  package.json
  panel.html

package.json:

{
  "name": "hello",
  "version": "0.1.0",
  "muxy": {
    "description": "Says hello",
    "permissions": ["panels:write", "notifications:write"],
    "panels": [{ "id": "hello", "title": "Hello", "entry": "panel.html" }],
    "commands": [
      {
        "id": "toggle",
        "title": "Hello: Toggle Panel",
        "action": { "kind": "togglePanel", "panel": "hello" },
        "defaultShortcut": "ctrl+opt+h"
      }
    ],
    "topbarItems": [
      { "id": "hello", "icon": "sparkles", "command": "toggle", "tooltip": "Hello" }
    ]
  }
}

panel.html:

<!doctype html>
<body style="background: var(--muxy-background); color: var(--muxy-foreground)">
  <button id="hi">Say hello</button>
  <script>
    document.getElementById("hi").onclick = () =>
      muxy.notifications.notify({ title: "Hello", body: "From my extension" });
  </script>
</body>

The extension name should use lowercase letters, digits, ., and -. Its pages don't load otherwise.

2. Load it

  1. Open Settings → Extensions and choose Load Unpacked….
  2. Pick the hello folder.
  3. Open its entry and turn it on. Extensions start disabled.
  4. Click the sparkles icon in the top bar, or press Ctrl+Opt+H.

The extension shows an Unpacked badge. After editing, choose Reload. Unload folder removes it from Muxy and keeps your files.

3. Use a build tool

For anything bigger, use any web tooling, such as Vite. Point every entry at paths inside your build output, and copy package.json into dist/ as part of the build. Only dist/ is published.

"scripts": {
  "build": "vite build && cp package.json dist/"
}

Debugging

  • console.log, console.warn, and console.error from pages and scripts go to the extension's log, along with uncaught errors.
  • The extension's page in Settings → Extensions shows recent log lines, load errors, and Reveal log.
  • The log file is logs/output.log inside the extension's loaded folder.

Next

Coming from 1.x

Most 1.x extensions work unchanged. The differences:

  • Install folder. Extensions live in Muxy 2's profile folder, not ~/.config/muxy/extensions. Importing the installed 1.x copies them over.
  • No scaffold. There is no Create button or starter kit. Use Load Unpacked….
  • Lowercase names. Pages only load for names made of a-z, 0-9, ., and -.
  • Background scripts run in-process, in JavaScriptCore on their own thread.
  • Not supported yet: remote methods for the phone app, home views, reading extension settings at runtime, and the worktree.offline event.
  • Bar items always sit in the top bar. There is no icon rail.
  • New: the openPanel command action, visible on panel header buttons, execAsync on pages and scripts, and the modal.opened and modal.closed events.