summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-01-25 19:31:39 -0600
committerCraig Jennings <c@cjennings.net>2026-01-25 19:31:39 -0600
commitbe7fc75bdd2b9702106dd77b915361b70218104c (patch)
tree13a8da39be83ae2c5836f12c403bb6dae4f69e26
parent4211501b901d530ee621399e07b81427ca497040 (diff)
feat(hyprland): add fuzzel launcher and pinentry-fuzzel
- Replace wofi with fuzzel in archsetup - Add fuzzel config with waybar-matching theme - Add pinentry-fuzzel script for GPG passphrase prompts - Add Hyprland-specific gpg-agent.conf using pinentry-fuzzel
-rwxr-xr-xarchsetup2
-rw-r--r--dotfiles/hyprland/.config/fuzzel/fuzzel.ini31
-rw-r--r--dotfiles/hyprland/.gnupg/gpg-agent.conf18
-rwxr-xr-xdotfiles/hyprland/.local/bin/pinentry-fuzzel107
4 files changed, 157 insertions, 1 deletions
diff --git a/archsetup b/archsetup
index 3360144..c0f95ca 100755
--- a/archsetup
+++ b/archsetup
@@ -1305,7 +1305,7 @@ hyprland() {
action="Hyprland Utilities" && display "subtitle" "$action"
pacman_install waybar # status bar
- pacman_install wofi # app launcher
+ pacman_install fuzzel # app launcher (native Wayland, pinentry support)
pacman_install swww # wallpaper
pacman_install grim # screenshot
pacman_install slurp # region select
diff --git a/dotfiles/hyprland/.config/fuzzel/fuzzel.ini b/dotfiles/hyprland/.config/fuzzel/fuzzel.ini
new file mode 100644
index 0000000..ce46448
--- /dev/null
+++ b/dotfiles/hyprland/.config/fuzzel/fuzzel.ini
@@ -0,0 +1,31 @@
+# Fuzzel config - matching waybar DWM-inspired theme
+# Colors from waybar: bg=#222222, cpu=#bbbbbb, clock=#eeeeee, accent=#daa520
+
+[main]
+font=BerkeleyMono Nerd Font:size=14
+prompt=Search:
+icon-theme=hicolor
+icons-enabled=yes
+width=30
+lines=12
+horizontal-pad=20
+vertical-pad=12
+inner-pad=8
+layer=overlay
+exit-on-keyboard-focus-loss=yes
+
+[colors]
+# Format: RRGGBBAA
+background=222222f0
+text=eeeeeeff
+selection=daa520ff
+selection-text=222222ff
+border=daa520ff
+match=daa520ff
+prompt=bbbbbbff
+placeholder=888888ff
+input=eeeeeeff
+
+[border]
+width=2
+radius=16
diff --git a/dotfiles/hyprland/.gnupg/gpg-agent.conf b/dotfiles/hyprland/.gnupg/gpg-agent.conf
new file mode 100644
index 0000000..068f889
--- /dev/null
+++ b/dotfiles/hyprland/.gnupg/gpg-agent.conf
@@ -0,0 +1,18 @@
+# Pinentry configuration (Wayland/Hyprland)
+pinentry-program ~/.local/bin/pinentry-fuzzel
+pinentry-timeout 10
+allow-loopback-pinentry
+
+# Cache passphrases for entire login session (400 days)
+default-cache-ttl 34560000
+max-cache-ttl 34560000
+
+# Enable SSH support (use gpg-agent for SSH keys too)
+enable-ssh-support
+
+# Prevent external programs from clearing cache
+no-allow-external-cache
+
+# Keep running even when no connections
+keep-display
+keep-tty
diff --git a/dotfiles/hyprland/.local/bin/pinentry-fuzzel b/dotfiles/hyprland/.local/bin/pinentry-fuzzel
new file mode 100755
index 0000000..4cbe6b7
--- /dev/null
+++ b/dotfiles/hyprland/.local/bin/pinentry-fuzzel
@@ -0,0 +1,107 @@
+#!/bin/sh
+
+ENABLE_LOGGING="TRUE"
+logger() {
+ if [ "$ENABLE_LOGGING" == "TRUE" ]; then
+ /usr/bin/logger -t "${0} [$]" "$@";
+ fi
+}
+
+# Decode URL-encoded characters (%0A = newline, %20 = space, etc.)
+decode() {
+ printf '%b' "$(echo "$1" | sed 's/%\([0-9A-Fa-f][0-9A-Fa-f]\)/\\x\1/g')"
+}
+
+# Base command and misc variables
+DESC=""
+PROMPT=""
+COUNTFILE="/tmp/pinentry-fuzzel-count-$$"
+
+# Check if this is a repeat prompt (within 5 seconds of last)
+LASTFILE="/tmp/pinentry-fuzzel-last"
+NOW=$(date +%s)
+if [ -f "$LASTFILE" ]; then
+ LAST=$(cat "$LASTFILE")
+ if [ $((NOW - LAST)) -lt 5 ]; then
+ REPEAT=1
+ else
+ REPEAT=0
+ fi
+else
+ REPEAT=0
+fi
+echo "$NOW" > "$LASTFILE"
+
+echo "OK Please go ahead"
+while read cmd rest; do
+ logger "RAW=< ${cmd} ${rest} >"
+ logger "cmd=<${cmd}> rest=<${rest}>"
+
+ case $cmd in
+ GETINFO)
+ case "$rest" in
+ flavor)
+ echo "D fuzzel"
+ echo "OK"
+ ;;
+ version)
+ echo "D 0.1"
+ echo "OK"
+ ;;
+ ttyinfo)
+ echo "D - - -"
+ echo "OK"
+ ;;
+ pid)
+ echo "D $$"
+ echo "OK"
+ ;;
+ esac
+ ;;
+
+ SETDESC)
+ DESC=$(decode "$rest")
+ echo "OK"
+ ;;
+
+ SETERROR)
+ logger "ERROR $rest"
+ # Silently acknowledge errors (e.g., empty passphrase on escape)
+ echo "OK"
+ ;;
+
+ SETPROMPT)
+ PROMPT=$(decode "$rest")
+ # Remove trailing colon if present (we add our own)
+ PROMPT="${PROMPT%:}"
+ echo "OK"
+ ;;
+
+ GETPIN | getpin)
+ if [ "$REPEAT" -eq 0 ]; then
+ LABEL="password: "
+ else
+ LABEL="reenter: "
+ fi
+ PASS=$(fuzzel --prompt "$LABEL" --width 25 --lines 0 --cache /dev/null --password --dmenu)
+ if [ -z "$PASS" ]; then
+ # User cancelled - return error to GPG
+ rm -f "$LASTFILE"
+ echo "ERR 83886179 Operation cancelled"
+ else
+ echo "D $PASS"
+ echo "OK"
+ fi
+ ;;
+
+ BYE|bye)
+ echo "OK closing connection"
+ logger "EXITING"
+ exit 0
+ ;;
+
+ *)
+ echo "OK"
+ ;;
+ esac
+done