wallutils: setting wallpapers and reading monitor state from the command line
:city_sunset: Utilities for handling monitors, resolutions, wallpapers and timed wallpapers + display available VRAM
At a glance
- What is it?
- wallutils is a set of Go utilities for handling monitors, resolutions, wallpapers and timed wallpapers on Linux, working across X11 and Wayland and across a long list of desktop environments and window managers. It also reads DPI and VRAM, and it introduces a portable file format for timed wallpapers that it can import from GNOME and macOS sources.
- Who is it for?
- Adopt wallutils if you script your desktop and want wallpaper and monitor handling that does not depend on which window manager or desktop environment you happen to be running. Do not adopt it if you need the GNOME or macOS dynamic wallpaper features on other platforms, because the conversion utilities are the part that handles those formats and the timed wallpaper support is explicitly unfinished in parts.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem, and why one utility set rather than many
The repository description is a compact statement of the scope: utilities for handling monitors, resolutions, wallpapers and timed wallpapers, plus display available VRAM.
The first bullet of the readme says it detects monitor resolutions and sets the desktop wallpaper, for any window manager, and asks you to file an issue if your window manager is not supported yet. That request tells you the shape of the project. There is no single API for setting a wallpaper in Linux, because every desktop environment and window manager has its own mechanism, and a user with a tiling window manager and a user with GNOME need different commands.
So the approach is one tool per operation, each of which knows how to talk to the backends that exist. The repository layout shows that breadth directly, with separate Go source files per environment: cinnamon.go, deepin.go, feh.go, gnome2.go, gnome3.go, hyprctl.go, hyprpaper.go, mate.go, pcmanfmqt.go, pekwm.go, plasma.go, sway.go, swaybg.go, weston.go and xfce4.go, alongside the generic monitor.go, wallpaper.go and res.go.
The interesting pair is gnome2.go and gnome3.go. GNOME changed its wallpaper mechanism between versions, and the older gsettings-based approach and the newer one are different enough to need separate implementations. The same is true across the rest of the list, where sway.go and swaybg.go cover two related but distinct sway mechanisms and feh.go covers the standalone wallpaper setter that many window managers use.
Two of the entries are worth calling out as evidence of how actively the list is maintained against the current desktop landscape. hyprpaper.go and hyprctl.go cover Hyprland, which is a recent arrival and needed two entry points because it offers both its own wallpaper command and a separate daemon. weston.go covers Weston, the reference Wayland compositor, which most people never use but which is the obvious thing to break when a protocol changes underneath you.
The library is also usable from Go directly, so the utilities are not the only interface. The repository has an include/ directory, a pkg/ directory and a vendor/ directory, and the module path is github.com/xyproto/wallutils.
The utility list, and what each one is for
The readme lists fifteen utilities and one script, and grouping them shows what the project is really for.
The setting utilities are setwallpaper, which works both over X and the Wayland protocol, setrandom for setting a random wallpaper, setcollection for setting a suitable wallpaper, in terms of resolution, from an installed collection, and settimed for setting timed wallpapers, which will continue to run to handle time events. The readme notes that this utility has recently been refactored and needs more testing.
The listing utilities are the mirror image. lsmon lists the connected monitors and resolutions discovered by the current window manager or desktop environment, with -d to also list DPI. lscollection lists installed wallpaper collections, with -l to also list the collection type and full path. lswallpaper lists all installed wallpapers, with -l and -s for more information. lstimed lists installed timed wallpapers, with -l to also list paths. And timedinfo shows more information about installed timed wallpapers.
Then the information utilities, which are the ones that go beyond wallpaper setting. getdpi retrieves the average DPI for all monitors, with -a or -l for all monitors and -b to see the DPI both horizontally and vertically. wayinfo shows detailed information about the connected monitors via Wayland, and xinfo shows detailed information about the current X setup.
And vram finds the minimum amount of VRAM available for non-integrated GPUs, with -l to list the bus ID, a description and available VRAM for each GPU, and -i to include integrated GPUs. That last one is unusual and specific enough to be worth explaining, because the answer it gives is the smallest VRAM figure across the discrete cards in the machine rather than the largest or the total. For deciding which GPU to run something on, that is the number that matters, and a tool that reports the maximum would answer a different question.
The example output for lsmon shows the shape of the result, a list of monitor IDs and resolutions:
$ lsmon
0: 1920x1200
1: 1920x1200
2: 1920x1200The script section adds heic-install, for installing a macOS dynamic wallpaper to /usr/share/backgrounds using both ImageMagick convert and heic2stw.
The utility set is also packaged widely, with a packaging status badge pointing at Repology, so the tools are already in most distribution repositories rather than needing to be built from source.
The Simple Timed Wallpaper format
The most interesting thing in the project is a file format, and it is worth understanding why it exists.
Timed wallpapers are the feature where the desktop background changes through the day. The Mojave timed wallpaper and other timed wallpapers can be set with the settimed command, and will cross fade from image to image as the day progresses. The readme also notes that some window managers make it hard to achieve smooth switches of desktop backgrounds, while others make it easy, which is the kind of caveat that only comes from having tried several.
The problem the format solves is that timed wallpaper data lives in mutually incompatible places. GNOME keeps it in XML inside the gsettings schema, and macOS keeps it inside the HEIF file with the .heic extension. Neither is usable elsewhere, and neither is pleasant to edit by hand.
So the project introduces the Simple Timed Wallpaper format, documented as Markdown and as PDF, and provides converters in both directions. GNOME timed wallpapers can be converted to the Simple Timed Wallpaper format with the xml2stw utility. And macOS dynamic wallpapers can be installed with heic-install and used with lstimed and settimed, which extracts the metadata with heic2stw, only timing information, not the azimuth and elevation for the sun yet, and extracts the images with convert that comes with ImageMagick.
That last parenthetical is the interesting limitation. The macOS format encodes not just when the wallpaper changes but where the sun is, which lets the background match the real sky. heic2stw extracts only the timing for now, so the position of the sun is lost in the conversion. It is an honest statement of what the tool does not do yet.
Because the format lives in the repository as a documented specification, a third party can write a converter, and a user can hand-write a timed wallpaper in a text editor rather than having to reverse-engineer GNOME's XML. That is the value of the format: it makes timed wallpapers a portable artefact instead of a per-desktop setting.
Building it, and the static option
The build requirements are explicit and there are more of them than a Go program would normally need.
Go 1.11 or later, with 1.17 or later recommended, although the go.mod in the repository declares go 1.26.0. A working C compiler, tested with GCC 8.2.1. Header files for Wayland and X. And libheif for heic2stw and heic-install.
The runtime requirements are the matching shared libraries, libwayland-client.so for Wayland support, libX11.so for X support and libheif.so for HEIF image support. Plus swaybg and pkill for Wayland-based window managers like Labwc, and lspci from pciutils plus nvidia-smi for NVIDIA GPUs for the vram utility.
The build options are where the design shows. The executables related to X can be removed after building if you only wish to keep the Wayland-related functionality, and the same for Wayland. And it is possible to build with make static, to only build the utilities that do not depend on any of the above .so files, as statically compiled ELF executables.
The Makefile handles the static case by listing the affected commands as commented-out lines. getdpi, heic2stw and lsmon are commented out in the static target because they depend on dynamic libraries, while lscollection, lstimed and lswallpaper are built statically. So a user who wants a single static binary for a minimal system gets exactly the subset that can be static, and the Makefile documents which ones those are by commenting them out.
The build flags are also tuned per platform. On Arch Linux, detected by the presence of /usr/share/factory/etc/arch-release, the LDFLAGS include optimisation, section sorting, as-needed, relro and now, and the build flags add position-independent executables, trimming and an external link mode. Elsewhere the defaults are simpler, with vendored modules and path trimming.
There is also a GOEXPERIMENT setting of greenteagc, which is the experimental garbage collector in the Go runtime, and the all target tolerates a failure of heic2stw specifically, on the grounds that the wrong version of libheif may be installed.
The build requirements list also names the C compiler and the X headers as a separate item from Go itself, which is what cgo needs, and the presence of backend_nocgo.go and closest_nocgo.go in the repository listing is the counterpart: the same functionality with a build-tag-free path for builds that cannot use cgo.
Using the package from Go
The utilities are the visible face of the project, but the library underneath is usable directly, and the readme shows how.
The two operations it documents are reading the monitors and setting a wallpaper. Retrieving monitor resolutions looks like this:
package main
import (
"fmt"
"os"
"github.com/xyproto/wallutils"
)
func main() {
// Retrieve a slice of Monitor structs, or exit with an error
monitors, err := wallutils.Monitors()
if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
os.Exit(1)
}
// For every monitor, output the ID, width and height
for _, monitor := range monitors {
fmt.Printf("%d: %dx%d\n", monitor.ID, monitor.Width, monitor.Height)
}
}The shape of that API is worth noting. Monitors returns a slice of Monitor structs and an error, and the error path is handled explicitly with a message to stderr and a non-zero exit, rather than a panic or a silent empty result. The Monitor struct carries an ID, a Width and a Height, and the example prints exactly those.
The wallpaper call is smaller:
fmt.Println("Setting background image to: " + imageFilename)
if err := wallutils.SetWallpaper(imageFilename); err != nil {
return err
}So the library exposes one function per operation with an error return, and the backends for the different desktops are hidden behind it. That is the design that makes the project useful as a dependency as well as a set of commands, and it is what allows a script to set a wallpaper without shelling out to the right utility for whatever compositor happens to be running.
The dependency list is short and tells you what the library needs to do the work. The anthonynsimon/bild package handles image manipulation, fatih/color is for terminal output, stretchr/powerwalk walks directory trees for the wallpaper collection search, urfave/cli is the command line framework the utilities are built on, xyproto/env is an environment helper, and xyproto/heic is the HEIF reader the macOS wallpaper extraction needs.
The indirect dependencies include nativewebp for WebP handling, the antchfx XML and XPath libraries for parsing GNOME's timed wallpaper XML, and howett.net/plist for property lists, which is the format macOS uses for its own metadata.
Editorial conclusion
Adopt wallutils if you script your desktop and want wallpaper and monitor handling that does not depend on which window manager or desktop environment you happen to be running. Do not adopt it if you need the GNOME or macOS dynamic wallpaper features on other platforms, because the conversion utilities are the part that handles those formats and the timed wallpaper support is explicitly unfinished in parts. Before you commit, check the list of supported desktop environments against your own, since the readme asks you to file an issue if yours is missing, and decide whether you want the CGO build or the static one.
Frequently asked questions
What is the wallutils project?
It is a set of Go utilities for handling monitors, resolutions, wallpapers and timed wallpapers, plus reporting available VRAM. It detects monitor resolutions and sets the desktop wallpaper for any window manager, with separate implementations per desktop environment and compositor, and it is packaged in most distribution repositories through Repology.
Which desktop environments and window managers does wallutils support?
The repository has separate source files per environment, including Cinnamon, Deepin, feh, GNOME 2 and GNOME 3, Hyprctl and Hyprpaper, Mate, PCManFM-Qt, PekWM, Plasma, Sway and swaybg, Weston and Xfce4. The readme asks you to file an issue if your window manager is not supported yet.
What is the Simple Timed Wallpaper format?
It is a new file format introduced by the project for timed wallpapers, documented as Markdown and PDF, so that timed wallpaper data is portable rather than locked inside GNOME's gsettings XML or a macOS .heic file. xml2stw converts GNOME timed wallpapers into it, and heic2stw extracts timing information from macOS dynamic wallpapers.
What does the vram utility in wallutils report?
It finds the minimum amount of VRAM available for non-integrated GPUs, with -l to list the bus ID, a description and available VRAM for each GPU, and -i to include integrated GPUs. It depends on lspci from pciutils and on nvidia-smi for NVIDIA GPUs.
How do I install a single wallutils utility?
With Go 1.17 or later you can install one command directly, for example go install github.com/xyproto/wallutils/cmd/getdpi@latest. Building the whole project also works, with make followed by sudo make PREFIX=/usr/local install, and there is a make static target that builds only the utilities not depending on the shared libraries.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/xyproto-wallutils)Was this useful?