70 lines
4.2 KiB
Markdown
70 lines
4.2 KiB
Markdown
---
|
|
type: research
|
|
status: analyzed
|
|
confidence: high
|
|
created: 2026-10-17
|
|
question: How should viexp's file-type modules and plugins be designed so Linux users can disable, replace and extend them easily?
|
|
tags: [research, plugins, architecture, lua, wasm]
|
|
---
|
|
|
|
# Extension architecture research
|
|
|
|
## Mechanism comparison
|
|
|
|
| Mechanism | Safety | Ease for users | Host complexity | Hot reload | Proof |
|
|
|---|---|---|---|---|---|
|
|
| External process contract (argv/env/stdout) | low (= shell) | **highest** — any language | very low | free | nnn plugins, lf previewer, ranger scope.sh |
|
|
| Declarative rules (TOML / rifle / mailcap) | high (data, not code) | high — one-liners | low | free | rifle.conf, yazi `[plugin]` tables |
|
|
| In-process Lua (mlua) | medium — sandboxes leak (2025 CVE); Luau is the hardened dialect | medium | medium-high | yes | yazi (mlua 0.12, vendored Lua 5.5), wezterm, neovim |
|
|
| Rhai | high | low (niche language) | low-medium | yes | niche |
|
|
| JS (deno_core/V8) | medium-high | medium | high (~30 MB) | yes | Deno |
|
|
| WASM (wasmtime/extism) | **highest** | lowest (compile a component) | high (WIT churn) | yes | zellij |
|
|
| Host-language plugins (Python) | lowest (monkeypatching) | high for pythonistas | medium, fragile | poor | ranger |
|
|
|
|
## Case-study lessons
|
|
|
|
- **ranger**: the script pipeline (scope.sh + rifle) carried ~90% of real customization; the
|
|
Python layer exists because previews/commands need *state*. Three disjoint mechanisms = confusion.
|
|
- **nnn**: cleanest "process as API": `$1`=file, `$2`=cwd, `$3`=picker; context in env
|
|
(`NNN_FIFO` hover stream); control back via `NNN_PIPE` with tiny opcodes (`1c/etc` = cd ctx 1).
|
|
- **lf**: minimum viable preview contract = `(path, w, h, x, y)` + `cleaner` hook + exit-code
|
|
caching semantics. Document SIGPIPE/exit codes or users suffer.
|
|
- **yazi**: built-ins are preset plugins routed through the same `[plugin]` TOML tables users
|
|
edit (`prepend_*`/`append_*` merge) — one dispatch model for built-in and user code. mlua
|
|
with vendored Lua so users install nothing. Still BETA → in-process scripting is the most
|
|
expensive layer to stabilize.
|
|
- **neovim**: Lua won because the host API is rich, stable and uniform — half-exposed APIs are
|
|
worse than external scripts.
|
|
- **zellij**: WASM gives real sandboxing but locks architecture (single-threaded synchronous
|
|
plugins; WASIp2 migration "a significant undertaking"). Not worth it for v1.
|
|
- **kakoune**: `disabled_hooks` regex = cheap runtime kill-switch worth copying.
|
|
|
|
## Cargo feature flags = compile-time layer, not the primary switch
|
|
|
|
Features (`pdf`, `video`, … default-on) trim binary size and C deps, but feature unification
|
|
breaks packagers, combinations explode, and removing a default feature is a breaking change.
|
|
**Runtime `enabled = false` in modules config must remain the real disable mechanism**; every
|
|
`#[cfg]`-gated module should degrade to a TOML rule pointing at an external tool.
|
|
|
|
## Recommended phasing (adopted)
|
|
|
|
- **v0.1 — declarative core**: every file-type module = rule in a TOML registry mapping
|
|
mime/glob → previewer/opener, with per-module `enabled` switch and `prepend_/append_` merge.
|
|
Built-ins already dispatch through this table → replacing/reordering needs no recompile.
|
|
- **v0.2 — external process protocol**: freeze the script contract —
|
|
`argv = (path, width, height, x, y)`, env context, FIFO/socket write-back, `cleaner` hook.
|
|
Ship bash + Python reference plugins. This is where 90% of Linux-user extensibility lives.
|
|
- **v1.0+ — embedded Lua** (mlua, vendored): only for what scripts cannot do — stateful,
|
|
in-process previews/fetchers — registered through the same tables. Evaluate Luau if
|
|
sandboxing becomes a requirement. WASM explicitly rejected for v1.
|
|
|
|
## Outcome
|
|
Adopted as [[decisions/ADR-002-extension-architecture|ADR-002]] and [[decisions/ADR-003-file-type-modules|ADR-003]].
|
|
|
|
## Sources
|
|
- yazi docs (plugins overview, configuration), yazi Cargo.tomls (mlua 0.12 lua55 vendored)
|
|
- nnn plugins README; lf doc.md; rifle(1); RFC 1524 (mailcap)
|
|
- zellij plugin docs + discussion #4139; wezterm config docs; neovim lua.txt; kakoune FAQ
|
|
- mlua/rhai/gluon repos; deno blog; Lua sandbox-bypass CVE coverage (2025)
|
|
- Cargo book: features.md
|