Build one verified extension package
Cheers extensions combine declarative scenes, seed files, scheduled-message templates, and optional macOS renderers in a deterministic .cheers-extension ZIP.
Package model
Global extensions are data-only and work in the browser, iOS, and macOS. Personal macOS extensions may include JavaScript generated from TypeScript, but run only inside an opaque-origin sandbox after the user selects a renderer.
manifest.json scenes/<scene-id>.json seed/<scene-id>/<workspace-path> renderers/<renderer-id>.js renderers/<renderer-id>.css
Minimal manifest
{
"schemaVersion": 1,
"id": "my-notes",
"version": "1.0.0",
"title": "My notes",
"contributes": {
"scenes": [
{ "id": "notes", "title": "Notes", "definition": "scenes/notes.json" }
],
"renderers": [
{ "id": "notes", "title": "Notes", "entry": "renderers/notes.js" }
]
},
"permissions": { "file.write": true }
}
Renderer entry point
import { defineRenderer } from "@haowei0520/cheers-workbench-sdk";
defineRenderer({
activate(ctx) {
const root = document.querySelector("#root");
ctx.file.onRender((file) => {
if (root) root.textContent = file.content;
});
return () => root?.replaceChildren();
},
});
The activation function must return lifecycle cleanup. Use the typed context for file saves, approved channel resources, navigation, composer prefills, automation management, and development logs. Never assume host DOM or Tauri access.
Pack and verify
cd packages/cheers-workbench-sdk npm install npm run build node dist/cli.js pack ../../extensions/my-notes ./my-notes.cheers-extension
The packer bundles every renderer as a single IIFE, normalizes archive ordering and timestamps, checks manifest paths and size limits, and produces reproducible bytes.
Permissions and network
Request only the capabilities the renderer uses. Network is blocked by default. Setting network: unrestricted produces a prominent installation warning and still does not grant access to host cookies, tokens, DOM, external scripts, or Tauri APIs.