automatically checking if the next gnome release breaks my gnome shell extensions

published on 15th April 2026

The thing about a new major GNOME version is that, usually, most of the GNOME shell extensions do not support it yet when it comes out. This is certainly the case when you use GNOME on Arch, because itz soo bleeding edge !!1!!111 ;)

And even though I have been back on GNOME for a good 5 years now (previously I used dwm), I always forget to check if the extensions I’m using support the new version already. Usually I just blindly run the update and get confused when the extensions are borked after a reboot, prompting me to read the pacman logs and then construct the commands to downgrade the relevant packages. Yes I know this is unsupported….. moving on.

To stop future me from getting tripped up by this madness ever again, I wrote a shell script that checks whether your installed GNOME extensions support the next version (see at the bottom of this page, or this gist). When I was finished, I had the idea to implement it as a pacman hook, because realistically, if it’s not enforced by the package manager before an upgrade, I would forget to run it anyways.

Pacman hooks allow you inject your own logic and scripts into the package operation flow, which is perfect for this use case. After reading man pacman-hooks:

/etc/pacman.d/hooks/90-gnome.hook copy
 1[Trigger]
 2# run this hook when the gnome-shell package is being upgraded
 3Type = Package
 4Operation = Upgrade
 5Target = gnome-shell
 6
 7[Action]
 8Description = Checking if new gnome-shell version supports your extensions
 9# run before installing
10When = PreTransaction
11# the checker script
12Exec = /usr/bin/runuser -u <YOUR_USER> -- "/usr/local/bin/check-gnome-compat.sh"
13# dependencies of the script
14Depends = jq
15Depends = curl
16# fail the pacman command if the script returns nonzero
17AbortOnFail

In line 12 replace <YOUR_USER> with your user name. The script needs to run as your user so that it can correctly resolve the installed GNOME extensions. And we also don’t want to curl to the internet as root :)

Below you can see a pacman run where the checker script successfully stopped gnome-shell version 50 from being installed because there were incompatibilities:

pacman running the described pacman hook and aborting after the checker script found some extensions which were not ready for the next gnome version yet
pacman running the hook and aborting

The way it is implemented now, pacman just aborts the whole update operation and tells you to adjust your IgnorePkg, which is fine for me. If gnome-shell is in IgnorePkg the hook will not be triggered.

And finally, here is the checker script, also hosted in this gist:

/usr/local/bin/check-gnome-compat.sh copy
 1#!/usr/bin/env bash
 2# check if your enabled GNOME Shell extensions support the next GNOME version.
 3# depends: curl, jq
 4
 5set -euo pipefail
 6
 7API="https://extensions.gnome.org/extension-info/?uuid="
 8
 9RED=$'\033[0;31m'
10GREEN=$'\033[0;32m'
11YELLOW=$'\033[0;33m'
12RESET=$'\033[0m'
13
14# get current and next version from pacman
15UPDATE_DATA=$(pacman -Qu gnome-shell 2>/dev/null) || true
16
17if [[ -z "$UPDATE_DATA" ]]; then
18  echo "Couldn't find any updates for gnome-shell."
19  exit 0
20fi
21
22# "gnome-shell 1:49.5-1 -> 1:50.0-1"  — strip epoch (N:) from both sides
23# and extract major version
24GNOME_VERSION=$(echo "$UPDATE_DATA" | grep -oP '\d+(?=\.\d+-\d+ ->)')
25GNOME_VERSION_NEXT=$(echo "$UPDATE_DATA" | grep -oP '(?<=-> )[\d:]+' | sed 's/^[0-9]*://' | grep -oP '^\d+')
26
27if [[ "$GNOME_VERSION_NEXT" -le "$GNOME_VERSION" ]]; then
28  echo "No major version change ($GNOME_VERSION -> $GNOME_VERSION_NEXT), nothing to check."
29  exit 0
30fi
31
32# get extension uuids
33mapfile -t UUIDS < <(/usr/bin/gnome-extensions list --enabled)
34
35if [[ ${#UUIDS[@]} -eq 0 ]]; then
36  echo "No enabled extensions found." >&2
37  exit 1
38fi
39
40echo -e "\nGNOME $GNOME_VERSION --> $GNOME_VERSION_NEXT extension compatibility check"
41
42COMPATIBLE=0
43INCOMPATIBLE=0
44UNKNOWN=0
45
46check_extension() {
47  local uuid="$1"
48  local encoded
49  # url encode the uuid
50  encoded=$(jq --raw-input --raw-output @uri <<< "$uuid")
51  local url="${API}${encoded}"
52
53  local http_code body
54  # read extension's properties from gnome extension api
55  body=$(curl --fail --silent --show-error --max-time 10 --write-out "\n%{http_code}" "$url" 2>/dev/null) || true
56  # read http code from last line
57  http_code=$(tail -1 <<< "$body")
58  body=$(sed '$d' <<< "$body")
59
60  if [[ "$http_code" == "404" || -z "$body" ]]; then
61    echo "[${YELLOW}??${RESET}]  $uuid  (not found)"
62    ((UNKNOWN++)) || true
63    return
64  fi
65
66  local name has_version
67  name=$(jq --raw-output '.name // ""' <<< "$body" 2>/dev/null || echo "")
68  has_version=$(jq --raw-output --arg v "$GNOME_VERSION_NEXT" 'if .shell_version_map[$v] then "yes" else "no" end' <<< "$body" 2>/dev/null || echo "no")
69
70  local display="$uuid"
71  [[ -n "$name" ]] && display="$name ($uuid)"
72
73  if [[ "$has_version" == "yes" ]]; then
74    echo "[${GREEN}OK${RESET}]  $display"
75    ((COMPATIBLE++)) || true
76  else
77    local latest_shell
78    latest_shell=$(jq --raw-output '.shell_version_map | keys | map(select(test("^[0-9]+$"))) | map(tonumber) | max // "?" | tostring' <<< "$body" 2>/dev/null || echo "?")
79    echo "[${RED}NO${RESET}]  $display  (latest: v$latest_shell)"
80    ((INCOMPATIBLE++)) || true
81  fi
82}
83
84for uuid in "${UUIDS[@]}"; do
85  [[ -z "$uuid" ]] && continue
86  check_extension "$uuid"
87  # dont be too quick
88  sleep 0.15
89done
90
91echo -e "\nFor GNOME $GNOME_VERSION_NEXT: $COMPATIBLE compatible, $INCOMPATIBLE incompatible, $UNKNOWN unknown"
92
93if [[ $INCOMPATIBLE -gt 0 ]]; then
94  echo -e "\n${RED}Some extensions are not compatible with the next GNOME version. Please update your IgnorePkg.${RESET}\n"
95  exit 1
96fi