Skip to content

Instantly share code, notes, and snippets.

@rsheldiii
Last active April 15, 2026 01:24
Show Gist options
  • Select an option

  • Save rsheldiii/a184caff1dd850bf34a9155901be6b1e to your computer and use it in GitHub Desktop.

Select an option

Save rsheldiii/a184caff1dd850bf34a9155901be6b1e to your computer and use it in GitHub Desktop.
Hyprland v0.54.3 build + config setup for Pop!_OS 24.04 (Ubuntu Noble) with NVIDIA
#!/usr/bin/env bash
# ─── Hyprland build+install for Pop!_OS 24.04 (Ubuntu Noble) ─────────────────
# Builds Hyprland and its full dependency chain from source.
# nvidia-drm.modeset=1 is already set by Pop!_OS NVIDIA — no changes needed.
#
# Run from a terminal: sudo bash ~/install-hyprland.sh
# Takes ~60 min on first run. Safe to re-run — skips already-built components.
# ─────────────────────────────────────────────────────────────────────────────
set -euo pipefail
SCRIPT_USER="${SUDO_USER:-$USER}"
SCRIPT_HOME=$(getent passwd "$SCRIPT_USER" | cut -d: -f6)
BUILD_DIR="$SCRIPT_HOME/Code/hyprland-build"
INSTALL_PREFIX="/usr/local"
# ── helpers ──────────────────────────────────────────────────────────────────
info() { echo -e "\e[34m==>\e[0m $*"; }
ok() { echo -e "\e[32m ✓\e[0m $*"; }
step() { echo -e "\n\e[1;36m━━━ $* ━━━\e[0m"; }
run_as_user() {
sudo -u "$SCRIPT_USER" bash -c "
export CC=gcc-15
export CXX=g++-15
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:/usr/local/lib/x86_64-linux-gnu/pkgconfig:/usr/local/share/pkgconfig\${PKG_CONFIG_PATH:+:\$PKG_CONFIG_PATH}
export CMAKE_PREFIX_PATH=/usr/local
export LDFLAGS=\"-L/usr/local/lib/x86_64-linux-gnu -L/usr/local/lib \${LDFLAGS:-}\"
export CPPFLAGS=\"-I/usr/local/include \${CPPFLAGS:-}\"
$*
"
}
# ── 0a. GCC 15 from ubuntu-toolchain-r (GCC 14.2 Ubuntu backport lacks C++26) ─
step "Installing GCC 15"
if ! command -v gcc-15 &>/dev/null; then
apt-get install -y software-properties-common
add-apt-repository -y ppa:ubuntu-toolchain-r/test
apt-get update -qq
apt-get install -y gcc-15 g++-15
ok "GCC 15 installed"
else
ok "GCC 15 already installed"
fi
# ── 0b. CMake 3.30+ from Kitware (Ubuntu 24.04 ships 3.28) ───────────────────
step "Installing CMake 3.30+ from Kitware"
if ! cmake --version 2>/dev/null | awk 'NR==1{split($3,v,"."); exit (v[1]>3 || (v[1]==3 && v[2]>=30)) ? 0 : 1}'; then
apt-get install -y ca-certificates gpg wget
wget -qO /tmp/kitware-archive-keyring.gpg \
https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null || \
curl -fsSL https://apt.kitware.com/keys/kitware-archive-latest.asc \
-o /tmp/kitware-archive-keyring.gpg
gpg --dearmor < /tmp/kitware-archive-keyring.gpg \
> /usr/share/keyrings/kitware-archive-keyring.gpg
echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ noble main' \
> /etc/apt/sources.list.d/kitware.list
apt-get update -qq
apt-get install -y cmake
ok "CMake $(cmake --version | head -1) installed from Kitware"
else
ok "CMake $(cmake --version | head -1) already satisfies 3.30+"
fi
# ── 1. Build dependencies ────────────────────────────────────────────────────
step "Installing build dependencies"
apt-get update -qq
apt-get install -y \
build-essential meson ninja-build pkg-config git bison \
autoconf automake libtool \
xcb-proto \
libwayland-dev wayland-protocols libwayland-bin \
libxkbcommon-dev libinput-dev libdrm-dev libgbm-dev \
libseat-dev libsystemd-dev libudev-dev \
libvulkan-dev libvulkan1 glslang-tools glslang-dev \
libpixman-1-dev libcairo2-dev libpango1.0-dev \
libgles2-mesa-dev libgl1-mesa-dev \
libegl1-mesa-dev libegl-dev \
libxcb1-dev libxcb-composite0-dev libxcb-damage0-dev \
libxcb-dpms0-dev libxcb-dri3-dev libxcb-ewmh-dev \
libxcb-icccm4-dev libxcb-render0-dev \
libxcb-render-util0-dev libxcb-res0-dev libxcb-shape0-dev \
libxcb-shm0-dev libxcb-sync-dev libxcb-util0-dev \
libxcb-xfixes0-dev libxcb-xinput-dev libxcb-xkb-dev \
libxcb-cursor-dev \
libx11-dev libx11-xcb-dev libxfixes-dev \
libmagic-dev libmagickwand-dev \
libdisplay-info-dev \
libliftoff-dev \
libtomlplusplus-dev \
libsdl2-dev \
libpugixml-dev \
libevdev-dev \
libmtdev-dev \
libwacom-dev \
libzip-dev \
libjpeg-dev \
libwebp-dev \
libre2-dev \
libffi-dev \
xutils-dev \
qt6-base-dev \
libpipewire-0.3-dev \
libspa-0.2-dev \
libmuparser-dev \
libxcb-util-dev \
uuid-dev \
hwdata \
xwayland \
python3-jinja2
ok "Build dependencies installed"
# ── 2. Ecosystem tools (all in noble repos) ──────────────────────────────────
step "Installing Hyprland ecosystem tools"
apt-get install -y \
waybar \
wofi \
mako-notifier \
grim \
slurp \
wl-clipboard \
wlr-randr \
policykit-1-gnome \
xdg-desktop-portal-gtk \
xdg-utils \
brightnessctl \
playerctl \
pavucontrol \
network-manager-gnome \
kitty \
thunar tumbler ffmpegthumbnailer \
fonts-noto-color-emoji \
fonts-font-awesome \
imagemagick
ok "Ecosystem tools installed"
# ── 3. cliphist binary ───────────────────────────────────────────────────────
step "Installing cliphist"
CLIPHIST_URL=$(curl -s https://api.github.com/repos/sentriz/cliphist/releases/latest \
| python3 -c "import sys,json; r=json.load(sys.stdin); \
[print(a['browser_download_url']) for a in r['assets'] \
if 'linux_amd64' in a['name'] and not a['name'].endswith('.sha256')]" \
| head -1)
if [ -n "$CLIPHIST_URL" ]; then
curl -sL "$CLIPHIST_URL" -o /usr/local/bin/cliphist
chmod +x /usr/local/bin/cliphist
ok "cliphist installed"
else
echo " WARNING: could not find cliphist release, skipping"
fi
# ── build helper: clone-or-update + cmake install ────────────────────────────
build_cmake() {
local name="$1" url="$2" tag="$3" build_target="${4:-}"
local dir="$BUILD_DIR/$name"
info "Building $name $tag..."
if [ -d "$dir" ]; then
run_as_user "cd '$dir' && git fetch --tags -q && git checkout -q '$tag'"
else
run_as_user "git clone --depth 1 --branch '$tag' '$url' '$dir'"
fi
# ofstream::native_handle() is C++26; not in GCC 14.2 on Ubuntu 24.04.
# The call only sets FD_CLOEXEC on the log file — safe to remove.
# (grep exits 1 when no matches; suppress that with || true so set -e doesn't abort)
grep -rl --include='*.cpp' --include='*.hpp' \
'native_handle.*FD_CLOEXEC\|FD_CLOEXEC.*native_handle' "$dir" 2>/dev/null | \
while read -r f; do
sed -i '/native_handle.*FD_CLOEXEC\|FD_CLOEXEC.*native_handle/d' "$f"
info " Patched $f (removed native_handle/FD_CLOEXEC)"
done || true
run_as_user "cmake -S '$dir' -B '$dir/build' \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX='$INSTALL_PREFIX' \
-DCMAKE_PREFIX_PATH='$INSTALL_PREFIX' \
-DCMAKE_C_COMPILER=gcc-15 \
-DCMAKE_CXX_COMPILER=g++-15 \
-DCMAKE_SHARED_LINKER_FLAGS='-L/usr/local/lib/x86_64-linux-gnu -L/usr/local/lib' \
-DCMAKE_EXE_LINKER_FLAGS='-L/usr/local/lib/x86_64-linux-gnu -L/usr/local/lib' \
-DBUILD_TESTING=OFF \
--fresh \
-G Ninja"
if [ -n "$build_target" ]; then
run_as_user "cmake --build '$dir/build' --target '$build_target' --parallel $(nproc)"
else
run_as_user "cmake --build '$dir/build' --parallel $(nproc)"
fi
cmake --install "$dir/build"
ldconfig
ok "$name installed to $INSTALL_PREFIX"
}
run_as_user "mkdir -p '$BUILD_DIR'"
# ── 4. Build dependency chain ────────────────────────────────────────────────
step "Building Hyprland dependency chain"
info "Order: libinput → xkbcommon → hyprutils → hyprwayland-scanner → hyprlang → aquamarine → hyprcursor → hyprgraphics → hyprland"
# libinput: Ubuntu 24.04 only has 1.25.0; Hyprland requires >= 1.28.0
LIBINPUT_DIR="$BUILD_DIR/libinput"
if [ -d "$LIBINPUT_DIR" ]; then
run_as_user "cd '$LIBINPUT_DIR' && git fetch --tags -q && git checkout -q '1.28.1'"
else
run_as_user "git clone --depth 1 --branch '1.28.1' \
https://gitlab.freedesktop.org/libinput/libinput.git '$LIBINPUT_DIR'"
fi
run_as_user "CC=gcc-15 CXX=g++-15 meson setup '$LIBINPUT_DIR/build' '$LIBINPUT_DIR' \
--buildtype=release \
--prefix='$INSTALL_PREFIX' \
--wipe \
-Ddocumentation=false \
-Ddebug-gui=false \
-Dtests=false \
-Dlibwacom=false"
run_as_user "ninja -C '$LIBINPUT_DIR/build' -j$(nproc)"
ninja -C "$LIBINPUT_DIR/build" install
ldconfig
ok "libinput 1.28.1 installed to $INSTALL_PREFIX"
# xkbcommon: Ubuntu 24.04 ships 1.6.0; Hyprland requires >= 1.11.0
XKBCOMMON_DIR="$BUILD_DIR/xkbcommon"
if [ -d "$XKBCOMMON_DIR" ]; then
run_as_user "cd '$XKBCOMMON_DIR' && git fetch --tags -q && git checkout -q 'xkbcommon-1.11.0'"
else
run_as_user "git clone --depth 1 --branch 'xkbcommon-1.11.0' \
https://github.com/xkbcommon/libxkbcommon.git '$XKBCOMMON_DIR'"
fi
run_as_user "CC=gcc-15 CXX=g++-15 meson setup '$XKBCOMMON_DIR/build' '$XKBCOMMON_DIR' \
--buildtype=release \
--prefix='$INSTALL_PREFIX' \
--wipe \
-Denable-docs=false \
-Denable-tools=false"
run_as_user "ninja -C '$XKBCOMMON_DIR/build' -j$(nproc)"
ninja -C "$XKBCOMMON_DIR/build" install
ldconfig
ok "xkbcommon 1.11.0 installed to $INSTALL_PREFIX"
build_cmake "hyprutils" "https://github.com/hyprwm/hyprutils" "v0.12.0"
build_cmake "hyprwayland-scanner" "https://github.com/hyprwm/hyprwayland-scanner" "v0.4.5"
build_cmake "hyprlang" "https://github.com/hyprwm/hyprlang" "v0.6.8"
build_cmake "aquamarine" "https://github.com/hyprwm/aquamarine" "v0.10.0" "aquamarine"
build_cmake "hyprcursor" "https://github.com/hyprwm/hyprcursor" "v0.1.13"
build_cmake "hyprgraphics" "https://github.com/hyprwm/hyprgraphics" "v0.1.6"
build_cmake "hyprwire" "https://github.com/hyprwm/hyprwire" "v0.3.0"
# xcb-errors: not in Ubuntu 24.04 repos, required for XWayland support
XCBERR_DIR="$BUILD_DIR/xcb-errors"
if [ -d "$XCBERR_DIR" ]; then
run_as_user "cd '$XCBERR_DIR' && git fetch --tags -q && git checkout -q 'xcb-util-errors-1.0.1'"
else
run_as_user "git clone --depth 1 --branch 'xcb-util-errors-1.0.1' \
https://gitlab.freedesktop.org/xorg/lib/libxcb-errors.git '$XCBERR_DIR'"
fi
# util-common-m4 submodule uses a dead protocol and the hosting server requires auth.
# Skip autotools entirely — build with gcc directly using xcb-proto XML files.
XCBPROTO_XMLDIR=$(pkg-config --variable=xcbincludedir xcb-proto)
info "xcb-proto XML dir: $XCBPROTO_XMLDIR"
# Generate extensions.c from xcb-proto XML
run_as_user "python3 '$XCBERR_DIR/src/extensions.py' '$XCBERR_DIR/src/extensions.c.tmp' $XCBPROTO_XMLDIR/*.xml && \
mv '$XCBERR_DIR/src/extensions.c.tmp' '$XCBERR_DIR/src/extensions.c'"
# Compile shared library
XCB_CFLAGS=$(pkg-config --cflags xcb)
XCB_LIBS=$(pkg-config --libs xcb)
gcc -shared -fPIC -O2 \
-o "$XCBERR_DIR/libxcb-errors.so.0.0.0" \
"$XCBERR_DIR/src/xcb_errors.c" \
"$XCBERR_DIR/src/extensions.c" \
$XCB_CFLAGS -I"$XCBERR_DIR/src" $XCB_LIBS \
-Wl,-soname,libxcb-errors.so.0
ln -sf libxcb-errors.so.0.0.0 "$XCBERR_DIR/libxcb-errors.so.0"
ln -sf libxcb-errors.so.0 "$XCBERR_DIR/libxcb-errors.so"
# Install
install -Dm755 "$XCBERR_DIR/libxcb-errors.so.0.0.0" \
"$INSTALL_PREFIX/lib/x86_64-linux-gnu/libxcb-errors.so.0.0.0"
ln -sf libxcb-errors.so.0.0.0 "$INSTALL_PREFIX/lib/x86_64-linux-gnu/libxcb-errors.so.0"
ln -sf libxcb-errors.so.0 "$INSTALL_PREFIX/lib/x86_64-linux-gnu/libxcb-errors.so"
install -Dm644 "$XCBERR_DIR/src/xcb_errors.h" \
"$INSTALL_PREFIX/include/xcb/xcb_errors.h"
# Write .pc file
mkdir -p "$INSTALL_PREFIX/lib/pkgconfig"
cat > "$INSTALL_PREFIX/lib/pkgconfig/xcb-errors.pc" << EOF
prefix=$INSTALL_PREFIX
exec_prefix=$INSTALL_PREFIX
libdir=$INSTALL_PREFIX/lib/x86_64-linux-gnu
includedir=$INSTALL_PREFIX/include
Name: XCB errors library
Description: XCB errors utility library
Version: 1.0.1
Requires: xcb
Libs: -L\${libdir} -lxcb-errors
Cflags: -I\${includedir}
EOF
ldconfig
ok "xcb-errors 1.0.1 installed to $INSTALL_PREFIX"
# sdbus-c++: apt has 1.4.0; xdg-desktop-portal-hyprland requires >= 2.0.0
build_cmake "sdbus-cpp" "https://github.com/Kistler-Group/sdbus-cpp" "v2.2.1"
# ── 5. Build Hyprland itself ─────────────────────────────────────────────────
step "Building Hyprland v0.54.3"
HYPR_DIR="$BUILD_DIR/hyprland"
if [ -d "$HYPR_DIR" ]; then
run_as_user "cd '$HYPR_DIR' && git fetch --tags -q && git checkout -q 'v0.54.3'"
else
run_as_user "git clone --depth 1 --branch 'v0.54.3' \
https://github.com/hyprwm/hyprland.git '$HYPR_DIR'"
fi
# Initialize submodules (udis86, hyprland-protocols, etc.)
run_as_user "cd '$HYPR_DIR' && git submodule update --init --depth 1"
# Install glaze headers system-wide so start-hyprland finds them (its CMakeLists
# includes glaze/glaze.hpp but never links glaze::glaze — cmake target won't help)
if [ ! -d /usr/local/include/glaze ]; then
GLAZE_DIR="$BUILD_DIR/glaze"
run_as_user "git clone --depth 1 --branch v7.0.0 \
https://github.com/stephenberry/glaze.git '$GLAZE_DIR'"
cp -r "$GLAZE_DIR/include/glaze" /usr/local/include/glaze
ok "glaze v7.0.0 headers installed to /usr/local/include"
else
ok "glaze headers already present"
fi
run_as_user "cmake -S '$HYPR_DIR' -B '$HYPR_DIR/build' \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX='$INSTALL_PREFIX' \
-DCMAKE_PREFIX_PATH='$INSTALL_PREFIX' \
-DCMAKE_C_COMPILER=gcc-15 \
-DCMAKE_CXX_COMPILER=g++-15 \
-DCMAKE_SHARED_LINKER_FLAGS='-L/usr/local/lib/x86_64-linux-gnu -L/usr/local/lib' \
-DCMAKE_EXE_LINKER_FLAGS='-L/usr/local/lib/x86_64-linux-gnu -L/usr/local/lib' \
--fresh \
-G Ninja"
run_as_user "cmake --build '$HYPR_DIR/build' --parallel $(nproc)"
cmake --install "$HYPR_DIR/build"
ldconfig
ok "Hyprland v0.54.3 installed"
# ── 6. Wayland session entry ─────────────────────────────────────────────────
step "Registering Hyprland session"
mkdir -p /usr/share/wayland-sessions
cat > /usr/share/wayland-sessions/hyprland.desktop << 'EOF'
[Desktop Entry]
Name=Hyprland
Comment=A dynamic tiling Wayland compositor
Exec=Hyprland
Type=Application
EOF
ok "Session registered — will appear in login screen dropdown"
# ── 7. xdg-desktop-portal-hyprland ──────────────────────────────────────────
step "Building xdg-desktop-portal-hyprland"
XDP_DIR="$BUILD_DIR/xdg-desktop-portal-hyprland"
if [ -d "$XDP_DIR" ]; then
run_as_user "cd '$XDP_DIR' && git fetch -q && git checkout -q master && git pull -q"
else
run_as_user "git clone --depth 1 https://github.com/hyprwm/xdg-desktop-portal-hyprland.git '$XDP_DIR'"
fi
run_as_user "cd '$XDP_DIR' && git submodule update --init --depth 1"
run_as_user "cmake -S '$XDP_DIR' -B '$XDP_DIR/build' \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_PREFIX_PATH='$INSTALL_PREFIX' \
-DCMAKE_C_COMPILER=gcc-15 \
-DCMAKE_CXX_COMPILER=g++-15 \
-DCMAKE_SHARED_LINKER_FLAGS='-L/usr/local/lib/x86_64-linux-gnu -L/usr/local/lib' \
-DCMAKE_EXE_LINKER_FLAGS='-L/usr/local/lib/x86_64-linux-gnu -L/usr/local/lib' \
--fresh \
-G Ninja"
run_as_user "cmake --build '$XDP_DIR/build' --parallel $(nproc)"
cmake --install "$XDP_DIR/build"
ldconfig
ok "xdg-desktop-portal-hyprland installed"
echo ""
echo "╔═══════════════════════════════════════════════════════════╗"
echo "║ Hyprland installation complete! ║"
echo "╠═══════════════════════════════════════════════════════════╣"
echo "║ Next: run the config setup script as yourself (no sudo): ║"
echo "║ bash ~/setup-hyprland-config.sh ║"
echo "╚═══════════════════════════════════════════════════════════╝"
#!/usr/bin/env bash
# ─── JaKooLit Hyprland-Dots dependency installer ─────────────────────────────
# Installs the packages, fonts, and tools required by JaKooLit's Hyprland
# dotfiles (https://github.com/JaKooLit/Hyprland-Dots), then copies the
# dotfiles into ~/.config.
#
# Assumes install-hyprland.sh has already run successfully (Hyprland, GCC 15,
# cmake 4.x, and the hyprwm dependency chain are already in place).
#
# Run as: sudo bash ~/install-jakoolit-deps.sh
# Safe to re-run — skips already-installed components.
# ─────────────────────────────────────────────────────────────────────────────
set -euo pipefail
SCRIPT_USER="${SUDO_USER:-$USER}"
SCRIPT_HOME=$(getent passwd "$SCRIPT_USER" | cut -d: -f6)
BUILD_DIR="$SCRIPT_HOME/Code/hyprland-build"
INSTALL_PREFIX="/usr/local"
info() { echo -e "\e[34m==>\e[0m $*"; }
ok() { echo -e "\e[32m ✓\e[0m $*"; }
step() { echo -e "\n\e[1;36m━━━ $* ━━━\e[0m"; }
# Mirrors the run_as_user from install-hyprland.sh: runs commands as the
# non-root user with the hyprwm build environment (GCC 15, /usr/local PKG paths).
run_as_user() {
sudo -u "$SCRIPT_USER" bash -c "
export CC=gcc-15
export CXX=g++-15
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:/usr/local/lib/x86_64-linux-gnu/pkgconfig:/usr/local/share/pkgconfig\${PKG_CONFIG_PATH:+:\$PKG_CONFIG_PATH}
export CMAKE_PREFIX_PATH=/usr/local
export LDFLAGS=\"-L/usr/local/lib/x86_64-linux-gnu -L/usr/local/lib \${LDFLAGS:-}\"
export CPPFLAGS=\"-I/usr/local/include \${CPPFLAGS:-}\"
$*
"
}
build_cmake() {
local name="$1" url="$2" tag="$3" build_target="${4:-}"
local dir="$BUILD_DIR/$name"
info "Building $name $tag..."
if [ -d "$dir" ]; then
run_as_user "cd '$dir' && git fetch --tags -q && git checkout -q '$tag'"
else
run_as_user "git clone --depth 1 --branch '$tag' '$url' '$dir'"
fi
run_as_user "cmake -S '$dir' -B '$dir/build' \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX='$INSTALL_PREFIX' \
-DCMAKE_PREFIX_PATH='$INSTALL_PREFIX' \
-DCMAKE_C_COMPILER=gcc-15 \
-DCMAKE_CXX_COMPILER=g++-15 \
-DCMAKE_SHARED_LINKER_FLAGS='-L/usr/local/lib/x86_64-linux-gnu -L/usr/local/lib' \
-DCMAKE_EXE_LINKER_FLAGS='-L/usr/local/lib/x86_64-linux-gnu -L/usr/local/lib' \
-DBUILD_TESTING=OFF \
--fresh \
-G Ninja"
if [ -n "$build_target" ]; then
run_as_user "cmake --build '$dir/build' --target '$build_target' --parallel $(nproc)"
else
run_as_user "cmake --build '$dir/build' --parallel $(nproc)"
fi
cmake --install "$dir/build"
ldconfig
ok "$name installed to $INSTALL_PREFIX"
}
# ── 1. apt packages ───────────────────────────────────────────────────────────
step "Installing apt packages"
# Notes on non-obvious packages and omissions:
# sway-notification-center — swaync; JaKooLit uses this instead of mako/dunst.
# It supports action buttons and inline replies in
# notifications, which mako does not.
# wlogout — full-screen logout/reboot/shutdown/suspend menu,
# bound to Super+Shift+W in JaKooLit's keybinds.
# qt5ct / qt6ct / kvantum — Qt theming tools. Without these, Qt apps ignore
# GTK themes and render with a bare system style.
# Kvantum adds SVG-based themes so Qt apps can match
# the Catppuccin look.
# pamixer — CLI PulseAudio/PipeWire volume control used by
# waybar's volume widget.
# yad — Yet Another Dialog; JaKooLit's scripts use it for
# in-session GUI prompts (theme switcher, etc.).
# btop — resource monitor with a polished TUI; replaces htop
# in JaKooLit's default keybind (Super+Shift+B).
# polkit-kde-agent-1 — graphical polkit authentication agent for Wayland;
# replaces polkit-gnome from our original setup. The
# KDE agent has better Wayland support.
# libpam0g-dev — PAM headers; required to build hyprlock (the lock
# screen uses PAM to verify your password).
# libgtk-3-dev — GTK3 headers; required to build swappy.
# jq / bc — JSON parser and math tool used by wallust and
# JaKooLit's waybar scripts.
# lib*-dev below — build deps for rofi-wayland (step 4).
#
# NOT in Ubuntu 24.04 repos — built from source in later steps:
# fastfetch — GitHub .deb (step 2)
# swappy — meson source build (step 3)
# hyprland-protocols — cmake source build (step 4); was only a submodule
# during our Hyprland build, needs a proper system install
# so hypridle/hyprlock can find it via pkg-config
# hypridle — cmake source build (step 5)
# hyprlock — cmake source build (step 6)
apt-get update -qq
apt-get install -y \
sway-notification-center \
wlogout \
btop \
cava \
yad \
pamixer \
nvtop \
qt5ct \
qt5-style-kvantum \
qt5-style-kvantum-themes \
qt6ct \
inxi \
python3-requests \
polkit-kde-agent-1 \
gvfs gvfs-backends \
xdg-user-dirs \
loupe \
mousepad \
mpv \
qalculate-gtk \
gnome-system-monitor \
fonts-firacode \
fonts-noto fonts-noto-cjk \
jq \
bc \
libpam0g-dev \
libgtk-3-dev \
libmpdclient-dev \
libasound2-dev \
libxcb-keysyms1-dev \
libxcb-randr0-dev \
libxcb-xinerama0-dev \
libxkbcommon-x11-dev \
libstartup-notification0-dev \
liblz4-dev \
flex
# swaync replaces mako — having both running causes duplicate notifications.
apt-get remove -y mako-notifier 2>/dev/null || true
ok "apt packages done"
# ── 2. fastfetch (GitHub .deb) ────────────────────────────────────────────────
step "Installing fastfetch"
# fastfetch is not in Ubuntu 24.04 repos. The project publishes .deb packages
# on GitHub releases, so we grab the latest one directly.
if ! command -v fastfetch &>/dev/null; then
FASTFETCH_DEB=$(curl -s https://api.github.com/repos/fastfetch-cli/fastfetch/releases/latest \
| python3 -c "import sys,json; r=json.load(sys.stdin); \
[print(a['browser_download_url']) for a in r['assets'] \
if a['name'].endswith('amd64.deb')]" | head -1)
curl -sL "$FASTFETCH_DEB" -o /tmp/fastfetch.deb
dpkg -i /tmp/fastfetch.deb
rm /tmp/fastfetch.deb
ok "fastfetch installed"
else
ok "fastfetch already installed"
fi
# ── 3. swappy (from source) ───────────────────────────────────────────────────
step "Building swappy v1.8.0"
# swappy is a screenshot annotation tool — JaKooLit's screenshot keybinds pipe
# grim/slurp output into it. Not in Ubuntu 24.04 repos; built with meson.
SWAPPY_DIR="$BUILD_DIR/swappy"
if ! command -v swappy &>/dev/null; then
if [ -d "$SWAPPY_DIR" ]; then
run_as_user "cd '$SWAPPY_DIR' && git fetch --tags -q && git checkout -q 'v1.8.0'"
else
run_as_user "git clone --depth 1 --branch 'v1.8.0' \
https://github.com/jtheoof/swappy.git '$SWAPPY_DIR'"
fi
run_as_user "CC=gcc-15 CXX=g++-15 meson setup '$SWAPPY_DIR/build' '$SWAPPY_DIR' \
--buildtype=release \
--prefix='$INSTALL_PREFIX' \
--wipe \
-Dman-pages=disabled"
run_as_user "ninja -C '$SWAPPY_DIR/build' -j$(nproc)"
ninja -C "$SWAPPY_DIR/build" install
ldconfig
ok "swappy installed"
else
ok "swappy already installed"
fi
# ── 4. hyprland-protocols (from source) ──────────────────────────────────────
step "Installing hyprland-protocols v0.7.0"
# hyprland-protocols provides the Wayland protocol extension XML files used by
# hyprlock and hypridle. During our Hyprland build it was only a git submodule —
# it was never installed to /usr/local as a proper pkgconfig package.
# Both hypridle and hyprlock require it via pkg-config at build time.
# Uses meson (no compilation — just installs XML files and a .pc file).
HPROTO_DIR="$BUILD_DIR/hyprland-protocols"
if ! pkg-config --exists hyprland-protocols 2>/dev/null; then
if [ -d "$HPROTO_DIR" ]; then
run_as_user "cd '$HPROTO_DIR' && git fetch --tags -q && git checkout -q 'v0.7.0'"
else
run_as_user "git clone --depth 1 --branch 'v0.7.0' \
https://github.com/hyprwm/hyprland-protocols.git '$HPROTO_DIR'"
fi
run_as_user "meson setup '$HPROTO_DIR/build' '$HPROTO_DIR' \
--buildtype=release \
--prefix='$INSTALL_PREFIX' \
--wipe"
ninja -C "$HPROTO_DIR/build" install
ldconfig
ok "hyprland-protocols installed"
else
ok "hyprland-protocols already installed"
fi
# ── 5. hypridle (from source) ─────────────────────────────────────────────────
step "Building hypridle v0.1.7"
# hypridle is the screen idle daemon from the hyprwm project. It watches for
# inactivity and triggers actions (dim screen, lock, suspend). Not in Ubuntu
# 24.04 repos, and it depends on the hyprwm libs we built from source
# (hyprutils, hyprlang, sdbus-c++) — which is why apt can't provide it.
build_cmake "hypridle" "https://github.com/hyprwm/hypridle" "v0.1.7"
# ── 6. hyprlock (from source) ─────────────────────────────────────────────────
step "Building hyprlock v0.9.4"
# hyprlock is the Hyprland lock screen. Same situation as hypridle: depends on
# hyprutils, hyprlang, hyprgraphics, sdbus-c++, and also libpam (for password
# verification) and OpenGL/EGL (for GPU-accelerated rendering with blur effects).
# Not in Ubuntu repos for the same reason — all its hyprwm deps are custom-built.
build_cmake "hyprlock" "https://github.com/hyprwm/hyprlock" "v0.9.4"
# ── 7. Nerd Fonts ─────────────────────────────────────────────────────────────
step "Installing Nerd Fonts (JetBrainsMono + FantasqueSansMono)"
# JaKooLit's waybar configs use Nerd Font icon glyphs (e.g. 󰋜 for home, for
# CPU) that only render correctly with a Nerd Font installed. The apt package
# fonts-nerd-fonts does not exist in Ubuntu 24.04 — these must be downloaded
# directly from the ryanoasis/nerd-fonts GitHub releases.
# JetBrainsMono — used as the primary monospace font in waybar and kitty.
# FantasqueSansMono — used as an alternative in some waybar styles.
FONT_DIR="$SCRIPT_HOME/.local/share/fonts"
if [ ! -d "$FONT_DIR/JetBrainsMonoNerd" ]; then
info "Downloading JetBrainsMono Nerd Font..."
run_as_user "mkdir -p '$FONT_DIR/JetBrainsMonoNerd' && \
curl -sL https://github.com/ryanoasis/nerd-fonts/releases/latest/download/JetBrainsMono.tar.xz \
| tar -xJf - -C '$FONT_DIR/JetBrainsMonoNerd'"
ok "JetBrainsMono Nerd Font installed"
else
ok "JetBrainsMono already present"
fi
if [ ! -d "$FONT_DIR/FantasqueSansMonoNerd" ]; then
info "Downloading FantasqueSansMono Nerd Font..."
run_as_user "mkdir -p '$FONT_DIR/FantasqueSansMonoNerd' && \
curl -sL https://github.com/ryanoasis/nerd-fonts/releases/download/v3.3.0/FantasqueSansMono.zip \
-o /tmp/FantasqueSansMono.zip && \
unzip -q /tmp/FantasqueSansMono.zip -d '$FONT_DIR/FantasqueSansMonoNerd' && \
rm /tmp/FantasqueSansMono.zip"
ok "FantasqueSansMono Nerd Font installed"
else
ok "FantasqueSansMono already present"
fi
run_as_user "fc-cache -f"
ok "Font cache updated"
# ── 8. wallust (from source via cargo) ───────────────────────────────────────
step "Installing wallust"
# wallust is a pywal replacement that extracts a 16-color palette from your
# wallpaper and applies it across all apps (waybar, kitty, rofi, swaync, etc.)
# by regenerating their config files from templates. JaKooLit's entire theming
# system is built around it — every theme switch runs wallust under the hood.
# Not in Ubuntu apt. Distributed as a Rust crate, compiled with cargo.
if ! command -v wallust &>/dev/null; then
if ! sudo -u "$SCRIPT_USER" bash -c 'command -v cargo &>/dev/null'; then
info "Installing Rust toolchain (needed for wallust)..."
run_as_user "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y"
fi
run_as_user "source '$SCRIPT_HOME/.cargo/env' && cargo install wallust"
install -m755 "$SCRIPT_HOME/.cargo/bin/wallust" /usr/local/bin/wallust
ok "wallust installed"
else
ok "wallust already installed"
fi
# ── 9. rofi-wayland (from source, tag 1.7.8+wayland1) ────────────────────────
step "Building rofi-wayland 1.7.8+wayland1"
# JaKooLit uses rofi for the app launcher, clipboard picker, theme switcher,
# and several other menus — it's deeply integrated throughout the config.
# The `rofi` package in Ubuntu apt is the X11 build: it runs via XWayland,
# has poor HiDPI scaling on Wayland, and lacks the -normal-window flag and
# native Wayland input handling. lbonn/rofi is a maintained fork that adds a
# native Wayland backend while keeping full X11 compatibility.
# Must be built from source — no Ubuntu PPA ships it.
ROFI_DIR="$BUILD_DIR/rofi-wayland"
if ! (rofi -version 2>/dev/null | grep -qi wayland); then
if [ -d "$ROFI_DIR" ]; then
run_as_user "cd '$ROFI_DIR' && git fetch --tags -q && git checkout -q '1.7.8+wayland1'"
else
run_as_user "git clone --depth 1 --branch '1.7.8+wayland1' \
https://github.com/lbonn/rofi.git '$ROFI_DIR'"
fi
run_as_user "cd '$ROFI_DIR' && git submodule update --init --depth 1"
run_as_user "CC=gcc-15 CXX=g++-15 meson setup '$ROFI_DIR/build' '$ROFI_DIR' \
--buildtype=release \
--prefix=/usr/local \
-Dwayland=enabled \
-Dxcb=enabled \
--wipe"
run_as_user "ninja -C '$ROFI_DIR/build' -j$(nproc)"
ninja -C "$ROFI_DIR/build" install
ldconfig
ok "rofi-wayland installed"
else
ok "rofi-wayland already installed"
fi
# ── 10. swww (from source via cargo) ─────────────────────────────────────────
step "Building swww v0.11.2"
# swww is the wallpaper daemon JaKooLit uses for all wallpaper switching,
# transitions, and effects. It runs as swww-daemon and is controlled by the
# swww client. No binary releases are published — must be built with cargo.
# Requires liblz4-dev for image compression at transition time.
SWWW_DIR="$BUILD_DIR/swww"
if ! command -v swww &>/dev/null; then
sudo apt-get install -y liblz4-dev 2>/dev/null || true
if [ -d "$SWWW_DIR" ]; then
run_as_user "cd '$SWWW_DIR' && git fetch --tags -q && git checkout -q 'v0.11.2'"
else
run_as_user "git clone --depth 1 --branch 'v0.11.2' \
https://github.com/LGFae/swww.git '$SWWW_DIR'"
fi
run_as_user "source '$SCRIPT_HOME/.cargo/env' && cd '$SWWW_DIR' && cargo build --release"
install -m755 "$SWWW_DIR/target/release/swww" /usr/local/bin/swww
install -m755 "$SWWW_DIR/target/release/swww-daemon" /usr/local/bin/swww-daemon
ok "swww installed"
else
ok "swww $(swww --version) already installed"
fi
# ── 11. Clone Hyprland-Dots ───────────────────────────────────────────────────
step "Cloning JaKooLit/Hyprland-Dots"
# The dotfiles repo is separate from the Ubuntu install scripts — it contains
# only configs, no package logic. We clone it here and copy the files manually
# rather than running copy.sh, which is interactive and prompts for keyboard
# layout, resolution, clock format, and per-app replace confirmations.
DOTS_DIR="$BUILD_DIR/Hyprland-Dots"
if [ -d "$DOTS_DIR" ]; then
run_as_user "cd '$DOTS_DIR' && git pull -q"
else
run_as_user "git clone --depth 1 https://github.com/JaKooLit/Hyprland-Dots.git '$DOTS_DIR'"
fi
ok "Hyprland-Dots at $DOTS_DIR"
# ── 12. Copy dotfiles ──────────────────────────────────────────────────────────
step "Copying JaKooLit dotfiles to ~/.config"
CONFIG="$SCRIPT_HOME/.config"
# Back up everything we're about to overwrite (hypr, waybar, kitty, etc.)
BACKUP="$SCRIPT_HOME/.config-backup-pre-jakoolit-$(date +%Y%m%d-%H%M%S)"
run_as_user "mkdir -p '$BACKUP'"
for d in hypr waybar kitty rofi swaync wofi mako; do
[ -d "$CONFIG/$d" ] && run_as_user "cp -r '$CONFIG/$d' '$BACKUP/$d'" || true
done
ok "Existing configs backed up to $BACKUP"
# Copy every top-level directory from config/ into ~/.config/
for d in "$DOTS_DIR/config"/*/; do
name=$(basename "$d")
run_as_user "rm -rf '$CONFIG/$name' && cp -r '$d' '$CONFIG/$name'"
done
ok "Dotfiles copied"
# ── 13. Post-copy tweaks ───────────────────────────────────────────────────────
step "Applying post-copy tweaks"
# JaKooLit separates user-specific settings into hypr/UserConfigs/ so they
# survive future dot updates. Set keyboard layout to 'us' there.
HYPR_USER="$CONFIG/hypr/UserConfigs"
if [ -f "$HYPR_USER/UserSettings.conf" ]; then
sed -i 's/kb_layout\s*=.*/kb_layout = us/' "$HYPR_USER/UserSettings.conf" 2>/dev/null || true
ok "Keyboard layout set to 'us' in UserSettings.conf"
fi
# JaKooLit ships two waybar density configs:
# "[TOP] Default" — for monitors < 1440p (more spacing, larger icons)
# "[TOP] Default Higher" — for monitors >= 1440p (tighter layout)
# The active config is selected via a symlink at configs/[TOP] Default.
# Our monitors are 3440x1440 so we use the Higher variant.
WAYBAR_CFG="$CONFIG/waybar"
if [ -d "$WAYBAR_CFG/configs" ]; then
HIGHER="$WAYBAR_CFG/configs/[TOP] Default Higher"
ACTIVE="$WAYBAR_CFG/configs/[TOP] Default"
if [ -f "$HIGHER" ] && [ ! -L "$ACTIVE" ]; then
run_as_user "ln -sf '$HIGHER' '$ACTIVE'" 2>/dev/null || true
ok "Waybar set to ≥1440p layout"
fi
fi
ok "Post-copy tweaks done"
# Reload Hyprland config if a session is running — otherwise the new dotfiles
# won't take effect until the user manually runs hyprctl reload or logs out.
if [ -n "$(ls /run/user/$(id -u "$SCRIPT_USER")/hypr/ 2>/dev/null)" ]; then
HYPRLAND_INSTANCE_SIGNATURE=$(ls /run/user/$(id -u "$SCRIPT_USER")/hypr/ | head -1)
export HYPRLAND_INSTANCE_SIGNATURE
sudo -u "$SCRIPT_USER" hyprctl reload 2>/dev/null && ok "Hyprland config reloaded" || true
fi
echo ""
echo "╔═══════════════════════════════════════════════════════════════╗"
echo "║ JaKooLit deps + dotfiles installed! ║"
echo "╠═══════════════════════════════════════════════════════════════╣"
echo "║ Config reloaded automatically. If anything looks off, ║"
echo "║ log out and back in for a clean session. ║"
echo "║ ║"
echo "║ Keybinds reference: ║"
echo "║ https://github.com/JaKooLit/Hyprland-Dots/wiki/Keybinds ║"
echo "╚═══════════════════════════════════════════════════════════════╝"
#!/usr/bin/env bash
set -euo pipefail
# ─── Hyprland user config setup for Pop!_OS 24.04 (NVIDIA, dual GPU) ─────────
# Run after install-hyprland.sh: bash ~/setup-hyprland-config.sh
CONFIG="$HOME/.config"
mkdir -p "$CONFIG/hypr" "$CONFIG/waybar" "$CONFIG/wofi" "$CONFIG/mako" \
"$CONFIG/kitty" "$HOME/.local/share/wallpapers"
# ─────────────────────────────────────────────────────────────────────────────
# hyprland.conf
# ─────────────────────────────────────────────────────────────────────────────
cat > "$CONFIG/hypr/hyprland.conf" << 'EOF'
# ── NVIDIA env vars (required for Pop!_OS NVIDIA build) ──────────────────────
env = LIBVA_DRIVER_NAME,nvidia
env = XDG_SESSION_TYPE,wayland
env = GBM_BACKEND,nvidia-drm
env = __GLX_VENDOR_LIBRARY_NAME,nvidia
env = NVD_BACKEND,direct
env = ELECTRON_OZONE_PLATFORM_HINT,wayland
env = MOZ_ENABLE_WAYLAND,1
env = QT_QPA_PLATFORM,wayland
env = QT_QPA_PLATFORMTHEME,qt5ct
env = SDL_VIDEODRIVER,wayland
# ── Monitors ─────────────────────────────────────────────────────────────────
# Use `hyprctl monitors` to list your displays and adjust resolution/position.
# Format: monitor=NAME,WIDTHxHEIGHT@RATE,POSITIONxY,SCALE
monitor=,preferred,auto,1
# ── Autostart ────────────────────────────────────────────────────────────────
exec-once = /usr/lib/policykit-1-gnome/polkit-gnome-authentication-agent-1
exec-once = waybar
exec-once = hyprpaper
exec-once = hypridle
exec-once = mako
exec-once = wl-paste --type text --watch cliphist store
exec-once = wl-paste --type image --watch cliphist store
exec-once = nm-applet --indicator
# ── Look & feel ──────────────────────────────────────────────────────────────
general {
gaps_in = 5
gaps_out = 10
border_size = 2
col.active_border = rgba(cba6f7ff) rgba(89b4faff) 45deg
col.inactive_border = rgba(595959aa)
layout = dwindle
resize_on_border = true
}
decoration {
rounding = 10
blur {
enabled = true
size = 6
passes = 3
}
shadow {
enabled = true
range = 4
render_power = 3
color = rgba(1a1a1aee)
}
}
animations {
enabled = true
bezier = myBezier, 0.05, 0.9, 0.1, 1.05
animation = windows, 1, 7, myBezier
animation = windowsOut, 1, 7, default, popin 80%
animation = border, 1, 10, default
animation = fade, 1, 7, default
animation = workspaces, 1, 6, default
}
dwindle {
pseudotile = true
preserve_split = true
}
misc {
force_default_wallpaper = 0
disable_hyprland_logo = true
}
# ── Input ─────────────────────────────────────────────────────────────────────
input {
kb_layout = us
follow_mouse = 1
sensitivity = 0
touchpad {
natural_scroll = true
}
}
gestures {
# workspace_swipe removed in newer Hyprland — use 3-finger swipe natively
}
# ── Keybindings ───────────────────────────────────────────────────────────────
$mod = SUPER
# Basics
bind = $mod, Return, exec, kitty
bind = $mod, Q, killactive
bind = $mod SHIFT, Q, exit
bind = $mod, E, exec, thunar
bind = $mod, Space, exec, wofi --show drun
bind = $mod, V, exec, cliphist list | wofi --dmenu | cliphist decode | wl-copy
bind = $mod, L, exec, hyprlock
bind = $mod, F, fullscreen
# Screenshot
bind = , Print, exec, hyprshot -m output
bind = SHIFT, Print, exec, hyprshot -m region
bind = $mod, Print, exec, hyprshot -m window
# Focus
bind = $mod, left, movefocus, l
bind = $mod, right, movefocus, r
bind = $mod, up, movefocus, u
bind = $mod, down, movefocus, d
bind = $mod, H, movefocus, l
bind = $mod, L, movefocus, r
bind = $mod, K, movefocus, u
bind = $mod, J, movefocus, d
# Move windows
bind = $mod SHIFT, left, movewindow, l
bind = $mod SHIFT, right, movewindow, r
bind = $mod SHIFT, up, movewindow, u
bind = $mod SHIFT, down, movewindow, d
bind = $mod SHIFT, H, movewindow, l
bind = $mod SHIFT, L, movewindow, r
bind = $mod SHIFT, K, movewindow, u
bind = $mod SHIFT, J, movewindow, d
# Resize
binde = $mod CTRL, right, resizeactive, 30 0
binde = $mod CTRL, left, resizeactive, -30 0
binde = $mod CTRL, up, resizeactive, 0 -30
binde = $mod CTRL, down, resizeactive, 0 30
# Workspaces
bind = $mod, 1, workspace, 1
bind = $mod, 2, workspace, 2
bind = $mod, 3, workspace, 3
bind = $mod, 4, workspace, 4
bind = $mod, 5, workspace, 5
bind = $mod, 6, workspace, 6
bind = $mod, 7, workspace, 7
bind = $mod, 8, workspace, 8
bind = $mod, 9, workspace, 9
bind = $mod, 0, workspace, 10
bind = $mod SHIFT, 1, movetoworkspace, 1
bind = $mod SHIFT, 2, movetoworkspace, 2
bind = $mod SHIFT, 3, movetoworkspace, 3
bind = $mod SHIFT, 4, movetoworkspace, 4
bind = $mod SHIFT, 5, movetoworkspace, 5
bind = $mod SHIFT, 6, movetoworkspace, 6
bind = $mod SHIFT, 7, movetoworkspace, 7
bind = $mod SHIFT, 8, movetoworkspace, 8
bind = $mod SHIFT, 9, movetoworkspace, 9
bind = $mod SHIFT, 0, movetoworkspace, 10
bind = $mod, mouse_down, workspace, e+1
bind = $mod, mouse_up, workspace, e-1
# Float / tile toggle
bind = $mod SHIFT, space, togglefloating
bind = $mod, P, pseudo
# Mouse window control
bindm = $mod, mouse:272, movewindow
bindm = $mod, mouse:273, resizewindow
# Media / brightness
bindel = , XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+
bindel = , XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
bindl = , XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
bindl = , XF86AudioPlay, exec, playerctl play-pause
bindl = , XF86AudioNext, exec, playerctl next
bindl = , XF86AudioPrev, exec, playerctl previous
bindel = , XF86MonBrightnessUp, exec, brightnessctl set 5%+
bindel = , XF86MonBrightnessDown, exec, brightnessctl set 5%-
# ── Window rules ─────────────────────────────────────────────────────────────
windowrule {
name = float-pavucontrol
match:class = pavucontrol
float = true
}
windowrule {
name = float-nm-connection-editor
match:class = nm-connection-editor
float = true
}
windowrule {
name = float-thunar-file-ops
match:class = thunar
match:title = File Operation.*
float = true
}
windowrule {
name = suppress-maximize-events
match:class = .*
suppress_event = maximize
}
EOF
# ─────────────────────────────────────────────────────────────────────────────
# hyprpaper.conf — using a solid color until you add a wallpaper
# ─────────────────────────────────────────────────────────────────────────────
# Create a minimal dark wallpaper with ImageMagick if available, else skip
if command -v convert &>/dev/null; then
convert -size 1920x1080 gradient:"#1e1e2e-#313244" \
"$HOME/.local/share/wallpapers/default.png" 2>/dev/null && \
cat > "$CONFIG/hypr/hyprpaper.conf" << WALLEOF
preload = $HOME/.local/share/wallpapers/default.png
wallpaper = ,$HOME/.local/share/wallpapers/default.png
splash = false
WALLEOF
echo " Wallpaper generated"
else
cat > "$CONFIG/hypr/hyprpaper.conf" << 'WALLEOF'
# Add your wallpaper:
# preload = /path/to/image.png
# wallpaper = ,/path/to/image.png
splash = false
WALLEOF
echo " No imagemagick — add wallpaper path to ~/.config/hypr/hyprpaper.conf manually"
fi
# ─────────────────────────────────────────────────────────────────────────────
# hypridle.conf
# ─────────────────────────────────────────────────────────────────────────────
cat > "$CONFIG/hypr/hypridle.conf" << 'EOF'
general {
lock_cmd = pidof hyprlock || hyprlock
before_sleep_cmd = loginctl lock-session
after_sleep_cmd = hyprctl dispatch dpms on
}
listener {
timeout = 300 # 5 min: dim
on-timeout = brightnessctl -s set 20%
on-resume = brightnessctl -r
}
listener {
timeout = 360 # 6 min: lock
on-timeout = loginctl lock-session
}
listener {
timeout = 600 # 10 min: turn off displays
on-timeout = hyprctl dispatch dpms off
on-resume = hyprctl dispatch dpms on
}
listener {
timeout = 1200 # 20 min: suspend
on-timeout = systemctl suspend
}
EOF
# ─────────────────────────────────────────────────────────────────────────────
# hyprlock.conf
# ─────────────────────────────────────────────────────────────────────────────
cat > "$CONFIG/hypr/hyprlock.conf" << 'EOF'
general {
disable_loading_bar = true
hide_cursor = true
grace = 0
}
background {
monitor =
path = screenshot
blur_passes = 3
blur_size = 7
noise = 0.0117
contrast = 0.8917
brightness = 0.8172
vibrancy = 0.1696
}
input-field {
monitor =
size = 250, 50
outline_thickness = 3
dots_size = 0.33
dots_spacing = 0.15
outer_color = rgb(151515)
inner_color = rgb(200, 200, 200)
font_color = rgb(10, 10, 10)
fade_on_empty = true
placeholder_text = <i>Password...</i>
hide_input = false
position = 0, -80
halign = center
valign = center
}
label {
monitor =
text = cmd[update:1000] echo "<b>$(date +"%H:%M")</b>"
color = rgba(200, 200, 200, 1.0)
font_size = 64
font_family = Noto Sans Bold
position = 0, 160
halign = center
valign = center
}
EOF
# ─────────────────────────────────────────────────────────────────────────────
# waybar config
# ─────────────────────────────────────────────────────────────────────────────
cat > "$CONFIG/waybar/config.jsonc" << 'EOF'
{
"layer": "top",
"position": "top",
"height": 36,
"spacing": 4,
"modules-left": ["hyprland/workspaces", "hyprland/window"],
"modules-center": ["clock"],
"modules-right": ["tray", "pulseaudio", "network", "battery", "cpu", "memory"],
"hyprland/workspaces": {
"format": "{id}",
"on-click": "activate"
},
"hyprland/window": {
"max-length": 60
},
"clock": {
"format": "{:%a %b %d %H:%M}",
"tooltip-format": "<big>{:%Y %B}</big>\n<tt><small>{calendar}</small></tt>"
},
"cpu": {
"format": " {usage}%",
"interval": 2
},
"memory": {
"format": " {used:.1f}G",
"interval": 5
},
"pulseaudio": {
"format": "{icon} {volume}%",
"format-muted": " muted",
"format-icons": { "default": ["", "", ""] },
"on-click": "pavucontrol"
},
"network": {
"format-wifi": " {essid}",
"format-ethernet": "󰈀 {ipaddr}",
"format-disconnected": "󰤭 offline",
"tooltip-format": "{ifname}: {ipaddr}/{cidr}"
},
"battery": {
"format": "{icon} {capacity}%",
"format-charging": " {capacity}%",
"format-icons": ["", "", "", "", ""],
"states": { "warning": 30, "critical": 15 }
},
"tray": {
"spacing": 8
}
}
EOF
cat > "$CONFIG/waybar/style.css" << 'EOF'
* {
font-family: "Noto Sans", "Font Awesome 6 Free", sans-serif;
font-size: 13px;
border: none;
border-radius: 0;
min-height: 0;
}
window#waybar {
background-color: rgba(30, 30, 46, 0.92);
color: #cdd6f4;
}
#workspaces button {
padding: 0 8px;
color: #6c7086;
background: transparent;
}
#workspaces button.active {
color: #cba6f7;
border-bottom: 2px solid #cba6f7;
}
#workspaces button:hover {
background: rgba(203, 166, 247, 0.15);
}
#clock, #cpu, #memory, #network, #pulseaudio, #battery, #tray {
padding: 0 10px;
color: #cdd6f4;
}
#battery.warning { color: #fab387; }
#battery.critical { color: #f38ba8; }
#window {
padding: 0 10px;
color: #a6adc8;
font-style: italic;
}
EOF
# ─────────────────────────────────────────────────────────────────────────────
# wofi config
# ─────────────────────────────────────────────────────────────────────────────
cat > "$CONFIG/wofi/style.css" << 'EOF'
window {
background-color: rgba(30, 30, 46, 0.95);
border-radius: 12px;
border: 2px solid #cba6f7;
}
#input {
background-color: #313244;
color: #cdd6f4;
border: none;
border-radius: 8px;
padding: 8px 12px;
margin: 8px;
font-size: 14px;
}
#inner-box {
background: transparent;
}
#outer-box {
padding: 8px;
}
#entry {
padding: 6px 10px;
border-radius: 6px;
}
#entry:selected {
background-color: #45475a;
}
#text {
color: #cdd6f4;
font-size: 13px;
}
EOF
cat > "$CONFIG/wofi/config" << 'EOF'
width=480
height=400
location=center
show=drun
prompt=Search...
filter_rate=100
allow_markup=true
no_actions=true
halign=fill
orientation=vertical
content_halign=fill
insensitive=true
allow_images=true
image_size=24
gtk_dark=true
EOF
# ─────────────────────────────────────────────────────────────────────────────
# mako (notifications)
# ─────────────────────────────────────────────────────────────────────────────
cat > "$CONFIG/mako/config" << 'EOF'
background-color=#1e1e2e
text-color=#cdd6f4
border-color=#cba6f7
border-radius=10
border-size=2
padding=12,16
default-timeout=5000
max-visible=5
font=Noto Sans 11
width=360
height=120
anchor=top-right
margin=10
layer=overlay
EOF
# ─────────────────────────────────────────────────────────────────────────────
# kitty (terminal)
# ─────────────────────────────────────────────────────────────────────────────
cat > "$CONFIG/kitty/kitty.conf" << 'EOF'
# Catppuccin Mocha theme to match waybar/wofi
foreground #CDD6F4
background #1E1E2E
background_opacity 0.92
# Colors
color0 #45475A
color1 #F38BA8
color2 #A6E3A1
color3 #F9E2AF
color4 #89B4FA
color5 #F5C2E7
color6 #94E2D5
color7 #BAC2DE
color8 #585B70
color9 #F38BA8
color10 #A6E3A1
color11 #F9E2AF
color12 #89B4FA
color13 #F5C2E7
color14 #94E2D5
color15 #A6ADC8
cursor #F5E0DC
cursor_text_color #1E1E2E
selection_foreground #1E1E2E
selection_background #F5E0DC
font_family monospace
font_size 12.0
window_padding_width 8
confirm_os_window_close 0
EOF
echo ""
echo "╔══════════════════════════════════════════════════════════╗"
echo "║ Hyprland config setup complete! ║"
echo "╠══════════════════════════════════════════════════════════╣"
echo "║ Configs written to: ║"
echo "║ ~/.config/hypr/ (hyprland, hyprpaper, ║"
echo "║ hypridle, hyprlock) ║"
echo "║ ~/.config/waybar/ (config.jsonc, style.css) ║"
echo "║ ~/.config/wofi/ (config, style.css) ║"
echo "║ ~/.config/mako/ (config) ║"
echo "║ ~/.config/kitty/ (kitty.conf) ║"
echo "╠══════════════════════════════════════════════════════════╣"
echo "║ To use: log out → select Hyprland at login screen ║"
echo "║ Key bindings: ║"
echo "║ Super+Return → kitty terminal ║"
echo "║ Super+Space → wofi app launcher ║"
echo "║ Super+Q → close window ║"
echo "║ Super+L → lock screen ║"
echo "║ Super+E → thunar file manager ║"
echo "║ Super+V → clipboard history ║"
echo "║ PrintScr → screenshot (full screen) ║"
echo "║ Shift+Print → screenshot (select region) ║"
echo "╚══════════════════════════════════════════════════════════╝"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment