Plugin authoring
Write small, vault-scoped extensions for Glyphary.
Plugins can add command palette actions, load declared stylesheets, insert templates, and run short WASM text transforms. Plugins do not get shell access, direct DOM access, arbitrary vault filesystem access, background daemons, or network access.
Plugin Location
<vault root>/.glyphary/plugins/<plugin id>/plugin.json
.glyphary/plugins/meeting_tools/
plugin.json
styles.css
templates/agenda.md
plugin.wasm
The plugin directory name must match the manifest id.
Enabling A Plugin
- Copy the plugin directory into
<vault root>/.glyphary/plugins. - Open Settings and go to the Plugins tab.
- Click Refresh if the plugin was added while Settings was open.
- Enable the plugin and save settings.
Enabled plugin commands appear in the command palette.
Manifest
Every plugin must have a plugin.json file.
{
"id": "meeting_tools",
"name": "Meeting Tools",
"runtime": "glyphary-wasm-transform@1",
"version": "0.1.0",
"description": "Commands and styles for meeting notes.",
"permissions": ["document:write", "styles:load"],
"styles": ["styles.css"],
"commands": [
{
"id": "insert_agenda",
"title": "Insert Agenda",
"template": "templates/agenda.md"
},
{
"id": "insert_decision_callout",
"title": "Insert Decision Callout",
"insertMarkdown": "::: callout note \"Decision\"\\nDecision:\\n\\nOwner:\\n:::\\n"
}
]
}
| id | Required. Must match the directory name. |
|---|---|
| name | Required. Display name shown in Settings. |
| runtime | Required. Currently only glyphary-wasm-transform@1 is supported. |
| permissions | Optional declared permissions. Unsupported values make the plugin invalid. |
| styles | Optional CSS files to load when enabled. |
| commands | Optional command palette actions. |
Runtime
The current runtime is glyphary-wasm-transform@1. It is not WASI, and it is not Extism.
Permissions
document:read
document:write
selection:read
selection:write
styles:load
Command Actions
| insertMarkdown | Inserts literal Markdown at the cursor or selection. |
|---|---|
| template | Reads a declared template file and inserts it. |
| wasm | Runs a pure WASM transform in a Web Worker. |
{
"id": "uppercase_selection",
"title": "Uppercase Selection",
"wasm": {
"module": "plugin.wasm",
"input": "selection",
"output": "replaceSelection",
"timeoutMs": 200
}
}
WASM Transform ABI
Runtime glyphary-wasm-transform@1 loads a raw WebAssembly module with no imports:
WebAssembly.instantiate(bytes, {})
The module must export:
memory
alloc(length) -> pointer
transform(pointer, length) -> outputPointer
It may also export dealloc(pointer, length).
outputPointer
+0 u32 little-endian output byte length
+4 UTF-8 output bytes
Examples
Rust Example
The sample Rust plugin lives at examples/plugins/uppercase_selection_rust.
rustup target add wasm32-unknown-unknown
cargo build --manifest-path examples/plugins/uppercase_selection_rust/Cargo.toml \
--release \
--target wasm32-unknown-unknown
Generated WASM Example
The dependency-free generated sample lives at examples/plugins/uppercase_selection.
Plugin Styles
Plugins can declare stylesheets and should follow the same public styling contract as CSS snippets; see the theming reference.
{
"permissions": ["styles:load"],
"styles": ["styles.css"]
}
Validation Limits
- Plugin manifest must be named
plugin.json. - Manifest id must match the plugin directory name.
- Manifest runtime must be
glyphary-wasm-transform@1. - Unknown runtimes, permissions, input modes, output modes, and file extensions make the plugin invalid.
Security Model
- Plugins are installed per vault and disabled until approved in Settings.
- Plugin files are restricted to their own plugin directory.
- WASM runs in a Web Worker with no imports and bounded timeouts.
- Use WASM only for deterministic text transforms.