diaryx_extism
Extism-based third-party plugin runtime for Diaryx.
Loads WebAssembly plugin modules via the Extism runtime
and adapts them to diaryx_core plugin traits. Guest plugins communicate with
the host through a JSON protocol (protocol.rs).
Plugin directory structure
~/.diaryx/plugins/
my-plugin/
plugin.wasm # The WASM module
manifest.json # Cached guest manifest
config.json # Plugin config sidecar
Guest-exported functions
| Function | Input | Output | When called |
|---|---|---|---|
manifest |
"" |
GuestManifest JSON |
At load time |
init |
PluginContext JSON |
"" |
Plugin initialization |
on_event |
GuestEvent JSON |
"" |
File/workspace events |
handle_command |
CommandRequest JSON |
CommandResponse JSON |
Command dispatch |
get_config |
"" |
config JSON | Config read |
set_config |
config JSON | "" |
Config write |
GuestManifest supports optional fields:
requested_permissions— install-time permission defaults and rationale textmin_app_version— minimum Diaryx version required (e.g."1.4.0"); the loader rejects plugins when the running app is too old
Host functions available to guests
| Function | Description |
|---|---|
host_log |
Plugin logging |
host_read_file / host_list_files / host_file_exists |
Workspace reads |
host_write_file / host_write_binary |
Workspace writes (create/edit split by file existence) |
host_delete_file |
Workspace deletes |
host_request_file |
Host-provided selected file bytes (raw bytes; no base64 wrapper on current hosts) |
host_http_request |
HTTP request bridge (feature-gated, supports optional timeout_ms) |
host_storage_get / host_storage_set |
Plugin persistent storage |
host_run_wasi_module |
Execute a WASI module loaded from plugin storage (feature-gated) |
host_plugin_command |
Call another loaded plugin through the host permission bridge |
host_get_runtime_context |
Read generic host runtime context (server/auth/workspace/guest-mode state) |
host_namespace_create / host_namespace_list |
Host-backed namespace creation and listing |
host_namespace_put_object / host_namespace_get_object / host_namespace_delete_object |
Host-backed namespace object writes, reads, and deletes |
host_namespace_list_objects |
Host-backed namespace object metadata listing with optional prefix/limit/offset |
host_emit_event / host_ws_request / host_get_timestamp / host_get_now |
Eventing and utility functions |
Permission enforcement
Permissions are checked in host functions via HostContext.permission_checker.
- If no checker is configured, host calls are denied.
HostContext::with_fs()defaults toDenyAllPermissionChecker.- Loader updates runtime
plugin_idfrom the guest manifestid, so checks are keyed to the canonical plugin ID.
Provided checkers:
DenyAllPermissionChecker— denies every requestAllowAllPermissionChecker— allows trusted bootstrap/plugin-test contexts where no root frontmatter exists yetFrontmatterPermissionChecker— reads root frontmatterpluginsconfig and normalizes workspace file targets to workspace-relative paths before delegating todiaryx_core::plugin::permissions::check_permission
Workspace write/delete host functions return permission and filesystem failures to the guest as ordinary error strings instead of trapping the whole Extism call. Guests can then surface a command error or collect per-file sync errors.
Storage keys are plugin-scoped in host functions ({plugin_id}:{key}), so one
plugin cannot read another plugin's storage by key collision.
plugin_storage is treated as sandbox-safe and defaults to allowed when no
explicit rule exists. File, HTTP, and cross-plugin command permissions still
flow through the configured checker.
Native and browser hosts now both support temporary host_request_file
payloads for plugin commands initiated from UI file-picking flows, so guest
plugins can rely on the same { file_key } -> raw bytes contract on both
platform families.
On iOS, the host also lowers Wasmtime's linear-memory reservation from the
default 4 GiB to a mobile-safe size before instantiating plugins. That avoids
mmap failed to reserve 0x100000000 bytes failures in TestFlight/App Store
builds while still using Pulley's non-JIT execution path.