Skip to content

Plugins

krwg edited this page Jul 8, 2026 · 2 revisions

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).


Quick start

  1. Open Settings → Plugins.
  2. Enable the master Plugins toggle.
  3. Browse the catalog (default registry: krwg/cultiva-plugins).
  4. 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

Official catalog (registry 3.0.0)

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.


Where plugins live on disk

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.


Security model (1.7)

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.


Main-window UI bridge

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.


Hooks

Hook When
onAppStart App launch after plugin load
onHabitComplete Habit toggled complete (via toggleHabitWithHooks)

Register with this.hooks.on('onHabitComplete', (habit) => { … }).


Known limitations (1.7)

  • 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.


Authoring plugins

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

See also

Clone this wiki locally