4.2 KiB
4.2 KiB
type, status, confidence, created, question, tags
| type | status | confidence | created | question | tags | |||||
|---|---|---|---|---|---|---|---|---|---|---|
| research | analyzed | high | 2026-10-17 | How should viexp's file-type modules and plugins be designed so Linux users can disable, replace and extend them easily? |
|
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_FIFOhover stream); control back viaNNN_PIPEwith tiny opcodes (1c/etc= cd ctx 1). - lf: minimum viable preview contract =
(path, w, h, x, y)+cleanerhook + 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_hooksregex = 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
enabledswitch andprepend_/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,cleanerhook. 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 and decisions/ADR-003-file-type-modules.
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