Extensions

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.

Installation

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).

WebAssembly Extensions

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.

Activation

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 }
    ]
}

Available Extensions

ExtensionDescription
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.

Protocol

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.

Authoring

Official extensions and the authoring guide are maintained in the xfetch-cli/extensions repository. The shared wire protocol types live in xfetch-cli/api.