With Titan, we added new tooling for detecting and installing the proper GPU drivers for all major GPUs. It doesn’t only install the base drivers, but also ensures that drivers for vulkan, mesa and GPU hardware decoding are also installed.
While we have been using it on the ISO for some time now, it can also be used to install and remove drivers in existing installs.
Here is some information on what it does and how to use it.
It has profiles for each type of GPU. The profile is then tied to a list of packages to install. It is also has profiles for VM environments and will install the VM client packages along with the drivers if you are inside a VM.
If you just want it to install the drivers it thinks are best based on your detected hardware, you can use:
sudo eos-hwtool --install-recommended
By default, it shows you the recommended profile for each GPU you have:
eos-hwtool
To list all the profiles supported by your GPUs:
eos-hwtool --list
To install all the drivers for a profile you can use:
sudo eos-hwtool --install <profile>
To remove the drivers for a profile you can use:
sudo eos-hwtool --remove <profile>
Please note that it will not remove things like mesa that may be needed even if you switch GPUs.
How do the user know if the packages included in each profiles are already installed?
Is there an option to check for the status of the packages of each profile if they are installed or not?
Here is my little contribution. A script to check the list of packages of each profile.
Note: The script provides a selection list for any conflicting required packages so the user can select the desired one. Also, there is preview panel for the package’s description and Ctrl-o will pop up a full description of the package in menu list entry.
The author of the eos-hwtool can easily integrate this code into the eos-hwtool if so desired.
#!/bin/bash
# ==============================================================================
# Script: eos-hwtool-check
# Version: 1.5.2
# Date: 2026-08-16
# Desc: Checks for installed packages based on EndeavourOS hardware profiles.
# Uses 'fzf' with a robust preview helper script for live package info.
# Includes colorized output, a preview timeout, and an auto-installer
# prompt for fzf.
# ==============================================================================
VERSION="1.5.2"
DATE="2026-08-16"
# --- ANSI Color Codes ---
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m' # No Color
# Preview timeout in seconds (can be overridden by env PREVIEW_TIMEOUT)
PREVIEW_TIMEOUT="${PREVIEW_TIMEOUT:-2}"
# Define available profiles and their associated packages
declare -A PROFILES
PROFILES[amd_amdgpu]="mesa vulkan-radeon gst-plugin-va lib32-mesa lib32-vulkan-radeon"
PROFILES[intel_gpu]="mesa vulkan-intel intel-media-driver lib32-mesa lib32-vulkan-intel"
PROFILES[nvidia_latest]="nvidia-dkms nvidia-utils nvidia-settings lib32-nvidia-utils egl-wayland"
PROFILES[nvidia_lts]="nvidia-lts nvidia-utils nvidia-settings lib32-nvidia-utils egl-wayland"
PROFILES[vmware_guest]="open-vm-tools xf86-video-vmware mesa"
PROFILES[virtualbox_guest]="virtualbox-guest-utils mesa"
show_help() {
echo -e "${BOLD}${CYAN}Usage:${NC} $(basename "$0") [OPTIONS]"
echo ""
echo -e "An interactive hardware profile package checker for EndeavourOS."
echo ""
echo -e "${BOLD}Options:${NC}"
echo -e " ${GREEN}-h, --help${NC} Show this help message and exit"
echo -e " ${GREEN}-v, --version${NC} Show version and date information and exit"
echo -e " ${GREEN}-l, --list${NC} List all available hardware profiles"
echo -e " ${GREEN}-i, --info [profile]${NC} Show the list of packages for a specific profile"
echo ""
echo -e "${YELLOW}Note:${NC} Install 'fzf' for an enhanced TUI experience when selecting packages."
echo -e "If no options are provided, the interactive profile selector will launch."
}
show_version() {
echo -e "${CYAN}eos-hwtool-check${NC} version ${BOLD}$VERSION${NC}"
echo -e "Release Date: $DATE"
}
show_list() {
echo -e "${BOLD}Available eos-hwtool profiles:${NC}"
echo "---------------------------------------------------"
for profile in "${!PROFILES[@]}"; do
echo "$profile"
done | sort | while read -r p; do echo -e " - ${CYAN}$p${NC}"; done
}
show_info() {
local profile_name=$1
if [[ -n "${PROFILES[$profile_name]}" ]]; then
echo -e "${BOLD}Profile:${NC} ${CYAN}$profile_name${NC}"
echo -e "${BOLD}Packages:${NC} ${PROFILES[$profile_name]}"
else
echo -e "${RED}Error:${NC} Profile '$profile_name' not found."
echo -e "Use '${GREEN}--list${NC}' to see available profiles."
exit 1
fi
}
# ------------------------------------------------------------------------------
# Create a small preview helper script (temporary, executable)
# This avoids exported-function and quoting issues when fzf runs preview commands.
# ------------------------------------------------------------------------------
create_preview_helper() {
# Create a temp file that will be removed on exit
PREVIEW_SCRIPT="$(mktemp /tmp/eos_hw_preview.XXXXXX)"
cat > "$PREVIEW_SCRIPT" <<'EOF'
#!/usr/bin/env bash
# Preview helper: prints a concise package preview (multi-line Description + header)
pkg="$1"
# Defensive trimming
pkg="${pkg#"${pkg%%[![:space:]]*}"}"
pkg="${pkg%"${pkg##*[![:space:]]}"}"
if [[ -z "$pkg" ]]; then
echo -e "\033[0;31mNo package specified.\033[0m"
exit 1
fi
if [[ "$pkg" == "Skip" ]]; then
echo -e "\033[1;33m[SKIP OPTION]\033[0m"
echo "Choose this option to skip installing this specific package."
exit 0
fi
# Helper function: print Description and any following indented lines (multi-line descriptions)
print_description() {
# Read pacman output from stdin and print Description block
awk '
BEGIN { in_desc=0 }
/^Description[[:space:]]*:/ {
# Remove "Description:" prefix and print the rest of the line
sub(/^Description[[:space:]]*:[[:space:]]*/, "")
print
in_desc=1
next
}
in_desc && /^[[:space:]]/ {
# continuation lines (indented)
print
next
}
in_desc { exit }'
}
: "${PREVIEW_DESC_LINES:=12}" # default if not set
# Prefer sync DB (pacman -Si) then local DB (pacman -Qi)
if pacman -Si "$pkg" &>/dev/null; then
# Print header
echo -e "\033[1;36m$pkg\033[0m"
echo "---------------------------------------------------"
# Print multi-line Description (if present)
pacman -Si "$pkg" 2>/dev/null | print_description | sed -n "1,${PREVIEW_DESC_LINES}p"
echo ""
# Show a compact header (repo, version, url) - lines before Description (increase lines shown)
pacman -Si "$pkg" 2>/dev/null | sed -n '1,10p' | sed '/^Description/,$d'
exit 0
elif pacman -Qi "$pkg" &>/dev/null; then
echo -e "\033[1;36m$pkg\033[0m"
echo "---------------------------------------------------"
pacman -Qi "$pkg" 2>/dev/null | print_description | sed -n "1,${PREVIEW_DESC_LINES}p"
echo ""
pacman -Qi "$pkg" 2>/dev/null | sed -n '1,10p' | sed '/^Description/,$d'
exit 0
else
echo -e "\033[0;31mNo package information available for '$pkg'.\033[0m"
exit 1
fi
EOF
chmod +x "$PREVIEW_SCRIPT"
# Ensure the temp file is removed on exit
trap 'rm -f "$PREVIEW_SCRIPT"' EXIT
}
# Create the helper now
create_preview_helper
# ------------------------------------------------------------------------------
# Parse command line arguments
# ------------------------------------------------------------------------------
while [[ "$#" -gt 0 ]]; do
case $1 in
-h|--help)
show_help
exit 0
;;
-v|--version)
show_version
exit 0
;;
-l|--list)
show_list
exit 0
;;
-i|--info)
if [[ -n "$2" && ! "$2" == -* ]]; then
show_info "$2"
exit 0
else
echo -e "${RED}Error:${NC} --info requires a profile name."
echo -e "Use '${GREEN}--list${NC}' to see available profiles."
exit 1
fi
;;
*)
echo -e "${RED}Unknown option:${NC} $1"
echo -e "Try '$(basename "$0") ${GREEN}--help${NC}' for more information."
exit 1
;;
esac
shift
done
# ------------------------------------------------------------------------------
# Main Logic (Interactive Mode)
# ------------------------------------------------------------------------------
# Optional fzf installation prompt
if ! command -v fzf &> /dev/null; then
echo -e "${YELLOW}[!] 'fzf' is not installed.${NC}"
echo -e "It is highly recommended for a rich TUI experience with live package info."
read -r -p "Would you like to install it now via pacman? (y/N): " install_fzf
if [[ "$install_fzf" =~ ^[Yy]$ ]]; then
sudo pacman -S --noconfirm fzf
echo -e "${GREEN}[OK] fzf installed successfully.${NC}\n"
else
echo -e "${YELLOW}Proceeding with standard fallback menus.${NC}\n"
fi
fi
echo -e "${BOLD}Available eos-hwtool profiles:${NC}"
echo "---------------------------------------------------"
readarray -t PROFILE_KEYS < <(printf '%s\n' "${!PROFILES[@]}" | sort)
# Use colored prompt for the bash select menu
PS3=$(echo -e "${CYAN}Select a profile (number): ${NC}")
select PROFILE_NAME in "${PROFILE_KEYS[@]}"; do
if [[ -n "$PROFILE_NAME" ]]; then
read -r -a PACKAGES <<< "${PROFILES[$PROFILE_NAME]}"
echo ""
echo -e "Selected profile: ${CYAN}${BOLD}$PROFILE_NAME${NC}"
echo -e "Required packages: ${PACKAGES[*]}"
echo "---------------------------------------------------"
break
else
echo -e "${RED}Invalid option. Try again.${NC}"
fi
done
# Reset PS3
PS3="#? "
INSTALL_LIST=()
is_installed() {
pacman -Qq "$1" &> /dev/null
}
get_alternatives() {
local pkg=$1
local conflicts
# Check sync db first, then local db for conflicts
conflicts=$(pacman -Si "$pkg" 2>/dev/null | grep -i "Conflicts With" | awk -F ':' '{print $2}' | xargs)
if [[ -z "$conflicts" || "$conflicts" == "None" ]]; then
conflicts=$(pacman -Qi "$pkg" 2>/dev/null | grep -i "Conflicts With" | awk -F ':' '{print $2}' | xargs)
fi
if [[ -n "$conflicts" && "$conflicts" != "None" ]]; then
echo "$conflicts"
else
echo ""
fi
}
echo -e "${BOLD}Checking packages...${NC}"
echo "---------------------------------------------------"
for pkg in "${PACKAGES[@]}"; do
if is_installed "$pkg"; then
echo -e "${GREEN}[OK]${NC} $pkg is already installed."
else
echo -e "${YELLOW}[MISSING]${NC} $pkg is not installed."
alts=$(get_alternatives "$pkg")
options=("$pkg")
if [[ -n "$alts" ]]; then
IFS=' ' read -r -a alt_array <<< "$alts"
for alt in "${alt_array[@]}"; do
if pacman -Si "$alt" &>/dev/null || pacman -Qi "$alt" &>/dev/null; then
options+=("$alt")
fi
done
fi
options+=("Skip")
# ----------------------------------------------------------------------
# TUI Package Selection using robust preview helper script
# ----------------------------------------------------------------------
if command -v fzf &> /dev/null; then
# If 'timeout' is available, use it; otherwise run without timeout.
# Build a robust preview command that calls the helper via bash -c.
# Use positional parameters so braces and spaces are handled safely.
# Build preview command (robust)
if command -v timeout &> /dev/null; then
PREVIEW_CMD="env PREVIEW_DESC_LINES=${PREVIEW_DESC_LINES:-12} timeout ${PREVIEW_TIMEOUT}s bash -c '\"$PREVIEW_SCRIPT\" \"\$1\"' --"
else
PREVIEW_CMD="env PREVIEW_DESC_LINES=${PREVIEW_DESC_LINES:-12} bash -c '\"$PREVIEW_SCRIPT\" \"\$1\"' --"
fi
opt=$(printf "%s\n" "${options[@]}" | fzf \
--prompt="Select package for '$pkg' > " \
--header="Use ARROW KEYS to browse. Press ENTER to select. Ctrl-O for more info" \
--preview="$PREVIEW_CMD {}" \
--preview-window=right:65%:wrap \
--height=20 \
--layout=reverse \
--color="prompt:#00ff00,pointer:#ff0000,hl:#00ffff,bg+:#262626,fg+:#ffffff" \
--bind "ctrl-o:execute(bash -c 'pacman -Si \"\$1\" | ${PAGER:-less}' -- {})")
# Handle ESC / Ctrl-C or Skip
if [[ -z "$opt" || "$opt" == "Skip" ]]; then
echo -e "${YELLOW}Skipping${NC} $pkg..."
else
echo -e "Queued: ${CYAN}$opt${NC}"
INSTALL_LIST+=("$opt")
fi
else
# Fallback to standard bash select if fzf is not installed
echo -e "Please select which package to install for '${CYAN}$pkg${NC}':"
PS3=$(echo -e "${CYAN}Selection: ${NC}")
select opt in "${options[@]}"; do
if [[ "$opt" == "Skip" ]]; then
echo -e "${YELLOW}Skipping${NC} $pkg..."
break
elif [[ -n "$opt" ]]; then
echo -e "Queued: ${CYAN}$opt${NC}"
INSTALL_LIST+=("$opt")
break
else
echo -e "${RED}Invalid option. Try again.${NC}"
fi
done
PS3="#? "
fi
echo "---------------------------------------------------"
fi
done
# Final installation prompt
if [[ ${#INSTALL_LIST[@]} -gt 0 ]]; then
echo -e "${BOLD}The following packages are queued for installation:${NC}"
echo -e "${CYAN}-> ${INSTALL_LIST[*]}${NC}"
echo ""
read -r -p "Proceed with installation via pacman? (y/N): " confirm
if [[ "$confirm" =~ ^[Yy]$ ]]; then
sudo pacman -S "${INSTALL_LIST[@]}"
else
echo -e "${YELLOW}Installation aborted by user.${NC}"
fi
else
echo -e "${GREEN}No missing packages selected. Your ${CYAN}$PROFILE_NAME${GREEN} configuration is complete!${NC}"
fi
Very usseful tool! I didn’t even know I had any missing packages for profile nvidia_open. Followed the guide, installed, rebooted, all is well. Thanks for this, @dalto!
┌[wombat☮endeavourmsi]-(~)
└> sudo eos-hwtool --install-recommended
:: Synchronizing package databases...
endeavouros is up to date
core is up to date
extra is up to date
multilib is up to date
cidercollective is up to date
warning: lib32-nvidia-utils-610.57.04-1 is up to date -- skipping
warning: nvidia-open-dkms-610.57.04-1 is up to date -- skipping
warning: libxnvctrl-610.57.04-1 is up to date -- skipping
warning: nvidia-settings-610.57.04-1 is up to date -- skipping
warning: nvidia-utils-610.57.04-1 is up to date -- skipping
warning: egl-wayland-4:1.1.21-1 is up to date -- skipping
:: Starting full system upgrade...
resolving dependencies...
looking for conflicting packages...
Package (3) New Version Net Change Download Size
multilib/lib32-opencl-nvidia 610.57.04-1 23.51 MiB 2.56 MiB
extra/libva-nvidia-driver 0.0.17-1 0.10 MiB 0.04 MiB
extra/opencl-nvidia 610.57.04-1 103.22 MiB 6.44 MiB
Total Download Size: 9.04 MiB
Total Installed Size: 126.83 MiB
:: Proceed with installation? [Y/n]
:: Retrieving packages...
libva-nvidia-driver-0.0.17-1-x86_64 43.4 KiB 244 KiB/s 00:00 [--------------------------------------------------] 100%
lib32-opencl-nvidia-610.57.04-1-x86_64 2.6 MiB 8.17 MiB/s 00:00 [--------------------------------------------------] 100%
opencl-nvidia-610.57.04-1-x86_64 6.4 MiB 19.1 MiB/s 00:00 [--------------------------------------------------] 100%
Total (3/3) 9.0 MiB 24.8 MiB/s 00:00 [--------------------------------------------------] 100%
(3/3) checking keys in keyring [--------------------------------------------------] 100%
(3/3) checking package integrity [--------------------------------------------------] 100%
(3/3) loading package files [--------------------------------------------------] 100%
(3/3) checking for file conflicts [--------------------------------------------------] 100%
:: Processing package changes...
(1/3) installing opencl-nvidia [--------------------------------------------------] 100%
Optional dependencies for opencl-nvidia
opencl-headers: headers necessary for OpenCL development
(2/3) installing lib32-opencl-nvidia [--------------------------------------------------] 100%
Optional dependencies for lib32-opencl-nvidia
opencl-headers: headers necessary for OpenCL development
(3/3) installing libva-nvidia-driver [--------------------------------------------------] 100%
:: Running post-transaction hooks...
(1/1) Arming ConditionNeedsUpdate...
Installing dracut conf to /etc/dracut.conf.d/eos_nvidia_open.conf
Running dracut for linux-lts-6.18.44-1-lts
Running dracut for linux-7.1.8-arch1-3
Running dracut for linux-zen-7.1.8-zen1-3-zen
┌[wombat☮endeavourmsi]-(~)
└>
┌[wombat☮endeavourmsi]-(~)
└> eos-hwtool --check
All packages installed for profile nvidia_open
┌[wombat☮endeavourmsi]-(~)
└>
I’ve been running my system since before the Titan release, so I only just installed the newly introduced eos-hwtool.
When checking the nvidia_open profile (eos-hwtool --check-profile nvidia_open), it reports nvidia-open-dkms as missing. On my system I have the prebuilt nvidia-open package installed (7.2.8-arch1-2, standard linux kernel), which provides the same open kernel module, so my driver is fully up to date and everything works fine (Vulkan, Steam, Heroic, Jackify).
Just a heads-up for other users who set up their NVIDIA driver before eos-hwtool was introduced: the “missing packages” list may not mean your system is broken. It might simply be the prebuilt package instead of the DKMS one.
Maybe the tool could recognize nvidia-open as an equivalent alternative to nvidia-open-dkms when the standard kernel is used?
And thanks for your work on the tool! It’s definitly a advantage for new EndeavourOS-Lads&Gents with a Nvidia GPU!
[user@EndeavourOSNeo-Machine ~]$ pacman -Qs nvidia
local/egl-gbm 1.1.4-1
The GBM EGL external platform library
local/egl-wayland 4:1.1.23-1
EGLStream-based Wayland external platform
local/egl-wayland2 1.0.2-1
EGLStream-based Wayland external platform (2)
local/egl-x11 1.0.6-1
NVIDIA XLib and XCB EGL Platform Library
local/lib32-nvidia-utils 615.71.09-1
NVIDIA drivers utilities (32-bit)
local/libvdpau 1.5-4
Nvidia VDPAU library
local/linux-firmware-nvidia 20260916-1
Firmware files for Linux - Firmware for NVIDIA GPUs and SoCs
local/nvidia-hook 1.5.3-1
pacman hook for nvidia
local/nvidia-inst 26.1.1-1
Script to install/uninstall nvidia driver packages in EndeavourOS
local/nvidia-open 615.71.09-6
NVIDIA open kernel modules
local/nvidia-utils 615.71.09-1
NVIDIA drivers utilities
local/nvtop 3.3.2-1
GPUs process monitoring for AMD, Intel and NVIDIA
On my system (prebuilt nvidia-open, standard linux kernel, set up with nvidia-inst before eos-hwtool existed), /etc/dracut.conf.d/ contains only eos-defaults.conf.
I saw in @UncleSpellbinders post that --install-recommended creates eos_nvidia_open.conf.
Is that file needed for nvidia_open setups, or does nvidia-inst handle this differently?
Everything works here (nvidia_drm modeset=Y, Vulkan and OpenGL on the RTX 3060)
I’m just curious whether I’m missing something.
It early loads the GPU drivers which is needed for certain hardware and in some situations. We early load all GPU drivers but if it is working fine without it there is no reason to add it.