~/tools/extensions/sdk

SDK des extensions

Créez des extensions monofichier qui s’exécutent localement dans Mentria — sans boutique, sans serveur, sans envoi.

Qu'est-ce que c'est ? Masquer les détails

Qu'est-ce que SDK des extensions ?

Les extensions sont des fichiers HTML uniques exécutés dans Mentria avec une petite API hôte : stockage propre à l’extension, jetons de thème, notifications, tuiles du lanceur et commandes. L’installation est un import local confirmé par l’utilisateur — rien n’est envoyé, revu à distance ni mis à jour automatiquement. Cette page documente le manifeste et l’API hôte, avec un starter à copier-coller.

sdk.md

A Mentria extension is a single .html file — markup, styles and script in one document. There is no build step, no bundler and no upload: the file lives only on your device, in local storage, and runs on the site the moment you install it.

Trust model — read this once

Your extension runs inside an <iframe> (its own document), but that frame is same-origin with the host page. That is structural isolation, not a security sandbox: an installed extension can reach the host. The real safeguards are human ones — you install it yourself after a naming prompt, the source never leaves your device, and the file size is capped. Only install extensions you would be willing to run as your own code.

Démarrage rapide

Copy the file below, drop it into the manager, and open it. It paints itself with the site theme, saves a note to its private storage, and raises a host toast — the three things almost every extension needs.

