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. This keeps the plugin system decoupled from the core and allows plugins to be installed independently.
The core looks for plugin executables in the following order:
- Explicit path in the config (if provided)
- PATH using the prefix xfetch-plugin-
- User plugin directory: ~/.config/xfetch/plugins
- Repository development path: ./plugins/<name>/target/release
Plugins are configured in the main config file. Each plugin section defines the name to run and any plugin-specific arguments. The plugin value can be a short name or a full path to an executable.
{
"logo_animation": {
"plugin": "animate-logo",
"fps": 12,
"duration_ms": 1200,
"loop": false
}
}
xfetch communicates with plugins using JSON over stdin/stdout. The request includes the logo lines and plugin arguments. The response returns either a list of frames (for animation) or transformed lines (for colorization).
{
"version": 1,
"kind": "logo_animation",
"lines": ["__ __", " \\ \\/ /"],
"args": {
"fps": 12,
"duration_ms": 1200,
"loop": false
}
}
{
"frames": [
{
"delay_ms": 80,
"lines": ["__ __", " \\ \\/ /"]
},
{
"delay_ms": 80,
"lines": ["__ __", " \\/\\ /"]
}
]
}
The animate-logo plugin lives in plugins/animate-logo. It reads the logo lines and outputs animated frames. The core will only run the plugin when stdout is a TTY, so non-interactive output stays static.
The plugin supports multiple styles controlled by the style field in the
logo_animation config section:
| Style | Description |
|---|---|
sweep | Color sweep left-to-right (default) |
wave | Sine-wave color pattern that moves across |
rainbow | Full RGB rainbow gradient shifting over time |
sparkle | Random characters light up in bright colors |
breathing | Warm amber fade in/out (breathing effect) |
frame | Cycles through multiple ASCII art files |
none | No coloring, display as-is |
Use style: "frame" with frames_path for animations with
multiple ASCII frames. You can use a single file with frames
separated by === on their own line, or an array of files.
{
"ascii": "~/.config/xfetch/logos/blink.txt",
"logo_animation": {
"plugin": "animate-logo",
"style": "frame",
"fps": 4,
"loop": true,
"frames_path": "~/.config/xfetch/logos/blink.txt"
}
}
Or with multiple files:
{
"ascii": "~/.config/xfetch/logos/blink_open.txt",
"logo_animation": {
"plugin": "animate-logo",
"style": "frame",
"fps": 4,
"frames_path": [
"~/.config/xfetch/logos/blink_open.txt",
"~/.config/xfetch/logos/blink_half.txt",
"~/.config/xfetch/logos/blink_closed.txt",
"~/.config/xfetch/logos/blink_half.txt"
]
}
}
cargo install --path plugins/animate-logocat request.json | xfetch-plugin-animate-logoThis example uses the sample ASCII logo stored in the repository and enables the animate-logo plugin for a full end-to-end test.
- Install the plugin:
cargo install --path plugins/animate-logo - Point the ASCII logo to
plugins/animate-logo/assets/xfetch_logo.txt - Enable the plugin in your config:
{
"ascii": "/path/to/xfetch/plugins/animate-logo/assets/xfetch_logo.txt",
"logo_animation": {
"plugin": "animate-logo",
"style": "sweep",
"fps": 12,
"duration_ms": 1200,
"loop": false
}
}
Run xfetch in a TTY-capable terminal to see the animated logo.
- Plugins should write errors to stderr and exit with a non-zero status.
- Plugin output must be valid JSON.
- Animations are only rendered on TTY terminals.
- The core only loops animations when a duration is provided.