A GTK4 desktop shell for Hyprland, built with AGS v3 and Astal. It provides a bar, launcher, overview, dock, desktop, notifications, quick settings, capture tools, and wallpaper-aware theming through Nix and native AGS bundles.
- Application launcher, favorites, dock, taskbar, and workspace overview
- Desktop icons with drag-and-drop, clipboard, rename, trash, and file operations
- Notification daemon and StatusNotifier system tray
- Network, Bluetooth, audio, battery, brightness, and power-profile controls
- MPRIS media controls, volume and brightness OSDs, and color picker
- Focused-monitor and area screenshots and recordings
- Per-monitor wallpaper surfaces with optional wallpaper-generated colors
- Configurable layout, scale, typography, colors, spacing, and widget behavior
- AGS v3, Astal, GTK4, and GTK4 Layer Shell
- A running Hyprland session with working IPC and systemd user-session integration
- A user D-Bus session and writable dconf/GSettings state
- No competing notification daemon; ags2-shell owns
org.freedesktop.Notifications
The Nix package currently exports x86_64-linux and supplies its core libraries and runtime commands. Native installations must provide those dependencies through the host distribution. Keep the AGS CLI installed for window toggles and request commands; hyprctl is supplied by Hyprland.
| Feature | Host requirement |
|---|---|
| Network controls | NetworkManager |
| Audio controls and OSD | PipeWire with WirePlumber |
| Bluetooth | BlueZ service and supported hardware |
| Battery status | UPower |
| Power profiles | power-profiles-daemon, or supported ASUS services |
| Internal brightness | An accessible backlight device and permission to use brightnessctl |
| External brightness | DDC/CI support and permission to use ddcutil |
| Media controls | Players exposing MPRIS on the user bus |
| ASUS controls | asusctl; optionally supergfxctl and rog-control-center |
| tmux accent sync | tmux; detected automatically and otherwise ignored |
Unavailable optional services disable only their corresponding controls.
Using the same nixpkgs and ags inputs keeps the shell and AGS control client aligned.
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
home-manager = {
url = "github:nix-community/home-manager/master";
inputs.nixpkgs.follows = "nixpkgs";
};
apple-fonts = {
url = "github:Lyndeno/apple-fonts.nix";
inputs.nixpkgs.follows = "nixpkgs";
};
mactahoe-icon-theme = {
url = "github:TheWolfStreet/MacTahoe-icon-theme.nix";
inputs.nixpkgs.follows = "nixpkgs";
};
ags = {
url = "github:Aylur/ags";
inputs.nixpkgs.follows = "nixpkgs";
};
ags2-shell = {
url = "github:TheWolfStreet/ags2-shell";
inputs.nixpkgs.follows = "nixpkgs";
inputs.ags.follows = "ags";
};
};
}The font and icon-theme inputs are used by the recommended appearance configuration below. They can be omitted if you use different themes.
Add the shell, matching AGS CLI, GTK portal backend, and user service to Home Manager:
{
inputs,
pkgs,
...
}: let
system = pkgs.stdenv.hostPlatform.system;
ags = inputs.ags.packages.${system}.default;
shell = inputs.ags2-shell.packages.${system}.default;
in {
home.packages = [ags shell];
# Exposes the GSettings color scheme to portal and Flatpak applications.
xdg.portal.extraPortals = [pkgs.xdg-desktop-portal-gtk];
systemd.user.services.ags = {
Unit = {
Description = "AGS desktop shell";
Documentation = ["https://github.com/TheWolfStreet/ags2-shell"];
After = ["graphical-session-pre.target"];
PartOf = ["graphical-session.target"];
};
Service = {
ExecStart = "${shell}/bin/ags2-shell";
KillMode = "mixed";
Restart = "on-failure";
};
Install.WantedBy = ["graphical-session.target"];
};
}The desktop session must also provide the main xdg-desktop-portal service and a compositor portal backend, normally xdg-desktop-portal-hyprland. The GTK backend is session integration rather than an application dependency: ags2-shell runs without it, but sandboxed applications will not reliably receive the shell's dark or light preference.
Apply the configuration with your normal NixOS or Home Manager switch, then verify the service:
systemctl --user status ags.service
journalctl --user -u ags.service -bThe AGS CLI flags belong to the toggle and request subcommands. The following bindings use the shell's ags2-shell instance name:
wayland.windowManager.hyprland.settings = {
bind = let
toggle = "exec, ags toggle --instance ags2-shell";
request = "exec, ags request --instance ags2-shell";
in [
"CTRL ALT, Delete, exec, systemctl --user restart ags.service"
"SUPER, R, ${toggle} launcher"
"SUPER, Tab, ${toggle} overview"
"SUPER SHIFT, R, ${toggle} settings-dialog"
",XF86PowerOff, ${request} shutdown"
"SUPER, Print, ${request} record-area"
"SUPER SHIFT, Print, ${request} record"
", Print, ${request} screenshot-area"
"SHIFT, Print, ${request} screenshot"
];
layerrule = [
"blur on, match:namespace gtk4-layer-shell"
"blur_popups on, match:namespace gtk4-layer-shell"
"ignore_alpha 0.29, match:namespace gtk4-layer-shell"
"no_anim on, match:namespace gtk4-layer-shell"
];
};record and screenshot target the focused monitor. Their -area variants prompt for a region.
The same controls can be called directly:
ags toggle --instance ags2-shell launcher
ags request --instance ags2-shell launcher-search firefox
ags request --instance ags2-shell screenshot-areaOn other distributions, ags2-shell installs as two AGS-bundled GJS launchers and a compiled stylesheet. It uses GTK4, GTK4 Layer Shell, host runtime commands, and the IO, Astal4, Apps, Battery, Bluetooth, Hyprland, MPRIS, Network, Notifd, PowerProfiles, Tray, and WirePlumber Astal libraries.
Install AGS v3 and those Astal libraries using the AGS installation guide and Astal installation guide for your distribution.
Install AGS and the Astal libraries from the AUR:
yay -S aylurs-gtk-shell-git libastal-metaInstall the build tool, shell runtime commands, and portal backends:
sudo pacman -S --needed \
dart-sass bluez-utils brightnessctl dconf ddcutil gjs glib2 \
gsettings-desktop-schemas gtk4 gtk4-layer-shell hyprland \
gnome-control-center grim hyprpicker libheif libwebp pavucontrol \
procps-ng slurp swappy wf-recorder wl-clipboard xdg-utils \
xdg-desktop-portal-hyprland xdg-desktop-portal-gtkInstall the host services from the Feature Services table as needed. For example, network, audio, Bluetooth, battery, and power-profile controls use NetworkManager, PipeWire/WirePlumber, BlueZ, UPower, and power-profiles-daemon respectively.
The native installer compiles the stylesheet, bundles the main and wallpaper entry points, and installs them under ~/.local by default:
git clone https://github.com/TheWolfStreet/ags2-shell
cd ags2-shell
./install-native.shEnsure the selected bin directory is in PATH, then add the shell to Hyprland autostart:
exec-once = ags2-shellThe control commands and Hyprland bindings documented above work unchanged because the native AGS installation provides the ags CLI.
The default shell font is SF Pro Display Nerd Font. The following Home Manager configuration installs the font, MacTahoe icons, Qogir cursor, and matching GTK theme used by the reference setup:
{
inputs,
pkgs,
...
}: let
system = pkgs.stdenv.hostPlatform.system;
font = {
name = "SF Pro Display Nerd Font";
size = 11;
package = inputs.apple-fonts.packages.${system}.sf-pro-nerd;
};
gtkTheme = {
name = "adw-gtk3-dark";
package = pkgs.adw-gtk3;
};
cursorTheme = {
name = "Qogir";
size = 24;
package = pkgs.qogir-icon-theme;
};
iconTheme = {
name = "MacTahoe";
package = inputs.mactahoe-icon-theme.packages.${system}.default;
};
in {
home.packages = [
font.package
gtkTheme.package
cursorTheme.package
iconTheme.package
];
home.pointerCursor = cursorTheme // {
enable = true;
gtk.enable = true;
};
home.sessionVariables = {
XCURSOR_THEME = cursorTheme.name;
XCURSOR_SIZE = toString cursorTheme.size;
};
fonts.fontconfig.enable = true;
gtk = {
enable = true;
theme = gtkTheme;
inherit font cursorTheme iconTheme;
};
qt.platformTheme.name = "gtk3";
}ags2-shell controls its own widgets through generated CSS. It does not replace the host GTK or cursor theme. When the shell's light or dark scheme changes, it updates org.gnome.desktop.interface color-scheme and selects an installed light or dark icon-theme variant when available. Wallpaper color generation is optional and can be enabled from Settings > Appearance > Generate from Wallpaper.
Enable Hyprlock and its PAM service, then add the Home Manager configuration below. The example uses the recommended SF Pro font and the account image at /var/lib/AccountsService/icons/$USER.
# NixOS configuration
security.pam.services.hyprlock = {};# Home Manager configuration
programs.hyprlock = {
enable = true;
settings = {
background = {
path = "screenshot";
blur_passes = 5;
contrast = 0.8916;
brightness = 0.8172;
vibrancy = 0.1696;
vibrancy_darkness = 0.0;
};
general = {
no_fade_in = false;
grace = 0;
disable_loading_bar = false;
};
label = [
{
text = ''cmd[update:1000] echo -e "$(date +"%A, %B %d")"'';
color = "rgba(216, 222, 233, 0.70)";
font_size = 25;
font_family = "SF Pro Display Nerd Font Bold";
position = "0, 350";
halign = "center";
valign = "center";
}
{
text = ''cmd[update:1000] echo "<span>$(date +"%H:%M")</span>"'';
color = "rgba(216, 222, 233, 0.70)";
font_size = 120;
font_family = "SF Pro Display Nerd Font Bold";
position = "0, 250";
halign = "center";
valign = "center";
}
{
text = "$USER";
color = "rgba(216, 222, 233, 0.80)";
font_size = 20;
font_family = "SF Pro Display Nerd Font Bold";
position = "0, -82";
halign = "center";
valign = "center";
}
];
image = {
path = "/var/lib/AccountsService/icons/$USER";
border_size = 2;
border_color = "rgba(255, 255, 255, .65)";
size = 180;
rounding = -1;
position = "0, 40";
halign = "center";
valign = "center";
};
input-field = {
size = "125, 50";
dots_center = true;
outline_thickness = 0;
outer_color = "rgba(0, 0, 0, 0)";
inner_color = "rgba(255, 255, 255, 0.1)";
check_color = "rgba(255, 255, 255, 0.1)";
fail_color = "rgba(255, 255, 255, 0.1)";
capslock_color = "rgba(255, 255, 255, 0.1)";
numlock_color = "rgba(255, 255, 255, 0.1)";
bothlock_color = "rgba(255, 255, 255, 0.1)";
font_color = "rgb(200, 200, 200)";
fade_on_empty = false;
font_family = "SF Pro Display Nerd Font Regular";
placeholder_text = "Password";
fail_text = "Incorrect";
hide_input = false;
position = "0, -140";
halign = "center";
valign = "center";
};
};
};Use the Settings window to change shell options. Changes are saved automatically.
| State | Location |
|---|---|
| Shell options | $XDG_CACHE_HOME/ags2-shell/options.json |
| Desktop icon layout | $XDG_CACHE_HOME/ags2-shell/desktop-layout.json |
| Color-picker history | $XDG_CACHE_HOME/ags2-shell/colors.json |
| Thumbnail cache | $XDG_CACHE_HOME/ags2-shell/previews/thumbnails/ |
| Wallpaper | ~/.config/background |
| Screenshots | ~/Pictures/Screenshots/ |
| Recordings | ~/Videos/Screencasting/ |
There is currently no declarative Nix option interface for shell settings. Removing options.json restores defaults on the next start.
Run the development shell from a checkout to get AGS, Sass, language tooling, and file watchers:
git clone https://github.com/TheWolfStreet/ags2-shell
cd ags2-shell
systemctl --user stop ags.service
nix develop -c ./dev.sh
systemctl --user start ags.serviceStop the packaged service only when it is enabled; a packaged and development instance cannot own the same ags2-shell name simultaneously. Build and validate the package with:
nix build
nix flake checksystemctl --user status ags.service
journalctl --user -u ags.service -b
ags listConfirm that the service inherited WAYLAND_DISPLAY, HYPRLAND_INSTANCE_SIGNATURE, and the graphical-session environment.
Confirm that both the compositor portal backend and xdg-desktop-portal-gtk are installed, then restart the portal after switching configuration:
systemctl --user restart xdg-desktop-portal.service
systemctl --user restart xdg-desktop-portal-gtk.serviceReopen affected applications after the restart.
Only one process can own org.freedesktop.Notifications. Disable another notification daemon before starting ags2-shell.
Verify that brightnessctl can access internal backlight devices and that ddcutil detect can access external DDC/CI displays. Device permissions must be configured by the host system.
ags2-shell is an independent GTK4/Astal evolution of Aylur's original AGS v1 shell. It retains that project's foundation while adding features such as a dock, desktop icons and file operations, multi-monitor wallpaper management, expanded settings, and standalone Nix packaging.
Thanks to Aylur for AGS, Astal, and the original shell design. See Marble Shell for Aylur's current shell project.