Skip to content

theHamdiz/wallfetch

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Wallfetch

A fast wallpaper fetcher and rotator written in Zig.

Download a fresh set of wallpapers, skip junk you already have, rotate them on a timer, and hook into your desktop without dragging in a pile of runtime dependencies.


What this project is

wallfetch started as a simple idea: grab a lot of good-looking wallpapers into one folder without having to babysit shell one-liners.

It grew into something more useful than that.

Now it is a small Zig CLI that focuses on a few things that matter in day-to-day use:

  • getting wallpapers quickly
  • not redownloading the same content forever
  • behaving nicely when the network is flaky
  • fitting into a normal Linux desktop setup
  • staying lightweight and easy to own

The project is meant to feel like a real tool, not a demo binary that happens to compile once and then ruins your afternoon.

Repository: https://github.com/theHamdiz/wallfetch


What wallfetch does

Download wallpapers in parallel

It pulls wallpaper candidates from online sources and downloads them with concurrency tuned for network throughput, not just CPU usage.

Retry when the internet does internet things

Each download can retry with exponential backoff, so a temporary failure does not kill the whole run.

Skip duplicates intelligently

It can hash files and avoid keeping the same content twice, even when filenames differ.

Work with categories

You can ask for a mood instead of a random grab bag.

Current categories include:

  • curated
  • dark
  • minimal
  • anime
  • nature
  • abstract
  • space
  • city

Rotate wallpapers automatically

It can install a user-level systemd timer so your wallpaper rotates in the background without sudo and without turning your machine into a science fair project.

Apply wallpapers to your desktop

Desktop integration is optional.

  • KDE: uses plasma-apply-wallpaperimage if it exists
  • Niri: uses swww if it exists

If those tools are not present, wallfetch still handles downloading, selecting, and rotation logic just fine.


Design goals

This project is built around a few simple rules:

  • fast first
  • zero external runtime dependency in the core downloader
  • safe file handling
  • good defaults
  • clean CLI output
  • no sudo for normal usage

That last one matters.

A normal zig build -Doptimize=ReleaseFast installs the binary to the usual Zig output path and to ~/.local/bin, so it is easy to run as a regular user as long as that directory is in your PATH.


Project layout

.
├── build.zig
├── README.md
└── src/
    └── main.zig

build.zig

The build script compiles the project and installs it in two places:

  • zig-out/bin/wallfetch
  • ~/.local/bin/wallfetch

That gives you the normal Zig workflow plus a user-friendly install target.

src/main.zig

This is the actual application:

  • argument parsing
  • interactive prompts
  • downloading
  • retries
  • hashing and deduplication
  • wallpaper selection
  • desktop integration
  • systemd timer installation

Build

zig build -Doptimize=ReleaseFast

That mode is chosen on purpose. wallfetch is built for runtime speed first.

If your shell does not already include ~/.local/bin in PATH, add it once:

bash / zsh

echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

fish

fish_add_path $HOME/.local/bin

Quick start

Download 100 wallpapers with defaults:

wallfetch --yes

Download dark wallpapers and skip files you already have:

wallfetch --yes --category dark --count 100 --existing skip

Download into a custom folder:

wallfetch --yes --dest ~/.local/share/backgrounds

Rotate a wallpaper from the folder and apply it if possible:

wallfetch rotate --yes --dest ~/.local/share/backgrounds --apply --backend auto

Install the user timer so rotation happens automatically every 20 minutes:

wallfetch install-timer --yes --dest ~/.local/share/backgrounds --backend auto --apply --interval-minutes 20
systemctl --user daemon-reload
systemctl --user enable --now wallfetch-rotate.timer

Commands

Download

Default command if you do not specify one.

wallfetch [options]
wallfetch download [options]

Rotate

Pick a wallpaper from disk and optionally apply it.

wallfetch rotate [options]

Apply

Apply a chosen wallpaper to a supported desktop backend.

wallfetch apply [options]

Install timer

Write the user-level systemd unit and timer for wallpaper rotation.

wallfetch install-timer [options]

Main options

--yes, -y
--dest <dir>
--state-dir <dir>
--count <n>
--category <name>
--width <px>
--height <px>
--pages <n>
--concurrency <n>
--retries <n>
--existing <skip|overwrite>
--backend <auto|kde|niri|none>
--interval-minutes <n>
--index <n>
--dry-run
--verbose
--no-dedup-scan
--apply

A few useful notes:

  • --existing skip is the sane everyday default
  • --verbose is for when you want the chatter
  • --dry-run is there when you do not trust anything yet, which is honestly healthy
  • --backend auto tries to do the sensible thing

Backends

KDE

If plasma-apply-wallpaperimage is available, wallfetch can tell KDE to switch the wallpaper directly.

Niri

If swww is available, wallfetch can use it as the wallpaper backend.

None

If you only want to download and rotate selections without applying them, use:

--backend none

How file handling works

This matters more than it sounds.

wallfetch does not write straight into the final file and hope for the best. The intended behavior is:

  1. download to a temporary path
  2. verify or hash when needed
  3. move into place

That keeps partial downloads from pretending to be valid wallpapers.


Performance notes

The project is aimed at throughput.

That means:

  • concurrency is tuned for network-heavy work
  • retries are built in
  • existing files can be skipped early
  • content hashing helps avoid silent duplication
  • ReleaseFast is the default build mode for a reason

This is not trying to win a smallest-binary contest. It is trying to get work done quickly and reliably.


Zero-dependency core, with one honest caveat

The core program is designed to avoid runtime dependency bloat.

Desktop wallpaper application is the only place where the outside world naturally leaks in:

  • KDE needs KDE's wallpaper tool
  • Niri generally relies on swww
  • systemd timer installation obviously assumes systemd if you want timer support

So the right way to think about it is:

  • downloader core: self-contained
  • desktop adapters: optional

Current state of the project

The repo represents the full tool, not just one isolated version bump.

The way to think about its evolution is roughly this:

  • v1: get wallpapers into a folder
  • v2: make it safer, cleaner, and more pleasant to use
  • v3: add better throughput, smarter deduplication, categories, rotation, and desktop integration

So while the current feature set is the most complete one, the project itself is the whole story: a wallpaper tool that kept getting sharper instead of bloating into nonsense.


Troubleshooting

The binary is not found after build

Make sure ~/.local/bin is in your PATH.

The wallpaper does not apply on KDE

Check that plasma-apply-wallpaperimage exists on your system.

The wallpaper does not apply on Niri

Check that swww is installed and running.

The timer does not start

Run:

systemctl --user daemon-reload
systemctl --user enable --now wallfetch-rotate.timer

Zig build complains about build API fields

Zig's build APIs do move around. If that happens, fix the build script first before assuming the application code is broken. The current build.zig avoids fragile compile-step fields that have changed between releases.


Contributing

If you want to improve the downloader, UI, desktop adapters, or source selection logic, great. Small focused pull requests are welcome.

Good tooling ages well when people keep trimming the stupid parts off it.


License

MIT

About

A wallpaper fetcher / manager built in zig.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Languages