# feh is an X11 image viewer that also catalogues, sorts and sets wallpapers

> feh is a small C program that does more than display images: it compiles thumbnail and text listings, runs custom action scripts, reloads on change, and can set the X11 background from a command line. The build is a plain makefile with per-feature flags, and the project is a hobby project with a deliberately narrow scope.

**derf/feh** — a fast and light image viewer

- Repository: https://github.com/derf/feh
- Website: https://feh.finalrewind.org
- Stars: 1,926 · Forks: 174
- Language: C
- License: NOASSERTION
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/derf-feh

## It is a viewer, a cataloguer and a wallpaper setter in one binary

feh describes itself as a light-weight, configurable and versatile image viewer aimed at command line users, though it can also be started from graphical file managers. The scope is wider than a viewer that opens a window. It can compile text and thumbnail listings, show files it cannot load, and set X11 backgrounds, and the feature list includes filelists, various image sorting modes, custom action scripts and image captions. Control is not only by keyboard and mouse: feh can be driven by configurable keyboard and mouse shortcuts, terminal input and signals, which is what makes it usable from a script or a tiling window manager keybinding. With no file arguments and no filelist, it displays everything in the current directory, so `feh` alone is a quick way to look at a directory of images.

## Optional features are make flags, not configure options

The build is a plain makefile with no autoconf step for the normal path, and every optional feature is a flag. The core dependencies are Imlib2, libpng, libX11 and libXt, with libcurl for HTTP images and libXinerama for multiscreen setups. Two more are conditional on their own flags: libexif for built-in EXIF tag display, and libmagic for filtering unsupported formats. The flag list is documented as a table, and a default of 1 means the feature is on by default. Two entries are worth reading closely. The `mkstemps` flag checks whether your libc provides `mkstemps()`, and setting it to 0 means feh cannot load gif images via libcurl, which is an oddly specific consequence to discover late. The `verscmp` flag covers `strvercmp()`, with an internal implementation as a fallback:

```bash
$ make xinerama=0 debug=1
```

That single command disables Xinerama support and produces a debug build, which enables the `--debug` option, while libcurl and natural sorting stay enabled.

## PREFIX and DESTDIR behave the way packagers expect

The install step takes the standard variables `CFLAGS`, `LDLIBS`, `PREFIX` and `DESTDIR`, and the defaults live in a separate `config.mk` file that is designed so you can set environment variables rather than edit it. `PREFIX` defaults to `/usr/local` and controls where the application and its data files land, and it has to be set both during the build and during `make install`. `DESTDIR` defaults to empty and sets the installation root, which is mostly useful for package maintainers. The documented pattern is to export both and then build and install:

```bash
$ export DESTDIR=/tmp/feh PREFIX=/usr
$ make && make install
```

The one wrinkle worth knowing about is the `app` flag, which defaults to 0 and installs icons to `/usr/share` regardless of `DESTDIR` and `PREFIX`, then calls `gtk-update-icon-cache` afterwards. The reason given is that installing icons under `/usr/local/share` does not work reliably, so end users are told to run `sudo make install app=1`, while package maintainers and users who do not want the icons in `/usr/share` run plain `sudo make install`. The bundled NotoSans-Medium font is installed by default too, and the `install_fonts` flag exists so a distribution can point at its own system-wide copy instead.

## The test suite runs without an X server

feh's tests are split into two tiers, and the split is the interesting part. The non-X11 parts are tested by `make test`, which requires perl 5.10 or newer and the `Test::Command` module. The tests are non-interactive and do not need a running X11, so they are safe on a headless build server. The Makefile shows the mechanics: the test target depends on the build, then runs `prove test/feh.t test/mandoc.t`, and on ARM or MIPS machines it appends a fallback that prints an imlib2 bug notice, because the same suites fail on those architectures for reasons outside feh's control. The second tier is `make test-x11`, which runs an interactive script and then a background-image test, so it needs a display. A related detail for packagers is that the man page is validated as part of the non-X11 run, since `test/mandoc.t` checks the manual, which catches option documentation drift that a unit test would miss.

## The manual and the help text have to be edited in two places

