xfetch supports external plugins that run as separate executables. The core binary discovers a plugin, sends a JSON request on stdin, and reads a JSON response on stdout. The runtime stays in the core repository, while official plugin implementations live in the dedicated plugins repository.
Official plugins and the full authoring guide are maintained at:
https://github.com/xfetch-cli/pluginsUse that repository for plugin source code, plugin-specific documentation, and contribution guidelines.
End users should install official plugins by name from the remote repository:
xfetch plugin install animate-logoThe core downloads the plugin source from the official remote, builds it, and installs the resulting binary into the xfetch plugin directory.
A plugin can be a WebAssembly artifact instead of a native executable. The
core detects wasm binaries by their header, runs them in a sandboxed wasmtime
runtime and keeps the same JSON protocol, so configuration, listing and
timeouts behave identically. Wasm plugins can be written in Rust, Python,
Go, C and other languages that target wasm32-wasip1 or the
component model.
xfetch plugin install ./plugins/wasm-pacman
xfetch plugin install https://example.com/releases/plugin.wasm
xfetch wasm inspect ~/.config/xfetch/plugins/xfetch-plugin-wasm-pacman.wasm
xfetch wasm run ./plugin.wasm --request '{"version":1,"kind":"info_provider"}'Capabilities (HTTP, processes, filesystem, environment) and limits are declared in a manifest next to the artifact. See WASM.md for the full reference and the example plugins.
Timeouts: wasm guests do not usewith_timeoutworker threads (not available onwasm32-wasip1); the runtime enforces the deadline through wasmtime epochs, using the manifesttimeout_msor the configtimeout_secsvalue.
Plugins are configured in the main config file. The plugin value can be a
short name or a full path to an executable.
{
"logo_animation": {
"plugin": "animate-logo",
"style": "frame",
"fps": 6,
"duration_ms": 8000,
"loop": true,
"frames_path": "~/.config/xfetch/logos/fox.txt"
}
}
For the frame style, frames_path can be a single file whose
frames are separated by a line containing ===, or an array of files (one
per frame). Other style values include sweep (default),
wave, rainbow, sparkle, breathing,
and none.
Note:duration_msandlooponly apply to the one-shot animation (daemon mode off). With"daemon": truethe animation loops indefinitely and these fields are ignored. See DAEMON.md.
Every plugin declares its own runtime budget in its code via
xfetch_plugin_api::with_timeout — this is the primary control
and is required by the official plugin standard (enforced in CI).
Plugins respond with fallback lines when the budget elapses, so the core
always gets a response.
As a safety net for uncooperative or third-party plugins, the core can also kill the plugin process after a per-plugin deadline set in the config. It is opt-in: without it, the current behavior is unchanged.
{
"info_plugins": [
{ "plugin": "weather", "timeout_secs": 20 }
],
"logo_animation": {
"plugin": "animate-logo",
"timeout_secs": 10
}
}
xfetch communicates with plugins using JSON over stdin/stdout. The request includes the plugin kind plus any plugin-specific arguments. The response returns either rendered lines or animation frames.
{
"version": 1,
"kind": "logo_animation",
"lines": ["__ __", " \\ \\/ /"],
"args": {
"fps": 12,
"duration_ms": 1200,
"loop": false
}
}
{
"frames": [
{
"delay_ms": 80,
"lines": ["__ __", " \\ \\/ /"]
}
]
}
All official plugins, their documentation, and the development guide are maintained in the xfetch-cli/plugins repository:
- Plugin catalog & reference: github.com/xfetch-cli/plugins
- Plugin development guide: docs/README.md
- Shared plugin API crate: github.com/xfetch-cli/api