Expand description
§znative — native plugin SDK for zshrs
zshrs is the first JIT-compiled Unix shell; this crate is what makes it
the first compiled shell that hosts third-party plugins written in
a native compiled language (Rust) and loaded at runtime — no
recompile of the shell, no zsh script glue. A plugin is an ordinary
cdylib that the shell dlopens via zmodload -R <path>.
The boundary between host and plugin is a hand-rolled, versioned
C ABI (#[repr(C)] structs + extern "C" fn pointers). Both
sides depend on THIS crate so they agree on the exact layout. Nothing
about Rust’s unstable repr(Rust) layout, allocator, or panic ABI
crosses the boundary — only C-representable data.
§Writing a plugin
use znative::{declare_plugin, Args, Host};
use std::os::raw::c_int;
fn hello(host: &Host, args: &Args) -> c_int {
host.print(&format!("hello from rust, argv={:?}\n", args.to_vec()));
0
}
declare_plugin! {
name: "hello",
version: "0.1.0",
builtins: { "rhello" => hello },
}Cargo.toml:
[lib]
crate-type = ["cdylib"]
[dependencies]
znative = "0.12"cargo build produces libhello.dylib / libhello.so; then inside
zshrs: zmodload -R ~/plugins/libhello.dylib and rhello is a live
command.
§Host API
Inside a handler, Host is the shell’s callback table:
| Method | Purpose |
|---|---|
print | write to the shell’s stdout |
eval | run shell code, return its exit status |
getvar / setvar | read/set a shell scalar parameter |
getfunction / addfunction | read a function’s deparsed body / define one (also deparse-as-a-service) — ABI v3 |
register_builtin | register a command handler dynamically |
add_match / install_completion | emit a completion candidate / wire a native completion into compsys — ABI v2 |
Macros§
- declare_
plugin - Declare a plugin: its identity, the builtins it registers, and the
native completions it provides. Expands to the
#[no_mangle] extern "C" fn znative_initthe host looks for, plus the'staticPluginInfo.
Structs§
- Args
- Safe view over a builtin’s
(argc, argv).argv[0]is the command name. - Host
- Safe wrapper over
*const HostApifor use inside a builtin. Cheap to construct; borrows the host table. - HostApi
- The host API table handed to the plugin. Every field is a C-ABI
function pointer into zshrs. Layout is frozen by
ABI_VERSION. - Plugin
Info - What a plugin returns from its
InitFn. The strings must have'staticlifetime (typically string literals via thedeclare_plugin!macro).
Constants§
- ABI_
VERSION - ABI version. Bumped on ANY change to
HostApi,PluginInfo,BuiltinFn, orInitFnlayout/semantics. The host refuses to load a plugin whoseabi_versiondoes not match its own — a mismatched struct layout is undefined behaviour, so this is a hard gate, not a warning. - INIT_
SYMBOL - The one symbol every plugin
cdylibmust export. The host resolves it withdlsymafterdlopen. Signature isInitFn.
Type Aliases§
- Builtin
Fn - A plugin-provided command handler.
- CompFn
- A plugin-provided compsys function override — the native replacement
for a shell completion function named
_NAME(e.g._command_names). Same C-ABI shape asBuiltinFn: registered viaHostApi::register_compfnand dispatched by the host’s completion router (try_rust_dispatch) in place of the built-in Rust port or the autoloaded shell function.argv[0]is the_NAME;argv[1..]are the completion-function arguments. (ABI v4.) - InitFn
- Signature of
INIT_SYMBOL. Called exactly once, right after the dylib is loaded. The plugin registers its builtins throughhost.register_builtinand returns a pointer to a'staticPluginInfodescribing itself (or null on failure).