A detail that catches contributors is stated plainly in the contributing section. feh's options, key bindings and format specifiers are documented in two different places: the manual in `man/feh.pre` and the help text in `src/help.raw`. The help text is not compiled in by default, but it should be kept up to date, and on space-constrained embedded systems the built-in help is more useful than the significantly larger man page. The `help` flag controls whether that text is included, defaulting to 0, and when it is off the help output refers to the man page instead. The repository has an `examples/` directory with `buttons`, `find-lowres`, `keys` and `themes` files, which are the starting points for custom action scripts and configuration. The `src/` tree is C, and the `scripts/` and `share/` directories hold the shell and data side of the project.

## The project is a hobby project with a stated scope

The contributing section sets expectations that are worth reading before you open an issue. Bugfixes are always welcome and can be sent as a pull request, but before proposing a feature you are asked to consider the scope of feh, which is an image viewer and cataloguer and not an image editor or similar, and to remember that the option list is already pretty long, with new features discussed in a feature request first. The maintainer also states that feh is developed as a hobby project and that there is absolutely no obligation for anyone to implement requested features or review merge requests. That is an honest statement of what a small volunteer project can promise, and it is a reasonable thing to weigh when you depend on a feature. The project also states that AI tools such as ChatGPT, Claude, Copilot, Cursor and Grok may not be used to generate code for contributions, while the code itself remains readable under the terms in the licence file, which GitHub does not classify under a standard identifier.

## Where it fits and where it does not

feh is built for X11 and for the command line. It needs Imlib2 for image handling and X11 libraries to draw, which rules it out as a drop-in on a pure Wayland session, and its own scope note rules out anything that wants editing rather than viewing. Within its scope it does two things unusually well: it can be driven entirely by script and by signal, so it fits into a keybinding-driven workflow, and it can produce machine-readable listings, which is what makes it a cataloguer rather than just a viewer. The `--auto-reload` feature needs the `inotify` flag, which is off by default, so a live-updating wallpaper or preview is something you have to ask for at build time. The homepage and the feh(1) manual are where the usage detail lives, since the README covers installation and contribution only.

## Conclusion

Adopt feh if you work on a minimal X11 system and want an image viewer you can drive from a script, a keybinding file or a file manager, since it exposes listings, sorting modes, action scripts and wallpaper setting rather than only a window. Do not adopt it for image editing or anything that needs a full toolkit, because the project states plainly that feh is an image viewer and cataloguer, not an editor, and that the option list is already long. Verify first that your system has the Imlib2, libpng and X11 development packages, and if you rely on HTTP image loading, check that libcurl is present, since the build can disable it.

## FAQ

### How do I build feh from source?

Run `make` and then `sudo make install`. The build needs Imlib2, libpng, libX11 and libXt, and you can add feature flags as make arguments, for example `make xinerama=0 debug=1` to disable multiscreen support and produce a debug build.

### What libraries does feh need?

The core dependencies are Imlib2, libpng, libX11 and libXt, with libcurl for viewing HTTP images and libXinerama for multiscreen setups. libexif is only needed when building with `exif=1` and libmagic only with `magic=1`.

### How do I run the feh test suite without a display?

Run `make test`, which drives the perl test suites `test/feh.t` and `test/mandoc.t`. It needs perl 5.10 or newer and the `Test::Command` module, and the tests are non-interactive so they work on a headless build server.

### What does the app=1 make flag do in feh?

It installs the icons to `/usr/share` regardless of `DESTDIR` and `PREFIX` and calls `gtk-update-icon-cache` afterwards, because installing icons under `/usr/local/share` does not work reliably. The flag defaults to 0, so end users are told to use `sudo make install app=1` while packagers use plain `sudo make install`.

### Does feh support loading images over HTTP?

Yes, through libcurl, which is enabled by default and can be turned off with the `curl=0` flag. The `mkstemps` flag matters here, because if it is set to 0 feh is unable to load gif images via libcurl.

## Sources

- [derf/feh on GitHub](https://github.com/derf/feh)
- [Issues](https://github.com/derf/feh/issues)
- [Project website](https://feh.finalrewind.org)
- [README](https://github.com/derf/feh/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/derf-feh
