Skip to content
WM KeyboardWM Keyboard
Accessibility

WM Keyboard plugins

Plugins are small sandboxed Python scripts that add tools to the keyboard.

A plugin is a small Python script that adds a tool to the keyboard. It draws a panel (some text, a few buttons, maybe a text box) and does whatever you write it to do.

main.py
def render():
return ui.column(
ui.label("Hello!", style="title"),
ui.button("wave", "Wave back"),
)
def on_event(e):
if e.id == "wave":
wm.log("👋")

That is a complete plugin, minus its plugin.json.

You can also write one on the phone. WM Keyboard  Tools  Plugins  Write a plugin opens an in-app editor with a live preview and starter templates, and its Install button installs the result directly, with no ZIP file.

Compute things, draw its own panel, and add buttons to the bar over selected text. That is the whole list. A plugin can also be nothing but those buttons: a selection action that turns the text you selected into something else, which is also how a Clink action installs.

  • See what you type. There is no key event API. A plugin cannot observe, change or delay a single keystroke going to your app.
  • Read the text you are writing in. No API returns the contents of the field. A selection action is handed the text you selected, when you tap it, and nothing else.
  • Read your clipboard. No API.
  • Use the internet. No HTTP, no sockets, no URLs.
  • Reach Android. No files, no reflection, no other apps, no device information, no permissions of its own.
  • Run in the background. A plugin only runs while its panel is open. A plugin with the reminders permission can ask the app to show a line of text at a set time, and the app shows it; the plugin does not run for that.

Text still gets into a plugin: you type into its box, tap Paste on it, or select text and tap one of its buttons on the selection bar. Results come back out when you tap Insert under a result, or in place of the selection. Every one of those is a deliberate tap, on a control the keyboard drew.

The five demo plugins in the addon repository are meant to be read. Each one is a single main.py:

PluginShows
Cipher ToolTabs, inputs, buttons, insertable output. The getting-started build.
UI Kitchen SinkEvery widget and every event, with a live event log.
Todo Listwm.storage, wm.reminders, json and the date widget: items with due dates, and a reminder when one is due.
Text ToolsThe paste-in, transform, insert-out flow.
Math ModeA real text engine: a tokenizer, symbol tables, a live result on every keystroke, and options kept in wm.storage.

Plugins were written in Lua until version 0.6.6, which replaced Lua with Python. When you update to 0.6.6, every Lua plugin on the phone is removed, since nothing is left to run it. The keyboard’s plugin list and the Plugins screen say which ones went.

What each one saved is kept. Install a Python plugin with the same id and its data comes back as it was. The five demos above kept their ids in the move, so installing the Python Todo List brings your list back. Only what a plugin saved with wm.storage is kept; its log and any reminders it had set are not.

Data that no plugin has claimed is listed on the Plugins screen, each with a button to delete it now. Anything still unclaimed 90 days after the update is deleted on its own.

WM Keyboard  Tools  Plugins  Manage plugins

A Lua plugin file opened after the update is refused with a reason that says it was written in Lua; Lua is refused has the exact rule.