xfetch has a plugin system that allows extending functionality through standalone executables. Plugins communicate with the core via a JSON protocol over stdin/stdout.
Plugins are standalone executables named xfetch-plugin-<name> (or xfetch-plugin-<name>.exe on Windows). They are spawned as child processes by the xfetch core.
xfetch core ---> stdin (JSON request) ---> plugin process
xfetch core <--- stdout (JSON response) <--- plugin process
xfetch core <--- stderr (error messages) <--- plugin process
There are two types of plugins:
| Kind | Identifier | Purpose |
|---|---|---|
| Logo Animation | logo_animation |
Animates ASCII logos with color effects |
| Info Provider | info_provider |
Returns system or external information lines |
Protocol Version: 1
Request:
{
"version": 1,
"kind": "info_provider",
"args": {
"username": "xscriptor",
"max_lines": 3
}
}The args field contains plugin-specific arguments from the configuration. If no arguments are configured, args is null.
Response:
{
"lines": [
"\uf09b X (@xscriptor)",
"\uf005 114 stars",
"\uf441 33 repos"
]
}Request:
{
"version": 1,
"kind": "logo_animation",
"lines": [
" __ __",
" \\ \\/ /",
" \\ /"
],
"frames": [
["frame 1 line 1", "frame 1 line 2"],
["frame 2 line 1", "frame 2 line 2"]
],
"args": {
"fps": 12,
"duration_ms": 1200,
"loop": false,
"style": "sweep"
}
}The lines field contains the current ASCII logo. The frames field contains optional pre-loaded frame sets. The args field contains animation parameters.
Response:
{
"frames": [
{
"delay_ms": 83,
"lines": ["\u001b[31mcolored line\u001b[0m", "\u001b[32mnext line\u001b[0m"]
}
]
}Each frame has a delay_ms (how long to display the frame) and lines (the frame content, potentially with ANSI escape codes for colors).
Plugins must write error messages to stderr and exit with a non-zero status code on failure.
When executing a plugin, xfetch searches for the binary in this order:
- Explicit path: If the plugin name contains a path separator, use it as a direct file path
- PATH: Search
$PATHforxfetch-plugin-<name> - User plugin directory:
~/.config/xfetch/plugins/(Linux/macOS) or%APPDATA%/xfetch/plugins/(Windows) - Workspace target directories: Various paths relative to the current working directory, including
./plugins/<name>/target/release/ - Development directories: Ancestor directory searches for development setups
# Install from a local directory
xfetch plugin install ./my-plugin
# Install from the official plugin repository
xfetch plugin install animate-logo
# Install from a custom git repository
xfetch plugin install my-plugin --repo https://github.com/user/plugins.git- If the plugin name is a local path, use it directly
- Otherwise, search locally in
./<name>/,./plugins/<name>/, or./plugins/plugins/<name>/ - If not found locally, clone the plugin repository (
https://github.com/xfetch-cli/plugins.gitby default) - Run
cargo build --releasein the plugin directory - Copy the built binary to
~/.config/xfetch/plugins/xfetch-plugin-<name>
# List installed plugins
xfetch plugin list
# Remove a plugin
xfetch plugin remove animate-logoEach plugin has its own reference page with full configuration details, arguments, and output examples.
| Plugin | Kind | Description |
|---|---|---|
| animate-logo | logo_animation |
Animated ASCII logos with color effects (sweep, wave, rainbow, sparkle, breathing, frame) |
| docker | info_provider |
Docker container statistics (total, running, paused, stopped) |
| github-stats | info_provider |
GitHub profile stats (stars, repos, PRs, issues, followers) |
| music-player | info_provider |
Currently playing music from MPD and/or Spotify |
| weather | info_provider |
Current weather via wttr.in (condition, temp, wind, humidity) |
| timezone | info_provider |
Local time, date, timezone name, and UTC offset |
| user-info | info_provider |
User account info (UID, GID, home, shell, groups) |
| display-resolution | info_provider |
Monitor resolution and refresh rate (cross-platform) |
| theme-detection | info_provider |
Desktop theme detection (GTK, KDE Plasma) |
| theme-manager | info_provider |
Theme registry browser and installer |
xfetch-plugin-<name> (Linux/macOS)
xfetch-plugin-<name>.exe (Windows)
[package]
name = "xfetch-plugin-my-plugin"
version = "0.1.0"
edition = "2024"
[dependencies]
serde = { version = "1", features = ["derive"] }
serde_json = "1"
xfetch-plugin-api = { git = "https://github.com/xfetch-cli/api", package = "xfetch-plugin-api" }use xfetch_plugin_api::{
read_info_plugin_args_or_default,
write_info_lines,
};
#[derive(Debug, Default, serde::Deserialize)]
struct PluginArgs {}
fn main() {
let _args = match read_info_plugin_args_or_default::<PluginArgs>() {
Ok(value) => value,
Err(err) => {
eprintln!("{}", err);
std::process::exit(1);
}
};
if let Err(err) = write_info_lines(vec!["Hello from plugin".to_string()]) {
eprintln!("{}", err);
std::process::exit(1);
}
}# Test an info plugin
echo '{"version":1,"kind":"info_provider","args":null}' \
| ./target/release/xfetch-plugin-my-plugin
# Test a logo animation plugin
echo '{"version":1,"kind":"logo_animation","lines":["hello"],"args":{"fps":12}}' \
| ./target/release/xfetch-plugin-my-pluginThe xfetch-plugin-api crate (source at github.com/xfetch-cli/api) provides all the types and helpers needed for plugin development:
- Protocol types:
AnimationFrame,EmptyArgs,InfoPluginRequest,InfoPluginResponse,LogoAnimationArgs,LogoAnimationRequest,LogoAnimationResponse,PluginKind - Entrypoint helpers:
read_logo_animation_request(),read_info_plugin_request(),read_info_plugin_args_or_default(),write_logo_animation_frames(),write_info_lines() - IO helpers:
read_json_from_stdin(),write_json_to_stdout() - Error types:
PluginApiErrorenum with variants for Io, Serialize, Deserialize, InvalidProtocolVersion, InvalidPluginKind, InvalidArgs, EmptyAnimationFrames
- Keep plugins focused on a single responsibility
- Write errors to stderr and exit with non-zero status
- Do not use display or terminal libraries (the core handles rendering)
- Minimize dependencies
- Use the shared
xfetch-plugin-apicrate for protocol types - Handle network or I/O failures gracefully