Build one by describing it
BetaAsk an LLM you already use to write a local Wrengle plugin for you, then load the files it gives you into Wrengle yourself. This works well for small tools that open in their own tab: calculators, converters, checklists, formatters, inspectors, or a dashboard for text you select in a note.
Start with a view-only plugin — it's the simplest kind, and it only needs two files:
my-plugin/
plugin.toml
ui/
index.htmlA view-only plugin needs no Rust, no WASM, no plugin.wasm file, and no
build step — just the two files above. It's local code you're choosing
to trust, the same as any program you download and run, so only load a
plugin folder you actually trust.
Every view has a mandatory host-owned offline policy, so direct network
requests and external resources are blocked. The httpHosts capability is
only for Wrengle host-bridge HTTP used by WASM action plugins; it never enables
networking in a view. Tell the LLM to keep the HTML completely self-contained.
If your LLM can open URLs, hand it the raw LLM plugin instructions along with your idea and you can skip the prompt below. Otherwise, copy the prompt below and fill in your idea.
Copy-paste prompt
Replace the bracketed parts, then paste the whole prompt into your LLM:
Create a local Wrengle view-only plugin for me.
Plugin idea:
[Describe what the plugin should do. Include what users type or paste, what
the plugin should show, and whether it should use selected text from a note.]
Wrengle plugin constraints:
- This is a local developer-preview plugin, not a marketplace or remote-install
plugin.
- Prefer a view-only plugin.
- Produce a complete plugin folder with at minimum these required files:
- plugin.toml
- ui/index.html
- Do not include a [runtime] block.
- Do not include plugin.wasm.
- Do not require Rust, WASM, Node, npm, a bundler, or a build step.
- Do not claim the plugin can open terminal tabs, run shell commands, use
process plugins, read arbitrary local files, install itself remotely, or use a
marketplace.
- Do not use network requests. Every view has a mandatory offline policy that
blocks fetch, XMLHttpRequest, WebSocket, WebRTC, navigation, nested frames,
forms, and external resources.
- Do not claim `httpHosts` enables view networking. `httpHosts` applies only
to Wrengle host-bridge HTTP made by WASM action plugins and never relaxes the
view policy.
The plugin.toml file must include:
- top-level id, name, version, schema_version = 1, and description
- a top-level id that starts with plugin.
- one [[views]] block with id, label, and entry
- entry = "ui/index.html", relative to the plugin folder, pointing to an
existing file
- a view id that starts with the plugin id plus a dot, such as
plugin.my-tool.view
- lowercase ASCII ids using letters, digits, dots, and hyphens, with no ".."
- accepts_selection = true and a clear selection_label if the plugin should
receive selected note text
The ui/index.html file must be one self-contained HTML file:
- inline all CSS and JavaScript
- do not reference external scripts or stylesheets
- do not reference companion JavaScript or CSS files
- keep the file under 5 MB
- use Wrengle CSS variables for all page surfaces, foreground text, borders,
muted surfaces/text, and primary controls
- prefer variables such as var(--background), var(--foreground), var(--card),
var(--card-foreground), var(--muted), var(--muted-foreground),
var(--border), var(--input), var(--primary), and
var(--primary-foreground)
- do not define an independent hard-coded light or dark color palette
- do not make network requests or reference external resources
- include this Wrengle message listener inside an HTML script element; Wrengle
owns and readies the per-document channel automatically:
function applyWrengleTheme(message) {
if (message.theme) {
document.documentElement.dataset.theme = message.theme;
}
if (!message.themeTokens || typeof message.themeTokens !== "object") return;
for (const [name, value] of Object.entries(message.themeTokens)) {
if (/^--[A-Za-z0-9_-]+$/.test(name) && typeof value === "string" && value.length > 0) {
document.documentElement.style.setProperty(name, value);
}
}
}
window.addEventListener("message", (event) => {
if (event.source !== window.parent) return;
const msg = event.data;
if (!msg || typeof msg !== "object") return;
if (msg.type === "wrengle:init" || msg.type === "wrengle:theme") {
applyWrengleTheme(msg);
} else if (msg.type === "wrengle:selection" && typeof msg.text === "string") {
// Use msg.text as the selected note text.
}
});
Return:
1. The folder tree.
2. The full contents of plugin.toml.
3. The full contents of ui/index.html.
4. Short steps to create the files, load the plugin in Settings -> Plugins,
open it from the command palette, and test selected note text if supported.Look over what it gives you
Read the LLM's answer before you create any files. Open plugin.toml
and check that schema_version = 1 is there, along with an id, a view
id built on that id, and an entry path that matches the HTML file
you're about to create. Skim ui/index.html for anything you didn't
ask for — a network call, a terminal or shell command, or a claim about
a marketplace — and ask the LLM to remove it before you go further.
Wrengle captures the exact loaded code — manifest, WASM, and view bytes — when you reload. Any positive grants are bound to that snapshot, so changed code needs approval again. Plugin state and keychain values remain in their stable plugin-and-path namespace across an approved update.
Load the generated plugin
Once the files look right:
- Create the plugin folder exactly as shown by the LLM.
- Open Wrengle.
- Open Settings → Plugins → Developer → Dev plugin paths.
- Add the absolute path to the plugin folder.
- Click Reload.
- Confirm the view appears under Loaded plugins.
- Open the command palette with Cmd+K on macOS or Ctrl+K on other platforms.
- Run Open <label>, where
labelis the view label inplugin.toml; the row also shows the plugin name for disambiguation.
If the plugin supports selected text:
- Open a note.
- Select some text.
- Open the floating toolbar's Actions menu.
- Choose the plugin's
selection_label. - Confirm the selected text appears in the plugin view.
If it does not load
Open Settings → Plugins → Developer → Plugin diagnostics, copy the message you see, and paste it back to your LLM with this instruction:
Fix this Wrengle plugin using the diagnostic below. Keep it view-only unless the
diagnostic proves a different local plugin type is needed. Return the corrected
plugin.toml and ui/index.html files in full.
Diagnostic:
[Paste the diagnostic here.]Common fixes:
| Problem | What to ask the LLM to check |
|---|---|
| View is missing from the command palette | Confirm plugin.toml has a valid [[views]] block and that you clicked Reload. |
| Blank tab | Confirm entry = "ui/index.html" and that the file exists inside the plugin folder. |
| Selection action is missing | Confirm accepts_selection = true and selection_label are present in the view block. |
| Theme looks wrong | Confirm the HTML uses Wrengle CSS variables and applies themeTokens from wrengle:init and wrengle:theme. |
For more detail on the bridge and the file contract, see
Views (custom plugin UI). The
JSON Compare tutorial walks through
examples/plugins/json-compare, a reference plugin that ships with
Wrengle's source — following it needs a local Wrengle source checkout.
If you'd rather write a WASM action yourself — Rust, host grants, the SDK
— see Writing one by hand.