-
Notifications
You must be signed in to change notification settings - Fork 4
Plugins
Cultiva 1.7.0 · Linden loads community plugins from a public registry over HTTPS. Plugin code runs in a strict sandbox; the desktop app bridges selected UI into the main window (header chips, garden widgets, modal sheets).
- Open Settings → Plugins.
- Enable the master Plugins toggle.
- Browse the catalog (default registry: krwg/cultiva-plugins).
- Click Install on a plugin, then configure via Settings or the plugin's header chip.
Registry URL (raw):
https://raw.githubusercontent.com/krwg/cultiva-plugins/main/registry.json
| Plugin | Surface | Permissions | Notes |
|---|---|---|---|
| Weather | Header + garden | network, storage, ui | Open-Meteo, 1100+ RU cities offline |
| Time | Header | storage, ui | Timezones, 12/24h, accent colors |
| Radio | Header | storage, ui | SomaFM streams, sleep timer |
| Pomodoro | Header | storage, ui | 25/5 focus timer |
| Quote of the Day | Garden | ui | Daily inspiration |
| Streak Celebrator | Hook | ui | Toast on habit complete |
Full catalog + install flow: cultiva-plugins docs.
Installed files are copied to your user profile, not the git clone:
%APPDATA%/Cultiva/cultiva-plugins/<plugin-id>/
The app verifies sha256 hashes from registry.json before loading.
| Layer | Role |
|---|---|
| Registry | Signed file list (sha256 per asset) |
| Sandbox iframe |
new Function('context','hooks', source) — no direct DOM |
| Permissions |
manifest.permissions: network, storage, ui — enforced at RPC |
| Main process | Optional data.read for bundled plugin files (Electron IPC) |
Plugins cannot access Cultiva's IndexedDB, arbitrary filesystem paths, or window.electron from the sandbox.
Sandboxed code cannot touch the real DOM. Use these APIs:
| API | Purpose |
|---|---|
context.ui.openMainSheet(html) |
Apple-style modal sheet |
context.ui.closeMainSheet() |
Close sheet |
context.ui.updateMainHeader({ label, icon, labelColor? }) |
Header chip |
context.ui.registerGardenWidget({ render, position?, onTapMethod? }) |
Garden HTML block |
context.ui.showNotification(title, body) |
OS-style toast |
context.storage.get/set |
Namespaced async KV |
context.data.read(path) |
Read bundled files from manifest data
|
onModalAction(action, payload) |
Handle data-cultiva-* sheet actions |
Set "minAppVersion": "1.7.0" if you use permissions, data.read, or manifest-driven settings.
| Hook | When |
|---|---|
onAppStart |
App launch after plugin load |
onHabitComplete |
Habit toggled complete (via toggleHabitWithHooks) |
Register with this.hooks.on('onHabitComplete', (habit) => { … }).
- Disabling the master Plugins toggle may not fully stop sandboxes — tracked in issues.
- Sheet search inputs lose focus when the sheet is fully rebuilt — core fix planned.
- Garden widget
position: 'top'|'bottom'is stored but not yet applied. - Pomodoro sheet styling depends on other plugins unless shared sheet CSS lands in core.
See Troubleshooting for workarounds.
| Resource | Link |
|---|---|
| Author guide (this wiki) | Cultiva Plugins Guide |
| In-repo guide | PLUGIN_AUTHOR_GUIDE.md |
| Registry repo | cultiva-plugins |
| Type definitions | cultiva-plugin.d.ts |
- Architecture — plugin-manager flow
- Privacy and Security
- Desktop Build