Plugin system
ReadAware plugins can work with reading data, add native actions and providers, extend the reading assistant, and ask the host for bounded services. Installed packages load dynamically; the app never needs a switch for each plugin ID.
One model, three capability families
Every executable plugin capability has one of three shapes. Choosing the right shape is the first authoring decision.
| Family | Use it when | Examples |
|---|---|---|
| Domain | ReadAware already owns the state or behavior. | Library, reading, annotations, conversations, settings |
| Contribution | The plugin supplies a new choice or implementation. | Actions, commands, voices, content, themes, agent providers |
| Service | The host must perform a bounded external operation. | Storage, secrets, schedules, network, LLM, clipboard |
Declarative view, settings, and theme schemas sit beside these families. They describe host-rendered data; they do not grant another source of authority.
Settings is a domain
Appearance is a Settings section, not a separate plugin API. A plugin that changes the selected theme requests exact Settings paths such as appearance.theme. A plugin that supplies a new theme uses the themes contribution. Choosing and supplying are deliberately separate powers.
What plugins can add
- Selection and header actions, command-palette commands, and host-rendered views.
- Voices, virtual-book content providers, reader modes, themes, and fonts.
- Agent tools, per-turn context, searchable private sources, and memory candidates.
- Plugin settings, dynamic options, recurring work, storage, and encrypted secrets.
- Reads, commands, and committed event subscriptions across granted product domains.
Browse the complete, versioned roster in the capability browser. It also includes a permission preview for manifest.json.
Native UI, by construction
Plugins do not mount React, HTML, CSS, iframes, or arbitrary DOM. They return validated view data and callbacks; ReadAware owns layout, navigation, accessibility, theme compatibility, loading states, and cleanup. New visual freedom arrives as a bounded schema or a real host contribution point, not a generic webview escape hatch.
The trust boundary
Each plugin runs in its own module Worker. It has no DOM, Tauri, SQLite, filesystem, or process handle, and ambient network and browser persistence APIs are disabled. Host calls cross a message boundary and are resolved against the plugin's actor-scoped capability view.
This limits accidental and direct overreach, but installation remains a software trust decision. Before code runs, ReadAware shows semantic permissions and exact Settings grants. Capability requirements are checked separately: permission answers “may it do this?”, while a version requirement answers “can it use this contract correctly?”
Activation and updates are transactional
activate() is a read-and-declare phase. Registrations stay invisible while the host drains calls and health-checks the Worker; writes, secrets, network, LLM, clipboard, UI effects, and navigation are blocked. Persistent data changes run later through a storage-only migrate(). Only a healthy, migrated candidate is promoted.
Updates snapshot files, plugin KV, document collections, and committed schema metadata. A failed activation or migration restores the previous files and data, then restarts the prior runtime when needed.
Current ecosystem
The plugins shipping today are built-in or first-party: Dictionary, Editorial Themes, RSS Reader, Sentence Reader, TTS Voices, and Theme Schedule. The public readaware-plugins repository contains the authoring template, public declarations, validation, and marketplace registry. There is no legacy third-party API to preserve; the current contract is the baseline.
Start building
Follow Build a plugin for the local loop, use the API reference while implementing, and read Publishing before submitting a marketplace change.