Files
nixos/Droidnix/README.org
T
2026-04-22 13:54:07 +02:00

5374 lines
146 KiB
Org Mode
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#+title: Droidnix: A Dendritic NixOS + Home Manager Configuration
#+author: Henro Veijer
#+options: toc:t num:nil htmlize:nil
#+PROPERTY: header-args:nix :prologue "# --- This file has been auto-generated. For permanent changes alter the appropriate block in the README.org. ---"
#+PROPERTY: header-args:sh :prologue "# --- This file has been auto-generated. For permanent changes alter the appropriate block in the README.org. ---"
#+PROPERTY: header-args:bash :prologue "# --- This file has been auto-generated. For permanent changes alter the appropriate block in the README.org. ---"
#+PROPERTY: header-args:css :prologue "/* --- This file has been auto-generated. For permanent changes alter the appropriate block in the README.org. --- */"
#+PROPERTY: header-args:conf :prologue "# --- This file has been auto-generated. For permanent changes alter the appropriate block in the README.org. ---"
#+PROPERTY: header-args:qml :prologue "// --- This file has been auto-generated. For permanent changes alter the appropriate block in the README.org. ---"
#+PROPERTY: header-args:json :prologue ""
#+PROPERTY: header-args:jsonc :prologue "// --- This file has been auto-generated. For permanent changes alter the appropriate block in the README.org. ---"
#+PROPERTY: header-args:el :prologue ";; --- This file has been auto-generated. For permanent changes alter the appropriate block in the README.org. ---"
#+PROPERTY: header-args:toml :prologue "# --- This file has been auto-generated. For permanent changes alter the appropriate block in the README.org. ---"
#+language: en
#+html_head: <style>pre.src { background-color: #1e1e2e; color: #cdd6f4; padding: 1em; border-radius: 4px; }</style>
#+HTML_HEAD: <script src="https://cdn.jsdelivr.net/npm/tree.js@1.0.0/dist/tree.min.js"></script>
#+HTML_HEAD: <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/tree.js@1.0.0/dist/tree.min.css">
* Shortcuts
[[#introduction][Introduction]]
[[#the-assets-folder][The Assets Folder]]
[[#the-actual-code][The Actual Code en configs]]
---
* Introduction :intro:
:PROPERTIES:
:CUSTOM_ID: introduction
:END:
** What is Droidnix
Droidnix is a modular, declarative NixOS + Home Manager configuration system. with configurations managed via Emacs Org and Nix Flakes. The project is designed for reproducibility, maintainability, and cross-machine compatibility.
*** Installed components:
**** Core
**** Hyprland
*** Goals, project Structure, import hierarchy
This project uses a **modular NixOS configuration** with **Hyprland** support, designed for **literate programming** and **cross-device reusability**.
The Droidnix repository is organized into two main parts:
1. =.assets/=: Static, non-generated files (e.g., configs, scripts, themes).
2. Generated files and folders
#+title: NixOS Configuration Structure
* Root Level
- = is the entry point and imports:
- =generated/assets/=
- =generated/<host>/modules/=
- =generated/hosts/=
* Generated Structure
The =generated/= directory contains all generated configurations, divided into three main groups: =system=, =hyprland=, and =mangowc=.
** First Setup
1. Clone this repository.
2. Run the setup script: =./setup_droid=.
3. Tangle this Org file to generate Nix configurations: =C-c C-v t= in Emacs or use this: =emacs README.org --batch -f org-babel-tangle && emacs --batch --eval "(setq org-html-htmlize-output-type nil)" README.org -f org-html-export-to-html=
5. Build and switch: =sudo nixos-rebuild switch --flake .#<hostname>=.
---
* The Assets Folder :assets:
:PROPERTIES:
:CUSTOM_ID: the-assets-folder
:END:
The =.assets/= folder contains all static files, such as configs, scripts, and themes. These files are not generated and can be edited directly.
** =generated/assets/2_b_installed.conf=
This is a list of additional apps to install
#+BEGIN_SRC toml :tangle generated/assets/2_b_installed.conf :noweb yes :mkdirp yes :eval never
#packages
_1password-gui
audacity
baobab
bat
blender
brave
btop
chromium
cliphist
comma
direnv
duf
delta
eza
fd
file
fzf
gimp
git
gparted
grim
grimblast
gnome-calculator
qalculate-gtk
handbrake
hyperfine
just
jq
libreoffice
lua
nextcloud-client
nextcloud-talk-desktop
nix-index
nix-output-monitor
nh
obsidian
openssl
pandoc
postman
python3
qdirstat
ripgrep
signal-desktop
slurp
solidtime-desktop
spotify
solaar
swappy
sweethome3d.application
tea
todoist
tree
usbutils
vlc
wev
wget
wl-clipboard
wf-recorder
yazi
z-lua
zed-editor
zoxide
#flatpaks
eu.betterbird.Betterbird
com.todoist.Todoist
com.logseq.Logseq
#+END_SRC
** =generated/assets/aliases.conf=
This is a list of additional apps to install
#+BEGIN_SRC conf :tangle generated/assets/aliases.conf :noweb yes :mkdirp yes :eval never
#File & navigation
repo=cd ~/Repos && ls -lah
#Nix commands
nps=xdg-open https://search.nixos.org
#system commands
please=sudo
pls=sudo
rb=sudo reboot
po=sudo poweroff
#flatpak commands
fpl=flatpak list
fps=flatpak search
fpi=flatpak install
fpr=flatpak run
fpu=flatpak update
#ssh commands
nxc=ssh henrov@nextcloud.data-pro.nu
#app shortcuts
vs=code
keys=hyprctl binds
#+END_SRC
* The Actual Code :code:
:PROPERTIES:
:CUSTOM_ID: the-actual-code
:END:
This section contains the Org blocks for tangling Nix code into the generated folders.
** =generated/flake.nix=
The Nix flake definition for Droidnix.
#+BEGIN_SRC nix :tangle flake.nix :noweb yes :mkdirp yes :eval never
{
description = "Droidnix: A dendritic NixOS + Home Manager configuration";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
};
quickshell = {
url = "git+https://git.outfoxxed.me/outfoxxed/quickshell";
inputs.nixpkgs.follows = "nixpkgs";
};
import-tree.url = "github:vic/import-tree";
stylix = {
url = "github:nix-community/stylix";
inputs.nixpkgs.follows = "nixpkgs";
};
flatpak = {
url = "github:gmodena/nix-flatpak";
};
emacs-overlay = {
url = "github:nix-community/emacs-overlay";
inputs.nixpkgs.follows = "nixpkgs";
};
zen-browser = {
url = "github:youwen5/zen-browser-flake";
inputs.nixpkgs.follows = "nixpkgs";
};
hyprland.url = "github:hyprwm/Hyprland";
};
outputs = { self,
nixpkgs,
home-manager,
import-tree,
stylix,
hyprland,
emacs-overlay,
zen-browser,
flatpak
,... }:
let
system = "x86_64-linux";
flakeRoot = self;
in {
nixosConfigurations = {
traveldroid = nixpkgs.lib.nixosSystem {
inherit system;
modules = [
({ ... }: {
nixpkgs.overlays = [ emacs-overlay.overlays.default ];
})
flatpak.nixosModules."nix-flatpak"
./generated/hosts/traveldroid/host.nix
./generated/users/henrov.nix
];
specialArgs = {
inherit
flakeRoot
home-manager
import-tree
stylix
hyprland
zen-browser
;
};
};
};
};
}
#+END_SRC
** =generated/modules/traveldroid/system/colors.nix=
Setting the colors for Droidnix.
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/system/colors.nix :noweb yes :mkdirp yes :eval never
{ lib, config, pkgs, flakeRoot, ... }:
let
colors = {
crust = "#11111b";
mantle = "#181825";
base = "#1e1e2e";
surface0 = "#313244";
surface1 = "#45475a";
surface2 = "#585b70";
overlay0 = "#6c7086";
overlay1 = "#7f849c";
overlay2 = "#9399b2";
subtext0 = "#a6adc8";
subtext1 = "#bac2de";
text = "#cdd6f4";
rosewater = "#f5e0dc";
flamingo = "#f2cdcd";
pink = "#f5c2e7";
mauve = "#cba6f7";
red = "#f38ba8";
maroon = "#eba0ac";
peach = "#fab387";
yellow = "#f9e2af";
green = "#a6e3a1";
teal = "#94e2d5";
sapphire = "#74c7ec";
blue = "#89b4fa";
lavender = "#b4befe";
};
username = config.defaultUser or "henrov";
qmlContent = ''
pragma Singleton
// Catppuccin Mocha Palette - auto-generated, do not edit manually
import QtQuick
QtObject {
readonly property color baseAlpha: Qt.rgba(30/255, 30/255, 46/255, 0.9)
'' + lib.concatStringsSep "\n" (
lib.mapAttrsToList (name: value:
" readonly property color ${name}: \"${value}\""
) colors
) + "\n}";
in
{
home-manager.users.${username} = {
home.file = {
".config/shared/colors.css" = {
source = "${flakeRoot}/generated/.config/shared/colors.css";
force = true;
};
".config/quickshell/Colors.qml" = {
text = qmlContent;
force = true;
};
".config/quickshell/powermenu/Colors.qml" = {
text = qmlContent;
force = true;
};
".config/quickshell/powermenu/qmldir" = {
text = "singleton Colors 1.0 Colors.qml";
force = true;
};
};
};
}
#+END_SRC
** =generated/hosts/traveldroid/boot.nix=
#+BEGIN_SRC nix :tangle generated/hosts/traveldroid/boot.nix :noweb yes :mkdirp yes :eval never
# --- This file has been auto-generated. For permanent changes alter the appropriate block in the README.org. ---
{ config, pkgs, lib, flakeRoot, ... }:
{
boot.loader = {
systemd-boot.enable = true;
efi.canTouchEfiVariables = true;
efi.efiSysMountPoint = "/boot";
timeout = 5;
};
boot.kernelPackages = pkgs.linuxPackages_latest;
boot.kernelParams = [
"quiet"
"splash"
"udev.log_level=3"
"rd.systemd.show_status=false"
# Sleep / power management
"mem_sleep_default=deep" # Use S3 deep sleep, fixes sleep not working
"acpi_osi=Linux" # Tell ACPI this is a Linux system
"acpi_backlight=native" # Proper backlight control
# Intel GPU — fixes screen blinking on sleep/wake
"i915.enable_psr=0"
"i915.enable_psr2_sel_fetch=0"
# Prevent nvme from waking the system
"nvme.noacpi=1"
];
boot.consoleLogLevel = 0;
#boot.initrd.systemd.enable = true;
boot.initrd.availableKernelModules = [
"xhci_pci"
"nvme"
"usb_storage"
"sd_mod"
"rtsx_usb_sdmmc"
];
hardware.enableAllFirmware = true;
boot.kernelModules = [
"kvm-intel"
"asus_wmi" # Asus-specific power/fan/keyboard control
];
boot.plymouth = {
enable = true;
};
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
# Power management
powerManagement.enable = true;
services.logind.settings.Login = {
HandleSleepKey = "ignore";
HandleSleepKeyLongPress = "ignore";
};
services.thermald.enable = true; # Intel thermal management daemon
services.tlp = {
enable = true;
settings = {
CPU_SCALING_GOVERNOR_ON_AC = "performance";
CPU_SCALING_GOVERNOR_ON_BAT = "powersave";
CPU_ENERGY_PERF_POLICY_ON_BAT = "power";
PLATFORM_PROFILE_ON_AC = "performance";
PLATFORM_PROFILE_ON_BAT = "low-power";
};
};
}
#+END_SRC
** =generated/hosts/traveldroid/hardware-configuration.nix=
1. Boot into NixOS Live ISO or your installed system.
2. Open a terminal.
3. Run: <code>sudo nixos-generate-config --root /mnt</code> (Omit --root /mnt if already running NixOS.)
#+BEGIN_SRC nix :tangle generated/hosts/traveldroid/hardware-configuration.nix :noweb yes :mkdirp yes :eval never
{
hostname,
pkgs,
lib,
modulesPath,
user,
config,
...
}:
{
imports = [
# (modulesPath + "/installer/scan/not-detected.nix")
#../../hardware/hardware.nix
];
boot.initrd.availableKernelModules = [
"xhci_pci"
"nvme"
"usb_storage"
"sd_mod"
"rtsx_usb_sdmmc"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-uuid/69433a14-fbaf-401b-af85-cd1bbf02b4e2";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/811D-0676";
fsType = "vfat";
options = [
"fmask=0077"
"dmask=0077"
];
};
swapDevices = [
{ device = "/dev/disk/by-uuid/b6c557c2-7682-460b-a5e7-8f6f2f429a3a"; }
];
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}
#+END_SRC
** =generated/hosts/traveldroid/host.nix=
#+BEGIN_SRC nix :tangle generated/hosts/traveldroid/host.nix :noweb yes :mkdirp yes :eval never
{ lib, config, pkgs, flakeRoot, import-tree, home-manager, ... }:
let
hostname = "traveldroid";
modulesPath = "${flakeRoot}/generated/modules/${hostname}";
hostModules = import-tree modulesPath;
allModules = hostModules.imports;
in
{
networking.hostName = hostname;
system.stateVersion = "26.05";
#################################
# Locale
#################################
i18n = {
defaultLocale = "nl_NL.UTF-8";
extraLocales = [
"nl_NL.UTF-8/UTF-8"
"en_US.UTF-8/UTF-8"
];
consoleKeyMap = "us";
};
time.timeZone = "Europe/Amsterdam";
#################################
# Imports
#################################
imports =
[ ../../../generated/users/henrov.nix
./boot.nix
./hardware-configuration.nix
]
++ allModules
++ [ home-manager.nixosModules.home-manager ];
#################################
# Home Manager integration
#################################
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
environment.systemPackages = [
pkgs.dconf
];
programs.dconf.enable = true;
}
#+END_SRC
* generated/traveldroid/modules/apps
** =generated/modules/traveldroid/apps/2_b_installed.nix=
This installs a list of apps
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/apps/2_b_installed.nix :noweb yes :mkdirp yes :eval never
{ lib, config, pkgs, flakeRoot, ... }:
let
#################################
# FILE
#################################
confPath = "${flakeRoot}/generated/assets/2_b_installed.conf";
raw = builtins.readFile confPath;
lines = lib.splitString "\n" raw;
#################################
# CLEAN LINE
#################################
cleanLine = line:
let
noCR = lib.replaceStrings [ "\r" ] [ "" ] line;
noInlineComment = lib.head (lib.splitString "#" noCR);
in
lib.strings.trim noInlineComment;
#################################
# PARSE SECTION
#################################
parseSection = section:
let
result =
builtins.foldl'
(acc: line:
let
l = lib.strings.trim line;
in
if l == section then
acc // { active = true; }
else if lib.hasPrefix "#" l then
acc // { active = false; }
else if acc.active then
acc // { entries = acc.entries ++ [ l ]; }
else
acc
)
{ active = false; entries = []; }
lines;
in
builtins.filter (l: l != "") (map cleanLine result.entries);
#################################
# NIX PACKAGES
#################################
packageEntries = parseSection "#packages";
resolvePkg = name:
let
parts = lib.splitString "." name;
found = lib.attrByPath parts null pkgs;
in
if found == null then
throw ''
packages.nix: package not found
Token: ${name}
File : ${confPath}
''
else
found;
packages = map resolvePkg packageEntries;
#################################
# FLATPAKS
#################################
flatpakEntries = parseSection "#flatpaks";
in {
#################################
# Allow unfree
#################################
nixpkgs.config.allowUnfree = true;
#################################
# System packages (Nix)
#################################
environment.systemPackages = packages;
#################################
# Flatpak setup
#################################
services.flatpak.enable = true;
services.flatpak.remotes = [
{
name = "flathub";
location = "https://flathub.org/repo/flathub.flatpakrepo";
}
];
#################################
# Flatpak apps
#################################
services.flatpak.packages = flatpakEntries;
}
#+END_SRC
** =generated/modules/traveldroid/apps/emacs/emacs.nix=
This installs emacs
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/apps/emacs/emacs.nix :noweb yes :mkdirp yes :eval never
{ config, pkgs, lib, flakeRoot, ... }:
let
username = config.defaultUser or "henrov";
assetPath = "${flakeRoot}/generated/.config/emacs";
# Emacs package with Tree-sitter support
emacsPkg = pkgs.emacs-pgtk.override { withTreeSitter = true; };
# Extra packages for Emacs via Home Manager
emacsExtraPackages = epkgs: [
epkgs.manualPackages.treesit-grammars.with-all-grammars
epkgs.nerd-icons
epkgs.doom-modeline
epkgs.diminish
epkgs.eldoc
epkgs.pulsar
epkgs.which-key
epkgs.expreg
epkgs.vundo
epkgs.puni
epkgs.avy
epkgs.consult
epkgs.vertico
epkgs.marginalia
epkgs.crux
epkgs.magit
epkgs.nerd-icons-corfu
epkgs.corfu
epkgs.cape
epkgs.orderless
epkgs.yasnippet
epkgs.yasnippet-snippets
epkgs.rg
epkgs.exec-path-from-shell
epkgs.eat
epkgs.rust-mode
epkgs.rustic
epkgs.nix-mode
epkgs.hcl-mode
epkgs.shell-pop
epkgs.envrc
epkgs.nixpkgs-fmt
epkgs.f
epkgs.gptel
epkgs.catppuccin-theme
epkgs.eldoc-box
epkgs.sideline
epkgs.sideline-flymake
epkgs.sideline-eglot
];
in
{
# System-wide installation
environment.systemPackages = [
emacsPkg
];
# Home Manager user-specific configuration for your default user
home-manager.users = {
${username} = {
home.sessionVariables = {
EDITOR = "emacs";
XDG_SCREENSHOTS_DIR = "~/screenshots";
};
programs.emacs = {
enable = true;
package = emacsPkg;
extraPackages = emacsExtraPackages;
};
home.file = {
".emacs.d/early-init.el" = {
source = "${assetPath}/early-init.el";
force = true; # <-- allow overwrite
};
".emacs.d/init.el" = {
source = "${assetPath}/init.el";
force = true; # <-- allow overwrite
};
};
};
};
}
#+END_SRC
** =generated/modules/traveldroid/apps/flameshot.nix=
This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/apps/flameshot.nix :noweb yes :mkdirp yes :eval never
{ pkgs, config, lib, ... }:
let
username = config.defaultUser or "henrov";
in
{
############################
# System-level packages
############################
environment.systemPackages = with pkgs; [
flameshot
];
############################
# Home Manager user-level configuration
############################
home-manager.users."${username}" = {
home.sessionVariables = {
SCREENSHOT_TOOL = "flameshot";
USERNAME = username;
};
# Create ~/Pictures/Screenshots by touching a dummy file
home.file."Pictures/Screenshots/.keep" = {
text = ""; # empty file
};
services.flameshot = {
enable = true;
settings = {
General = {
uiColor = "#97cbbe";
contrastUiColor = "#1e1e2e";
showDesktopNotification = true;
savePath = "/home/${username}/Pictures/Screenshots";
filenamePattern = "$Y-$m-$d_$H-$M-$S";
useGrimAdapter = true;
};
};
};
};
}
#+END_SRC
** =generated/modules/traveldroid/apps/kdeconnect.nix=
This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/apps/kdeconnect.nix :noweb yes :mkdirp yes :eval never
# --- This file has been auto-generated. For permanent changes alter the appropriate block in the README.org. ---
{ config, pkgs, ... }:
let
username = config.defaultUser or "henrov";
in
{
environment.systemPackages = with pkgs; [
kdePackages.kdeconnect-kde
];
systemd.user.services.kdeconnect = {
enable = true;
description = "KDE Connect daemon";
wantedBy = ["default.target"];
serviceConfig = {
ExecStart = "${pkgs.kdePackages.kdeconnect-kde}/bin/kdeconnectd";
Restart = "on-failure";
};
};
}
#+END_SRC
** =generated/modules/traveldroid/apps/kitty.nix=
This file sets up Kitty terminal
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/apps/kitty.nix :noweb yes :mkdirp yes :eval never
{ lib, pkgs, config, flakeRoot, ... }:
let
username = config.defaultUser or "henrov";
extraConfigFile = "${flakeRoot}/generated/.config/kitty/extra.conf";
extraConfig =
if builtins.pathExists extraConfigFile
then builtins.readFile extraConfigFile
else "";
in
{
#################################
# System-wide install
#################################
environment.systemPackages = [
pkgs.kitty
];
#################################
# Home Manager
#################################
home-manager.users = {
"${username}" = {
programs.kitty = {
enable = true;
settings = {
confirm_os_window_close = lib.mkForce 0;
dynamic_background_opacity = lib.mkForce true;
enable_audio_bell = lib.mkForce false;
mouse_hide_wait = lib.mkForce "-1.0";
window_padding_width = lib.mkForce 10;
background_opacity = lib.mkForce "0.5";
background_blur = lib.mkForce 5;
notify_on_command_complete = lib.mkForce "never";
};
extraConfig = ''
${extraConfig}
# Theme
include themes/Catppuccin-Mocha.conf
'';
};
};
};
}
#+END_SRC
** =generated/modules/traveldroid/apps/starship.nix=
This file sets up starship prompt
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/apps/starship.nix :noweb yes :mkdirp yes :eval never
{ lib, config, pkgs, flakeRoot, ... }:
let
# Default username fallback
username = config.defaultUser or "henrov";
# Path to the starship config in assets
starshipConfSrc = "${flakeRoot}/generated/.config/starship.toml";
in
{
#################################
# Install Starship system-wide
#################################
environment.systemPackages = [ pkgs.starship ];
#################################
# Home Manager user configuration
#################################
home-manager.users = {
${username} = {
home.file = {
".config/starship.toml" = {
text = builtins.readFile "${starshipConfSrc}";
force = true;
};
};
};
};
}
#+END_SRC
** =generated/modules/traveldroid/apps/thunar.nix=
This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/apps/thunar.nix :noweb yes :mkdirp yes :eval never
{ pkgs, config, lib, ... }:
let
# Resolve the default username from host config
username = config.defaultUser or "henrov";
in
{
############################
# System-level packages
############################
environment.systemPackages = with pkgs; [
thunar # main file manager
thunar-archive-plugin # zip, tar, rar, 7z support
thunar-volman # auto-mount removable drives
gvfs # support for external drives and network shares
xarchiver # optional GUI archive manager
tumbler # Showing thumbnails
libmtp
mtpfs
jmtpfs
];
############################
# Home Manager user-level configuration
############################
# Direct assignment to the user avoids recursiveUpdate issues
home-manager.users."${username}" = {
home.stateVersion = "26.05"; # required
home.sessionVariables = {
FILE_MANAGER = "thunar";
USERNAME = username;
};
};
# Enable gvfs as a service
services.gvfs.enable = true;
}
#+END_SRC
** =generated/modules/traveldroid/apps/wofi.nix=
This is the install for Wofi, the launcher
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/apps/wofi.nix :noweb yes :mkdirp yes :eval never
{ lib, config, pkgs, flakeRoot, ... }:
let
username = config.defaultUser or "henrov";
assetPath = "${flakeRoot}/generated/.config/wofi";
in
{
environment.systemPackages = [ pkgs.wofi ];
home-manager.users = {
${username} = {
home.file = {
".config/wofi/config" = {
text = builtins.readFile "${assetPath}/config";
force = true;
};
".config/wofi/style.css" = {
text = builtins.replaceStrings ["PLACEHOLDER_USERNAME"] [username] (builtins.readFile "${assetPath}/style.css");
force = true;
};
};
};
};
}
#+END_SRC
** =generated/modules/traveldroid/apps/zenbrowser.nix=
This installs zen browser
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/apps/zenbrowser.nix :noweb yes :mkdirp yes :eval never
{ config, pkgs, lib, zen-browser, ... }:
let
# Grab the Zen Browser package for this host system
zenBrowser = zen-browser.packages.${pkgs.stdenv.hostPlatform.system}.default;
in
{
environment.systemPackages = [
zenBrowser
];
}
#+END_SRC
** =generated/modules/traveldroid/apps/zsh.nix=
This sets up the zsh in the terminal
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/apps/zsh.nix :noweb yes :mkdirp yes :eval never
{ lib, config, pkgs, flakeRoot, ... }:
let
#################################
# User config
#################################
username = config.defaultUser or "henrov";
generatedZsh = "${flakeRoot}/generated/.config/zsh/.zshrc";
#################################
# Alias parsing
#################################
aliasFile = "${flakeRoot}/generated/assets/aliases.conf";
content = builtins.readFile aliasFile;
lines =
lib.filter (l: l != "")
(map (l:
let
noComment = builtins.head (lib.splitString "#" l);
in lib.trim noComment
) (lib.splitString "\n" content));
parseLine = line:
let
parts = lib.splitString "=" line;
in
if lib.length parts < 2 then null else {
name = lib.trim (lib.head parts);
value = lib.trim (lib.concatStringsSep "=" (lib.tail parts));
};
parsed =
lib.filter (x: x != null)
(map parseLine lines);
functions =
lib.concatStringsSep "\n"
(map (x: ''
${x.name}() {
${x.value} "$@"
}
'') parsed);
in
{
#################################
# Packages
#################################
environment.systemPackages = with pkgs; [
zsh
oh-my-zsh
starship
zsh-syntax-highlighting
];
#################################
# Zsh config location
#################################
environment.etc."zshenv".text = ''
export ZDOTDIR=$HOME/.config/zsh
'';
#################################
# Generated alias functions (system-wide)
#################################
environment.etc."profile.d/99-alias-functions.sh".text = ''
# system-wide functions generated from aliases.conf
${functions}
'';
#################################
# Global zshrc
#################################
environment.etc."zshrc".text = ''
export ZSH=${pkgs.oh-my-zsh}/share/oh-my-zsh
ZSH_THEME=""
plugins=(git sudo extract colored-man-pages command-not-found history docker kubectl)
source $ZSH/oh-my-zsh.sh
# Init starship FIRST (prompt)
eval "$(starship init zsh)"
# Load alias functions
if [ -f /etc/profile.d/99-alias-functions.sh ]; then
source /etc/profile.d/99-alias-functions.sh
fi
# Load optional generated user config
[ -f "${generatedZsh}" ] && source "${generatedZsh}"
# Syntax highlighting MUST be last
source ${pkgs.zsh-syntax-highlighting}/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
'';
#################################
# Home Manager integration
#################################
home-manager.users.${username} = {
programs.zsh.enable = true;
home.file.".config/zsh/.zshrc".source = generatedZsh;
};
}
#+END_SRC
* generated/modules/traveldroid/desktop
** =generated/modules/traveldroid/desktop/fonts.nix=
This file installs and configures fonts
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/desktop/fonts.nix :noweb yes :mkdirp yes :eval never
{ lib, pkgs, config, ... }:
{
fonts.packages = with pkgs; [
nerd-fonts.iosevka
nerd-fonts.fira-code
nerd-fonts.jetbrains-mono
];
}
#+END_SRC
** =generated/modules/traveldroid/desktop/gtk.nix=
Setting up GTK
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/desktop/gtk.nix :noweb yes :mkdirp yes :eval never
{ pkgs, config, lib, ... }:
let
username = config.defaultUser or "henrov";
in
{
environment.systemPackages = with pkgs; [
gtk3
gtk4
];
home-manager.users."${username}" = {
gtk = {
enable = true;
};
};
}
#+END_SRC
** =generated/modules/traveldroid/desktop/hyprland.nix=
Setting up Hyprland
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/desktop/hyprland.nix :noweb yes :mkdirp yes :eval never
{ lib, config, pkgs, flakeRoot, home-manager, inputs, ... }:
let
username = config.defaultUser or "henrov";
assetPath = "${flakeRoot}/generated/.config/hypr";
hyprlandPkg =
pkgs.hyprland or
pkgs.hyprland-git or
inputs.hyprland.packages.${pkgs.system}.default;
in
{
# Install Hyprland systemwide
environment.systemPackages = [ hyprlandPkg ];
# Home Manager user configuration
home-manager.users = {
${username} = {
home.file = {
".config/hypr/animations.conf" = { source = "${assetPath}/animations.conf"; force = true; };
".config/hypr/behaviour.conf" = { source = "${assetPath}/behaviour.conf"; force = true; };
".config/hypr/bindings.conf" = { source = "${assetPath}/bindings.conf"; force = true; };
".config/hypr/exec-once.conf" = { source = "${assetPath}/exec-once.conf"; force = true; };
".config/hypr/hypridle.conf" = { source = "${assetPath}/hypridle.conf"; force = true; };
".config/hypr/hyprland.conf" = { source = "${assetPath}/hyprland.conf"; force = true; };
".config/hypr/hyprlock.conf" = { source = "${assetPath}/hyprlock.conf"; force = true; };
".config/hypr/layer-rules.conf" = { source = "${assetPath}/layer-rules.conf"; force = true; };
".config/hypr/layout.conf" = { source = "${assetPath}/layout.conf"; force = true; };
".config/hypr/monitor-rules.conf" = { source = "${assetPath}/monitor-rules.conf"; force = true; };
".config/hypr/theming.conf" = { source = "${assetPath}/theming.conf"; force = true; };
".config/hypr/window-rules.conf" = { source = "${assetPath}/window-rules.conf"; force = true; };
".config/hypr/workspace-rules.conf" = { source = "${assetPath}/workspace-rules.conf"; force = true; };
};
};
};
}
#+END_SRC
** =generated/modules/traveldroid/desktop/stylix.nix=
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/desktop/stylix.nix :noweb yes :mkdirp yes :eval never
{ lib, config, pkgs, flakeRoot, stylix, ... }:
let
username = config.defaultUser or "henrov";
moduleName = "stylix";
assetPath = "${flakeRoot}/generated/.config/${moduleName}";
stylixConfFile = "${assetPath}/stylix.conf";
stylixConf =
if builtins.pathExists stylixConfFile
then builtins.readFile stylixConfFile
else "";
cursorName = "phinger-cursors-light";
cursorSize = 24;
in
{
#################################
# Enable Stylix module
#################################
imports = [
stylix.nixosModules.stylix
];
#################################
# System packages
#################################
environment.systemPackages = [
pkgs.feh
pkgs.st
];
#################################
# Stylix system config
#################################
stylix = {
enable = true;
base16Scheme = "${flakeRoot}/assets/traveldroid/theming/stylix/catppuccin-mocha.yaml";
polarity = "dark";
targets = {
gtk.enable = true;
qt.enable = true;
};
cursor = {
name = cursorName;
package = pkgs.phinger-cursors;
size = cursorSize;
};
};
#################################
# Home Manager
#################################
home-manager.users = {
"${username}" = {
#################################
# ONLY custom file (safe)
#################################
home.file.".config/stylix/stylix.conf" = {
text = stylixConf;
force = true;
};
#################################
# Environment variables
#################################
home.sessionVariables = {
STYLIX_CONF = "$HOME/.config/stylix/stylix.conf";
XCURSOR_THEME = cursorName;
XCURSOR_SIZE = toString cursorSize;
HYPRCURSOR_THEME = cursorName;
HYPRCURSOR_SIZE = toString cursorSize;
};
};
};
}
#+END_SRC
** =generated/modules/traveldroid/desktop/wallpaper.nix=
Setting up wallpaper engine + wallpaper gui
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/desktop/wallpaper.nix :noweb yes :mkdirp yes :eval never
{ lib, config, pkgs, flakeRoot, ... }:
let
username = config.defaultUser or "henrov";
homeDir = "/home/${username}";
wallpaperSrc = "${flakeRoot}/assets/traveldroid/Wallpapers";
wallpaperDst = "${homeDir}/Wallpapers";
randoScript = "${homeDir}/Wallpapers/scripts/randomizeWallpapers.sh";
in
{
# Make bash available
environment.systemPackages = [ pkgs.bash pkgs.rsync pkgs.jq pkgs.awww pkgs.waypaper pkgs.socat ];
# Create the copy script using Home Manager, following Waybar style
home-manager.users = {
${username} = {
home.file = {
"copy-wallpapers.sh" = {
text = ''
#!/run/current-system/sw/bin/bash
set -euo pipefail
echo "Running as $(whoami)"
echo "Copying wallpapers from ${wallpaperSrc} to ${wallpaperDst} ..."
if [ ! -d "${wallpaperSrc}" ]; then
echo "ERROR: ${wallpaperSrc} does not exist"
exit 1
fi
mkdir -p "${wallpaperDst}"
# Simple copy, overwrite everything
cp -r "${wallpaperSrc}/." "${wallpaperDst}/"
# Fix permissions
chmod -R u+rwx "${wallpaperDst}"
echo "Done copying wallpapers."
'';
executable = true;
force = true;
};
};
};
};
# User service to run the script that copies the Wallpaperstuff
systemd.user.services.copyWallpapers = {
description = "Copy wallpapers from repo to ~/Wallpapers";
serviceConfig = {
Type = "oneshot";
ExecStart = "${homeDir}/copy-wallpapers.sh";
Restart = "no";
WorkingDirectory = homeDir;
};
wantedBy = [ "default.target" ];
};
# User service to randomize wallpapers
systemd.user.services.randomizeWallpapers = {
description = "Randomize wallpapers in ~/Wallpapers/pictures";
serviceConfig = {
Type = "oneshot";
ExecStart = "${randoScript}";
Restart = "no";
WorkingDirectory = homeDir;
};
wantedBy = [ "default.target" ];
};
############################
# Random background per workspace at logon
############################
systemd.user.services.workspaceWallpapers = {
description = "Dynamic wallpapers per workspace for Hyprland";
after = [ "graphical-session.target" ];
wants = [ "graphical-session.target" ];
serviceConfig = {
Type = "simple";
ExecStart = "${homeDir}/Wallpapers/scripts/workspace-wallpapers.sh";
Restart = "on-failure";
RestartSec = 5;
WorkingDirectory = homeDir;
Environment = [
"HYPRLAND_INSTANCE_SIGNATURE=${builtins.getEnv "HYPRLAND_INSTANCE_SIGNATURE"}"
"WAYLAND_DISPLAY=wayland-1"
"PATH=/run/current-system/sw/bin:/usr/bin:/bin"
];
};
wantedBy = [ "default.target" ];
};
}
#+END_SRC
** =generated/modules/traveldroid/desktop/waybar.nix=
This file installs and configures waybar
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/desktop/waybar.nix :noweb yes :mkdirp yes :eval never
{ lib, config, pkgs, flakeRoot, ... }:
let
# Use the config option defaultUser directly, fallback to "henrov"
username = config.defaultUser or "henrov";
basePath = "${flakeRoot}/generated/.config";
assetPath = "${flakeRoot}/generated/.config/waybar";
in
{
# Install Waybar system-wide
environment.systemPackages = [ pkgs.waybar ];
home-manager.users = {
${username} = {
home.file = {
".config/waybar/config.jsonc" = {
text = builtins.readFile "${assetPath}/config.jsonc";
force = true;
};
".config/waybar/style-dark.css" = {
text = builtins.replaceStrings ["henrov"] [username] (builtins.readFile "${assetPath}/style-dark.css");
force = true;
};
".config/scripts/bluetooth-status.sh" = {
text = builtins.readFile "${basePath}/scripts/bluetooth-status.sh";
force = true;
executable = true;
};
".config/scripts/hypr-workspaces.sh" = {
text = builtins.readFile "${basePath}/scripts/hypr-workspaces.sh";
force = true;
executable = true;
};
".config/scripts/hypr-workspacesmenu.sh" = {
text = builtins.readFile "${basePath}/scripts/hypr-workspacesmenu.sh";
force = true;
executable = true;
};
};
};
};
# Systemd user service for Waybar
systemd.user.services.waybar = {
description = "Waybar for Hyprland";
after = [ "graphical-session.target" ];
serviceConfig = {
ExecStart = "${pkgs.waybar}/bin/waybar";
Restart = "always";
Environment = ''
WAYLAND_DISPLAY=${config.environment.sessionVariables.WAYLAND_DISPLAY or "wayland-0"}
XDG_CURRENT_DESKTOP=Hyprland
'';
};
wantedBy = [ "default.target" ];
};
}
#+END_SRC
** =generated/modules/traveldroid/desktop/wayland.nix=
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/desktop/wayland.nix :noweb yes :mkdirp yes :eval never
{ lib, config, pkgs, ... }:
{
#################################
# Core Wayland packages
#################################
environment.systemPackages = with pkgs; [
wayland
wl-clipboard # optional but commonly used for copy/paste
];
#################################
# enable graphics stack
#################################
hardware.graphics.enable = true;
#################################
# Optional session variables for Wayland
#################################
environment.sessionVariables = {
# Forces some apps to use Wayland
NIXOS_OZONE_WL = "1";
};
}
#+END_SRC
** =generated/modules/traveldroid/desktop/xdg.nix=
This sets the XDG implementation
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/desktop/xdg.nix :noweb yes :mkdirp yes :eval never
{ lib, config, pkgs, flakeRoot, ... }:
let
username = config.defaultUser or "henrov";
homeDir = "/home/${username}";
# Portal backends
basePortal = pkgs.xdg-desktop-portal-gtk;
hyprlandPortal = pkgs.xdg-desktop-portal-hyprland;
in
{
#################################
# XDG Desktop Portals (system)
#################################
xdg.portal.enable = true;
xdg.portal.extraPortals = [
basePortal
hyprlandPortal
];
xdg.portal.config = {
"org.freedesktop.impl.portal.Screencast".backend = "hyprland";
};
#################################
# System packages
#################################
environment.systemPackages = [
basePortal
hyprlandPortal
];
#################################
# Home Manager user config
#################################
home-manager.users.${username} = {
#################################
# User packages
#################################
home.packages = [
basePortal
hyprlandPortal
];
#################################
# XDG user directories (HOME ONLY)
#################################
xdg.userDirs = {
enable = true;
createDirectories = true;
desktop = null;
download = "${homeDir}/Downloads";
documents = "${homeDir}/Documents";
pictures = "${homeDir}/Pictures";
music = null;
publicShare = null;
templates = "${homeDir}/Experiments";
videos = "${homeDir}/Videos";
extraConfig = {
XDG_PROJECTS_DIR = "${homeDir}/Projects";
XDG_WORK_DIR = "${homeDir}/Work";
};
};
};
}
#+END_SRC
* generated/modules/traveldroid/system
** =generated/modules/traveldroid/system/audio.nix=
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/system/audio.nix :noweb yes :mkdirp yes :eval never
{ lib, config, pkgs, ... }:
{
############################
# Audio system
############################
environment.systemPackages = with pkgs; [
pulseaudio # PulseAudio daemon
pavucontrol # GUI mixer
pamixer # CLI mixer
playerctl # Player controls
];
}
#+END_SRC
** =generated/modules/traveldroid/system/avahi.nix=
Avahi helps discovering services
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/system/avahi.nix :noweb yes :mkdirp yes :eval never
{ ... }:
{
services.avahi = {
enable = true;
nssmdns4 = true;
publish = {
enable = true;
addresses = true;
};
};
}
#+END_SRC
** =generated/modules/traveldroid/system/bluetooth.nix=
Installing Bluetooth services and supporting aps
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/system/bluetooth.nix :noweb yes :mkdirp yes :eval never
{ lib, config, pkgs, home-manager, ... }:
let
username = config.defaultUser or "henrov";
in
{
############################
# Bluetooth daemon
############################
hardware.bluetooth = {
enable = true;
powerOnBoot = true;
package = pkgs.bluez;
};
environment.systemPackages = with pkgs; [ blueman ];
}
#+END_SRC
** =generated/modules/traveldroid/system/copy_scripts.nix=
This copies any scripts from /generated/.config/scripts to ~/.config/scripts and makes any .sh files executable.
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/system/copy_scripts.nix :noweb yes :mkdirp yes :eval never
{ lib, config, pkgs, flakeRoot, ... }:
let
username = config.defaultUser or "henrov";
configPath = flakeRoot + "/generated/.config/scripts";
allFiles = lib.filesystem.listFilesRecursive configPath;
toRelative = file:
let
base = toString flakeRoot + "/generated/";
relative = lib.removePrefix base (toString file);
in
builtins.unsafeDiscardStringContext relative;
isShellScript = file:
lib.hasSuffix ".sh" (toString file);
toFileEntry = file: {
name = toRelative file;
value = {
source = file;
executable = isShellScript file;
force = true;
};
};
in
{
home-manager.users = {
${username} = {
home.file = builtins.listToAttrs (map toFileEntry allFiles);
};
};
}
#+END_SRC
** =generated/modules/traveldroid/system/dbus.nix=
This sets the dbus implementation
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/system/dbus.nix :noweb yes :mkdirp yes :eval never
{ config, pkgs, ... }:
{
# Enable classic D-Bus service
services.dbus.enable = true;
# Use default dbus package (classic D-Bus)
services.dbus.dbusPackage = pkgs.dbus;
# Include some essential system packages so shell and tools exist
environment.systemPackages = with pkgs; [
bashInteractive
coreutils
];
# Do not attempt to wrap dbus-daemon-launch-helper manually
# No extra security.wrappers needed
}
#+END_SRC
** =generated/modules/traveldroid/system/firewall.nix=
This sets the firewall.
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/system/firewall.nix :noweb yes :mkdirp yes :eval never
{ pkgs, ... }:
{
# Use nftables as the firewall backend
networking.nftables.enable = true;
networking.firewall = {
enable = true;
filterForward = false; # don't filter forwarded traffic
# outbound is allowed by default UNLESS you've set:
# LAN-only ports — Wi-Fi interface
interfaces."wlan0" = {
allowedTCPPorts = [
22 # SSH
80 # allow HTTP globally for outbound
443 # allow HTTPS globally for outbound
631 # CUPS / IPP network printing
9100 # AppSocket/JetDirect printing
6566 # SANE network scanner
57621 # Spotify Connect
57622 # Spotify local file sync
];
allowedTCPPortRanges = [
{ from = 1714; to = 1764; } # KDE Connect
];
allowedUDPPorts = [
5353 # mDNS / Avahi (printer + device discovery)
631 # CUPS / IPP
67 # DHCP
123 # NTP time sync
1900 # UPnP device discovery
57621 # Spotify Connect
];
allowedUDPPortRanges = [
{ from = 1714; to = 1764; } # KDE Connect
];
};
# LAN-only ports — ethernet (ready for when you plug in)
interfaces."enp0s31f6" = {
allowedTCPPorts = [
631 # CUPS / IPP network printing
9100 # AppSocket/JetDirect printing
6566 # SANE network scanner
57621 # Spotify Connect
57622 # Spotify local file sync
];
allowedTCPPortRanges = [
{ from = 1714; to = 1764; } # KDE Connect
];
allowedUDPPorts = [
5353 # mDNS / Avahi (printer + device discovery)
631 # CUPS / IPP
67 # DHCP
123 # NTP time sync
1900 # UPnP device discovery
57621 # Spotify Connect
];
allowedUDPPortRanges = [
{ from = 1714; to = 1764; } # KDE Connect
];
};
};
# CLI tool for temporary rule changes without rebuilding
# Usage: sudo nixos-firewall-tool open tcp 8080
environment.systemPackages = with pkgs; [
nixos-firewall-tool
];
}
#+END_SRC
** =generated/modules/traveldroid/system/hypridle.nix=
This installs hypridle
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/system/hypridle.nix :noweb yes :mkdirp yes :eval never
{ lib, config, pkgs, flakeRoot, ... }:
let
username = config.defaultUser or "henrov";
basePath = "${flakeRoot}/generated/.config";
assetPath = "${flakeRoot}/generated/.config/hypr";
in
{
#################################
# Install hypridle system-wide
#################################
environment.systemPackages = [ pkgs.hypridle ];
#################################
# Deploy config
#################################
home-manager.users = {
${username} = {
home.file = {
".config/hypr/hypridle.conf" = {
text = builtins.readFile "${assetPath}/hypridle.conf";
force = true;
};
};
};
};
#################################
# Systemd user service
#################################
systemd.user.services.hypridle = {
description = "Hypridle (Hyprland idle daemon)";
after = [ "hyprland-session.target" ];
bindsTo = [ "hyprland-session.target" ];
serviceConfig = {
ExecStart = "${pkgs.hypridle}/bin/hypridle";
Restart = "on-failure";
RestartSec = "5s";
Environment = [
"HOME=/home/${username}"
"WAYLAND_DISPLAY=wayland-1"
"XDG_RUNTIME_DIR=/run/user/1000"
];
};
wantedBy = [ "hyprland-session.target" ];
};
}
#+END_SRC
** =generated/modules/traveldroid/system/hyprlock.nix=
This installs hyprlock
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/system/hyprlock.nix :noweb yes :mkdirp yes :eval never
{ lib, config, pkgs, flakeRoot, ... }:
let
username = config.defaultUser or "henrov";
basePath = "${flakeRoot}/generated/.config";
assetPath = "${flakeRoot}/generated/.config/hypr";
in
{
#################################
# Install hyprlock system-wide
#################################
environment.systemPackages = [
pkgs.hyprlock
];
#################################
# Deploy configuration file
#################################
home-manager.users = {
${username} = {
home.file = {
".config/hypr/hyprlock.conf" = {
text = builtins.readFile "${assetPath}/hyprlock.conf";
force = true;
};
};
};
};
#################################
# Optional: helper systemd user service (manual start use)
#################################
systemd.user.services.hyprlock = {
description = "Hyprlock (manual lock session)";
after = [ "graphical-session.target" ];
serviceConfig = {
ExecStart = "${pkgs.hyprlock}/bin/hyprlock";
Restart = "no";
Environment = ''
WAYLAND_DISPLAY=${config.environment.sessionVariables.WAYLAND_DISPLAY or "wayland-0"}
XDG_CURRENT_DESKTOP=Hyprland
'';
};
wantedBy = [ ];
};
}
#+END_SRC
** =generated/modules/traveldroid/system/gnome-keyring.nix=
This sets the dbus implementation
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/system/gnome-keyring.nix :noweb yes :mkdirp yes :eval never
{ config, pkgs, ... }:
{
##################################################
# Core services
##################################################
# Enable GNOME Keyring
services.gnome.gnome-keyring.enable = true;
##################################################
# PAM (auto unlock keyring on login)
##################################################
security.pam.services = {
login.enableGnomeKeyring = true;
greetd.enableGnomeKeyring = true;
sddm.enableGnomeKeyring = true;
gdm.enableGnomeKeyring = true;
};
##################################################
# Environment packages
##################################################
environment.systemPackages = with pkgs; [
polkit_gnome
seahorse
libsecret
];
##################################################
# Security / Polkit
##################################################
security.polkit.enable = true;
}
#+END_SRC
** =generated/modules/traveldroid/system/login-tuigreet.nix=
This sets up tuigreeter which is not fancy but imo fits the aesthetic I am aiming for
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/system/login-tuigreet.nix :noweb yes :mkdirp yes :eval never
{ config, pkgs, lib, ... }:
let
tuigreetBin = "${pkgs.tuigreet}/bin/tuigreet";
sessionsDir = "${pkgs.hyprland}/share/wayland-sessions";
in
{
#################################
# Greetd (tuigreet)
#################################
services.greetd = {
enable = true;
settings = {
default_session = {
command = ''
${tuigreetBin} \
--time \
--remember \
--remember-session \
--sessions ${sessionsDir} \
--cmd "start-hyprland"
'';
user = "greeter";
};
};
};
#################################
# Fix TTY / boot noise issues
#################################
systemd.services.greetd.serviceConfig = {
Type = "idle";
StandardInput = "tty";
StandardOutput = "tty";
StandardError = "journal";
# Prevent boot log spam on tty
TTYReset = true;
TTYVHangup = true;
TTYVTDisallocate = true;
};
}
#+END_SRC
** =generated/modules/traveldroid/system/networking.nix=
This sets the networking.
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/system/networking.nix :noweb yes :mkdirp yes :eval never
{ lib, config, pkgs, ... }:
{
#################################
# Networking core
#################################
networking = {
# Let DHCP be default unless overridden elsewhere
useDHCP = lib.mkDefault true;
#################################
# NetworkManager (primary stack)
#################################
networkmanager = {
enable = true;
# Use iwd backend for WiFi
wifi.backend = "iwd";
};
#################################
# iwd (WiFi daemon)
#################################
wireless.iwd = {
enable = true;
# Allow user control via NM / CLI
settings.General.EnableNetworkConfiguration = true;
};
};
#################################
# System packages
#################################
environment.systemPackages = [
pkgs.networkmanager
pkgs.linux-firmware
pkgs.networkmanagerapplet
pkgs.networkmanager_dmenu
pkgs.iwgtk
];
}
#+END_SRC
** =generated/modules/traveldroid/system/nix.nix=
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/system/nix.nix :noweb yes :mkdirp yes :eval never
{ lib, config, ... }:
{
nix.settings = {
experimental-features = [ "nix-command" "flakes" ];
download-buffer-size = 536870912; # 512 MB
cores = 2;
max-jobs = 1;
};
}
#+END_SRC
** =generated/modules/traveldroid/system/printing.nix=
This sets the dbus implementation
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/system/printing.nix :noweb yes :mkdirp yes :eval never
{ lib, config, pkgs, ... }:
{
############################
# Printing system
############################
services.printing.enable = true; # enable CUPS printing service
############################
# System packages for GUI management
############################
environment.systemPackages = with pkgs; [
system-config-printer # GUI to manage printers
];
}
#+END_SRC
** =generated/modules/traveldroid/system/quickshell.nix=
This sets the dbus implementation
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/system/quickshell.nix :noweb yes :mkdirp yes :eval never
{ pkgs, lib, config, flakeRoot, ... }:
let
username = config.defaultUser or "henrov";
quickshellPath = flakeRoot + "/generated/.config/quickshell";
allFiles = lib.filesystem.listFilesRecursive quickshellPath;
toRelative = file:
let
base = toString flakeRoot + "/generated/";
relative = lib.removePrefix base (toString file);
in
builtins.unsafeDiscardStringContext relative;
toFileEntry = file: {
name = toRelative file;
value = {
source = file;
force = true;
};
};
in
{
environment.systemPackages = with pkgs; [
quickshell
qt6.qtdeclarative
qt6.qttools
qt6.qtsvg
qt6.qtimageformats
qt6.qtmultimedia
qt6.qt5compat
];
qt = {
enable = true;
platformTheme = "qt5ct";
};
home-manager.users = {
${username} = {
home.file = builtins.listToAttrs (map toFileEntry allFiles);
};
};
}
#+END_SRC
** =generated/modules/traveldroid/system/swaync.nix=
This sets the dbus implementation
#+BEGIN_SRC nix :tangle generated/modules/traveldroid/system/swaync.nix :noweb yes :mkdirp yes :eval never
{ lib, config, pkgs, flakeRoot, ... }:
let
username = config.defaultUser or "henrov";
assetPath = "${flakeRoot}/generated/.config/swaync";
in
{
environment.systemPackages = [ pkgs.swaynotificationcenter pkgs.libnotify ];
home-manager.users.${username} = {
# Do NOT enable services.swaync — it would claim the config files
# and conflict with our home.file entries below.
home.file = {
".config/swaync/config.json" = {
text = builtins.readFile "${assetPath}/config.json";
force = true;
};
".config/swaync/style.css" = {
text = builtins.replaceStrings ["henrov"] [username] (builtins.readFile "${assetPath}/style.css");
force = true;
};
};
};
# Autostart swaync as a systemd user service instead
systemd.user.services.swaync = {
description = "SwayNotificationCenter";
after = [ "graphical-session.target" ];
serviceConfig = {
ExecStart = "${pkgs.swaynotificationcenter}/bin/swaync";
Restart = "always";
Environment = [
"WAYLAND_DISPLAY=${config.environment.sessionVariables.WAYLAND_DISPLAY or "wayland-1"}"
"XDG_CURRENT_DESKTOP=Hyprland"
];
};
wantedBy = [ "default.target" ];
};
}
#+END_SRC
* generated/users
** =generated/users/=
This is the default user, just search and replace henrov another name if you want to change
#+BEGIN_SRC nix :tangle generated/users/henrov.nix :noweb yes :mkdirp yes :eval never
{ lib, config, pkgs, ... }:
let
username = "henrov";
in
{
#################################
# NixOS system user
#################################
users.users.${username} = {
isNormalUser = true;
home = "/home/${username}";
hashedPassword = "$6$S7iShgBxB.77CwmP$i0njK.2r3OL5UEvgZbmwZ0rnpZ4QyJcv8p9uCmJ4AiVPSMXkQkIwMLzyAOnJ0q8.tPLIp/7EquEIZeK8qbmgw/";
extraGroups = [ "wheel" "networkmanager" "bluetooth" "input" ];
ignoreShellProgramCheck = true; # <-- avoids the assertion
shell = pkgs.zsh;
};
#################################
# Home Manager user definition
#################################
home-manager.users = {
${username} = {
home.username = username;
home.homeDirectory = "/home/${username}";
home.stateVersion = "26.05";
programs.zsh.enable = true;
home.packages = [
# add packages here
];
# Activation to ensure the directory is writable
home.activation.fixStylixPermissions = ''
mkdir -p $HOME/.config
chmod -R u+rwx $HOME/.config
'';
# Locale and timezone settings
home.sessionVariables = {
LANG = "nl_NL.UTF-8";
LC_ALL = "nl_NL.UTF-8";
TZ = "Europe/Amsterdam";
};
};
};
}
#+END_SRC
* These are all the prepared config files
:PROPERTIES:
:CUSTOM_ID: the-config-files
:END:
** =generated/.config/emacs/early-init.el=
This contaions emacs
#+BEGIN_SRC el :tangle generated/.config/emacs/early-init.el :noweb yes :mkdirp yes :eval never
;;; package --- early init -*- lexical-binding: t -*-
;;; Commentary:
;;; Prevents white flash and better Emacs defaults
;;; Code:
(set-language-environment "UTF-8")
(setq-default
default-frame-alist
'((background-color . "#1e1e2e")
(bottom-divider-width . 1) ; Thin horizontal window divider
(foreground-color . "#bac2de") ; Default foreground color
(fullscreen . maximized) ; Maximize the window by default
(horizontal-scroll-bars . nil) ; No horizontal scroll-bars
(left-fringe . 8) ; Thin left fringe
(menu-bar-lines . 0) ; No menu bar
(right-divider-width . 1) ; Thin vertical window divider
(right-fringe . 8) ; Thin right fringe
(tool-bar-lines . 0) ; No tool bar
(undecorated . t) ; Remove extraneous X decorations
(vertical-scroll-bars . nil)) ; No vertical scroll-bars
user-full-name "Henrov henrov" ; ME!
;; memory configuration
;; Higher garbage collection threshold, prevents frequent gc locks, reset later
gc-cons-threshold most-positive-fixnum
;; Ignore warnings for (obsolete) elisp compilations
byte-compile-warnings '(not obsolete)
;; And other log types completely
warning-suppress-log-types '((comp) (bytecomp))
;; Large files are okay in the new millenium.
large-file-warning-threshold 100000000
;; dont show garbage collection messages at startup, will reset later
garbage-collection-messages nil
;; native compilation
package-native-compile t
native-comp-warning-on-missing-source nil
native-comp-async-report-warnings-errors 'silent
;; Read more based on system pipe capacity
read-process-output-max (max (* 10240 10240) read-process-output-max)
;; scroll configuration
scroll-margin 0 ; Lets scroll to the end of the margin
scroll-conservatively 100000 ; Never recenter the window
scroll-preserve-screen-position 1 ; Scrolling back and forth
;; frame config
;; Improve emacs startup time by not resizing to adjust for custom settings
frame-inhibit-implied-resize t
;; Dont resize based on character height / width but to exact pixels
frame-resize-pixelwise t
;; backups & files
backup-directory-alist '(("." . "~/.backups/")) ; Don't clutter
backup-by-copying t ; Don't clobber symlinks
create-lockfiles nil ; Don't have temp files
delete-old-versions t ; Cleanup automatically
kept-new-versions 6 ; Update every few times
kept-old-versions 2 ; And cleanup even more
version-control t ; Version them backups
delete-by-moving-to-trash t ; Dont delete, send to trash instead
;; startup
inhibit-startup-screen t ; I have already done the tutorial. Twice
inhibit-startup-message t ; I know I am ready
inhibit-startup-echo-area-message t ; Yep, still know it
initial-scratch-message nil ; I know it is the scratch buffer!
initial-buffer-choice nil
inhibit-startup-buffer-menu t
inhibit-x-resources t
initial-major-mode 'fundamental-mode
pgtk-wait-for-event-timeout 0.001 ; faster child frames
ad-redefinition-action 'accept ; dont care about legacy things being redefined
inhibit-compacting-font-caches t
;; tabs
tab-width 4 ; Always tab 4 spaces.
indent-tabs-mode nil ; Never use actual tabs.
;; rendering
cursor-in-non-selected-windows nil ; dont render cursors other windows
;; packages
use-package-always-defer t
load-prefer-newer t
default-input-method nil
use-dialog-box nil
use-file-dialog nil
use-package-expand-minimally t
package-enable-at-startup nil
use-package-enable-imenu-support t
auto-mode-case-fold nil ; No second pass of case-insensitive search over auto-mode-alist.
package-archives '(("melpa" . "https://melpa.org/packages/")
("gnu" . "https://elpa.gnu.org/packages/")
("nongnu" . "https://elpa.nongnu.org/nongnu/")
("melpa-stable" . "https://stable.melpa.org/packages/"))
package-archive-priorities '(("gnu" . 99)
("nongnu" . 80)
("melpa" . 70)
("melpa-stable" . 50))
)
;;; early-init.el ends here
#+END_SRC
** =generated/.config/emacs/init.el=
This contaions emacs
#+BEGIN_SRC el :tangle generated/.config/emacs/init.el :noweb yes :mkdirp yes :eval never
;;; package --- Summary - My minimal Emacs init file -*- lexical-binding: t -*-
;;; Commentary:
;;; Simple Emacs setup I carry everywhere
;;; Code:
(setq custom-file (locate-user-emacs-file "custom.el"))
(load custom-file 'noerror) ;; no error on missing custom file
(require 'package)
(package-initialize)
(defun reset-custom-vars ()
"Resets the custom variables that were set to crazy numbers"
(setopt gc-cons-threshold (* 1024 1024 100))
(setopt garbage-collection-messages t))
(use-package emacs
:custom
(native-comp-async-query-on-exit t)
(read-answer-short t)
(use-short-answers t)
(enable-recursive-minibuffers t)
(which-func-update-delay 1.0)
(visible-bell nil)
(custom-buffer-done-kill t)
(whitespace-line-column nil)
(x-underline-at-descent-line t)
(imenu-auto-rescan t)
(uniquify-buffer-name-style 'forward)
(confirm-nonexistent-file-or-buffer nil)
(create-lockfiles nil)
(make-backup-files nil)
(kill-do-not-save-duplicates t)
(sentence-end-double-space nil)
(treesit-enabled-modes t)
:init
;; base visual
(menu-bar-mode -1) ;; no menu bar
(toggle-scroll-bar -1) ;; no scroll bar
(tool-bar-mode -1) ;; no tool bar either
(blink-cursor-mode -1) ;; stop blinking
;; font of the century
(set-frame-font "Aporetic Sans Mono 12" nil t)
:bind
(("C-<wheel-up>" . pixel-scroll-precision) ; dont zoom in please, just scroll
("C-<wheel-down>" . pixel-scroll-precision) ; dont zoom in either, just scroll
("C-x k" . kill-current-buffer)) ; kill the buffer, dont ask
:hook
(text-mode . delete-trailing-whitespace-mode)
(prog-mode . delete-trailing-whitespace-mode)
(after-init . global-display-line-numbers-mode) ;; always show line numbers
(after-init . column-number-mode) ;; column number in the mode line
(after-init . size-indication-mode) ;; file size in the mode line
(after-init . pixel-scroll-precision-mode) ;; smooth mouse scroll
(after-init . electric-pair-mode) ;; i mean ... parens should auto create
(after-init . reset-custom-vars)
)
(use-package autorevert
:ensure nil
:custom
(auto-revert-interval 3)
(auto-revert-remote-files nil)
(auto-revert-use-notify t)
(auto-revert-avoid-polling nil)
(auto-revert-verbose t)
:hook
(after-init . global-auto-revert-mode))
(use-package recentf
:ensure nil
:commands (recentf-mode recentf-cleanup)
:hook
(after-init . recentf-mode)
:custom
(recentf-auto-cleanup 'never)
(recentf-exclude
(list "\\.tar$" "\\.tbz2$" "\\.tbz$" "\\.tgz$" "\\.bz2$"
"\\.bz$" "\\.gz$" "\\.gzip$" "\\.xz$" "\\.zip$"
"\\.7z$" "\\.rar$"
"COMMIT_EDITMSG\\'"
"\\.\\(?:gz\\|gif\\|svg\\|png\\|jpe?g\\|bmp\\|xpm\\)$"
"-autoloads\\.el$" "autoload\\.el$"))
:config
;; A cleanup depth of -90 ensures that `recentf-cleanup' runs before
;; `recentf-save-list', allowing stale entries to be removed before the list
;; is saved by `recentf-save-list', which is automatically added to
;; `kill-emacs-hook' by `recentf-mode'.
(add-hook 'kill-emacs-hook #'recentf-cleanup -90))
(use-package savehist
:ensure nil
:commands (savehist-mode savehist-save)
:hook
(after-init . savehist-mode)
:custom
(savehist-autosave-interval 600)
(savehist-additional-variables
'(kill-ring ; clipboard
register-alist ; macros
mark-ring global-mark-ring ; marks
search-ring regexp-search-ring)))
(use-package hl-line
:ensure nil
:custom
(hl-line-sticky-flag nil)
(global-hl-line-sticky-flag nil)
:hook
(after-init . global-hl-line-mode))
(use-package saveplace
:ensure nil
:commands (save-place-mode save-place-local-mode)
:hook
(after-init . save-place-mode)
:custom
(save-place-limit 400))
(use-package nerd-icons
:custom
;; disable bright icon colors
(nerd-icons-color-icons nil))hells.nix
(use-package doom-modeline
:custom
(inhibit-compacting-font-caches t) ;; speed
(doom-modeline-buffer-file-name-style 'relative-from-project)
(doom-modeline-major-mode-icon nil) ;; distracting icons, no thank you
(doom-modeline-buffer-encoding nil) ;; everything is utf-8 anyway
(doom-modeline-buffer-state-icon nil) ;; the filename already shows me
(doom-modeline-lsp nil) ;; lsp state is too distracting, too often
:hook (after-init . doom-modeline-mode))
(load-theme 'catppuccin :no-confirm)
(use-package diminish :demand t) ;; declutter the modeline
(use-package eldoc
:diminish eldoc-mode
:custom
(eldoc-echo-area-use-multiline-p nil)) ;; docs for everything
(use-package eldoc-box
:defer t
:config
(set-face-background 'eldoc-box-border (catppuccin-color 'green))
(set-face-background 'eldoc-box-body (catppuccin-color 'base))
:bind
(("M-h" . eldoc-box-help-at-point)))
(use-package pulsar
:commands pulsar-global-mode pulsar-recenter-top pulsar-reveal-entry
:init
(defface pulsar-catppuccin
`((default :extend t)
(((class color) (min-colors 88) (background light))
:background ,(catppuccin-color 'sapphire))
(((class color) (min-colors 88) (background dark))
:background ,(catppuccin-color 'sapphire))
(t :inverse-video t))
"Alternative nord face for `pulsar-face'."
:group 'pulsar-faces)
:custom
(pulsar-face 'pulsar-catppuccin)
:hook
(after-init . pulsar-global-mode))
(use-package which-key
:commands which-key-mode
:diminish which-key-mode
:hook
(after-init . which-key-mode))
(use-package expreg
:bind ("M-m" . expreg-expand))
(use-package vundo) ;; undo tree
;; better structured editing
(use-package puni
:commands puni-global-mode
:hook
(after-init . puni-global-mode))
(use-package avy
:bind
("M-i" . avy-goto-char-2)
:custom
(avy-background t))
(use-package consult
:bind
("C-x b" . consult-buffer) ;; orig. switch-to-buffer
("M-y" . consult-yank-pop) ;; orig. yank-pop
("M-g M-g" . consult-goto-line) ;; orig. goto-line
("M-g i" . consult-imenu) ;; consult version is interactive
("M-g r" . consult-ripgrep) ;; find in project also works
:custom
(consult-narrow-key "<"))
(use-package vertico
:commands vertico-mode
:custom
(read-file-name-completion-ignore-case t)
(read-buffer-completion-ignore-case t)
(completion-ignore-case t)
(enable-recursive-minibuffers t)
(minibuffer-prompt-properties '(read-only t cursor-intangible t face minibuffer-prompt))
:init
(vertico-mode)
:hook
(minibuffer-setup-hook . cursor-intangible-mode))
(use-package marginalia
:commands marginalia-mode
:hook (after-init . marginalia-mode))
(use-package crux
:bind
("C-c M-e" . crux-find-user-init-file)
("C-c C-w" . crux-transpose-windows)
("C-c M-d" . crux-find-current-directory-dir-locals-file)
("C-a" . crux-move-beginning-of-line))
(use-package magit
:bind (("C-M-g" . magit-status)))
(use-package nerd-icons-corfu
:commands nerd-icons-corfu-formatter
:defines corfu-margin-formatters)
(use-package corfu
:commands global-corfu-mode
:custom
(corfu-cycle t)
(corfu-auto t)
(corfu-auto-delay 1)
(corfu-auto-prefix 3)
(corfu-separator ?_)
:hook
(after-init . global-corfu-mode)
:config
(add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter))
(use-package cape)
(use-package orderless
:custom
(completion-styles '(orderless partial-completion basic))
(completion-category-defaults nil)
(completion-category-overrides nil))
(use-package yasnippet
:commands yas-global-mode
:diminish yas-minor-mode
:hook
(after-init . yas-global-mode))
(use-package yasnippet-snippets :after yasnippet)
(use-package exec-path-from-shell
:commands exec-path-from-shell-initialize
:custom
(exec-path-from-shell-arguments nil)
:hook
(after-init . exec-path-from-shell-initialize))
(use-package nixpkgs-fmt
:custom
(nixpkgs-fmt-command "nixfmt"))
(use-package eat
:bind
(("C-c e p" . eat-project)
("C-c e t" . eat)))
(use-package f :demand t)
(use-package envrc
:commands envrc-global-mode
:hook
(after-init . envrc-global-mode))
(use-package gptel
:commands gptel-make-anthropic f-read-text
:config
(gptel-make-anthropic "Claude"
:stream t :key (f-read-text "/run/secrets/claude_key")))
(use-package sideline-flymake)
(use-package sideline-eglot)
(use-package sideline
:custom
(sideline-backends-right '(sideline-flymake sideline-eglot))
:hook
(eglot-managed-mode . sideline-mode)
(flymake-mode . sideline-mode))
(use-package eglot
:custom
(eglot-extend-to-xref t)
(eglot-ignored-server-capabilities '(:inlayHintProvider))
(jsonrpc-event-hook nil)
:hook
(eglot-managed-mode . eldoc-box-hover-mode)
(before-save . eldoc-format-buffer)
:bind
(:map eglot-mode-map
("C-c l a" . eglot-code-actions)
("C-c l r" . eglot-rename)
("C-c l h" . eldoc)
("C-c l g" . xref-find-references)
("C-c l w" . eglot-reconnect)))
(use-package proced
:custom
(proced-auto-update-flag t)
(proced-auto-update-interval 3)
(proced-enable-color-flag t)
(proced-show-remote-processes t))
(use-package org
:ensure t
:defer t
:commands (org-mode org-capture org-agenda)
:init
(defvar org-journal-file "~/nextcloud/org/journal.org")
(defvar org-archive-file "~/nextcloud/org/archive.org")
(defvar org-notes-file "~/nextcloud/org/notes.org")
(defvar org-inbox-file "~/nextcloud/org/inbox.org")
(defvar org-work-file "~/nextcloud/org/work.org")
(defun my/org-capture-project-target-heading ()
"Determine Org target headings from the current file's project path.
This function assumes a directory structure like '~/projects/COMPANY/PROJECT/'.
It extracts 'COMPANY' and 'PROJECT' to use as nested headlines
for an Org capture template.
If the current buffer is not visi
ting a file within such a
project structure, it returns nil, causing capture to default to
the top of the file."
(when-let* ((path (buffer-file-name))) ; Ensure we are in a file-visiting buffer
(let ((path-parts (split-string path "/" t " ")))
(when-let* ((projects-pos (cl-position "projects" path-parts :test #'string=))
(company (nth (+ 1 projects-pos) path-parts))
(project (nth (+ 2 projects-pos) path-parts)))
;; Return a list of headlines for Org to find or create.
(list company project)))))
:bind
(("C-c c" . org-capture)
("C-c i" . org-store-link)
("C-c a" . org-agenda)
:map org-mode-map
("C-c t" . org-toggle-inline-images)
("C-c l" . org-toggle-link-display))
:custom
(org-agenda-files (list org-inbox-file org-journal-file))
(org-directory "~/nextcloud/org")
(org-default-notes-file org-inbox-file)
(org-archive-location (concat org-archive-file "::* From %s"))
(org-log-done 'time)
(org-log-into-drawer t)
(org-hide-emphasis-markers t)
(org-src-fontify-natively t)
(org-src-tab-acts-natively t)
(org-capture-templates '(("t" "Todo" entry (file org-inbox-file)
"* TODO %?\n:PROPERTIES:\n:CREATED: %U\n:END:\n\n%a\n\n)")
("j" "Journal" entry (file+olp+datetree org-journal-file)
"* %?\n:PROPERTIES:\n:CREATED: %U\n:END:\n\n%a\n\n")
("n" "Note" entry (file org-notes-file)
"* %?\n:PROPERTIES:\n:CREATED: %U\n:END:\n\n%a\n\n")
("p" "Project Task" item
(file+function org-work-file my/org-capture-project-target-heading)
"* TODO %? \n CLOCK: %U"
))
)
:config
;; Enable syntax highlighting in code blocks
(add-hook 'org-mode-hook 'turn-on-font-lock)
(add-hook 'org-mode-hook 'org-indent-mode))
;; extras
(use-package comp-run
:ensure nil
:config
(push "tramp-loaddefs.el.gz" native-comp-jit-compilation-deny-list)
(push "cl-loaddefs.el.gz" native-comp-jit-compilation-deny-list))
(use-package rustic
:custom
(rustic-lsp-client 'eglot))
(provide 'init)
;;; init.el ends here
#+END_SRC
** =generated/.config/hypr/animations.conf=
These are config files for .config/hypr
#+BEGIN_SRC conf :tangle generated/.config/hypr/animations.conf :noweb yes :mkdirp yes :eval never
animations {
enabled = yes
bezier = myBezier, 0.05, 0.9, 0.1, 1.05
animation = windows, 1, 7, myBezier
animation = windowsOut, 1, 7, default, popin 80%
animation = border, 1, 10, default
animation = borderangle, 1, 8, default
animation = fade, 1, 7, default
animation = workspaces, 1, 6, default
}
#+END_SRC
** =generated/.config/hypr/behaviour.conf=
These are config files for .config/hypr
#+BEGIN_SRC conf :tangle generated/.config/hypr/behaviour.conf :noweb yes :exports code :wrap nil :mkdirp yes :eval never
# Keyboard and mouse settings
input {
numlock_by_default = true
touchpad {
natural_scroll = true
tap-to-click = true
drag_lock = true
}
}
# Scrolling modifier settings
# Touchpad settings (applies to all touchpads)
# Focus settings
# Miscellaneous settings
#+END_SRC
** =generated/.config/hypr/bindings.conf=
These are config files for .config/hypr
#+BEGIN_SRC conf :tangle generated/.config/hypr/bindings.conf :noweb yes :mkdirp yes :eval never
$mainMod = SUPER
# launcher / kill / reload
bind = $mainMod, Space, exec, ~/.config/scripts/wofi-launcher.sh
bind = ALT, Space, exec, ~/.config/scripts/wofi-launcher.sh
bind = $mainMod, Q, killactive,
bind = $mainMod SHIFT, Q, exit,
bind = $mainMod SHIFT, R, exec, hyprctl reload
bind = $mainMod, X , exec, qs -c powermenu
bind = $mainMod, L, exec, hyprlock
# grimblast
# bind = $mainMod SHIFT, P, exec, grimblast -n -f copysave active
# bind = $mainMod SHIFT, S, exec, grimblast -n -f copysave area
# bind = , XF86Screenshot, exec, grimblast -n -f copysave area
# bind = $mainMod ALT, P, exec, grimblast -n -f copysave output
# bind = $mainMod CTRL, P, exec, grimblast -n -f copysave screen
# Flameshot keybindings
bind = $mainMod SHIFT, P, exec, flameshot full -p ~/Pictures/Screenshots -c
bind = $mainMod SHIFT, S, exec, flameshot gui
bind = , XF86Screenshot, exec, flameshot gui
bind = $mainMod ALT, P, exec, flameshot full -d 5000 -p ~/Pictures/Screenshots -c
bind = $mainMod CTRL, P, exec, flameshot screen -n 0 -p ~/Pictures/Screenshots -c
# Switch windows
bind = ALT, TAB, cyclenext, prev
bind = ALT SHIFT, TAB, cyclenext, prev
bind = ALT, mouse_down, cyclenext, prev
bind = ALT , mouse_up, cyclenext, prev
bindel = CTRL ALT, mouse_up, layoutmsg, addmaster
bindel = CTRL ALT, mouse_down, layoutmsg, removemaster
bind = CTRL ALT, right, layoutmsg, colwidth +conf
bind = CTRL ALT, left, layoutmsg, colwidth -conf
# switch layouts
# Hyprscrolling
bind = $mainMod, period, layoutmsg, move +col
bind = $mainMod, comma, layoutmsg, swapcol l
# Column resize
bind = $mainMod SHIFT, period, layoutmsg, colresize +conf
bind = $mainMod SHIFT, comma, layoutmsg, colresize -conf
# Make / break a tab-group (stack)
bind = $mainMod, S, togglegroup
# Cycle tabs in the group
bind = $mainMod, bracketright, changegroupactive, f
bind = $mainMod, bracketleft, changegroupactive, b
bind = $mainMod, T, exec, ~/.config/scripts/layout-selector.sh
# Focus movement
bind = $mainMod, H, movefocus, l
bind = $mainMod, L, movefocus, r
bind = $mainMod, K, movefocus, u
bind = $mainMod, J, movefocus, d
bind = $mainMod, left, movefocus, l
bind = $mainMod, right, movefocus, r
bind = $mainMod, up, movefocus, u
bind = $mainMod, down, movefocus, d
# Move windows
bind = $mainMod SHIFT, H, movewindow, l
bind = $mainMod SHIFT, L, movewindow, r
bind = $mainMod SHIFT, K, movewindow, u
bind = $mainMod SHIFT, J, movewindow, d
bind = $mainMod SHIFT, left, movewindow, l
bind = $mainMod SHIFT, right, movewindow, r
bind = $mainMod SHIFT, up, movewindow, u
bind = $mainMod SHIFT, down, movewindow, d
# Resize windows
bind = $mainMod CTRL, H, resizeactive, -30 0
bind = $mainMod CTRL, L, resizeactive, 30 0
bind = $mainMod CTRL, K, resizeactive, 0 -30
bind = $mainMod CTRL, J, resizeactive, 0 30
# Floating / fullscreen
bind = $mainMod, V, togglefloating,
bind = $mainMod, F, fullscreen, 0
bind = $mainMod SHIFT, F, fullscreen, 1
# Workspaces
bind = $mainMod, 1, workspace, 1
bind = $mainMod, 2, workspace, 2
bind = $mainMod, 3, workspace, 3
bind = $mainMod, 4, workspace, 4
bind = $mainMod, 5, workspace, 5
bind = $mainMod, 6, workspace, 6
bind = $mainMod, 7, workspace, 7
bind = $mainMod, 8, workspace, 8
bind = $mainMod, 9, workspace, 9
bind = $mainMod, 0, workspace, 10
bind = $mainMod SHIFT, 1, movetoworkspace, 1
bind = $mainMod SHIFT, 2, movetoworkspace, 2
bind = $mainMod SHIFT, 3, movetoworkspace, 3
bind = $mainMod SHIFT, 4, movetoworkspace, 4
bind = $mainMod SHIFT, 5, movetoworkspace, 5
bind = $mainMod SHIFT, 6, movetoworkspace, 6
bind = $mainMod SHIFT, 7, movetoworkspace, 7
bind = $mainMod SHIFT, 8, movetoworkspace, 8
bind = $mainMod SHIFT, 9, movetoworkspace, 9
bind = $mainMod SHIFT, 0, movetoworkspace, 10
# Cycle workspaces
bind = $mainMod, mouse_down, workspace, e+1
bind = $mainMod, mouse_up, workspace, e-1
# Mouse drag
bindm = $mainMod, mouse:272, movewindow
bindm = $mainMod, mouse:273, resizewindow
#########################
# Audio (pamixer)
#########################
bind = , XF86AudioRaiseVolume, exec, pamixer -i 5
bind = , XF86AudioLowerVolume, exec, pamixer -d 5
bind = , XF86AudioMute, exec, pamixer -t
bind = , XF86AudioMicMute, exec, pamixer --default-source -t
#########################
# Media (playerctl)
#########################
bind = , XF86AudioPlay, exec, playerctl play-pause
bind = , XF86AudioPause, exec, playerctl pause
bind = , XF86AudioNext, exec, playerctl next
bind = , XF86AudioPrev, exec, playerctl previous
bind = , XF86AudioStop, exec, playerctl stop
#########################
# Brightness (brightnessctl)
#########################
bind = , XF86MonBrightnessUp, exec, brightnessctl set +10%
bind = , XF86MonBrightnessDown, exec, brightnessctl set 10%-
bind = , XF86KbdBrightnessUp, exec, brightnessctl -d '*kbd_backlight*' set +10%
bind = , XF86KbdBrightnessDown, exec, brightnessctl -d '*kbd_backlight*' set 10%-
#########################
# Power / session
#########################
bind = , XF86Sleep, exec, systemctl suspend
bind = , XF86PowerOff, exec, systemctl poweroff
bind = , XF86WakeUp, exec, systemctl suspend
bind = CTRL ALT, L, exec, loginctl lock-session
#########################
# Start apps
#########################
bind = $mainMod, E, exec, thunar
bind = $mainMod, RETURN, exec, kitty
bind = CTRL ALT, B, exec, flatpak run eu.betterbird.Betterbird
bind = CTRL ALT, S, exec, spotify
bind = $mainMod, Z, exec, zeditor
bind = $mainMod, W, exec, zen
bind = CTRL ALT, T, exec, solidtime-desktop
#########################
# Auto apps
#########################
bind = , workspace, exec, ~/.config/scripts/set-workspace-wallpaper.sh
#########################
# System stuff
#########################
bind = $mainMod, U, exec, kitty -e bash -lc "$HOME/.config/scripts/update.sh"
#+END_SRC
** =generated/.config/hypr/exec-once.conf=
These are config files for .config/hypr
#+BEGIN_SRC conf :tangle generated/.config/hypr/exec-once.conf :noweb yes :mkdirp yes :eval never
exec-once = dbus-update-activation-environment --systemd --all
exec-once = hypridle
exec-once = systemd-run --user --scope --unit=elephant elephant
exec-once = waybar
exec-once = awww-daemon
exec-once = awww img ~/Wallpapers/pictures/01.jpg
exec-once = ~/.config/scripts/set-workspace-wallpaper.sh
exec-once = ~/.config/scripts/workspace-listener.sh
exec-once = /run/current-system/sw/libexec/polkit-gnome-authentication-agent-1
exec-once = nextcloud --background
exec-once = dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP
exec-once = flameshot
#+END_SRC
** =generated/.config/hypr/hypridle.conf=
These are config files for .config/hypr
#+BEGIN_SRC conf :tangle generated/.config/hypr/hypridle.conf :noweb yes :mkdirp yes :eval never
general {
lock_cmd = hyprlock
before_sleep_cmd = hyprlock
after_sleep_cmd = hyprctl dispatch dpms on
ignore_dbus_inhibit = false
}
listener {
timeout = 600
on-timeout = hyprlock
}
listener {
timeout = 900
on-timeout = hyprctl dispatch dpms off
on-resume = hyprctl dispatch dpms on
}
listener {
timeout = 1200
on-timeout = systemctl suspend
}
#+END_SRC
** =generated/.config/hypr/hyprlock.conf=
These are config files for .config/hypr
#+BEGIN_SRC conf :tangle generated/.config/hypr/hyprlock.conf :noweb yes :mkdirp yes :eval never
general {
grace = 2
hide_cursor = true
}
background {
monitor =
path = screenshot
blur_passes = 3
blur_size = 8
}
input-field {
monitor =
size = 250, 50
position = 0, -80
outline_thickness = 2
dots_center = true
fade_on_empty = false
}
#+END_SRC
** =generated/.config/hypr/hyprland.conf=
These are config files for .config/hypr
#+BEGIN_SRC conf :tangle generated/.config/hypr/hyprland.conf :noweb yes :mkdirp yes :eval never
source = ./theming.conf
source = ./animations.conf
source = ./bindings.conf
source = ./behaviour.conf
source = ./exec-once.conf
source = ./layer-rules.conf
source = ./layout.conf
source = ./monitor-rules.conf
source = ./window-rules.conf
source = ./workspace-rules.conf
#+END_SRC
** =generated/.config/hypr/layer-rules.conf=
These are config files for .config/hypr
#+BEGIN_SRC conf :tangle generated/.config/hypr/layer-rules.conf :noweb yes :mkdirp yes :eval never
layerrule = blur on, ignore_alpha 1, match:namespace waybar
layerrule = xray 1, match:namespace waybar
#+END_SRC
** =generated/.config/hypr/layout.conf=
These settings control Hyprland config
#+BEGIN_SRC conf :tangle generated/.config/hypr/layout.conf :noweb yes :mkdirp yes :eval never
scrolling {
fullscreen_on_one_column = true
column_width = 0.32 # default: 3 windows side by side
explicit_column_widths = 0.329, 0.5, 0.667, 1.0
}
#+END_SRC
** =generated/.config/hypr/monitor-rules.conf=
These are config files for .config/hypr
#+BEGIN_SRC conf :tangle generated/.config/hypr/monitor-rules.conf :noweb yes :mkdirp yes :eval never
monitor = DP-1, preferred, 0x0, 1
monitor = eDP-1, preferred, auto-left, 1.5
#+END_SRC
** =generated/.config/hypr/theming.conf=
These are config files for .config/hypr
#+BEGIN_SRC conf :tangle generated/.config/hypr/theming.conf :noweb yes :mkdirp yes :eval never
# Hyprland Catppuccin Mocha Theme (solid colors)
# Colors
$base = #1e1e2e
$baseshadow = #1e1e2e99
$mantle = #181825
$surface0 = #313244
$surface1 = #45475a
$surface2 = #585b70
$text = #cdd6f4
$rosewater = #f5e0dc
$lavender = #b4befe
$red = #f38ba8
$peach = #fab387
$yellow = #f9e2af
$green = #a6e3a1
$teal = #94e2d5
$blue = #89b4fa
$mauve = #cba6f7
$flamingo = #f2cdcd
$inactive = #595959aa
# General
general {
gaps_in = 2
gaps_out = 4
border_size = 4
resize_on_border = true
extend_border_grab_area = 20
col.active_border = rgb(89b4fa) rgb(a6e3a1) 45deg
col.inactive_border = rgba(595959aa)
}
# Decorations
decoration {
rounding = 8
shadow {
color = rgba(1e1e2e99)
}
}
# Groups
group {
col.border_active = rgb(89b4fa)
col.border_inactive = rgb(45475a)
col.border_locked_active = rgb(94e2d5)
groupbar {
col.active = rgb(89b4fa)
col.inactive = rgb(45475a)
text_color = rgb(cdd6f4)
}
}
# Misc
misc {
background_color = rgb(1e1e2e)
}
#+END_SRC
** =generated/.config/hypr/window-rules.conf=
These are config files for .config/hypr
#+BEGIN_SRC conf :tangle generated/.config/hypr/window-rules.conf :noweb yes :mkdirp yes :eval never
# Network Manager editor
windowrule {
name = Network-Manager-editor
match:class = nm-connection-editor
float = on
move = move onscreen 100%-w 0
size = 900 700
}
# PulseAudio Volume Control
windowrule {
name = pavucontrol
match:class = org.pulseaudio.pavucontrol
float = on
move = move onscreen 100%-w 0
size = 900 700
}
# Blueman Manager
windowrule {
name = blueman
match:class = .blueman-manager-wrapped
float = on
move = move onscreen 100%-w 0
size = 900 700
}
#Quickshell powermenu
windowrule {
name = quickshell-powermenu
match:title = quickshell-powermenu
opacity = 1.0 0.8
float = on
move = cursor -50% 0
pin = on
}
#Quickshell media menu
windowrule {
name = quickshell-media
match:title = quickshell-media
float = on
move = cursor -50% 0
pin = on
}
# Wofi window rules
# (match: fields do not support $variables, hardcoded intentionally)
windowrule {
name = wofi
match:class = ^(wofi)$
border_color = rgb(89b4fa) rgb(a6e3a1) 45deg
rounding = 14
}
#+END_SRC
** =generated/.config/hypr/workspace-rules.conf=
These setttings configure rules for workspaces
#+BEGIN_SRC conf :tangle generated/.config/hypr/workspace-rules.conf :noweb yes :mkdirp yes :eval never
workspace = 1, monitor:eDP-1, layout:master
workspace = 2, monitor:eDP-1, layout:monocle
workspace = 3, monitor:eDP-1, layout:master
workspace = 4, monitor:DP-1, layout:scrolling
workspace = 5, monitor:DP-1, layout:dwindle
workspace = 6, monitor:DP-1, layout:dwindle
#+END_SRC
** =generated/.config/quickshell/media/shell.qml=
offers a adio widget
#+BEGIN_SRC qml :tangle generated/.config/quickshell/media/shell.qml :noweb yes :mkdirp yes :eval never
import Quickshell
import Quickshell.Io
import QtQuick
import QtQuick.Layouts
ShellRoot {
QtObject {
id: colors
readonly property color baseAlpha: Qt.rgba(30/255, 30/255, 46/255, 0.95)
readonly property color base: "#1e1e2e"
readonly property color surface0: "#313244"
readonly property color surface1: "#45475a"
readonly property color surface2: "#585b70"
readonly property color text: "#cdd6f4"
readonly property color subtext0: "#a6adc8"
readonly property color subtext1: "#bac2de"
readonly property color blue: "#89b4fa"
readonly property color green: "#a6e3a1"
readonly property color teal: "#94e2d5"
readonly property color red: "#f38ba8"
readonly property color mauve: "#cba6f7"
readonly property color peach: "#fab387"
readonly property color lavender: "#b4befe"
}
QtObject {
id: media
property string artist: ""
property string title: ""
property string album: ""
property string artUrl: ""
property string status: ""
property string device: ""
property string player: ""
property real progress: 0.0
property real duration: 0.0
property real position: 0.0
property int shuffleMode: 0
readonly property bool isSpotify: player.indexOf("spotify") !== -1
}
Timer {
interval: 1000
running: true
repeat: true
onTriggered: {
playerProc.running = true
artistProc.running = true
titleProc.running = true
albumProc.running = true
artProc.running = true
statusProc.running = true
positionProc.running = true
lengthProc.running = true
if (media.isSpotify)
shuffleProc.running = true
}
}
Process {
id: playerProc
command: ["playerctl", "-l"]
stdout: StdioCollector {
onStreamFinished: {
var lines = text.trim().split("\n")
for (var i = 0; i < lines.length; i++) {
if (lines[i].indexOf("spotify") !== -1) {
media.player = lines[i].trim()
return
}
}
media.player = lines[0] ? lines[0].trim() : ""
}
}
}
Process {
id: artistProc
command: ["playerctl", "metadata", "artist"]
stdout: StdioCollector { onStreamFinished: media.artist = text.trim() }
}
Process {
id: titleProc
command: ["playerctl", "metadata", "title"]
stdout: StdioCollector { onStreamFinished: media.title = text.trim() }
}
Process {
id: albumProc
command: ["playerctl", "metadata", "album"]
stdout: StdioCollector { onStreamFinished: media.album = text.trim() }
}
Process {
id: artProc
command: ["playerctl", "metadata", "mpris:artUrl"]
stdout: StdioCollector { onStreamFinished: media.artUrl = text.trim() }
}
Process {
id: statusProc
command: ["playerctl", "status"]
stdout: StdioCollector { onStreamFinished: media.status = text.trim() }
}
Process {
id: positionProc
command: ["playerctl", "position"]
stdout: StdioCollector {
onStreamFinished: {
media.position = parseFloat(text.trim()) || 0
if (media.duration > 0)
media.progress = media.position / media.duration
}
}
}
Process {
id: lengthProc
command: ["playerctl", "metadata", "mpris:length"]
stdout: StdioCollector {
onStreamFinished: {
media.duration = (parseFloat(text.trim()) || 0) / 1000000
}
}
}
Process {
id: shuffleProc
command: ["playerctl", "--player=" + media.player, "shuffle"]
stdout: StdioCollector {
onStreamFinished: {
media.shuffleMode = (text.trim() === "On") ? 1 : 0
}
}
}
Process { id: shuffleOnProc; command: ["playerctl", "--player=" + media.player, "shuffle", "on"] }
Process { id: shuffleOffProc; command: ["playerctl", "--player=" + media.player, "shuffle", "off"] }
function cycleShuffleMode() {
var next = (media.shuffleMode + 1) % 2
media.shuffleMode = next
if (next === 0)
shuffleOffProc.running = true
else
shuffleOnProc.running = true
}
// Focus spotify — uses exact lowercase class as reported by hyprctl
Process {
id: focusSpotifyProc
command: ["hyprctl", "dispatch", "focuswindow", "class:^(spotify)$"]
}
function focusPlayer() {
if (media.isSpotify) {
focusSpotifyProc.running = true
}
}
Process { id: prevProc; command: ["playerctl", "previous"] }
Process { id: playProc; command: ["playerctl", "play-pause"] }
Process { id: nextProc; command: ["playerctl", "next"] }
FloatingWindow {
id: root
title: "quickshell-media"
visible: true
implicitWidth: 300
implicitHeight: 420
color: "transparent"
Shortcut {
sequence: "Escape"
onActivated: Qt.quit()
}
// Gradient border — hidden when app has focus
Rectangle {
anchors.fill: parent
anchors.margins: -2
radius: 18
z: -1
opacity: Qt.application.active ? 0 : 1
Behavior on opacity {
NumberAnimation { duration: 150 }
}
gradient: Gradient {
orientation: Gradient.Horizontal
GradientStop { position: 0.0; color: colors.blue }
GradientStop { position: 1.0; color: colors.green }
}
}
Rectangle {
anchors.fill: parent
radius: 16
color: colors.base
ColumnLayout {
anchors {
fill: parent
margins: 16
}
spacing: 12
// Album art — click to focus player
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 200
radius: 12
color: colors.surface0
clip: true
Image {
anchors.fill: parent
source: media.artUrl
fillMode: Image.PreserveAspectCrop
visible: media.artUrl !== ""
}
Text {
anchors.centerIn: parent
text: "󰝚"
font.pixelSize: 48
color: colors.surface2
visible: media.artUrl === ""
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: focusPlayer()
}
}
// Artist
Text {
Layout.fillWidth: true
text: media.artist || "Unknown artist"
color: colors.subtext1
font.pixelSize: 12
elide: Text.ElideRight
}
// Title
Text {
Layout.fillWidth: true
text: media.title || "Nothing playing"
color: colors.text
font.pixelSize: 14
font.bold: true
elide: Text.ElideRight
}
// Album
Text {
Layout.fillWidth: true
text: media.album
color: colors.subtext0
font.pixelSize: 11
elide: Text.ElideRight
visible: media.album !== ""
}
// Device (Spotify)
Text {
Layout.fillWidth: true
text: "󰓻 " + media.device
color: colors.green
font.pixelSize: 11
visible: media.device !== ""
}
// Progress bar
Rectangle {
Layout.fillWidth: true
height: 4
radius: 2
color: colors.surface1
Rectangle {
width: parent.width * media.progress
height: parent.height
radius: parent.radius
gradient: Gradient {
orientation: Gradient.Horizontal
GradientStop { position: 0.0; color: colors.blue }
GradientStop { position: 1.0; color: colors.green }
}
}
}
// Time
RowLayout {
Layout.fillWidth: true
Text {
text: {
var m = Math.floor(media.position / 60)
var s = Math.floor(media.position % 60)
return m + ":" + (s < 10 ? "0" + s : s)
}
color: colors.subtext0
font.pixelSize: 11
}
Item { Layout.fillWidth: true }
Text {
text: {
var m = Math.floor(media.duration / 60)
var s = Math.floor(media.duration % 60)
return m + ":" + (s < 10 ? "0" + s : s)
}
color: colors.subtext0
font.pixelSize: 11
}
}
// Playback controls + shuffle
RowLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
spacing: 20
// Shuffle button (Spotify only)
Item {
visible: media.isSpotify
width: 28
height: 28
Text {
anchors.centerIn: parent
text: "󰒟"
font.pixelSize: 18
color: media.shuffleMode === 0 ? colors.surface2 : colors.blue
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: cycleShuffleMode()
}
}
Text {
text: "󰒮"
font.pixelSize: 22
color: prevHover.containsMouse ? colors.blue : colors.text
MouseArea {
id: prevHover
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: prevProc.running = true
}
}
Text {
text: media.status === "Playing" ? "󰏤" : "󰐊"
font.pixelSize: 28
color: playHover.containsMouse ? colors.green : colors.text
MouseArea {
id: playHover
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: playProc.running = true
}
}
Text {
text: "󰒭"
font.pixelSize: 22
color: nextHover.containsMouse ? colors.blue : colors.text
MouseArea {
id: nextHover
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: nextProc.running = true
}
}
}
}
}
}
}
#+END_SRC
** =generated/.config/quickshell/powermenu/shell.qml=
Provides a powermenu
#+BEGIN_SRC qml :tangle generated/.config/quickshell/powermenu/shell.qml :noweb yes :mkdirp yes :eval never
import Quickshell
import Quickshell.Io
import QtQuick
import QtQuick.Layouts
ShellRoot {
QtObject {
id: colors
readonly property color baseAlpha: Qt.rgba(30/255, 30/255, 46/255, 0.9)
readonly property color base: "#1e1e2e"
readonly property color surface0: "#313244"
readonly property color surface1: "#45475a"
readonly property color surface2: "#585b70"
readonly property color text: "#cdd6f4"
readonly property color subtext0: "#a6adc8"
readonly property color subtext1: "#bac2de"
readonly property color blue: "#89b4fa"
readonly property color green: "#a6e3a1"
readonly property color teal: "#94e2d5"
readonly property color red: "#f38ba8"
readonly property color mauve: "#cba6f7"
readonly property color peach: "#fab387"
readonly property color lavender: "#b4befe"
}
FloatingWindow {
id: root
title: "quickshell-powermenu"
visible: true
width: 220
height: contentLayout.implicitHeight + 32
color: colors.base
Shortcut {
sequence: "Escape"
onActivated: Qt.quit()
}
// Gradient border — hidden when app has focus
Rectangle {
anchors.fill: parent
anchors.margins: -2
radius: 18
z: -1
opacity: Qt.application.active ? 0 : 1
Behavior on opacity {
NumberAnimation { duration: 150 }
}
gradient: Gradient {
orientation: Gradient.Horizontal
GradientStop { position: 0.0; color: colors.blue }
GradientStop { position: 1.0; color: colors.green }
}
}
Rectangle {
anchors.fill: parent
radius: 16
color: colors.base
ColumnLayout {
id: contentLayout
anchors {
top: parent.top
left: parent.left
right: parent.right
margins: 16
}
spacing: 4
Text {
text: " Power Menu"
color: colors.text
font.pixelSize: 13
font.bold: true
Layout.bottomMargin: 8
}
Repeater {
model: [
{ label: "󰌾 Lock", cmd: ["hyprlock"] },
{ label: "󰐥 Shutdown", cmd: ["systemctl", "poweroff"] },
{ label: "󰑙 Reboot", cmd: ["systemctl", "reboot"] },
{ label: "󰍃 Logout", cmd: ["bash", "-c", "loginctl terminate-session $XDG_SESSION_ID"] },
{ label: "󰒲 Hibernate", cmd: ["systemctl", "hibernate"] },
{ label: "󰤄 Suspend", cmd: ["systemctl", "suspend"] },
]
delegate: Rectangle {
id: item
Layout.fillWidth: true
height: 38
radius: 8
color: hovered ? colors.surface1 : colors.base
property bool hovered: false
Rectangle {
anchors.fill: parent
anchors.margins: -2
radius: parent.radius + 2
visible: item.hovered
z: -1
gradient: Gradient {
orientation: Gradient.Horizontal
GradientStop { position: 0.0; color: colors.blue }
GradientStop { position: 1.0; color: colors.green }
}
}
Text {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 12
text: modelData.label
color: item.hovered ? colors.text : colors.subtext1
font.pixelSize: 13
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: item.hovered = true
onExited: item.hovered = false
onClicked: proc.running = true
}
Process {
id: proc
command: modelData.cmd
onExited: Qt.quit()
}
}
}
Item { height: 4 }
}
}
}
}
#+END_SRC
** =generated/.config/scripts/batterywarn.sh=
Providing an media
#+BEGIN_SRC sh :tangle generated/.config/scripts/batterywarn.sh :shebang "#!/usr/bin/env bash" :noweb yes :mkdirp yes :eval never
capacity=$(cat /sys/class/power_supply/BAT*/capacity)
status=$(cat /sys/class/power_supply/BAT*/status)
if [ "$status" != "Charging" ] && [ "$capacity" -lt 15 ]; then
echo " $capacity%"
else
echo ""
fi
#+END_SRC
** =generated/.config/scripts/media.sh=
Providing an media
#+BEGIN_SRC sh :tangle generated/.config/scripts/media.sh :shebang "#!/usr/bin/env bash" :noweb yes :mkdirp yes :eval never
# Player selection — prefer actively playing player
player=$(playerctl -l 2>/dev/null | while read -r p; do
st=$(playerctl --player="$p" status 2>/dev/null)
[ "$st" = "Playing" ] && echo "$p" && break
done)
[ -z "$player" ] && player=$(playerctl -l 2>/dev/null | head -n1)
if [ -z "$player" ]; then
jq -c -n '{text: "", tooltip: "", class: "inactive"}'
exit 0
fi
status=$(playerctl --player="$player" status 2>/dev/null)
if [ "$status" != "Playing" ] && [ "$status" != "Paused" ]; then
jq -c -n '{text: "", tooltip: "", class: "inactive"}'
exit 0
fi
artist=$(playerctl --player="$player" metadata artist 2>/dev/null)
title=$(playerctl --player="$player" metadata title 2>/dev/null)
album=$(playerctl --player="$player" metadata album 2>/dev/null)
art=$(playerctl --player="$player" metadata mpris:artUrl 2>/dev/null)
length=$(playerctl --player="$player" metadata mpris:length 2>/dev/null)
position=$(playerctl --player="$player" position 2>/dev/null)
# Progress percentage — pure bash, no bc needed
if [ -n "$length" ] && [ -n "$position" ] && [ "$length" -gt 0 ] 2>/dev/null; then
pos_us=$(echo "$position" | awk '{printf "%d", $1 * 1000000}')
progress=$(( pos_us * 100 / length ))
else
progress=0
fi
# Spotify device
device=""
if [[ "$player" == *"spotify"* ]]; then
device=$(playerctl --player="$player" metadata xesam:url 2>/dev/null | grep -o 'device=[^&]*' | cut -d= -f2)
fi
# Icon
if [ "$status" = "Paused" ]; then
icon="⏸ "
else
icon="▶ "
fi
# Scrolling ticker
CACHE_FILE="/tmp/waybar_media_scroll_${player//\//_}"
full_text="${artist} — ${title}"
text_len=${#full_text}
display_len=30
# Reset scroll offset when track changes
TRACK_FILE="/tmp/waybar_media_track_${player//\//_}"
last_track=""
[ -f "$TRACK_FILE" ] && last_track=$(cat "$TRACK_FILE")
if [ "$full_text" != "$last_track" ]; then
echo "0" > "$CACHE_FILE"
echo "$full_text" > "$TRACK_FILE"
fi
if [ "$text_len" -le "$display_len" ]; then
text="$full_text"
else
offset=0
[ -f "$CACHE_FILE" ] && offset=$(cat "$CACHE_FILE")
padded="${full_text} ${full_text}"
text="${padded:$offset:$display_len}"
next_offset=$(( (offset + 1) % (text_len + 4) ))
echo "$next_offset" > "$CACHE_FILE"
fi
# Build tooltip
tooltip="Artist: ${artist}
Title: ${title}
Album: ${album}"
if [ -n "$device" ]; then
tooltip="${tooltip}
󰓻 ${device}"
fi
tooltip="${tooltip}"
jq -c -n \
--arg text "${icon}${text}" \
--arg tooltip "$tooltip" \
--arg class "$player" \
--arg art "$art" \
'{text: $text, tooltip: $tooltip, class: $class, alt: $art}'
#+END_SRC
** =generated/.config/scripts/layout-selector.sh=
Choose your layout
#+BEGIN_SRC bash :tangle generated/.config/scripts/layout-selector.sh :shebang "#!/usr/bin/env bash" :noweb yes :mkdirp yes :eval never
# layout-selector.sh
# Select a workspace layout using Wofi, shows description, applies with layoutmsg
# Define layouts and descriptions
declare -A LAYOUTS=(
[dwindle]="舘 Dwindle: Auto-tiling, windows shrink progressively"
[master]=" Master: One main window, others stacked"
[scrolling]=" Scrolling: Vertical list, scroll through windows"
[monocle]=" Monocle: One window fills the screen"
[floating]=" Floating: Free move & resize"
)
ORDER=(dwindle master scrolling monocle floating)
# Prepare Wofi menu: show "layoutname: description"
MENU_ITEMS=()
for key in "${ORDER[@]}"; do
MENU_ITEMS+=("$key: ${LAYOUTS[$key]}")
done
# Show selection menu via Wofi
CHOICE=$(printf '%s\n' "${MENU_ITEMS[@]}" | wofi --dmenu --prompt "Select Layout")
# Exit if cancelled
[ -z "$CHOICE" ] && exit 0
# Extract layout name from selection (before colon)
LAYOUT_NAME="${CHOICE%%:*}"
# Apply layout via layoutmsg
hyprctl dispatch layoutmsg setlayout "$LAYOUT_NAME"
# Show OSD feedback
hyprctl dispatch oSD "Layout: $LAYOUT_NAME" 2000
#+END_SRC
** =generated/.config/scripts/power.sh=
Enables a terminal power menu
#+BEGIN_SRC sh :tangle generated/.config/scripts/power.sh :shebang "#!/usr/bin/env bash" :noweb yes :mkdirp yes :eval never
#
# Launch a power menu
#
# Requires fzf and systemd (loginctl, systemctl)
#
# Author: Jesse Mirabel <sejjymvm@gmail.com>
# Date: August 19, 2025
# License: MIT
main() {
local list=(
"󰌾 Lock"
"󰐥 Shutdown"
"󰑙 Reboot"
"󰍃 Logout"
"󰒲 Hibernate"
"󰤄 Suspend"
)
local options=(
"--border=sharp"
"--border-label= Power Menu "
"--cycle"
"--ghost=Search"
"--height=~100%"
"--highlight-line"
"--info=inline-right"
"--pointer="
"--reverse"
)
local selected
selected=$(printf "%s\n" "${list[@]}" | fzf "${options[@]}")
case $selected in
Lock) loginctl lock-session ;;
Shutdown) systemctl poweroff ;;
Reboot) systemctl reboot ;;
Logout) loginctl terminate-session "$XDG_SESSION_ID" ;;
Hibernate) systemctl hibernate ;;
Suspend) systemctl suspend ;;
*) return 1 ;;
esac
}
main
#+END_SRC
** =generated/.config/scripts/update.sh=
A file containing color variables
#+BEGIN_SRC sh :tangle generated/.config/scripts/update.sh :shebang "#!/usr/bin/env bash" :noweb yes :mkdirp yes :eval never
set -e
REPO="/home/$USER/Repos/nixos/Droidnix"
HOSTNAME="$(hostname)"
cd "$REPO"
echo "🔧 Fixing ownership..."
sudo chown "$USER":"$USER" flake.lock 2>/dev/null || true
echo "🔄 Updating flake..."
nix flake update
echo "🏗 Rebuilding NixOS..."
sudo nixos-rebuild switch --flake ".#$HOSTNAME"
echo "📦 Updating Flatpaks..."
flatpak update -y
#+END_SRC
** =generated/.config/scripts/wofi-launcher.sh=
Providing an media
#+BEGIN_SRC sh :tangle generated/.config/scripts/wofi-launcher.sh :shebang "#!/usr/bin/env bash" :noweb yes :mkdirp yes :eval never
wofi --show drun \
--style ~/.config/wofi/style.css \
--no-actions \
--allow-images=false \
--columns 1 \
--prompt "Apps ..."
#+END_SRC
** =generated/.config/shared/colors.css=
A file containing color variables
#+BEGIN_SRC css :tangle generated/.config/shared/colors.css :noweb yes :mkdirp yes :eval never
/* Catppuccin Mocha Palette */
@define-color crust #11111b;
@define-color mantle #181825;
@define-color base #1e1e2e;
@define-color base-alpha rgba(30, 30, 46, 0.9);
@define-color surface0 #313244;
@define-color surface1 #45475a;
@define-color surface2 #585b70;
@define-color overlay0 #6c7086;
@define-color overlay1 #7f849c;
@define-color overlay2 #9399b2;
@define-color subtext0 #a6adc8;
@define-color subtext1 #bac2de;
@define-color text #cdd6f4;
@define-color rosewater #f5e0dc;
@define-color flamingo #f2cdcd;
@define-color pink #f5c2e7;
@define-color mauve #cba6f7;
@define-color red #f38ba8;
@define-color maroon #eba0ac;
@define-color peach #fab387;
@define-color yellow #f9e2af;
@define-color green #a6e3a1;
@define-color teal #94e2d5;
@define-color sapphire #74c7ec;
@define-color blue #89b4fa;
@define-color lavender #b4befe;
#+END_SRC
** =generated/.config/starship.toml=
These are config files for Starship
#+BEGIN_SRC toml :tangle generated/.config/starship.toml :noweb yes :mkdirp yes :eval never
"$schema" = 'https://starship.rs/config-schema.json'
format = """
[](red)\
$os\
$username\
[](bg:peach fg:red)\
$directory\
[](bg:yellow fg:peach)\
$git_branch\
$git_status\
[](fg:yellow bg:green)\
$c\
$rust\
$golang\
$nodejs\
$php\
$java\
$kotlin\
$haskell\
$python\
[](fg:green bg:sapphire)\
$conda\
[](fg:sapphire bg:lavender)\
$time\
[ ](fg:lavender)\
$cmd_duration\
$line_break\
$character"""
palette = 'catppuccin_mocha'
[os]
disabled = false
style = "bg:red fg:crust"
[os.symbols]
Windows = ""
Ubuntu = "󰕈"
SUSE = ""
Raspbian = "󰐿"
Mint = "󰣭"
Macos = "󰀵"
Manjaro = ""
Linux = "󰌽"
Gentoo = "󰣨"
Fedora = "󰣛"
Alpine = ""
Amazon = ""
Android = ""
AOSC = ""
Arch = "󰣇"
Artix = "󰣇"
CentOS = ""
Debian = "󰣚"
Redhat = "󱄛"
RedHatEnterprise = "󱄛"
[username]
show_always = true
style_user = "bg:red fg:crust"
style_root = "bg:red fg:crust"
format = '[ $user]($style)'
[directory]
style = "bg:peach fg:crust"
format = "[ $path ]($style)"
truncation_length = 3
truncation_symbol = "…/"
[directory.substitutions]
"Documents" = "󰈙 "
"Downloads" = " "
"Music" = "󰝚 "
"Pictures" = " "
"Developer" = "󰲋 "
[git_branch]
symbol = ""
style = "bg:yellow"
format = '[[ $symbol $branch ](fg:crust bg:yellow)]($style)'
[git_status]
style = "bg:yellow"
format = '[[($all_status$ahead_behind )](fg:crust bg:yellow)]($style)'
[nodejs]
symbol = ""
style = "bg:green"
format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
[c]
symbol = " "
style = "bg:green"
format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
[rust]
symbol = ""
style = "bg:green"
format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
[golang]
symbol = ""
style = "bg:green"
format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
[php]
symbol = ""
style = "bg:green"
format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
[java]
symbol = " "
style = "bg:green"
format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
[kotlin]
symbol = ""
style = "bg:green"
format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
[haskell]
symbol = ""
style = "bg:green"
format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
[python]
symbol = ""
style = "bg:green"
format = '[[ $symbol( $version)(\(#$virtualenv\)) ](fg:crust bg:green)]($style)'
[docker_context]
symbol = ""
style = "bg:sapphire"
format = '[[ $symbol( $context) ](fg:crust bg:sapphire)]($style)'
[conda]
symbol = "  "
style = "fg:crust bg:sapphire"
format = '[$symbol$environment ]($style)'
ignore_base = false
[time]
disabled = false
time_format = "%R"
style = "bg:lavender"
format = '[[  $time ](fg:crust bg:lavender)]($style)'
[line_break]
disabled = false
[character]
disabled = false
success_symbol = '[](bold fg:green)'
error_symbol = '[](bold fg:red)'
vimcmd_symbol = '[](bold fg:green)'
vimcmd_replace_one_symbol = '[](bold fg:lavender)'
vimcmd_replace_symbol = '[](bold fg:lavender)'
vimcmd_visual_symbol = '[](bold fg:yellow)'
[cmd_duration]
show_milliseconds = true
format = " in $duration "
style = "bg:lavender"
disabled = false
show_notifications = true
min_time_to_notify = 45000
[palettes.catppuccin_mocha]
rosewater = "#f5e0dc"
flamingo = "#f2cdcd"
pink = "#f5c2e7"
mauve = "#cba6f7"
red = "#f38ba8"
maroon = "#eba0ac"
peach = "#fab387"
yellow = "#f9e2af"
green = "#a6e3a1"
teal = "#94e2d5"
sky = "#89dceb"
sapphire = "#74c7ec"
blue = "#89b4fa"
lavender = "#b4befe"
text = "#cdd6f4"
subtext1 = "#bac2de"
subtext0 = "#a6adc8"
overlay2 = "#9399b2"
overlay1 = "#7f849c"
overlay0 = "#6c7086"
surface2 = "#585b70"
surface1 = "#45475a"
surface0 = "#313244"
base = "#1e1e2e"
mantle = "#181825"
crust = "#11111b"
[palettes.catppuccin_frappe]
rosewater = "#f2d5cf"
flamingo = "#eebebe"
pink = "#f4b8e4"
mauve = "#ca9ee6"
red = "#e78284"
maroon = "#ea999c"
peach = "#ef9f76"
yellow = "#e5c890"
green = "#a6d189"
teal = "#81c8be"
sky = "#99d1db"
sapphire = "#85c1dc"
blue = "#8caaee"
lavender = "#babbf1"
text = "#c6d0f5"
subtext1 = "#b5bfe2"
subtext0 = "#a5adce"
overlay2 = "#949cbb"
overlay1 = "#838ba7"
overlay0 = "#737994"
surface2 = "#626880"
surface1 = "#51576d"
surface0 = "#414559"
base = "#303446"
mantle = "#292c3c"
crust = "#232634"
[palettes.catppuccin_latte]
rosewater = "#dc8a78"
flamingo = "#dd7878"
pink = "#ea76cb"
mauve = "#8839ef"
red = "#d20f39"
maroon = "#e64553"
peach = "#fe640b"
yellow = "#df8e1d"
green = "#40a02b"
teal = "#179299"
sky = "#04a5e5"
sapphire = "#209fb5"
blue = "#1e66f5"
lavender = "#7287fd"
text = "#4c4f69"
subtext1 = "#5c5f77"
subtext0 = "#6c6f85"
overlay2 = "#7c7f93"
overlay1 = "#8c8fa1"
overlay0 = "#9ca0b0"
surface2 = "#acb0be"
surface1 = "#bcc0cc"
surface0 = "#ccd0da"
base = "#eff1f5"
mantle = "#e6e9ef"
crust = "#dce0e8"
[palettes.catppuccin_macchiato]
rosewater = "#f4dbd6"
flamingo = "#f0c6c6"
pink = "#f5bde6"
mauve = "#c6a0f6"
red = "#ed8796"
maroon = "#ee99a0"
peach = "#f5a97f"
yellow = "#eed49f"
green = "#a6da95"
teal = "#8bd5ca"
sky = "#91d7e3"
sapphire = "#7dc4e4"
blue = "#8aadf4"
lavender = "#b7bdf8"
text = "#cad3f5"
subtext1 = "#b8c0e0"
subtext0 = "#a5adcb"
overlay2 = "#939ab7"
overlay1 = "#8087a2"
overlay0 = "#6e738d"
surface2 = "#5b6078"
surface1 = "#494d64"
surface0 = "#363a4f"
base = "#24273a"
mantle = "#1e2030"
crust = "#181926"
#+END_SRC
** =generated/.config/stylix/stylix.conf=
These are config files for .config/stylix
#+BEGIN_SRC conf :tangle generated/.config/stylix/stylix.conf :noweb yes :mkdirp yes :eval never
enable = true;
base16Scheme = ../../../assets/system/theming/stylix/catppuccin-mocha.yaml;
image = ../../../assets/hyprland/wallpaperstuff/pictures/wall1.jpg;
polarity = "dark";
cursor = {
package = "phinger-cursors"; # symbolic reference
name = "phinger-cursors-light";
size = 24;
};
fonts = {
monospace = {
package = "nerd-fonts-fira-code";
name = "Fira Code Nerd Font";
};
sansSerif = {
package = "lato";
name = "Lato";
};
};
icons = {
enable = true;
package = "papirus-icon-theme";
dark = "Papirus-Dark";
light = "Papirus-Light";
};
#+END_SRC
** =generated/.config/stylix/palette.json=
These are config files for .config/stylix
#+BEGIN_SRC json :tangle generated/.config/stylix/palette.json :noweb yes :mkdirp yes :eval never
{
"base00": "1e1e2e",
"base01": "181825",
"base02": "313244",
"base03": "45475a",
"base04": "585b70",
"base05": "cdd6f4",
"base06": "f5e0dc",
"base07": "b4befe",
"base08": "f38ba8",
"base09": "fab387",
"base0A": "f9e2af",
"base0B": "a6e3a1",
"base0C": "94e2d5",
"base0D": "89b4fa",
"base0E": "cba6f7",
"base0F": "f2cdcd",
"author": "https://github.com/catppuccin/catppuccin",
"scheme": "Catppuccin Mocha",
"slug": "catppuccin-mocha"
}
#+END_SRC
** =generated/.config/stylix/palette.html=
These are config files for .config/stylix
#+BEGIN_SRC html :tangle generated/.config/stylix/palette.html :noweb yes :mkdirp yes :eval never
<html>
<head>
<style>
body {
margin: 2rem;
font-family: sans-serif;
}
body > div {
display: flex;
flex-direction: row;
flex-leader: wrap;
gap: 1em;
}
body > div > div {
width: 5rem;
height: 5rem;
display: flex;
justify-content: center;
align-items: center;
}
#base00 { background-color: #1e1e2e; color: #cdd6f4; }
#base01 { background-color: #181825; color: #cdd6f4; }
#base02 { background-color: #313244; color: #cdd6f4; }
#base03 { background-color: #45475a; color: #1e1e2e; }
#base04 { background-color: #585b70; color: #1e1e2e; }
#base05 { background-color: #cdd6f4; color: #1e1e2e; }
#base06 { background-color: #f5e0dc; color: #1e1e2e; }
#base07 { background-color: #b4befe; color: #1e1e2e; }
#base08 { background-color: #f38ba8; color: #1e1e2e; }
#base09 { background-color: #fab387; color: #1e1e2e; }
#base0A { background-color: #f9e2af; color: #1e1e2e; }
#base0B { background-color: #a6e3a1; color: #1e1e2e; }
#base0C { background-color: #94e2d5; color: #1e1e2e; }
#base0D { background-color: #89b4fa; color: #1e1e2e; }
#base0E { background-color: #cba6f7; color: #1e1e2e; }
#base0F { background-color: #f2cdcd; color: #1e1e2e; }
</style>
</head>
<body>
<h2>Primary colors</h2>
<div>
<div id="base00">00</div>
<div id="base01">01</div>
<div id="base02">02</div>
<div id="base03">03</div>
<div id="base04">04</div>
<div id="base05">05</div>
<div id="base06">06</div>
<div id="base07">07</div>
</div>
<h2>Accents</h2>
<div>
<div id="base08">08</div>
<div id="base09">09</div>
<div id="base0A">0A</div>
<div id="base0B">0B</div>
<div id="base0C">0C</div>
<div id="base0D">0D</div>
<div id="base0E">0E</div>
<div id="base0F">0F</div>
</div>
<h2>Documentation</h2>
<p>Each color should be used as described in <a href="https://github.com/chriskempson/base16/blob/main/styling.md#styling-guidelines"> this table</a>.</p>
<p>See the <a href="https://nix-community.github.io/stylix">Stylix documentation</a> for how to apply these colors on NixOS.</p>
</body>
</html>
#+END_SRC
** =generated/.config/swaync/config.json=
These are config files for waybar
#+BEGIN_SRC json :tangle generated/.config/swaync/config.json :noweb yes :mkdirp yes :eval never
{
"positionX": "right",
"positionY": "top",
"layer": "overlay",
"control-center-layer": "top",
"layer-shell": true,
"cssPriority": "application",
"control-center-margin-top": 8,
"control-center-margin-bottom": 8,
"control-center-margin-right": 8,
"control-center-margin-left": 0,
"notification-2fa-action": true,
"notification-inline-replies": false,
"notification-icon-size": 48,
"notification-body-image-height": 100,
"notification-body-image-width": 200,
"timeout": 10,
"timeout-low": 5,
"timeout-critical": 0,
"fit-to-screen": false,
"control-center-height": -1,
"control-center-width": 300,
"notification-window-width": 400,
"keyboard-shortcuts": true,
"image-visibility": "when-available",
"transition-time": 200,
"hide-on-clear": false,
"hide-on-action": true,
"script-fail-notify": true,
"widgets": [
"inhibitors",
"title",
"dnd",
"notifications"
],
"widget-config": {
"inhibitors": {
"text": "Inhibitors",
"button-text": "Clear All",
"clear-all-button": true
},
"title": {
"text": "Notifications",
"clear-all-button": true,
"button-text": "Clear All"
},
"dnd": {
"text": "Do Not Disturb"
},
"notifications": {}
}
}
#+END_SRC
** =generated/.config/swaync/style.css=
These are config files for waybar
#+BEGIN_SRC css :tangle generated/.config/swaync/style.css :noweb yes :mkdirp yes :eval never
@import url("/home/henrov/.config/shared/colors.css");
* {
all: unset;
font-size: 13px;
font-family: sans-serif;
transition: 200ms;
}
/* ── Notification rows ─────────────────────────────────────────────────── */
.notification-row {
outline: none;
margin: 4px 0;
}
.notification-row:focus,
.notification-row:hover {
opacity: 0.85;
}
/* ── Individual notification ───────────────────────────────────────────── */
.notification {
border-radius: 12px;
padding: 8px;
margin: 4px 8px;
color: @text;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
/* gradient border */
border: 1px solid transparent;
background-image:
linear-gradient(@base-alpha, @base-alpha),
linear-gradient(45deg, @blue, @green);
background-clip: padding-box, border-box;
background-origin: padding-box, border-box;
}
.notification-content {
padding: 4px;
}
.notification-default-action {
border-radius: 12px;
}
.notification-default-action:hover {
background: alpha(@blue, 0.1);
}
/* ── Text elements ─────────────────────────────────────────────────────── */
.summary {
font-size: 13px;
font-weight: bold;
color: @text;
}
.time {
font-size: 11px;
color: @overlay0;
}
.body {
font-size: 12px;
color: @subtext1;
}
/* ── Control center ────────────────────────────────────────────────────── */
.control-center {
border-radius: 16px;
padding: 8px;
margin: 8px;
color: @text;
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.5);
/* gradient border */
border: 1px solid transparent;
background-image:
linear-gradient(@base, @base), /* ← was @mantle, @mantle */
linear-gradient(45deg, @blue, @green);
background-clip: padding-box, border-box;
background-origin: padding-box, border-box;
}
.control-center-list {
background: transparent;
}
.control-center-list-placeholder {
opacity: 0.4;
font-size: 14px;
}
/* ── Misc windows ──────────────────────────────────────────────────────── */
.floating-notifications {
background: transparent;
}
.blank-window {
background: transparent;
}
/* ── Widget: title ─────────────────────────────────────────────────────── */
.widget-title {
font-size: 14px;
font-weight: bold;
color: @blue;
padding: 8px 4px 4px 4px;
}
.widget-title > button {
font-size: 12px;
color: @overlay0;
background: alpha(@blue, 0.1);
border-radius: 8px;
padding: 2px 8px;
}
.widget-title > button:hover {
background: alpha(@blue, 0.2);
color: @text;
}
/* ── Widget: Do Not Disturb ────────────────────────────────────────────── */
.widget-dnd {
padding: 4px;
}
.widget-dnd > switch {
border-radius: 20px;
background: alpha(@surface1, 0.3);
/* gradient border */
border: 1px solid transparent;
background-image:
linear-gradient(alpha(@surface1, 0.3), alpha(@surface1, 0.3)),
linear-gradient(45deg, @blue, @green);
background-clip: padding-box, border-box;
background-origin: padding-box, border-box;
}
.widget-dnd > switch:checked {
background-image:
linear-gradient(alpha(@blue, 0.5), alpha(@blue, 0.5)),
linear-gradient(45deg, @blue, @green);
background-clip: padding-box, border-box;
background-origin: padding-box, border-box;
}
.widget-dnd > switch slider {
border-radius: 20px;
background: @text;
min-width: 20px;
min-height: 20px;
}
/* ── Widget: inhibitors ────────────────────────────────────────────────── */
.widget-inhibitors {
padding: 4px;
color: @red;
font-size: 12px;
}
/* ── Close button ──────────────────────────────────────────────────────── */
.close-button {
background: alpha(@red, 0.15);
border-radius: 6px;
color: @red;
padding: 2px 6px;
font-size: 11px;
}
.close-button:hover {
background: alpha(@red, 0.3);
}
#+END_SRC
** =generated/.config/waybar/config.jsonc=
These are config files for waybar
#+BEGIN_SRC json :tangle generated/.config/waybar/config.jsonc :noweb yes :mkdirp yes :eval never
{
"layer": "top",
"position": "top",
"autohide": true,
"autohide-blocked": false,
"exclusive": true,
"passthrough": false,
"gtk-layer-shell": true,
/*******************************************************************/
"modules-left": [
"group/connections"
,"group/hardware"
],
"modules-center": [
"group/workspaces"
,"custom/power"
,"custom/media"
,"custom/batterywarn"
/* ,"custom/kdeconnect" */
],
"modules-right": [
"group/audio"
,"tray"
,"clock"
,"idle_inhibitor"
,"custom/notifications"
],
/*******************************************************************/
"group/workspaces": {
"orientation": "horizontal",
"modules": [
"hyprland/workspaces",
"custom/windows"
]
},
/*******************************************************************/
"group/hardware": {
"orientation": "horizontal",
"drawer": {
"transition-duration": 500,
"transition-left-to-right": true
},
"modules": [
"custom/hardware-anchor",
"battery",
"cpu",
"memory",
"temperature"
]
},
"custom/hardware-anchor": {
"format": " ",
"tooltip": false
},
/*************************/
"group/connections": {
"orientation": "horizontal",
"drawer": {
"transition-duration": 500,
"transition-left-to-right": true
},
"modules": [
"custom/connections-anchor",
"custom/bluetooth",
"network"
]
},
"custom/connections-anchor": {
"format": " ",
"tooltip": false
},
/*************************/
"group/audio": {
"orientation": "horizontal",
"modules": [
/* "custom/media", */
"pulseaudio",
"pulseaudio/slider",
]
},
/*******************************************************************/
"hyprland/workspaces": {
"align": 1,
"format": "{name}",
"interval": 2,
},
"custom/windows": {
"align": 0,
"format": "{text}",
"exec": "~/.config/scripts/hypr-workspaces.sh",
"interval": 2,
"return-type": "json",
"on-click": "~/.config/scripts/hypr-workspacesmenu.sh",
"tooltip": true
},
"custom/media": {
"exec": "~/.config/scripts/media.sh",
"interval": 1,
"return-type": "json",
"format": "{}",
"on-click": "qs -c media",
"max-length": 20,
"scroll-step": 1,
"tooltip": true
},
"custom/bluetooth": {
"exec": "~/.config/scripts/bluetooth-status.sh",
"interval": 5,
"return-type": "json",
"on-click": "blueman-manager",
"format": "{}"
},
"custom/batterywarn": {
"exec": "~/.config/scripts/batterywarn.sh",
"interval": 60,
"format": "{}"
},
"custom/kdeconnect": {
"format": "{name} {battery}% ",
"interval": 10,
"exec": "~/.config/scripts/kdeconnect-status.sh",
"tooltip": true
},
"custom/notifications": {
"tooltip": false,
"return-type": "json",
"exec-if": "which swaync-client",
"exec": "swaync-client -swb",
"format": "{icon}",
"format-icons": {
"notification": "",
"none": "",
"dnd-notification": "󰂠",
"dnd-none": "󰪓",
},
"on-click": "swaync-client -t",
"on-click-right": "swaync-client -d",
"on-click-middle": "swaync-client -dn",
},
"custom/power": {
"format": "󰤄",
"on-click": "qs -c powermenu",
"tooltip-format": "Power Menu"
},
"pulseaudio": {
"format": "{volume}% {icon}",
"format-bluetooth": "{volume}% {icon}",
"format-muted": "",
"format-icons": {
"headphones": "",
"headset": "",
"phone": "",
"portable": "",
"default": ["", ""]
},
"on-click": "pavucontrol"
},
"pulseaudio/slider": {
"min": 0,
"max": 100,
"orientation": "horizontal"
},
"idle_inhibitor": {
"tooltip": true,
"format": "{icon}",
"format-icons": {
"activated": "  ",
"deactivated": " 󰒲 "
},
"tooltip-format-activated": "Staying awake",
"tooltip-format-deactivated": "Might sleep...."
},
"network": {
"format-wifi": " ({bandwidthDownBits})",
"format-ethernet": " ({bandwidthDownBits})",
"format-disconnected": "Disconnected ⚠",
"tooltip-format-wifi": "{essid} ({signalStrength}%)",
"tooltip-format-ethernet": "{ifname}: {ipaddr}/{cidr}",
"on-click": "networkmanager_dmenu --dmenu --style ~/.config/wofi/style.css --allow-images=false",
"on-click-right": "nm-connection-editor"
},
"cpu": {
"format": "{usage}%  ",
"tooltip": false
},
"memory": {
"format": "{percentage}%  "
},
"temperature": {
"format": "{temperatureC}°C ",
"tooltip": false
},
"tray": {
"spacing": 10,
"icon-size": 14
},
"clock": {
"format": "{:%H:%M}",
"tooltip-format": "<tt><small>{calendar}</small></tt>",
"calendar": {
"mode" : "year",
"mode-mon-col" : 3,
"weeks-pos" : "left",
"on-scroll" : 1,
"on-click-right": "mode",
"format": {
"months": "<span color='#fab387'><b>{}</b></span>",
"days": "<span color='#cba6f7'><b>{}</b></span>",
"weeks": "<span color='#a6e3a1'><b>W{}</b></span>",
"weekdays": "<span color='#f9e2af'><b>{}</b></span>",
"today": "<span color='#1e1e2e' bgcolor='#a6e3a1'>{}</span>"
}
},
"on-click": "flatpak run eu.betterbird.Betterbird -calendar"
},
"battery": {
"bat": "BAT0",
"states": {
"good": 95,
"warning": 30,
"critical": 15
},
"format": "{capacity}% {icon}",
"format-charging": "{capacity}% 󰂄",
"format-plugged": "{capacity}%  ",
"format-icons": ["󰁺", "󰁼", "󰁾", "󰂀", "󱈏 "]
}
}
#+END_SRC
** =generated/.config/waybar/style-dark.css=
This file contains all css for waybar
#+BEGIN_SRC css :tangle generated/.config/waybar/style-dark.css :noweb yes :mkdirp yes :eval never
@import url("file:///home/henrov/.config/shared/colors.css");
/* --- Global --- */
* {
font-family:
Aporetic Sans Mono,
Iosevka Nerd Font,
Roboto,
Helvetica,
Arial,
sans-serif;
font-size: 13px;
}
window#waybar {
background-color: transparent;
color: @text;
}
/* --------------------------------------------------------- */
/* --- Group anchors default visible --- */
#custom-hardware-anchor,
#custom-connections-anchor {
min-width: 80px;
padding: 0 5px;
margin: 0 2px;
opacity: 1;
transition: opacity 0.2s ease, min-width 0.2s ease, padding 0.2s ease;
}
/* --- Hide anchors on hover of the group --- */
#hardware:hover #custom-hardware-anchor,
#connections:hover #custom-connections-anchor {
opacity: 0;
min-width: 0;
padding: 0;
margin: 0;
}
#hardware:hover,
#connections:hover {
min-width: 80px;
}
/* MODULES */
.modules-left > widget,
.modules-center > widget,
.modules-right > widget {
min-width: 80px;
color: @text;
font-weight: bold;
border-radius: 30px;
background:
linear-gradient(@base-alpha, @base-alpha) padding-box,
linear-gradient(45deg, @blue, @green) border-box;
border: 2px solid transparent;
}
.modules-left > box + box,
.modules-center > box + box,
.modules-right > box + box {
margin-left: 5px;
}
.modules-left > widget label,
.modules-left > label ,
.modules-center > widget label,
.modules-center > label,
.modules-right > widget label,
.modules-right > label {
padding: 0px 5px;
transition: padding 0.2s ease;
}
/* -----------------------------
WORKSPACES / WINDOWS MODULE
----------------------------- */
/* Disable hover effects completely */
#workspaces button,
#workspaces button:hover {
border: 2px solid transparent;
padding: 0 6px;
margin: 0;
border-radius: 30px;
transition: none; /* disable hover animation */
}
/* Active vs inactive workspace colors */
#workspaces button.active {
background: linear-gradient(45deg, @blue, @green);
color: @base;
}
activeworkspaces:not(.active) {
background: linear-gradient(@base-alpha, @base-alpha);
border: 2px solid transparent;
color: @text-muted; /* inactive text color */
}
label#custom-windows.module {
font-size: 14px;
color: @base;
padding: 0 8px;
border-radius: 30px;
transition: all 0.3s ease;
}
label#custom-windows.active {
background: linear-gradient(45deg, alpha(@blue, 0.5), alpha(@green, 0.5));
}
label#custom-windows:not(.active) {
background: transparent;
color: transparent;
}
/* ---- Media ---*/
#custom-media {
padding: 0 8px;
color: @text;
}
#custom-media.inactive {
background: transparent;
color: transparent;
opacity: 0;
padding: 0;
margin: 0;
min-width: 0;
}
/* ---- Pulseaudio ---*/
#pulseaudio-slider {
padding: 0;
margin: 0;
}
#pulseaudio-slider slider {
min-height: 0px;
min-width: 0px;
opacity: 0;
border-radius: 30px;
background: linear-gradient(45deg, @blue, @green);
border: none;
box-shadow: none;
}
#pulseaudio-slider trough {
min-height: 10px;
min-width: 80px;
border-radius: 30px;
background: transparent;
}
#pulseaudio-slider highlight {
min-width: 10px;
border-radius: 30px;
background: linear-gradient(45deg, @blue, @green);
border: 2px solid transparent;
}
/* --------------------------------------------------------- */
/* STATES / SPECIALS */
#idle_inhibitor.activated {
background: linear-gradient(45deg, @blue, @green);
border: 2px solid transparent;
color: @base;
border-radius: 30px;
}
#battery.charging {
color: @green;
}
#battery.warning:not(.charging) {
color: white;
animation: blink 0.5s linear infinite alternate;
border-radius: 30px;
border: 2px solid transparent;
}
#custom-battery-warn {
margin: 0 5px;
padding: 0 10px;
color: white;
animation: blink 0.5s linear infinite alternate;
}
@keyframes blink {
to {
background-color: #ffffff;
color: black;
border-radius: 30px;
border: 2px solid transparent;
}
}
#network.disconnected {
background-color: @red;
border-radius: 30px;
border: 2px solid transparent;
}
#temperature.critical {
background-color: @red;
border-radius: 30px;
border: 2px solid transparent;
}
/* --------------------------------------------------------- */
/* GLOBAL MODULE SPACING */
#clock,
#idle_inhibitor,
#battery:not(.warn),
#cpu,
#memory,
#temperature,
#network,
#pulseaudio,
#tray {
margin: 0 5px;
padding: 0 10px;
}
#+END_SRC
** =generated/.config/scripts/bluetooth-status.sh=
These are config files for waybar
#+BEGIN_SRC sh :tangle generated/.config/scripts/bluetooth-status.sh :shebang "#!/usr/bin/env bash" :noweb yes :mkdirp yes :eval never
bt_connected=""
while read -r _ mac name_rest; do
if [ "$(bluetoothctl info "$mac" | awk '/Connected:/ {print $2}')" = "yes" ]; then
bt_connected+="$name_rest\n"
fi
done < <(bluetoothctl devices)
# icon
if [ -n "$bt_connected" ]; then
icon=""
tooltip=$(printf "%b" "$bt_connected")
else
icon=""
tooltip="No devices connected"
fi
# ALWAYS produce valid JSON
printf '{"text": "%s", "tooltip": "%s"}\n' "$icon" "$tooltip"
#+END_SRC
** =generated/.config/scripts/hypr-workspaces.sh=
These are config files for waybar
#+BEGIN_SRC sh :tangle generated/.config/scripts/hypr-workspaces.sh :shebang "#!/usr/bin/env bash" :noweb yes :mkdirp yes :eval never
# Get focused monitor name
focused_monitor=$(hyprctl monitors -j | jq -r '.[] | select(.focused==true) | .name')
monitor="${WAYBAR_OUTPUT_NAME:-$focused_monitor}"
# Hide if not focused monitor
if [ "$monitor" != "$focused_monitor" ]; then
jq -c -n '{text:"", class:"hidden"}'
exit 0
fi
# Get active workspace on this monitor
active_ws=$(hyprctl monitors -j | jq -r \
".[] | select(.name==\"$monitor\") | .activeWorkspace.id")
# Get clients
clients=$(hyprctl clients -j | jq -r \
".[] | select(.workspace.id==$active_ws) | \"\(.title)\"")
count=$(echo "$clients" | grep -c '\S')
# Hide if 0 or 1 clients — no point showing window switcher
if [ "$count" -le 1 ]; then
jq -c -n '{text:"", class:"hidden"}'
exit 0
fi
tooltip=$(echo "$clients" | sed 's/^/• /' | paste -sd '\n' -)
jq -c -n \
--arg text "$count" \
--arg tooltip "$tooltip" \
--arg class "active" \
'{text:$text, tooltip:$tooltip, class:$class}'
#+END_SRC
** =generated/.config/scripts/hypr-workspacesmenu.sh=
These are config files for waybar
#+BEGIN_SRC sh :tangle generated/.config/scripts/hypr-workspacesmenu.sh :shebang "#!/usr/bin/env bash" :noweb yes :mkdirp yes :eval never
active_ws=$(hyprctl activeworkspace -j | jq -r '.id')
clients=$(hyprctl clients -j | jq -r \
".[] | select(.workspace.id==$active_ws) | \"\(.address)|\(.title)\"")
choice=$(echo "$clients" | cut -d'|' -f2 \
| wofi --dmenu \
--style ~/.config/wofi/style.css \
--allow-images=false \
--prompt "Active windows ...")
[ -z "$choice" ] && exit 0
addr=$(echo "$clients" | grep "|$choice" | head -n1 | cut -d'|' -f1)
hyprctl dispatch focuswindow address:"$addr"
#+END_SRC
** =generated/.config/scripts/kdeconnect-status.sh=
These are config files for waybar
#+BEGIN_SRC sh :tangle generated/.config/scripts/kdeconnect-status.sh :shebang "#!/usr/bin/env bash" :noweb yes :mkdirp yes :eval never
DEVICE=$(kdeconnect-cli --list-devices | grep -oP '(?<=\().*?(?=\))' | head -n 1)
if [ -z "$DEVICE" ]; then
echo "No phone"
exit 0
fi
NAME=$(kdeconnect-cli -d "$DEVICE" --name 2>/dev/null)
BATTERY=$(kdeconnect-cli -d "$DEVICE" --battery 2>/dev/null | grep -o '[0-9]\+' | head -n 1)
if [ -z "$BATTERY" ]; then
echo "$NAME"
else
echo "$NAME $BATTERY%"
fi
#+END_SRC
** =generated/.config/waypaper/config.ini=
These are config files for waypaper
#+BEGIN_SRC conf :tangle generated/.config/waypaper/config.ini :noweb yes :mkdirp yes :eval never
[Settings]
language = en
backend = awww
folder = ~/Wallpapers/pictures
monitors = All
wallpaper = ~/Wallpapers/pictures/13.jpg
show_path_in_tooltip = True
fill = fill
sort = name
color = #ffffff
subfolders = False
all_subfolders = False
show_hidden = False
show_gifs_only = False
zen_mode = False
post_command =
number_of_columns = 3
awww_transition_type = any
awww_transition_step = 63
awww_transition_angle = 0
awww_transition_duration = 2
awww_transition_fps = 60
mpvpaper_sound = False
mpvpaper_options =
use_xdg_state = False
stylesheet = /home/henrov/.config/waypaper/style.css
keybindings = ~/.config/waypaper/keybindings.ini
#+END_SRC
** =generated/.config/waypaper/config.ini=
These are config files for .config/waypaper
#+BEGIN_SRC ini :tangle generated/.config/waypaper/config.ini :noweb yes :mkdirp yes :eval never
[Settings]
language = en
backend = awww
folder = ~/Wallpapers/pictures
monitors = All
wallpaper = ~/Wallpapers/pictures/13.jpg
show_path_in_tooltip = True
fill = fill
sort = name
color = #ffffff
subfolders = False
all_subfolders = False
show_hidden = False
show_gifs_only = False
zen_mode = False
post_command =
number_of_columns = 3
awww_transition_type = any
awww_transition_step = 63
awww_transition_angle = 0
awww_transition_duration = 2
awww_transition_fps = 60
mpvpaper_sound = False
mpvpaper_options =
use_xdg_state = False
stylesheet = /home/henrov/.config/waypaper/style.css
keybindings = ~/.config/waypaper/keybindings.ini
#+END_SRC
** =generated/.config/wofi/config=
These are config files for .config/wofi
#+BEGIN_SRC toml :tangle generated/.config/wofi/config :noweb yes :mkdirp yes :eval never
[global]
allow_markup = true
location = center
anchor = center
lines = 10
columns = 1
sort_order = last-used
sort_method = fuzzy
allow_scrolling = true
scroll_wrap = true
scroll_step = 10
cycle = true
hide_scroll = false
hide_search = false
prompt = > ...
#+END_SRC
** =generated/.config/wofi/style.css=
This is the default layout for wofi
#+BEGIN_SRC css :tangle generated/.config/wofi/style.css :noweb yes :mkdirp yes :eval never
@import "~/.config/shared/colors.css";
* {
background-color: transparent;
color: @text;
font-family: "JetBrainsMono Nerd Font", monospace;
font-size: 12pt;
}
#window {
background: linear-gradient(45deg, #89b4fa, #a6e3a1);
border-radius: 28px;
padding: 2px;
}
#outer-box {
background-color: rgba(30, 30, 46, 0.98); /* almost solid */
border-radius: 26px;
padding: 12px;
}
#inner-box {
background: transparent;
padding: 0;
}
#input {
background-color: @surface1; /* stronger than surface0 */
color: @text;
border: 1px solid @surface2;
border-radius: 18px;
padding: 10px 14px;
margin-bottom: 10px;
}
#input:focus {
border: 1px solid @blue;
background-color: @surface2;
}
#entry {
background-color: rgba(0, 0, 0, 0.35);
color: @subtext1;
border-radius: 18px;
padding: 10px 14px;
margin: 2px 0;
transition: all 0.15s ease;
}
#entry:hover {
background-color: rgba(0, 0, 0, 0.5);
color: @text;
}
#entry:focus {
background: linear-gradient(45deg, #89b4fa, #89b4fa);
color: @lavender;
border-radius: 18px;
}
#entry:selected {
background: linear-gradient(45deg, #89b4fa, #a6e3a1);
border-radius: 18px;
font-weight: bold;
}
#entry image {
margin-right: 10px;
opacity: 0.9;
}
#scrollbar {
background-color: @surface1;
border-radius: 20px;
width: 6px;
}
#scrollbar handle {
background: linear-gradient(45deg, #89b4fa, #a6e3a1);
border-radius: 20px;
}
#prompt {
color: @subtext0;
margin-right: 6px;
}
#+END_SRC
** =generated/.config/zed/settings.json=
These are config files for Zed editor
#+BEGIN_SRC json :tangle generated/.config/zed/settings.json :noweb yes :mkdirp yes :eval never
// Zed settings
//
// For information on how to configure Zed, see the Zed
// documentation: https://zed.dev/docs/configuring-zed
//
// To see all of Zed's default settings without changing your
// custom settings, run `zed: open default settings` from the
// command palette (cmd-shift-p / ctrl-shift-p)
{
"icon_theme": "Catppuccin Mocha",
"agent": {
"default_model": {
"provider": "ollama",
"model": "codellama:34b",
"enable_thinking": false
},
"favorite_models": [],
"model_parameters": []
},
"ui_font_size": 16,
"buffer_font_size": 15,
"theme": {
"mode": "dark",
"light": "One Light",
"dark": "Catppuccin Mocha",
},
}
#+END_SRC
** =generated/.config/zsh/.zshrc=
This sets up the zsh in the terminal
#+BEGIN_SRC bash :tangle generated/.config/zsh/.zshrc :noweb yes :mkdirp yes :eval never
# Path to syntax highlighting installed by Nix
ZSH_SYNTAX_HIGHLIGHTING="${HOME}/.nix-profile/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh"
# Load syntax highlighting if available
if [ -f "$ZSH_SYNTAX_HIGHLIGHTING" ]; then
source "$ZSH_SYNTAX_HIGHLIGHTING"
fi
# Initialize Starship prompt
if command -v starship >/dev/null 2>&1; then
eval "$(starship init zsh)"
fi
source /etc/profile.d/99-alias-functions.sh
eval "$(/run/current-system/sw/bin/z.lua --init zsh)"
cd() {
if [ "$#" -eq 0 ]; then
builtin cd ~
else
builtin cd "$@" || return
fi
command z "$PWD"
}
#+END_SRC