gravityfile features a state-of-the-art, language-agnostic plugin architecture. You can extend the explorer's functionality using Lua, Rhai, or WebAssembly (WASM).
The plugin system is built on three core pillars:
- Event Hooks: React to file system events (scans, navigation, deletions).
- Custom Actions: Implement new file operations with progress reporting.
- Isolated Runtimes: Background tasks (like previews or heavy analysis) run in restricted sandboxes.
Fast, lightweight, and the industry standard for TUI extensibility.
- Engine:
mlua(Lua 5.4) - Best for: UI modifications, event hooks, and simple file operations.
A native Rust scripting language with seamless integration.
- Engine:
rhai - Best for: Performance-critical logic and deep integration with Rust types.
The gold standard for security and portability.
- Engine:
extism - Best for: Complex binary plugins, custom previewers, and untrusted third-party extensions.
Plugins are discovered in the following directories:
- macOS:
~/Library/Application Support/gravityfile/plugins/ - Linux:
~/.config/gravityfile/plugins/ - Windows:
%AppData%\gravityfile\plugins
See examples/plugins/lua/git_notify.lua for a more complex example.
-- Respond to scan completion
function on_scan_complete(self, hook)
local tree = hook.tree
gf.notify(string.format("Scan complete: %d files found", tree.stats.total_files), "info")
end
return {
on_scan_complete = on_scan_complete
}- 🌙 Lua: Git Status Notifier - Alerts when entering a directory with untracked files.
- 🦀 Rhai: Large File Warning - Logs a warning if a massive file is detected during a scan.
- 🕸️ WASM: Rust PDK Example - A starter template for high-performance binary plugins.
gravityfile employs a "Security First" approach. Plugins can be restricted using a SandboxConfig:
- Read/Write Caps: Restrict plugins to specific directory subtrees.
- Resource Limits: Enforce memory (e.g., 64MB) and execution time (e.g., 5s) limits.
- API Permissions: Opt-in to dangerous APIs like
ExecuteorNetwork.
The fs namespace provides safe, sandboxed access to the filesystem:
fs.read(path, limit): Read file content (string).fs.read_bytes(path, limit): Read raw bytes.fs.exists(path): Check existence.fs.metadata(path): Get size, timestamps, and permissions.
Note: In isolated contexts, all fs calls are validated against the plugin's allowed_read_paths.
gf.log_info(msg)/gf.log_warn(msg)/gf.log_error(msg)gf.notify(msg, level): Show a TUI notification.gf.version: Current gravityfile version.
ui.span(text, style): Create a styled text fragment.ui.line({spans}): Create a line of text.ui.paragraph({lines}): Create a multi-line text block.ui.colors: Access theme colors (colors.red,colors.blue, etc.).
WASM plugins must export specific functions following the Extism pattern. Input and output are exchanged via JSON-serialized buffers.
Example Export (Rust/WASM):
#[extism_pdk::plugin_fn]
pub fn on_scan_complete(hook: Hook) -> FnResult<HookResult> {
// Logic here...
Ok(HookResult::ok())
}Plugins are executed asynchronously where possible. For high-latency operations (like network calls or heavy computation), always use the Isolated Context to prevent UI hangs.