This commit is contained in:
Javier Feliz 2025-08-07 18:51:03 -04:00
parent be825f91d5
commit e8d0950852
8 changed files with 233 additions and 315 deletions

85
CLAUDE.md Normal file
View File

@ -0,0 +1,85 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Repository Overview
This is an Arch Linux Hyprland desktop setup automation repository based on [omarchy.org](https://omarchy.org). It provides a comprehensive collection of shell scripts to set up a fresh Arch Linux installation with the Hyprland window manager and various desktop applications.
## Project Structure
### Main Scripts
- `base_install.sh` - The main entry point script (currently empty, but serves as the base installer)
- `scripts/` - Contains all installation and configuration scripts organized by category:
- `config/` - System configuration scripts (keyboard, network, timezones, etc.)
- `desktop/` - Desktop environment installation scripts (Hyprland, themes, applications)
- `aur.sh`, `development.sh`, `firewall.sh`, etc. - Specialized installation scripts
### Theme System
- `themes/` - Contains multiple theme configurations, each including:
- Color schemes for various applications (alacritty, waybar, mako, etc.)
- Hyprland configuration files (`hyprland.conf`, `hyprlock.conf`)
- Background images and icon themes
- Application-specific styling (CSS, config files)
Available themes: catppuccin, catppuccin-latte, everforest, gruvbox, kanagawa, matte-black, nord, osaka-jade, ristretto, rose-pine, tokyo-night
## Development Commands
This repository consists entirely of shell scripts for system configuration. There are no build, test, or lint commands as this is a collection of installation scripts.
### Running Scripts
```bash
# Make scripts executable
chmod +x script_name.sh
# Run installation scripts
./base_install.sh
./scripts/desktop/hyprlandia.sh
./scripts/desktop/theme.sh
```
## Architecture and Key Components
### Package Management
All scripts use `yay` (AUR helper) for package installation with standard flags:
- `--noconfirm` - Non-interactive installation
- `--needed` - Only install if not already present
### Theme Management System
The theme system uses symlinks to manage active themes:
- Themes are linked from `~/.local/share/omarchy/themes/` to `~/.config/omarchy/themes/`
- Active theme is symlinked to `~/.config/omarchy/current/theme`
- Individual application configs are symlinked from the current theme
### Configuration Approach
- Configurations are copied from `~/.local/share/omarchy/config/` to `~/.config/`
- GPG configurations are set up system-wide in `/etc/gnupg/`
- Git aliases and user information are configured globally
- PAM faillock settings are modified for security
### Key Installation Categories
1. **System Config** - Keyboard layout detection, network setup, timezone configuration
2. **Desktop Environment** - Hyprland compositor and related tools
3. **Applications** - File managers, media players, web browsers
4. **Development Tools** - Available via `development.sh`
5. **Theming** - Comprehensive theme support across all applications
### GPU-Aware Installation
Scripts detect GPU type and install appropriate software:
- NVIDIA GPUs: `wf-recorder` for screen recording
- Other GPUs: `wl-screenrec` for screen recording
## Working with Themes
Each theme directory contains configuration files for:
- Terminal emulator (alacritty)
- Status bar (waybar)
- Notifications (mako)
- Application launcher (walker)
- Screen locker (hyprlock)
- System monitor (btop)
- Text editor (neovim)
- Volume/brightness OSD (swayosd)
Theme switching is handled through the symlink system managed by `scripts/desktop/theme.sh`.

View File

@ -0,0 +1,57 @@
#!/bin/bash
# Arch Hyprland Setup - Base Installer
# Runs all installation scripts in the correct order
set -e # Exit on any error
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SCRIPTS_DIR="$SCRIPT_DIR/scripts"
echo "Starting Arch Hyprland Setup..."
# Function to run a script and check for errors
run_script() {
local script="$1"
local name="$2"
if [[ -f "$script" ]]; then
echo "Running $name..."
chmod +x "$script"
bash "$script"
echo " $name completed"
else
echo "<EFBFBD> Warning: $name not found at $script"
fi
}
# Step 1: Install AUR helper (yay)
run_script "$SCRIPTS_DIR/aur.sh" "AUR helper installation"
# Step 2: System configuration
echo "Configuring system settings..."
run_script "$SCRIPTS_DIR/config/detect-keyboard-layout.sh" "Keyboard layout detection"
run_script "$SCRIPTS_DIR/config/network.sh" "Network configuration"
run_script "$SCRIPTS_DIR/config/nvidia.sh" "NVIDIA configuration"
run_script "$SCRIPTS_DIR/config/power.sh" "Power management"
run_script "$SCRIPTS_DIR/config/fix-fkeys.sh" "Function keys configuration"
run_script "$SCRIPTS_DIR/config/config.sh" "General system configuration"
# Step 3: Desktop environment
echo "Installing desktop environment..."
run_script "$SCRIPTS_DIR/desktop/fonts.sh" "Font installation"
run_script "$SCRIPTS_DIR/desktop/hyprlandia.sh" "Hyprland installation"
run_script "$SCRIPTS_DIR/desktop/uwsm.sh" "Universal Wayland Session Manager"
run_script "$SCRIPTS_DIR/desktop/desktop.sh" "Desktop applications"
run_script "$SCRIPTS_DIR/desktop/bluetooth.sh" "Bluetooth setup"
run_script "$SCRIPTS_DIR/desktop/theme.sh" "Theme configuration"
# Step 4: Additional software and configurations
echo "Installing additional software..."
run_script "$SCRIPTS_DIR/development.sh" "Development tools"
run_script "$SCRIPTS_DIR/firewall.sh" "Firewall configuration"
run_script "$SCRIPTS_DIR/mimetypes.sh" "MIME types configuration"
run_script "$SCRIPTS_DIR/xtras.sh" "Extra applications"
echo "<<3C> Arch Hyprland Setup completed successfully!"
echo "Please reboot your system to ensure all changes take effect."

View File

@ -1,4 +0,0 @@
#!/bin/bash
export OMARCHY_USER_NAME=$(gum input --placeholder "Enter full name" --prompt "Name> ")
export OMARCHY_USER_EMAIL=$(gum input --placeholder "Enter email address" --prompt "Email> ")

View File

@ -1,267 +0,0 @@
#!/bin/bash
# Hyprland launched via UWSM and login directly as user, rely on disk encryption + hyprlock for security
if ! command -v uwsm &>/dev/null || ! command -v plymouth &>/dev/null; then
yay -S --noconfirm --needed uwsm plymouth
fi
# ==============================================================================
# PLYMOUTH SETUP
# ==============================================================================
if ! grep -Eq '^HOOKS=.*plymouth' /etc/mkinitcpio.conf; then
# Backup original mkinitcpio.conf just in case
backup_timestamp=$(date +"%Y%m%d%H%M%S")
sudo cp /etc/mkinitcpio.conf "/etc/mkinitcpio.conf.bak.${backup_timestamp}"
# Add plymouth to HOOKS array after 'base udev' or 'base systemd'
if grep "^HOOKS=" /etc/mkinitcpio.conf | grep -q "base systemd"; then
sudo sed -i '/^HOOKS=/s/base systemd/base systemd plymouth/' /etc/mkinitcpio.conf
elif grep "^HOOKS=" /etc/mkinitcpio.conf | grep -q "base udev"; then
sudo sed -i '/^HOOKS=/s/base udev/base udev plymouth/' /etc/mkinitcpio.conf
else
echo "Couldn't add the Plymouth hook"
fi
# Regenerate initramfs
sudo mkinitcpio -P
fi
# Add kernel parameters for Plymouth
if [ -d "/boot/loader/entries" ]; then # systemd-boot
echo "Detected systemd-boot"
for entry in /boot/loader/entries/*.conf; do
if [ -f "$entry" ]; then
# Skip fallback entries
if [[ "$(basename "$entry")" == *"fallback"* ]]; then
echo "Skipped: $(basename "$entry") (fallback entry)"
continue
fi
# Skip if splash it already present for some reason
if ! grep -q "splash" "$entry"; then
sudo sed -i '/^options/ s/$/ splash quiet/' "$entry"
else
echo "Skipped: $(basename "$entry") (splash already present)"
fi
fi
done
elif [ -f "/etc/default/grub" ]; then # Grub
echo "Detected grub"
# Backup GRUB config before modifying
backup_timestamp=$(date +"%Y%m%d%H%M%S")
sudo cp /etc/default/grub "/etc/default/grub.bak.${backup_timestamp}"
# Check if splash is already in GRUB_CMDLINE_LINUX_DEFAULT
if ! grep -q "GRUB_CMDLINE_LINUX_DEFAULT.*splash" /etc/default/grub; then
# Get current GRUB_CMDLINE_LINUX_DEFAULT value
current_cmdline=$(grep "^GRUB_CMDLINE_LINUX_DEFAULT=" /etc/default/grub | cut -d'"' -f2)
# Add splash and quiet if not present
new_cmdline="$current_cmdline"
if [[ ! "$current_cmdline" =~ splash ]]; then
new_cmdline="$new_cmdline splash"
fi
if [[ ! "$current_cmdline" =~ quiet ]]; then
new_cmdline="$new_cmdline quiet"
fi
# Trim any leading/trailing spaces
new_cmdline=$(echo "$new_cmdline" | xargs)
sudo sed -i "s/^GRUB_CMDLINE_LINUX_DEFAULT=\".*\"/GRUB_CMDLINE_LINUX_DEFAULT=\"$new_cmdline\"/" /etc/default/grub
# Regenerate grub config
sudo grub-mkconfig -o /boot/grub/grub.cfg
else
echo "GRUB already configured with splash kernel parameters"
fi
elif [ -d "/etc/cmdline.d" ]; then # UKI
echo "Detected a UKI setup"
# Relying on mkinitcpio to assemble a UKI
# https://wiki.archlinux.org/title/Unified_kernel_image
if ! grep -q splash /etc/cmdline.d/*.conf; then
# Need splash, create the omarchy file
echo "splash" | sudo tee -a /etc/cmdline.d/omarchy.conf
fi
if ! grep -q quiet /etc/cmdline.d/*.conf; then
# Need quiet, create or append the omarchy file
echo "quiet" | sudo tee -a /etc/cmdline.d/omarchy.conf
fi
elif [ -f "/etc/kernel/cmdline" ]; then # UKI Alternate
# Alternate UKI kernel cmdline location
echo "Detected a UKI setup"
# Backup kernel cmdline config before modifying
backup_timestamp=$(date +"%Y%m%d%H%M%S")
sudo cp /etc/kernel/cmdline "/etc/kernel/cmdline.bak.${backup_timestamp}"
current_cmdline=$(cat /etc/kernel/cmdline)
# Add splash and quiet if not present
new_cmdline="$current_cmdline"
if [[ ! "$current_cmdline" =~ splash ]]; then
new_cmdline="$new_cmdline splash"
fi
if [[ ! "$current_cmdline" =~ quiet ]]; then
new_cmdline="$new_cmdline quiet"
fi
# Trim any leading/trailing spaces
new_cmdline=$(echo "$new_cmdline" | xargs)
# Write new file
echo $new_cmdline | sudo tee /etc/kernel/cmdline
else
echo ""
echo " None of systemd-boot, GRUB, or UKI detected. Please manually add these kernel parameters:"
echo " - splash (to see the graphical splash screen)"
echo " - quiet (for silent boot)"
echo ""
fi
if [ "$(plymouth-set-default-theme)" != "omarchy" ]; then
sudo cp -r "$HOME/.local/share/omarchy/default/plymouth" /usr/share/plymouth/themes/omarchy/
sudo plymouth-set-default-theme -R omarchy
fi
# ==============================================================================
# SEAMLESS LOGIN
# ==============================================================================
if [ ! -x /usr/local/bin/seamless-login ]; then
# Compile the seamless login helper -- needed to prevent seeing terminal between loader and desktop
cat <<'CCODE' >/tmp/seamless-login.c
/*
* Seamless Login - Minimal SDDM-style Plymouth transition
* Replicates SDDM's VT management for seamless auto-login
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/kd.h>
#include <linux/vt.h>
#include <sys/wait.h>
#include <string.h>
int main(int argc, char *argv[]) {
int vt_fd;
int vt_num = 1; // TTY1
char vt_path[32];
if (argc < 2) {
fprintf(stderr, "Usage: %s <session_command>\n", argv[0]);
return 1;
}
// Open the VT (simple approach like SDDM)
snprintf(vt_path, sizeof(vt_path), "/dev/tty%d", vt_num);
vt_fd = open(vt_path, O_RDWR);
if (vt_fd < 0) {
perror("Failed to open VT");
return 1;
}
// Activate the VT
if (ioctl(vt_fd, VT_ACTIVATE, vt_num) < 0) {
perror("VT_ACTIVATE failed");
close(vt_fd);
return 1;
}
// Wait for VT to be active
if (ioctl(vt_fd, VT_WAITACTIVE, vt_num) < 0) {
perror("VT_WAITACTIVE failed");
close(vt_fd);
return 1;
}
// Critical: Set graphics mode to prevent console text
if (ioctl(vt_fd, KDSETMODE, KD_GRAPHICS) < 0) {
perror("KDSETMODE KD_GRAPHICS failed");
close(vt_fd);
return 1;
}
// Clear VT and close (like SDDM does)
const char *clear_seq = "\33[H\33[2J";
if (write(vt_fd, clear_seq, strlen(clear_seq)) < 0) {
perror("Failed to clear VT");
}
close(vt_fd);
// Set working directory to user's home
const char *home = getenv("HOME");
if (home) chdir(home);
// Now execute the session command
execvp(argv[1], &argv[1]);
perror("Failed to exec session");
return 1;
}
CCODE
gcc -o /tmp/seamless-login /tmp/seamless-login.c
sudo mv /tmp/seamless-login /usr/local/bin/seamless-login
sudo chmod +x /usr/local/bin/seamless-login
rm /tmp/seamless-login.c
fi
if [ ! -f /etc/systemd/system/omarchy-seamless-login.service ]; then
cat <<EOF | sudo tee /etc/systemd/system/omarchy-seamless-login.service
[Unit]
Description=Omarchy Seamless Auto-Login
Documentation=https://github.com/basecamp/omarchy
Conflicts=getty@tty1.service
After=systemd-user-sessions.service getty@tty1.service plymouth-quit.service systemd-logind.service
PartOf=graphical.target
[Service]
Type=simple
ExecStart=/usr/local/bin/seamless-login uwsm start -- hyprland.desktop
Restart=always
RestartSec=2
User=$USER
TTYPath=/dev/tty1
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
StandardInput=tty
StandardOutput=journal
StandardError=journal+console
PAMName=login
[Install]
WantedBy=graphical.target
EOF
fi
if [ ! -f /etc/systemd/system/plymouth-quit.service.d/wait-for-graphical.conf ]; then
# Make plymouth remain until graphical.target
sudo mkdir -p /etc/systemd/system/plymouth-quit.service.d
sudo tee /etc/systemd/system/plymouth-quit.service.d/wait-for-graphical.conf <<'EOF'
[Unit]
After=multi-user.target
EOF
fi
# Mask plymouth-quit-wait.service only if not already masked
if ! systemctl is-enabled plymouth-quit-wait.service | grep -q masked; then
sudo systemctl mask plymouth-quit-wait.service
sudo systemctl daemon-reload
fi
# Enable omarchy-seamless-login.service only if not already enabled
if ! systemctl is-enabled omarchy-seamless-login.service | grep -q enabled; then
sudo systemctl enable omarchy-seamless-login.service
fi
# Disable getty@tty1.service only if not already disabled
if ! systemctl is-enabled getty@tty1.service | grep -q disabled; then
sudo systemctl disable getty@tty1.service
fi

View File

@ -1,9 +0,0 @@
#!/bin/bash
if ! command -v tzupdate &>/dev/null; then
yay -S --noconfirm --needed tzupdate
sudo tee /etc/sudoers.d/omarchy-tzupdate >/dev/null <<EOF
%wheel ALL=(root) NOPASSWD: /usr/bin/tzupdate, /usr/bin/timedatectl
EOF
sudo chmod 0440 /etc/sudoers.d/omarchy-tzupdate
fi

View File

@ -1,16 +0,0 @@
#!/bin/bash
sudo pacman -S --noconfirm cups cups-pdf cups-filters cups-browsed system-config-printer avahi nss-mdns
sudo systemctl enable --now cups.service
# Disable multicast dns in resolved. Avahi will provide this for better network printer discovery
sudo mkdir -p /etc/systemd/resolved.conf.d
echo -e "[Resolve]\nMulticastDNS=no" | sudo tee /etc/systemd/resolved.conf.d/10-disable-multicast.conf
sudo systemctl enable --now avahi-daemon.service
# Enable automatically adding remote printers
if ! grep -q '^CreateRemotePrinters Yes' /etc/cups/cups-browsed.conf; then
echo 'CreateRemotePrinters Yes' | sudo tee -a /etc/cups/cups-browsed.conf
fi
sudo systemctl enable --now cups-browsed.service

View File

@ -17,22 +17,4 @@ fi
gsettings set org.gnome.desktop.interface gtk-theme "Adwaita-dark"
gsettings set org.gnome.desktop.interface color-scheme "prefer-dark"
gsettings set org.gnome.desktop.interface icon-theme "Yaru-blue"
# Setup theme links
mkdir -p ~/.config/omarchy/themes
for f in ~/.local/share/omarchy/themes/*; do ln -nfs "$f" ~/.config/omarchy/themes/; done
# Set initial theme
mkdir -p ~/.config/omarchy/current
ln -snf ~/.config/omarchy/themes/tokyo-night ~/.config/omarchy/current/theme
ln -snf ~/.config/omarchy/current/theme/backgrounds/1-scenery-pink-lakeside-sunset-lake-landscape-scenic-panorama-7680x3215-144.png ~/.config/omarchy/current/background
# Set specific app links for current theme
ln -snf ~/.config/omarchy/current/theme/neovim.lua ~/.config/nvim/lua/plugins/theme.lua
mkdir -p ~/.config/btop/themes
ln -snf ~/.config/omarchy/current/theme/btop.theme ~/.config/btop/themes/current.theme
mkdir -p ~/.config/mako
ln -snf ~/.config/omarchy/current/theme/mako.ini ~/.config/mako/config
gsettings set org.gnome.desktop.interface icon-theme "Yaru-blue"

90
scripts/desktop/uwsm.sh Normal file
View File

@ -0,0 +1,90 @@
#!/bin/bash
# Install and configure UWSM (Universal Wayland Session Manager) for Hyprland
# Install UWSM and dbus-broker (recommended)
yay -S --noconfirm --needed uwsm dbus-broker
# Enable and start dbus-broker
sudo systemctl enable dbus-broker.service
sudo systemctl --global enable dbus-broker.service
# Create uwsm config directory
mkdir -p ~/.config/uwsm
# Create common environment variables file
cat > ~/.config/uwsm/env << 'EOF'
# Common environment variables for all graphical sessions
export GTK_THEME=Adwaita:dark
export QT_STYLE_OVERRIDE=Adwaita-Dark
export XCURSOR_THEME=Yaru
export XCURSOR_SIZE=24
export MOZ_ENABLE_WAYLAND=1
export QT_QPA_PLATFORM=wayland
export SDL_VIDEODRIVER=wayland
export _JAVA_AWT_WM_NONREPARENTING=1
export XDG_CURRENT_DESKTOP=Hyprland
export XDG_SESSION_TYPE=wayland
export XDG_SESSION_DESKTOP=Hyprland
EOF
# Create Hyprland-specific environment variables file
cat > ~/.config/uwsm/env-hyprland << 'EOF'
# Hyprland-specific environment variables
export HYPRLAND_LOG_WLR=1
export HYPRLAND_NO_RT=1
EOF
# Create desktop entry for display manager
sudo mkdir -p /usr/share/wayland-sessions
sudo tee /usr/share/wayland-sessions/hyprland-uwsm.desktop > /dev/null << 'EOF'
[Desktop Entry]
Name=Hyprland (with UWSM)
Comment=Hyprland managed by Universal Wayland Session Manager
Exec=uwsm start hyprland.desktop
Type=Application
DesktopNames=Hyprland
EOF
# Add UWSM startup to .profile if not already present
if ! grep -q "uwsm check may-start" ~/.profile 2>/dev/null; then
echo "Adding UWSM startup to ~/.profile"
cat >> ~/.profile << 'EOF'
# Start UWSM if conditions are met
if uwsm check may-start && uwsm select; then
exec uwsm start default
fi
EOF
fi
# Create a UWSM service to handle Hyprland autostart applications
mkdir -p ~/.config/systemd/user
cat > ~/.config/systemd/user/uwsm-app-daemon.service << 'EOF'
[Unit]
Description=UWSM Application Daemon
PartOf=graphical-session.target
After=graphical-session.target
[Service]
Type=forking
ExecStart=/bin/bash -c 'uwsm finalize'
RemainAfterExit=yes
[Install]
WantedBy=graphical-session.target
EOF
# Enable the UWSM service
systemctl --user enable uwsm-app-daemon.service
echo "UWSM installation and configuration completed!"
echo ""
echo "Usage:"
echo " - From TTY: The system will automatically start UWSM when logging in"
echo " - From display manager: Select 'Hyprland (with UWSM)' from the session menu"
echo " - Launch applications: Use 'uwsm app -- command' instead of just 'command'"
echo " - Stop session: Use 'uwsm stop' (do not use Hyprland's exit command)"
echo ""
echo "Note: Update your Hyprland config to use 'uwsm app --' for exec-once commands"
echo "Example: exec-once = uwsm app -- waybar"