Asger Geel Weirsøe f951cb9c6d
All checks were successful
Test / test (push) Successful in 6m2s
docs: rewrite readme; add macOS install script
- Clarify that the sprite is the author's face on Nedry's body
- Explicit Wayland (gtklock module) vs X11/macOS (PAM module) comparison table
  with an explanation of how each integration works
- Accurate per-distro PAM paths (standard/Fedora multilib/Debian multiarch)
- scripts/install-macos.sh: one-shot installer for macOS — checks Homebrew,
  installs brew deps, builds from source, copies binaries, and patches
  /etc/pam.d/screensaverui (or screensaver) after the last auth line

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 15:16:26 +02:00
2025-11-30 21:08:42 +01:00
2025-11-30 21:08:42 +01:00
2025-11-30 21:08:42 +01:00
2026-05-06 09:25:39 +02:00
2026-05-06 09:25:39 +02:00
2025-12-01 08:57:48 +01:00

Ah ah ah, you didn't say the magic word

On a failed lock-screen unlock attempt, this spawns a looping animation of the author's face photoshopped onto Dennis Nedry's body and plays the "ah ah ah, you didn't say the magic word" clip from Jurassic Park. Each wrong guess adds another sprite at a random screen position. Volume is forced to 100% on the first failure and restored when the screen unlocks.

Platform support

The integration method differs by display server:

Platform Display server Module loaded How it works
Linux Wayland ahfail-module.so Loaded directly by gtklock via its module API
Linux X11 libahfail_pam.so + ahfail-display PAM cleanup hook spawns the display binary after each failed auth
macOS libahfail_pam.so + ahfail-display Same PAM approach, hooks into the screensaver PAM stack

The gtklock module is Wayland-only — it uses gtklock's internal window API to overlay sprites directly on the lock screen. The PAM module works on X11 and macOS by registering a cleanup callback that fires on each failed authentication attempt; it double-forks a standalone display binary (ahfail-display) that runs independently of the PAM stack.


Linux — Wayland (gtklock)

Install dependencies (Arch)

sudo pacman -S meson ninja rust gtk3 gstreamer gst-plugins-base gst-plugins-good gst-plugins-bad gtklock

Build and install

meson setup builddir
meson compile -C builddir
sudo meson install -C builddir

Installs:

  • /usr/lib/gtklock/ahfail-module.so — gtklock module
  • /usr/lib/ahfail/libahfail_pam.so — PAM module (for X11)
  • /usr/lib/ahfail/ahfail-display — standalone display binary

Run

gtklock -m /usr/lib/gtklock/ahfail-module.so

Arguments

Pass module arguments after --:

gtklock -m /usr/lib/gtklock/ahfail-module.so -- --deadzone=860,440,200,200
  • --deadzone=X,Y,W,H — rectangle where sprites will not spawn (keep your password field clear)
  • --audio-uri=URI — override the default audio clip, e.g. file:///home/user/custom.mp3

Linux — X11 (i3lock, xscreensaver, etc.)

Add the PAM module to your screen locker's PAM service file. Use the full path — $(libdir)/ahfail is not in PAM's default search path.

Arch / standard:

auth optional /usr/lib/ahfail/libahfail_pam.so

Fedora / RHEL (multilib):

auth optional /usr/lib64/ahfail/libahfail_pam.so

Debian / Ubuntu (multiarch):

auth optional /usr/lib/x86_64-linux-gnu/ahfail/libahfail_pam.so

Common service files: /etc/pam.d/i3lock, /etc/pam.d/xscreensaver, /etc/pam.d/lightdm.

Optionally pass the display binary path as an argument if it is not at the default location:

auth optional /usr/lib/ahfail/libahfail_pam.so display_path=/usr/lib/ahfail/ahfail-display

macOS

git clone https://gitea.weircon.dk/agw/gtk-ahfail.git
cd gtk-ahfail
bash scripts/install-macos.sh

The script installs Homebrew dependencies, builds from source, copies binaries to /usr/local/lib/ahfail/, and patches the screensaver PAM configuration automatically.

Manual install

Prerequisites

brew install gtk+3 gstreamer gst-plugins-base gst-plugins-good meson ninja

Rust: install via rustup.rs if not already present.

Build

meson setup builddir
meson compile -C builddir

Install

sudo mkdir -p /usr/local/lib/ahfail
sudo cp builddir/libahfail_pam.so /usr/local/lib/ahfail/
sudo cp builddir/ahfail-display /usr/local/lib/ahfail/

Configure PAM

Find the screensaver PAM service file:

  • macOS 13 (Ventura) and later: /etc/pam.d/screensaverui
  • macOS 12 and earlier: /etc/pam.d/screensaver

Add this line after the existing auth entries (requires sudo):

auth optional /usr/local/lib/ahfail/libahfail_pam.so

Customization

The sprite is the author's face on Nedry's body. To use your own:

  1. Replace the sprite frames in assets/sprites/ with your own PNG sequence.
  2. Update assets/ahfail.gresource.xml if you add or remove files.
  3. Rebuild with Meson.

To replace the audio clip, swap assets/audio/magic-word.mp3 and rebuild.


Development

cargo test                                        # unit + integration tests (needs display)
cargo test --test benchmarks -- --nocapture       # sprite placement benchmarks
cargo clippy                                      # lint
meson setup builddir && meson compile -C builddir # full build including .so
xvfb-run meson test -C builddir --verbose        # Meson tests headless
Description
gtklock module for going jurassic
Readme AGPL-3.0 2.5 MiB
v0.9.0 Latest
2026-05-07 22:01:02 +02:00
Languages
Rust 79.6%
Shell 10.8%
C 5.2%
Meson 4.4%