Skip to content
WM KeyboardWM Keyboard
Accessibility

Permissions

The one permission a plugin can declare, and what it grants.

There is one.

plugin.json (excerpt)
"permissions": ["storage"]

Most plugins declare [] and need nothing.

Gives you wm.storage: a small string-to-string map that belongs to your plugin alone.

wm.storage.set("items", wm.json.encode(items))
local saved = wm.storage.get("items")
  • Local to the device. It cannot leave — there is no network API in the sandbox for it to leave through.
  • Local to your plugin. No other plugin can read it.
  • Deleted when the user uninstalls you, and clearable by them any time from WM KeyboardToolsPluginsyour plugin
  • 128 keys, 64 characters per key, 8 KB per value, 64 KB in total.

Declared permissions are shown to the user before they install, on the addon page and in the file-import confirmation. There is no runtime prompt, because with no way for data to leave the device there is nothing for a prompt to protect — and a prompt for something harmless mostly teaches people to dismiss prompts without reading them.

Not “what requires a permission” — what has no API at all:

What the user typesNo key event API of any kind.
The text they are writing inNo API returns the field’s contents.
The clipboardNo API.
The networkNo HTTP, no sockets, no URL handling.
FilesNo paths, no filesystem.
Other apps, or the deviceNo package list, no identifiers, no sensors.
Android permissionsA plugin cannot request any; it does not have that reach.
Background workNo timers. Execution stops when the panel closes.

The replacement for the text APIs is the user, and it is less limiting than it sounds.

In: draw a ui.input. The user types into it, or taps Paste beside it to drop in whatever they already copied. You are told the contents through input_changed. They can see exactly what they gave you.

Out: draw a ui.output. The keyboard puts an Insert button under it, and tapping that puts your text where they are writing.

So the flow for “encrypt the message I just wrote” is: select it, copy it, open your plugin, tap Paste, tap Encode, tap Insert. Six taps instead of two, and in exchange nothing on the keyboard can read anyone’s messages.

A keyboard sees everything its user types. Third-party code that could read that text and reach the network is a keylogger with extra steps, and no consent dialog makes that untrue — the user cannot audit what a script does with a permission after they grant it.

Google Play’s Device and Network Abuse policy takes the same view for runtime-loaded interpreted code, and names Lua specifically: such code “must not allow potential violations of Google Play policies”. That is a question about what is possible, not about what is consented to. The only answer that holds is not to build the capability.

Security covers how that is enforced.