Extensions hook into the xfetch lifecycle at config load time: they receive the fully resolved configuration via stdin and return a modified version via stdout. They can change layouts, modules, colors, icons, logos, or load an entirely different config file.
Unlike plugins (which provide info lines or animate logos), extensions operate on the config itself before rendering happens.
xfetch extension install <name>
Or install from a local path / repository:
xfetch extension install /path/to/xfetch-extension-name
xfetch extension install my-extension --repo https://github.com/user/extensions.git
List, inspect and remove installed extensions:
xfetch extension list
xfetch extension list --verbose
xfetch extension info <name>
xfetch extension search <query>
xfetch extension available
xfetch extension remove <name>
search reads the extensions catalog (index.json),
filters by name, description or runtime, and prints the matching install
command. available lists the whole catalog, --json
emits JSON, and XFETCH_EXTENSION_INDEX overrides the catalog URL.
After a successful install, xfetch prints the
"config_providers" entry, the declared capabilities and the
manifest limits. list --verbose adds the manifest kind, runtime,
version and whether the extension is enabled; info prints the
details for one extension. Direct wasm files and URLs accept
--name and --manifest; directory and repository
installs use their own name and manifest.
Installed binaries live in ~/.config/xfetch/extensions/ and are named
xfetch-extension-<name> (.exe on Windows).
Extensions can be WebAssembly artifacts: the core detects the header, runs the guest in the sandbox and feeds it the resolved config JSON. Capabilities (for example reading an allowlisted config directory) come from the manifest, and limits are enforced by the runtime.
xfetch extension install ./extensions/wasm-night-mode
xfetch extension install ./extensions/wasm-updates-footer
See WASM.md for the manifest schema, host calls and examples.
Pin an extension with --sha256 <64-hex-digest> from a
channel independent of the artifact; the digest is enforced on downloaded,
checked-in, built and direct-file wasm installs. A manifest
sha256 field is checked too, but it is integrity-only because
it shares the artifact's origin. A mismatch aborts the install; an unpinned
download prints an unverified integrity warning.
Native extensions run as ordinary processes, unsandboxed, with your user privileges; only wasm extensions use the wasmtime sandbox.
Extensions are enabled with the config_providers field in the config.
They run in declaration order, after the theme merge:
{
"config_providers": [
{
"extension": "config-roulette",
"args": {
"routes": "~/.config/xfetch/routes.json",
"strategy": "random"
}
}
]
}
Extensions declare their own runtime budget via
xfetch_extension_api::with_timeout (required by the official
standard). As a safety net, the core can kill an extension after an
optional per-extension deadline:
{
"config_providers": [
{ "extension": "config-roulette", "timeout_secs": 5 }
]
}
| Extension | Description |
|---|---|
layout-override |
Overrides the layout and/or modules at load time. |
config-roulette |
Picks a random ("random") or per-day ("daily") config from a JSON list of routes — every invocation can show a different look. |
The core and extensions communicate with JSON over stdin/stdout:
Request
{
"version": 1,
"kind": "config_provider",
"config": { ... },
"args": { ... }
}
Response
{
"config": { ... }
}
The extension receives the fully resolved xfetch configuration (defaults + config file + theme), modifies the fields it cares about, and returns the entire config object. Unchanged fields are preserved.
Errors should be printed to stderr and the process should exit with a non-zero status.
Official extensions and the authoring guide are maintained in the xfetch-cli/extensions repository. The shared wire protocol types live in xfetch-cli/api.