gtheme v2.0.0 — the rebuild
gtheme used to be a command-line tool. It is now an app: one GTK4/libadwaita window for GNOME 49 and 50 that changes your wallpaper, colours, icons, pointer, text, top bar, windows and add-ons — explained in plain words, with an Undo that always works. Every change is recorded before it happens, applies all-or-nothing, and can be put back. This release also carries a full audit pass done before it was called finished: the rebuild was read back against its own promises — every page, every path that writes to your computer, every sentence in the documentation — and what did not hold up was fixed. That was 63 verified review findings (1 critical, 13 high, 30 medium, 19 low) plus 10 usability findings from cold first-time-user runs and a set of promoted extras; roughly a hundred tracked items in all, and none left open. The test suite grew from 1,967 to 2,610 collected tests along the way.
Safety
- Restore points. One is taken automatically before every change, you can take one whenever you like, and "Before gtheme" — how the computer looked before this app ever ran — is kept forever. On a machine that never ran v1, the first launch now saves your desktop as it is, instead of promising a restore point it could not deliver.
- Changes made on the individual pages are recorded and undoable. This was the largest correction in the audit: flipping a switch on Fonts or Top Bar used to change your desktop without leaving a trace, so Undo, "Before gtheme" and
gtheme rescueall had a blind spot exactly where a cautious person experiments. Every row now writes through a recording layer, and takes one restore point per burst of edits rather than one per switch. - A Look can only change the way things look, and that is now enforced rather than intended. One written policy decides where a Look may write, checked when it is compiled and again before it is applied. Anything that could make your computer run something is refused by name — autostart entries, systemd units,
environment.d, shell start-up files,.desktopand.servicefiles anywhere, media-key commands, default-application entries, and any settings tree not on the allow-list. The refusal is decided on the fully resolved path too, so a symlink cannot step around it. - Rollback covers every way an apply can fail, not only the anticipated ones. Any error during a change rolls the whole thing back and says whether your desktop was restored — and where gtheme genuinely cannot tell, it now says so instead of guessing in its own favour.
gtheme rescue— a headless "put it back" command that needs no graphical session, for the day the desktop itself will not come up.- No telemetry, no network calls you did not ask for. The apply preview names missing add-ons from data already on your computer; opening it does not go online.
New
- Fifteen pages in one window, including a Home page that reads back the app style, icon set and text style you are actually using — something GNOME's own Appearance panel cannot show you.
- Six bundled Looks: HYPERCLASS, MAGMA, NETRUNNER, NIGHTBLOOM, DAYBREAK (light) and HEARTH (warm). Wallpapers ship in the repository, so applying one needs no internet connection.
- Applying a Look shows you exactly what it will change first — every setting as before → after, every file by destination, every add-on by name — and warns you when the Look wants an icon set, pointer, style or font this computer does not have, when it would switch on two add-ons known to fight each other, or when it would write over an accessibility setting you deliberately turned on.
- A long apply shows its progress and can be stopped. Pressing Stop rolls back what had already landed.
- Add-ons: search, install, configure and update from inside the app, with twenty-four hand-written settings panels for popular ones and a generic, honestly-labelled panel for the rest. Identifiers are never shown. The log-out question is answered honestly — gtheme asks the desktop what it actually knows and says either "it's on" or "it starts working after you log out and back in".
- Terminals are themed through the same transaction as everything else — one snapshot, one restore point, one rollback. GNOME Terminal and Console join Ptyxis, Alacritty and Ghostty, plus starship, fish, btop, cava and fastfetch.
- Ctrl+F searches everything — every setting, its explanation, and its synonyms in the words a Windows or macOS switcher would use — and jumps to the row.
- A four-slide introduction on first run that ends in a real action: saving your desktop exactly as it is.
- Keyboard and screen-reader work: Ctrl+? opens the shortcuts window, Ctrl+Z undoes, F6 jumps to the page list, pictures carry descriptions, and the window is clamped to the usable area of your screen.
- When something goes wrong, you can say what: a rotating log, an uncaught-error hook, and "Copy details for a bug report" in the main menu — versions plus the last forty lines of the log, and no setting values.
Fixed
- The app used to say "Nothing was changed. Your desktop is exactly as it was." after a failure that had, in fact, changed things. It now tells the truth, including the uncomfortable version of it.
- Errors raised late in an apply — after the last change landed — used to escape while the app was still saying nothing had happened.
- Saving your desktop as a Look now captures the whole desktop, not the subset the app happened to know about, and tells you what it could not take, grouped by kind. Export writes through a hidden partial file, so a failed export never leaves half a file behind.
install.shchecks before it installs: it refuses on GNOME older than 49 or libadwaita older than 1.9, validates a virtual environment it finds already there rather than reusing it on faith, prints your distribution's own command when it cannot build one, and--uninstallrefuses while gtheme still owns settings on this computer.- If a change was interrupted hard enough to leave its rollback journal behind, the next launch says so and offers to put things back — once, and the answer is remembered.
- The documentation was swept against the code sentence by sentence, and the claims that had drifted were corrected rather than softened — including several the audit pass itself had made false.
- The README was rewritten as a landing page for someone who has never used Linux or GitHub, and every command it tells you to type is checked by a test on every run.
For authors and scripters
- Looks are declarative only. Format v2 has no hooks section and the engine has no script-execution machinery. v1 presets no longer validate — they are converted, and the converter names every hook it dropped and what that hook used to do. Some v1 capabilities genuinely do not come across; each bundled Look's
README.mdnames its own exclusions. themes/index.jsonis nowversion = 2. The path and repository name do not change and the six fields v1 clients read still mean the same thing, but the version bump is a documented break. Four fields are added:format,screenshots,min_shell,provenance.- The
gthemecommand keeps four subcommands:gui(the default),rescue,validate <folder>, andapply <name-or-folder>. The interactive text menu is gone, as arenew,build,captureandexport— capturing and sharing are buttons in the app now. gtheme applytakes a restore point first, like the app does, and has a--dry-runthat prints what would change and writes nothing.gtheme validatewarns when a Look's text-on-background contrast fails WCAG AA.- v2 state lives under
~/.local/state/gtheme/v2/. v1's files are never written to and never deleted; a read-only copy of them is what materialises the "Before gtheme" restore point. - Packaging is pure
pyproject.tomlplusPKGBUILD,PKGBUILD-gitandinstall.sh. No meson, and nocurl | bashanywhere in the project.
Known limits
Written down here so you can decide before you install rather than after.
- The interface is English only, with no translation machinery behind it yet — no language files, nothing for a translator to fill in. The launcher entry and store listing are searchable in German, Spanish, French and Brazilian Portuguese. If you want the app in your language, say so in an issue.
- gtheme has never been tested with Orca, GNOME's screen reader. Its widgets are libadwaita's own, which carry names and roles for free, so much of it should work — but "should" is not "was tried".
- The community Looks tab is empty, honestly: nobody has published a Look yet. The six bundled ones are there, and "Add a Look from a file…" installs one you were given, but the browse grid will stay empty until people publish.
- Deferred on purpose, not forgotten: full translation of the interface; Flatpak, AppImage and
.debpackages; an offline-mode switch; hiding setting rows for hardware you do not have. - Named exceptions inside otherwise-transactional work: fish keeps its variables in a store only fish can write, so they are updated after the transaction with the old values recorded first —
gtheme rescuereaches them, Undo does not. Ghostty's "take them over" button still moves a folder outside the transaction. Copied wallpaper files and the background-catalogue entry gtheme writes are not in the ownership record and are left behind bygtheme rescue; both are documented in the README and SECURITY.md. - The GNOME Terminal and Console adapters were written on a computer that had neither installed. Every key is probed against your computer's own settings description before it is written, and 21 tests cover them, but they have not met the real programs.
- On GNOME older than 49, gtheme shows a screen saying so and changes nothing. It never half-works.
Install
The easy way. Download the ZIP from the repository's green Code button, extract it, right-click the folder → Open in Terminal, and run:
./install.shIt checks GNOME, libadwaita and Python before creating anything, sets itself up in its own private corner of that folder, and adds Gtheme to your applications list. Then press Super, type gtheme, Enter. Keep the folder where it is — the app runs from it.
Arch, CachyOS, EndeavourOS.
git clone https://github.com/blyatiful1/gtheme
cd gtheme
makepkg -siThat builds the released source archive and installs it with pacman, running the test suite before it packages anything; sudo pacman -R gtheme removes it. makepkg -si -p PKGBUILD-git builds the checkout you have instead, as gtheme-git.
Requirements: GNOME 49 or 50, libadwaita 1.9 or newer, Python 3.11 or newer, about 60 MB of disk.
Upgrading
- From v1: install v2 as above. v1's state under
~/.local/state/gtheme/is never written to and never deleted — it is what "Before gtheme" is built from. v1 presets need converting (the converter tells you what it dropped), and v1 itself is preserved in full on thelegacy-v1branch and at thev1-finaltag. - Already on v2: unpack the new version over the old folder and run
./install.shagain, or rebuild with the samemakepkgrecipe you used the first time. Your restore points and records carry over — a new version reads the same records the old one wrote. - Removing it: put your desktop back first — Undo & Restore Points, or
gtheme rescue— because removing the app takes away the only thing that can read those records. Then./install.sh --uninstall, which takes back the five things it put outside its folder (the command, the app-list entry, the store listing and two icons) and names each one. It restores no settings itself: while gtheme still owns any, it refuses and tells you to put them back in the app first, so nobody is stranded by an uninstall. Your saved moments and Looks are never deleted by either route. Packaged installs usesudo pacman -R gtheme.
Verification
The release was gated on ./verify.sh --full: ruff clean, 2,579 tests passed with 2 skipped, 29 more against a real headless GNOME Shell on a private session bus (each of which proves afterwards that the live desktop was untouched), and the 30 README screenshots regenerated and checked for being pictures of actually different things.