starter.html
<script type="application/json" id="mentria-ext">
{
  "id": "starter",
  "name": "Starter",
  "version": "1.0.0",
  "icon": "✨",
  "author": "you",
  "description": "A minimal Mentria extension: theme tokens, a storage roundtrip, and a toast.",
  "permissions": ["storage"],
  "mounts": {
    "tool": {},
    "commands": [
      { "name": "starter", "usage": "starter [text]", "description": "open the starter extension" }
    ]
  }
}
</script>
<style>
  body { margin: 0; padding: 2rem; font-family: var(--ext-font, monospace);
         background: var(--ext-bg, #0b0e11); color: var(--ext-fg, #e6edf3); }
  input, button { font: inherit; padding: .5rem .8rem; border-radius: 6px; }
  input  { width: 100%; box-sizing: border-box; margin-bottom: .6rem;
           background: transparent; color: inherit; border: 1px solid var(--ext-muted, #7d8590); }
  button { background: transparent; cursor: pointer;
           color: var(--ext-accent, #6ef3c5); border: 1px solid var(--ext-accent, #6ef3c5); }
</style>
<h1>My note</h1>
<input id="note" placeholder="type something, then Save…">
<button id="save">Save</button>
<script>
  // window.mentria is injected by the run host before this script runs.
  const { storage, theme, notify, args } = window.mentria;

  // Paint the host theme onto our CSS variables.
  const s = document.documentElement.style;
  s.setProperty('--ext-bg', theme.bg);
  s.setProperty('--ext-fg', theme.fg);
  s.setProperty('--ext-accent', theme.accent);
  s.setProperty('--ext-muted', theme.muted);
  s.setProperty('--ext-font', theme.fontMono);

  const box = document.getElementById('note');

  // Storage roundtrip: last saved note, or text passed on the command line.
  box.value = storage.get('note') || (args && args.args) || '';

  document.getElementById('save').addEventListener('click', () => {
    storage.set('note', box.value);   // persisted under extdata.starter
    notify('saved');                  // host toast, bottom-center
  });
</script>

Install it: open the manager, expand paste source, paste the file, and confirm the trust prompt. Because it declares mounts.tool it also gets a launcher tile, and its starter command shows up in the terminal.

Référence

Manifest

The manifest is a JSON block with id="mentria-ext". It is the only required piece of structure; everything else is ordinary HTML.

FieldTypeReqRules
idstringyeskebab-case ([a-z0-9-]), 3–48 chars, unique. Reserved: extensions run tools feed search about comms.
namestringyes1–40 chars. Shown in the manager, launcher tile and run bar.
versionstringyesmajor.minor.patch (e.g. 1.0.0). Reinstalling a higher version triggers an update prompt.
iconstringnoAn emoji (≤8 chars) or a data:image/… URI up to 8 KB.
authorstringno≤200 chars.
descriptionstringno≤200 chars.
permissionsstring[]noUp to 16 labels (≤32 chars each). Vocabulary: storage ai bluetooth usb serial network notifications share. Advisory only — surfaced in the trust prompt and the manager row; not enforced by a sandbox.
mountsobjectnoWhere the extension appears (below).
mounts.toolobjectnoPresent (usually {}) → a launcher tile plus the manager's open button.
mounts.commandsobject[]noEach { name, description, usage? } registers a terminal/palette command. name kebab-case 2–16 chars; description required; usage is an optional hint. Colliding names are skipped.
mounts.widgetobjectno{ key, label } → a live status tile on the home launcher (see Widgets). key (1–64 chars) is the storage key the tile watches; label (1–48 chars) names the tile.

The host object — window.mentria

The run host injects a frozen window.mentria before your script executes. Everything an extension can do goes through it.

MemberShapeWhat it does
manifestobjectA frozen copy of your parsed manifest.
storage.get(key) → valueRead from your extdata.<id> namespace. storage.get('note')
storage.set(key, value) → boolWrite any JSON value. Returns false when storage is full. storage.set('note', text)
storage.remove(key) → boolDelete one key. storage.remove('note')
storage.list() → string[]List your keys. storage.list()
theme{ accent, bg, fg, muted, fontMono }The site's live CSS token values. root.style.setProperty('--x', theme.accent)
argsnull | { cmd, args }Set when opened via a command (#cmd=…&args=…); otherwise null. if (args) run(args.args)
notify(msg) → voidHost toast, bottom-center, first 120 chars. notify('saved')
close() → voidLeave the extension and return to the home launcher. close()

The run frame is granted the feature policy bluetooth; usb; serial; camera; microphone, so those Web APIs work from inside an extension when the browser and user allow them.

Storage

Each extension owns a private namespace, extdata.<id>, reachable only through window.mentria.storage. It is backed by the browser's localStorage (via MentriaStore), so reads and writes are synchronous and every value must be JSON-serializable.

  • Quota is real and shared: localStorage is roughly 5 MB for the whole origin, split across every tool. Keep extension data small; storage.set returns false if the write would overflow.
  • Your data is covered by the site's encrypted local backup, and shows up in the Files tool grouped as extension: <id>.
  • Removing the extension in the manager also clears its extdata.<id> keys.
  • The whole .html is stored too: over 512 KB warns at install, over 1536 KB is rejected outright.

Widgets

Declare mounts.widget and the home launcher shows a live status tile for your extension, named by label and linking to your run page. The tile renders the snapshot object stored under key in your own storage — e.g. storage.set('note', { text: 'bought milk', progress: 0.4 }) — and refreshes on every write.

Snapshot fieldTypeReqRules
textstringyesThe tile's value line. Trimmed, capped at 80 chars; must be non-empty.
detailstringnoA secondary line below the value. Trimmed, capped at 120 chars.
progressnumbernoDrawn as a progress bar; clamped to 0–1.

Anything else under that key — a plain string, an array, an empty text — is ignored silently: the tile simply stays hidden until the key holds a valid snapshot object.

Install & share

  • Manager (/tools/extensions/): drop an .html file, choose a file, or paste the source. Every install shows a human trust prompt naming the extension, its version and its declared permissions; updates call out permissions the new version adds or drops, and installing an older version is labeled as a replacement, not an update.
  • Share over comms: from an installed row, share hands the file to an open comms session; the peer gets the same trust prompt, attributed from you, before anything installs. If comms is closed it points you there.
  • Export: export downloads the stored source back out as <id>.html, so an extension is always portable.