Compare commits

...

26 Commits

Author SHA1 Message Date
434f14707c Enabled stylix to configure gtk 2026-06-02 12:48:09 +02:00
f94f6e63b1 Enable qt support in stylix, cleaned up comments and made stylix manage niri colors 2026-06-02 12:24:39 +02:00
ca285c92f7 Add noctalia module and removed waybar and other configurations no longer needed with noctalia 2026-06-02 12:22:05 +02:00
bcf0c17c51 Changed yakuake autostart to only start in KDE Plasma 2026-06-02 12:07:02 +02:00
5b9b48fede Configured git to be able to use lfs 2026-06-02 12:02:35 +02:00
fe2730b673 Added a symlink for cookiez assets flake input to /var/lib/assets 2026-06-02 12:01:54 +02:00
31b70d4221 Disabled specialisations as they arent needed for now 2026-06-02 11:59:45 +02:00
b9c0ab5f85 Fix: Added pinned kernel to flake outputs 2026-06-02 11:58:41 +02:00
09f39d1537 Removed awww as wallpapers will be handeled by noctalia 2026-06-02 11:57:56 +02:00
b696672f11 Pinned linux kernel version so I can rollback to specific versions in the past for things like bluetooth issues 2026-06-02 11:51:58 +02:00
1ed32e29b0 Added automatic nix store optimisation and garbage collection of versions older than 14 days 2026-05-31 20:11:19 +02:00
f04a72f19d Deleted hyprpaper and replaced it with awww. Also deleted self declared niri systemd services, as they arent needed with running commands at startup 2026-05-29 21:51:48 +02:00
3cf1f4f11f Merge pull request 'ncli-refactor' (#3) from ncli-refactor into main
Reviewed-on: #3
2026-05-29 20:49:44 +02:00
dbf7c1cd2e Refactored ncli to rebuild boot first, and then switch to new configuration after. 2026-05-29 11:13:35 +02:00
134fc441a5 - Simplified command cases by removing unnecessary semicolons.
- Improved error handling in rebuild.nix for clarity and consistency.
2026-05-29 09:29:31 +02:00
d989792774 Merge remote-tracking branch 'origin/main' into ncli-refactor 2026-05-28 15:30:40 +02:00
275d07f6e2 Merge pull request 'separate-big-files' (#2) from separate-big-files into main
Reviewed-on: #2
2026-05-28 15:11:14 +02:00
8357053c2a Removed plasma profile pic script as it doesnt work with new assets structure. 2026-05-28 15:06:46 +02:00
09585ce7ea Add wallpapers from cookiez-assets to KDE wallpaper settings 2026-05-28 15:00:39 +02:00
1221a3a984 Removed cookiez-assets from top level imports, it is now imported via inputs.cookiez-assets 2026-05-28 14:59:47 +02:00
89a2eb335e Merge remote-tracking branch 'origin/main' into separate-big-files 2026-05-27 15:04:25 +02:00
efca1819b4 Added gamescope and moved gamemode from plasma to general settings 2026-05-27 14:53:28 +02:00
d94e534ee4 Split ncli across multiple files in its own directory 2026-05-27 14:34:25 +02:00
6b60113552 Added error reason to ncli if rebuilds fail with memory overload 2026-05-26 16:23:09 +02:00
a62b187832 Removed images from main repo 2026-04-14 11:06:55 +02:00
1991a88884 Changed Configurations to use the assets repo instead of paths in main repo 2026-04-14 11:06:44 +02:00
38 changed files with 1120 additions and 1226 deletions

81
flake.lock generated
View File

@ -45,6 +45,28 @@
"type": "github" "type": "github"
} }
}, },
"awww": {
"inputs": {
"flake-compat": "flake-compat_2",
"nixpkgs": [
"nixpkgs"
],
"rust-overlay": "rust-overlay_2"
},
"locked": {
"lastModified": 1779666993,
"narHash": "sha256-W0yA7Y37oj5BBzl4ojO8dtv9MuOvdrIZDxtRjs7kpdg=",
"ref": "refs/heads/main",
"rev": "9b7f47f7f394dce0a17a7b161e0d2fe391ce72b3",
"revCount": 1366,
"type": "git",
"url": "https://codeberg.org/LGFae/awww"
},
"original": {
"type": "git",
"url": "https://codeberg.org/LGFae/awww"
}
},
"base16": { "base16": {
"inputs": { "inputs": {
"fromYaml": "fromYaml" "fromYaml": "fromYaml"
@ -113,6 +135,26 @@
"type": "github" "type": "github"
} }
}, },
"cookiez-assets": {
"flake": false,
"locked": {
"lastModified": 1776155298,
"lfs": true,
"narHash": "sha256-cOiaPp5vRLc6LglqgMoXXBHLCqixVM5YuJsI1Zj+kv4=",
"ref": "main",
"rev": "10e02d22a16707548897047323fe78ccf5d58dc1",
"shallow": true,
"type": "git",
"url": "https://gitea.cookiee.org/cookiez/Nix-Assets.git"
},
"original": {
"lfs": true,
"ref": "main",
"shallow": true,
"type": "git",
"url": "https://gitea.cookiee.org/cookiez/Nix-Assets.git"
}
},
"fenix": { "fenix": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@ -167,6 +209,22 @@
"type": "github" "type": "github"
} }
}, },
"flake-compat_2": {
"flake": false,
"locked": {
"lastModified": 1761588595,
"narHash": "sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "f387cd2afec9419c8ee37694406ca490c3f34ee5",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-parts": { "flake-parts": {
"inputs": { "inputs": {
"nixpkgs-lib": [ "nixpkgs-lib": [
@ -598,6 +656,8 @@
"inputs": { "inputs": {
"aagl": "aagl", "aagl": "aagl",
"alejandra": "alejandra", "alejandra": "alejandra",
"awww": "awww",
"cookiez-assets": "cookiez-assets",
"grub2-themes": "grub2-themes", "grub2-themes": "grub2-themes",
"home-manager": "home-manager", "home-manager": "home-manager",
"niri": "niri", "niri": "niri",
@ -650,6 +710,27 @@
"type": "github" "type": "github"
} }
}, },
"rust-overlay_2": {
"inputs": {
"nixpkgs": [
"awww",
"nixpkgs"
]
},
"locked": {
"lastModified": 1764038373,
"narHash": "sha256-M6w2wNBRelcavoDAyFL2iO4NeWknD40ASkH1S3C0YGM=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "ab3536fe850211a96673c6ffb2cb88aab8071cc9",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"stylix": { "stylix": {
"inputs": { "inputs": {
"base16": "base16", "base16": "base16",

View File

@ -4,6 +4,9 @@
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
pinned-kernel.url = "github:NixOS/nixpkgs/3b5ec87c520b3f3f890c439da30b9fc3f7e173d3";
#To pin Kernel versin 7.0.10 because others have bluetooth issues
nix-index-database = { nix-index-database = {
url = "github:nix-community/nix-index-database"; url = "github:nix-community/nix-index-database";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
@ -32,8 +35,8 @@
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
quickshell = { noctalia = {
url = "github:outfoxxed/quickshell"; url = "github:noctalia-dev/noctalia-shell/v5";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
@ -57,6 +60,11 @@
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
cookiez-assets = {
url = "git+https://gitea.cookiee.org/cookiez/Nix-Assets.git?ref=main&lfs=1&shallow=1";
flake = false;
};
nix-flatpak.url = "github:gmodena/nix-flatpak"; nix-flatpak.url = "github:gmodena/nix-flatpak";
grub2-themes.url = "github:vinceliuice/grub2-themes"; grub2-themes.url = "github:vinceliuice/grub2-themes";
@ -66,8 +74,11 @@
nixpkgs, nixpkgs,
alejandra, alejandra,
pam-fprint-grosshack, pam-fprint-grosshack,
pinned-kernel,
cookiez-assets,
home-manager, home-manager,
plasma-manager, plasma-manager,
noctalia,
nixos-hardware, nixos-hardware,
aagl, aagl,
stylix, stylix,
@ -98,6 +109,7 @@
inherit system; inherit system;
inherit project; inherit project;
inherit alejandra; inherit alejandra;
inherit cookiez-assets;
pam-fprint-grosshack-pkg = pam-fprint-grosshack.packages.${system}.default; pam-fprint-grosshack-pkg = pam-fprint-grosshack.packages.${system}.default;
host = hostname; host = hostname;
}; };

View File

@ -15,7 +15,9 @@
system, system,
pam-fprint-grosshack-pkg, pam-fprint-grosshack-pkg,
... ...
}: { }: let
kernel-pinned = import inputs.pinned-kernel {inherit system;};
in {
#Assign Swap to the PC #Assign Swap to the PC
swapDevices = [ swapDevices = [
{ {
@ -25,7 +27,15 @@
} }
]; ];
nix = { nix = {
settings.nix-path = config.nix.nixPath; gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 14d";
};
settings = {
auto-optimise-store = true;
nix-path = config.nix.nixPath;
};
nixPath = ["nixpkgs=${inputs.nixpkgs}"]; nixPath = ["nixpkgs=${inputs.nixpkgs}"];
}; };
@ -46,7 +56,7 @@
# Bootloader. # Bootloader.
boot = { boot = {
kernelPackages = pkgs.linuxPackages_latest; kernelPackages = kernel-pinned.linuxPackages_latest;
kernelParams = ["quiet" "splash"]; kernelParams = ["quiet" "splash"];
initrd = { initrd = {
systemd.enable = true; #For swap to automatically work systemd.enable = true; #For swap to automatically work
@ -186,9 +196,14 @@
openssh.enable = true; openssh.enable = true;
}; };
systemd.services.fprintd = { systemd = {
wantedBy = ["multi-user.target"]; tmpfiles.rules = [
serviceConfig.Type = "simple"; "L+ /var/lib/assets - - - - ${inputs.cookiez-assets}"
];
services.fprintd = {
wantedBy = ["multi-user.target"];
serviceConfig.Type = "simple";
};
}; };
fonts = { fonts = {
@ -218,6 +233,10 @@
programs = { programs = {
steam.enable = true; steam.enable = true;
gamemode.enable = true;
gamescope.enable = true;
nix-index-database.comma.enable = true; nix-index-database.comma.enable = true;
direnv = { direnv = {
@ -300,7 +319,7 @@
users.users.${username} = { users.users.${username} = {
isNormalUser = true; isNormalUser = true;
description = "Cookiez"; description = "Cookiez";
extraGroups = ["networkmanager" "wheel" "docker"]; extraGroups = ["networkmanager" "wheel" "docker" "gamemode" "dialout" "tty"];
packages = with pkgs; [ packages = with pkgs; [
#User Packages Here #User Packages Here
]; ];
@ -371,9 +390,8 @@
max-substitution-jobs = 32; max-substitution-jobs = 32;
http-connections = 50; http-connections = 50;
#Both needed for sleepy-launcher to work extra-substituters = ["https://ezkea.cachix.org" "https://noctalia.cachix.org" "https://nix-community.cachix.org"];
extra-substituters = ["https://ezkea.cachix.org" "https://nix-community.cachix.org"]; extra-trusted-public-keys = ["ezkea.cachix.org-1:ioBmUbJTZIKsHmWWXPe1FSFbeVe+afhfgqgTSNd34eI=" "noctalia.cachix.org-1:pCOR47nnMEo5thcxNDtzWpOxNFQsBRglJzxWPp3dkU4=" "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="];
extra-trusted-public-keys = ["ezkea.cachix.org-1:ioBmUbJTZIKsHmWWXPe1FSFbeVe+afhfgqgTSNd34eI=" "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="];
}; };
# Allow unfree packages # Allow unfree packages

View File

@ -7,40 +7,40 @@
../niri ../niri
]; ];
specialisation = { #specialisation = {
"plasma" = { # "plasma" = {
inheritParentConfig = false; # inheritParentConfig = false;
configuration = { # configuration = {
imports = [ # imports = [
../plasma # ../plasma
./configuration.nix # ./configuration.nix
]; # ];
#
# environment.etc."nixos-tags".text = "plasma";
# };
# };
environment.etc."nixos-tags".text = "plasma"; # "minimal" = {
}; # inheritParentConfig = false;
}; # configuration = {
# imports = [
# ./minimal.nix
# ];
#
# environment.etc."nixos-tags".text = "minimal";
# };
# };
# "minimal" = { # "niri" = {
# inheritParentConfig = false; # inheritParentConfig = false;
# configuration = { # configuration = {
# imports = [ # imports = [
# ./minimal.nix # ../niri
# ]; # ./configuration.nix
# # ];
# environment.etc."nixos-tags".text = "minimal"; #
# }; # environment.etc."nixos-tags".text = "niri";
# }; # };
# };
"niri" = { #};
inheritParentConfig = false;
configuration = {
imports = [
../niri
./configuration.nix
];
environment.etc."nixos-tags".text = "niri";
};
};
};
} }

View File

@ -1,5 +1,6 @@
{ {
pkgs, pkgs,
inputs,
username, username,
project, project,
... ...
@ -19,11 +20,13 @@
noDisplay = true; noDisplay = true;
}; };
dataFile."icons/hicolor/256x256/apps/vencord-custom.png".source = "${inputs.cookiez-assets}/apps/discord.png";
desktopEntries."discord" = { desktopEntries."discord" = {
categories = ["Network" "InstantMessaging" "Chat"]; categories = ["Network" "InstantMessaging" "Chat"];
exec = "vesktop %U"; exec = "vesktop %U";
genericName = "Internet Messenger"; genericName = "Internet Messenger";
icon = "/home/${username}/${project}/other/discord.app.png"; icon = "vencord-custom";
name = "Discord"; name = "Discord";
type = "Application"; type = "Application";
}; };
@ -37,6 +40,8 @@
type = "Application"; type = "Application";
}; };
dataFile."icons/hicolor/256x256/apps/kitty-custom.png".source = "${inputs.cookiez-assets}/apps/kitty.png";
desktopEntries.kitty = { desktopEntries.kitty = {
name = "kitty"; name = "kitty";
genericName = "Terminal emulator"; genericName = "Terminal emulator";
@ -45,7 +50,8 @@
terminal = false; terminal = false;
categories = ["System" "TerminalEmulator"]; categories = ["System" "TerminalEmulator"];
icon = "/home/${username}/${project}/other/kitty.app.png"; #icon = "${inputs.cookiez-assets}/apps/kitty.png";
icon = "kitty-custom";
}; };
desktopEntries."org.kde.kinfocenter" = { desktopEntries."org.kde.kinfocenter" = {

View File

@ -7,6 +7,7 @@
project, project,
host, host,
version, version,
cookiez-assets,
... ...
}: { }: {
# Home Manager needs a bit of information about you and the # Home Manager needs a bit of information about you and the
@ -14,7 +15,7 @@
home.username = username; home.username = username;
home.homeDirectory = "/home/${username}"; home.homeDirectory = "/home/${username}";
home.packages = [ home.packages = [
(import ./ncli.nix { (import ./ncli/default.nix {
inherit pkgs host project; inherit pkgs host project;
backupFiles = [ backupFiles = [
".gtkrc-2.0.backup" ".gtkrc-2.0.backup"
@ -73,6 +74,7 @@
git = { git = {
enable = true; enable = true;
lfs.enable = true;
settings = { settings = {
user = { user = {
name = "Cookiez"; name = "Cookiez";

View File

@ -1,32 +0,0 @@
{
pkgs,
inputs,
username,
project,
...
}: {
imports = [
];
services = {
hyprpaper = {
enable = false;
settings = {
preload = [
#"/home/${username}/${project}/other/wallpaper1.png"
#"/home/${username}/${project}/other/wallpaper2.png"
#"/home/${username}/${project}/other/wallpaper3.png"
"/home/${username}/${project}/other/wallpaper4.png"
];
wallpaper = [
#"eDP-1,/home/${username}/${project}/other/wallpaper1.png"
#"eDP-1,/home/${username}/${project}/other/wallpaper2.png"
#"eDP-1,/home/${username}/${project}/other/wallpaper3.png"
"eDP-1,/home/${username}/${project}/other/wallpaper4.png"
];
};
};
};
}

View File

@ -1,732 +0,0 @@
{
pkgs,
host,
backupFiles ? [".config/mimeapps.list.backup"],
project,
...
}: let
backupFilesString = pkgs.lib.strings.concatStringsSep " " backupFiles;
in
pkgs.writeShellScriptBin "ncli" ''
#!${pkgs.bash}/bin/bash
set -euo pipefail
# --- Configuration ---
PROJECT="${project}"
HOST="${host}"
BACKUP_FILES_STR="${backupFilesString}"
VERSION="2.1.3"
FLAKE_NIX_PATH="$HOME/$PROJECT/flake.nix"
read -r -a BACKUP_FILES <<< "$BACKUP_FILES_STR"
# --- Read Colors file ---
source /$HOME/$PROJECT/other/colors.sh
# --- Helper Functions ---
print_help() {
echo "NixOS CLI Utility -- version $VERSION"
echo ""
echo "Usage: ncli [command]"
echo ""
echo "System Commands:"
echo " rebuild - Rebuild the NixOS system configuration."
echo " update - Update the flake and rebuild the system."
echo ""
echo "Maintenance Commands:"
echo " cleanup - Clean up old system generations. Can specify a number to keep."
echo " diag - Create a system diagnostic report (saves to ~/diag.txt)."
echo " list-gens - List user and system generations."
echo " trim - Trim filesystems to improve SSD performance."
echo ""
echo "Git Commands:"
echo " commit [msg] - Add all changes and commit with message."
echo " push - Push changes to origin."
echo " pull - Pull latest changes from origin."
echo " status - Show git status."
echo ""
echo "Development Commands:"
echo " dev - Initialize a Nix development environment (flake.nix + direnv)."
echo " dev track - Remove assume-unchanged flag from flake files."
echo " dev untrack - Mark flake files as assume-unchanged in a directory."
echo ""
echo " help - Show this help message."
echo ""
}
handle_backups() {
if [ ''${#BACKUP_FILES[@]} -eq 0 ]; then
echo "No backup files configured to check."
return
fi
echo "Checking for backup files to remove..."
for file_path in "''${BACKUP_FILES[@]}"; do
full_path="$HOME/$file_path"
if [ -f "$full_path" ]; then
echo "Removing stale backup file: $full_path"
rm "$full_path"
fi
done
}
# --- Dev Init Helper Functions ---
print_header() {
echo ""
echo -e "''${BLUE}==============================================''${NOCOLOR}"
echo -e "''${BLUE} Nix Flake Development Environment Initializer''${NOCOLOR}"
echo -e "''${BLUE}==============================================''${NOCOLOR}"
echo ""
}
print_success() {
echo -e "''${GREEN}[OK]''${NOCOLOR} $1"
}
print_error() {
echo -e "''${RED}[ERR]''${NOCOLOR} $1"
}
print_info() {
echo -e "''${YELLOW}[->]''${NOCOLOR} $1"
}
# --- Main Logic ---
if [ "$#" -eq 0 ]; then
echo "Error: No command provided." >&2
print_help
exit 1
fi
case "$1" in
cleanup)
echo "Warning! This will remove old generations of your system."
read -p "How many generations to keep (default: all)? " keep_count
if [ -z "$keep_count" ]; then
read -p "This will remove all but the current generation. Continue (y/N)? " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
nh clean all -v
else
echo "Cleanup cancelled."
fi
else
read -p "This will keep the last $keep_count generations. Continue (y/N)? " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
nh clean all -k "$keep_count" -v
else
echo "Cleanup cancelled."
fi
fi
LOG_DIR="$HOME/ncli-cleanup-logs"
mkdir -p "$LOG_DIR"
LOG_FILE="$LOG_DIR/ncli-cleanup-$(date +%Y-%m-%d_%H-%M-%S).log"
echo "Cleaning up old log files..." >> "$LOG_FILE"
find "$LOG_DIR" -type f -mtime +3 -name "*.log" -delete >> "$LOG_FILE" 2>&1
echo "Cleanup process logged to $LOG_FILE"
;;
diag)
echo "Generating system diagnostic report..."
{
echo "=== NixOS System Diagnostic Report ==="
echo "Generated: $(date)"
echo ""
echo "=== System Information ==="
inxi --full 2>/dev/null || echo "inxi not available"
echo ""
echo "=== Git Status ==="
cd "$HOME/$PROJECT" 2>/dev/null && git status 2>/dev/null || echo "Git status not available"
echo ""
} > "$HOME/diag.txt"
echo "Diagnostic report saved to $HOME/diag.txt"
;;
help)
print_help
;;
list-gens)
echo "--- User Generations ---"
nix-env --list-generations | cat || echo "Could not list user generations."
echo ""
echo "--- System Generations ---"
nix profile history --profile /nix/var/nix/profiles/system | cat || echo "Could not list system generations."
;;
rebuild)
handle_backups
geno=$(sudo nix-env --list-generations --profile /nix/var/nix/profiles/system | grep current | awk '{print $1}')
echo -e "Starting NixOS rebuild for current host: $HOST on generation: $YELLOW$geno$NOCOLOR"
cd "$HOME/$PROJECT" || { echo "Error: Could not change to $HOME/$PROJECT"; exit 1; }
current=""
if [ -f /etc/nixos-tags ]; then
current=$(cat /etc/nixos-tags)
fi
if sudo nixos-rebuild switch --flake .; then
echo " Rebuild finished successfully for $HOST"
if [ -n "$current" ]; then
sudo /run/current-system/specialisation/$current/bin/switch-to-configuration test
else
echo "No specialization tag found, staying on default system."
fi
genn=$(sudo nix-env --list-generations --profile /nix/var/nix/profiles/system | grep current | awk '{print $1}')
echo -e "Running on new generation: $YELLOW $geno $NOCOLOR-> $GREEN$genn$NOCOLOR"
else
echo " Rebuild failed for $HOST" >&2
exit 1
fi
;;
update)
handle_backups
geno=$(sudo nix-env --list-generations --profile /nix/var/nix/profiles/system | grep current | awk '{print $1}')
echo -e "Updating flake and rebuilding system for current host: $HOST on generation: $YELLOW$geno$NOCOLOR"
cd "$HOME/$PROJECT" || { echo "Error: Could not change to $HOME/$PROJECT"; exit 1; }
# --- Selective flake update ---
read -rp "Update [a]ll inputs or [s]elect manually? (a/s): " choice
case "$choice" in
a|A)
echo "Updating all inputs..."
if nix flake update --flake .; then
echo " Flake updated successfully"
else
echo " Flake update failed" >&2
exit 1
fi
;;
s|S)
echo "Fetching available updates (this may take a moment)..."
TEMP_LOCK=$(mktemp)
trap 'rm -f "$TEMP_LOCK"' EXIT
nix flake update --output-lock-file "$TEMP_LOCK" --flake . 2>/dev/null
outdated=$(jq -r --slurpfile new "$TEMP_LOCK" '
.nodes as $old |
$new[0].nodes as $newn |
($old | keys[]) |
select(. != "root") |
select(
($old[.].locked.lastModified // 0) !=
($newn[.].locked.lastModified // 0)
)
' flake.lock)
if [[ -z "$outdated" ]]; then
echo " All inputs are already up to date, skipping flake update."
else
echo
echo "Updates available for:"
printf '%s\n' "$outdated"
echo
echo "Tab to select, Enter to update, Esc to cancel."
selected=$(printf '%s\n' "$outdated" | fzf --multi) || {
echo "No inputs selected, skipping flake update."
selected=""
}
if [[ -n "$selected" ]]; then
if nix flake update --flake . $selected; then
echo " Flake updated successfully"
else
echo " Flake update failed" >&2
exit 1
fi
fi
fi
;;
*)
echo "Invalid choice, skipping flake update."
;;
esac
# --- End selective flake update ---
current=""
if [ -f /etc/nixos-tags ]; then
current=$(cat /etc/nixos-tags)
fi
if [ -n "$current" ]; then
echo "Rebuilding system... Current specialization: $current"
else
echo "Rebuilding system... Staying on current specialization"
fi
if sudo nixos-rebuild switch --flake .; then
echo " Update and rebuild finished successfully for $HOST"
if [ -n "$current" ]; then
sudo /run/current-system/specialisation/$current/bin/switch-to-configuration test
else
echo "No specialization tag found, staying on default system."
fi
genn=$(sudo nix-env --list-generations --profile /nix/var/nix/profiles/system | grep current | awk '{print $1}')
echo -e "Running on new generation: $YELLOW $geno $NOCOLOR-> $GREEN$genn$NOCOLOR"
else
echo " Update and rebuild failed for $HOST" >&2
exit 1
fi
;;
commit)
cd "$HOME/$PROJECT" || { echo "Error: Could not change to $HOME/$PROJECT"; exit 1; }
if [ "$#" -lt 2 ]; then
read -p "Enter commit message: " commit_msg
else
shift
commit_msg="$*"
fi
if [ -z "$commit_msg" ]; then
echo "Error: Commit message cannot be empty" >&2
exit 1
fi
git add -A && git commit -m "$commit_msg"
;;
home-backups)
ls -a ~ | grep backup
;;
switch)
current=""
if [ -f /etc/nixos-tags ]; then
current=$(cat /etc/nixos-tags)
fi
if [ "$#" -ge 2 ]; then
spec_name="$2"
if [ -n "$current" ]; then
echo "Already on specialization: $current. Cannot switch directly to '$spec_name'. Please reboot or return to default first."
else
if [ -d "/run/current-system/specialisation/$spec_name" ]; then
echo "Switching to specialization: $spec_name"
sudo /run/current-system/specialisation/$spec_name/bin/switch-to-configuration test
else
echo "Error: Specialization '$spec_name' not found."
echo "Available specializations:"
ls /run/current-system/specialisation/
fi
fi
else
if [ -n "$current" ]; then
echo "Already on a specialization: $current. To switch, please reboot, or use 'sudo nixos-rebuild switch --flake .' to get back to default, and then switch after."
else
specs=$(ls /run/current-system/specialisation/)
echo "Specializations available:"
echo "$specs"
echo ""
echo "To switch to a specialization, run: 'ncli switch <tag>'"
fi
fi
;;
push)
cd "$HOME/$PROJECT" || { echo "Error: Could not change to $HOME/$PROJECT"; exit 1; }
git push origin $(git branch --show-current)
;;
pull)
cd "$HOME/$PROJECT" || { echo "Error: Could not change to $HOME/$PROJECT"; exit 1; }
git pull origin $(git branch --show-current)
;;
status)
cd "$HOME/$PROJECT" || { echo "Error: Could not change to $HOME/$PROJECT"; exit 1; }
git status
;;
format)
nix fmt .
;;
trim)
echo "Running 'sudo fstrim -v /' may take a few minutes and impact system performance."
read -p "Enter to run now or enter to exit (y/N): " -n 1 -r
echo # move to a new line
if [[ $REPLY =~ ^[Yy]$ ]]; then
echo "Running fstrim..."
sudo fstrim -v /
echo "fstrim complete."
else
echo "Trim operation cancelled."
fi
;;
dev)
# Only flake files need assume-unchanged (Nix requires them in the index).
# .envrc and .direnv are handled via .git/info/exclude instead.
DEV_FILES=(flake.nix flake.lock)
DIRENV_LOCAL_FILES=(.envrc .direnv)
_dev_resolve_dir() {
read -rp " Enter target directory [./]: " TARGET_DIR
TARGET_DIR="''${TARGET_DIR:-./}"
if [[ ! -d "$TARGET_DIR" ]]; then
print_error "Directory '$TARGET_DIR' does not exist."
exit 1
fi
TARGET_ABS="$(cd "$TARGET_DIR" && pwd)"
if ! git -C "$TARGET_ABS" rev-parse --git-dir > /dev/null 2>&1; then
print_error "No Git repository found at '$TARGET_ABS'."
exit 1
fi
}
# Add .envrc and .direnv to .git/info/exclude (local-only, never committed).
_add_local_excludes() {
local repo_abs="$1"
local git_dir exclude_file
git_dir="$(git -C "$repo_abs" rev-parse --git-dir)"
exclude_file="$git_dir/info/exclude"
mkdir -p "$(dirname "$exclude_file")"
touch "$exclude_file"
for entry in "''${DIRENV_LOCAL_FILES[@]}"; do
if ! grep -qxF "$entry" "$exclude_file" 2>/dev/null; then
echo "$entry" >> "$exclude_file"
print_success "$entry ignored via .git/info/exclude (local only)"
else
print_info "$entry already in .git/info/exclude, skipping."
fi
done
}
_remove_local_excludes() {
local repo_abs="$1"
local git_dir exclude_file tmp_file
git_dir="$(git -C "$repo_abs" rev-parse --git-dir)"
exclude_file="$git_dir/info/exclude"
[[ -f "$exclude_file" ]] || return 0
tmp_file="$(mktemp)"
cp "$exclude_file" "$tmp_file"
for entry in "''${DIRENV_LOCAL_FILES[@]}"; do
if grep -qxF "$entry" "$tmp_file" 2>/dev/null; then
grep -vxF "$entry" "$tmp_file" > "''${tmp_file}.new" || true
mv "''${tmp_file}.new" "$tmp_file"
print_success "$entry removed from .git/info/exclude"
else
print_info "$entry not present in .git/info/exclude, skipping."
fi
done
mv "$tmp_file" "$exclude_file"
}
case "''${2:-init}" in
untrack)
echo ""
echo -e "''${BLUE}--- Dev: Track Files (assume-unchanged) ---''${NOCOLOR}"
echo ""
_dev_resolve_dir
acted=false
for f in "''${DEV_FILES[@]}"; do
full="$TARGET_ABS/$f"
if [[ ! -f "$full" ]]; then
print_info "$f not found in $TARGET_ABS skipping."
continue
fi
if ! git -C "$TARGET_ABS" ls-files --error-unmatch "$f" > /dev/null 2>&1; then
git -C "$TARGET_ABS" add --intent-to-add "$f"
fi
git -C "$TARGET_ABS" update-index --assume-unchanged "$f"
print_success "$f untracked (assume-unchanged)"
acted=true
done
_add_local_excludes "$TARGET_ABS"
if ! $acted; then
print_info "No dev files found in '$TARGET_ABS' to track."
fi
;;
track)
echo ""
echo -e "''${BLUE}--- Dev: Untrack Files (remove assume-unchanged) ---''${NOCOLOR}"
echo ""
_dev_resolve_dir
acted=false
for f in "''${DEV_FILES[@]}"; do
if git -C "$TARGET_ABS" ls-files -v "$f" 2>/dev/null | grep -q "^h "; then
git -C "$TARGET_ABS" update-index --no-assume-unchanged "$f"
print_success "$f tracked (assume-unchanged removed)"
acted=true
else
print_info "$f is not marked assume-unchanged skipping."
fi
done
_remove_local_excludes "$TARGET_ABS"
if ! $acted; then
print_info "No files in '$TARGET_ABS' had the assume-unchanged bit set."
fi
;;
init|*)
# ---- Defaults -----
SOURCE_FLAKE="$HOME/$PROJECT/other/dev-template.nix"
# ---- Check source flake exists ------------------------------
if [[ ! -f "$SOURCE_FLAKE" ]]; then
print_error "Source flake template not found: $SOURCE_FLAKE"
echo "Please ensure dev-template.nix exists in $HOME/$PROJECT/other/"
exit 1
fi
print_header
# ---- Step 1: Target Directory -----------------------------------
echo -e "''${YELLOW}Step 1/5: Target Directory''${NOCOLOR}"
echo ""
read -p " Enter target directory [./]: " TARGET_DIR
if [[ -z "$TARGET_DIR" ]]; then
TARGET_DIR="./"
fi
if [[ ! -d "$TARGET_DIR" ]]; then
print_error "Directory '$TARGET_DIR' does not exist. Exiting."
exit 1
fi
print_success "Target directory: $TARGET_DIR"
echo ""
# ---- Check for existing flake ----------------------------------
if [[ -f "$TARGET_DIR/flake.nix" ]]; then
echo ""
print_error "A flake.nix already exists in '$TARGET_DIR'!"
echo ""
read -p " Would you like to just place the .envrc instead? [y/N]: " ENVRC_ONLY
ENVRC_ONLY="''${ENVRC_ONLY:-N}"
if [[ "$ENVRC_ONLY" =~ ^[Yy]$ ]]; then
TARGET_ABS="$(cd "$TARGET_DIR" && pwd)"
echo ""
print_info "Placing .envrc only..."
if ! grep -qxF "use flake" "$TARGET_ABS/.envrc" 2>/dev/null; then
echo "use flake" >> "$TARGET_ABS/.envrc"
print_success ".envrc created at $TARGET_ABS/"
else
print_info ".envrc already contains 'use flake', nothing to do."
fi
echo ""
print_info "Next steps:"
echo " cd $TARGET_DIR"
echo " direnv allow"
echo ""
exit 0
else
print_info "Aborting. No files were changed."
exit 1
fi
fi
# ---- Step 2: Project Name ---------------------------------------
echo -e "''${YELLOW}Step 2/5: Project Name''${NOCOLOR}"
echo ""
read -p " Enter development environment name [devShell]: " PROJECT_NAME
if [[ -z "$PROJECT_NAME" ]]; then
PROJECT_NAME="devShell"
fi
print_success "Project name: $PROJECT_NAME"
echo ""
# ---- Step 3: Select template ----------------------------------------
echo -e "''${YELLOW}Step 3/5: Select Template''${NOCOLOR}"
echo ""
echo " 1) Empty - Basic shell, add packages yourself"
echo " 2) Python - Python 3, pip, venv setup"
echo " 3) Node.js - Node.js, npm"
echo " 4) Rust - Rustc, cargo, rust-analyzer"
echo " 5) Go - Go, gopls, golangci-lint"
echo " 6) C/C++ - GCC, CMake, GDB, pkg-config"
echo " 7) Java - JDK 21, Maven"
echo ""
read -p " Select template [1-7] (default: 1): " TEMPLATE_CHOICE
case "$TEMPLATE_CHOICE" in
2)
TEMPLATE="python3"
PACKAGES="python3 python3Packages.pip python3Packages.virtualenv"
BUILD_INPUTS=""
SHELL_HOOK_EXTRA="
# Create venv if it doesn't exist
if [ ! -d .venv ]; then
echo 'Creating Python virtual environment...'
python3 -m venv .venv
fi
# Activate venv
source .venv/bin/activate
echo 'Python venv activated.'
"
;;
3)
TEMPLATE="node"
PACKAGES="nodejs_22"
BUILD_INPUTS=""
SHELL_HOOK_EXTRA='echo "Node.js $(node --version) ready."'
;;
4)
TEMPLATE="rust"
PACKAGES="rustc cargo rust-analyzer"
BUILD_INPUTS="openssl pkg-config"
SHELL_HOOK_EXTRA='echo "Rust $(rustc --version) ready."'
;;
5)
TEMPLATE="go"
PACKAGES="go gopls golangci-lint"
BUILD_INPUTS=""
SHELL_HOOK_EXTRA='
export GOPATH="$PWD/.gopath"
export PATH="$GOPATH/bin:$PATH"
mkdir -p "$GOPATH"
echo "Go $(go version) ready. GOPATH: $GOPATH"
'
;;
6)
TEMPLATE="cpp"
PACKAGES="gcc gdb cmake gnumake"
BUILD_INPUTS="pkg-config"
SHELL_HOOK_EXTRA='echo "GCC $(gcc --version | head -1) ready."'
;;
7)
TEMPLATE="java"
PACKAGES="jdk21 maven"
BUILD_INPUTS=""
SHELL_HOOK_EXTRA='echo "Java $(java --version | head -1) ready."'
;;
*)
TEMPLATE="empty"
PACKAGES=""
BUILD_INPUTS=""
SHELL_HOOK_EXTRA=""
;;
esac
print_success "Selected template: $TEMPLATE"
echo ""
# ---- Step 4: Copy and modify flake ----------------------------------
echo -e "''${YELLOW}Step 4/5: Generating flake.nix''${NOCOLOR}"
echo ""
cp "$SOURCE_FLAKE" "$TARGET_DIR/flake.nix"
print_success "Copied flake.nix to $TARGET_DIR/"
sed -i "s|name = \"replaceNameHere\";|name = \"''${PROJECT_NAME}\";|" "$TARGET_DIR/flake.nix"
print_success "Set project name: $PROJECT_NAME"
if [[ -n "$PACKAGES" ]]; then
sed -i "s|# replacePackagesHere|$PACKAGES|" "$TARGET_DIR/flake.nix"
print_success "Added packages: $PACKAGES"
fi
if [[ -n "$BUILD_INPUTS" ]]; then
BUILD_INPUTS_LINE="buildInputs = with pkgs; [ $BUILD_INPUTS ];"
sed -i "s|# replaceBuildInputsHere|$BUILD_INPUTS_LINE|" "$TARGET_DIR/flake.nix"
print_success "Added build inputs: $BUILD_INPUTS"
fi
if [[ -n "$SHELL_HOOK_EXTRA" ]]; then
awk -v hook="$SHELL_HOOK_EXTRA" '/# replaceShellHookHere/ { print hook; next } { print }' \
"$TARGET_DIR/flake.nix" > "$TARGET_DIR/flake.nix.tmp" \
&& mv "$TARGET_DIR/flake.nix.tmp" "$TARGET_DIR/flake.nix"
print_success "Added template-specific shell hook"
fi
# ---- Step 5: Git Integration & .envrc --------------------------------
echo -e "''${YELLOW}Step 5/5: Git Integration''${NOCOLOR}"
echo ""
TARGET_ABS="$(cd "$TARGET_DIR" && pwd)"
echo "Creating .envrc for direnv to automatically work!"
if ! grep -qxF "use flake" "$TARGET_ABS/.envrc" 2>/dev/null; then
echo "use flake" >> "$TARGET_ABS/.envrc"
print_success ".envrc created at $TARGET_ABS/"
else
print_info ".envrc already contains 'use flake', skipping."
fi
if git -C "$TARGET_ABS" rev-parse --git-dir > /dev/null 2>&1; then
echo " A Git repository was detected at:"
echo " $(git -C "$TARGET_ABS" rev-parse --show-toplevel)"
echo ""
# Always add .envrc and .direnv to local exclude no prompt needed,
# these should never be committed regardless.
_add_local_excludes "$TARGET_ABS"
echo ""
echo " Nix flakes require flake.nix (and flake.lock) to be Git-tracked."
echo " This script can stage them as 'assume-unchanged' so Nix sees them,"
echo " but they will NEVER be committed or show up in git status."
echo ""
read -p " Set up flake files as tracked-but-invisible to Git? [y/N]: " GIT_CHOICE
GIT_CHOICE="''${GIT_CHOICE:-N}"
if [[ "$GIT_CHOICE" =~ ^[Yy]$ ]]; then
cat > "$TARGET_ABS/flake.lock" << 'EOF'
{
"nodes": {
"root": {}
},
"root": "root",
"version": 7
}
EOF
print_success "flake.lock ready (Nix will populate it on first run if empty)"
git -C "$TARGET_ABS" add --intent-to-add flake.nix flake.lock
git -C "$TARGET_ABS" update-index --assume-unchanged flake.nix flake.lock
print_success "flake.nix + flake.lock tracked (assume-unchanged)"
else
print_info "Skipped. You can do this manually later:"
echo ""
echo " git -C \"$TARGET_ABS\" add --intent-to-add flake.nix flake.lock"
echo " git -C \"$TARGET_ABS\" update-index --assume-unchanged flake.nix flake.lock"
echo ""
fi
else
print_info "No Git repository detected skipping Git integration."
echo ""
fi
# ---- Done ---------------------------------------------------
echo -e "''${GREEN}==============================================''${NOCOLOR}"
echo -e "''${GREEN} Done! Your flake is ready at:''${NOCOLOR}"
echo -e "''${GREEN} $TARGET_DIR/flake.nix''${NOCOLOR}"
echo -e "''${GREEN}==============================================''${NOCOLOR}"
echo ""
print_info "Next steps:"
echo " cd $TARGET_DIR"
echo " direnv allow # Trust the .envrc so direnv auto-activates"
echo " nix develop # Or just: cd out and back in"
echo ""
;;
esac
;;
*)
echo "Error: Invalid command '$1'" >&2
print_help
exit 1
;;
esac
''

136
modules/ncli/builder.nix Normal file
View File

@ -0,0 +1,136 @@
# ncli/builder.nix — Assembles all modules into the final script
{
pkgs,
host,
backupFiles ? [".config/mimeapps.list.backup"],
project,
...
}: let
# --- Shared library ---
lib = import ./lib.nix {inherit pkgs host project backupFiles;};
# --- Command modules ---
rebuild = import ./commands/rebuild.nix lib;
maintenance = import ./commands/maintenance.nix lib;
git = import ./commands/git.nix lib;
switch = import ./commands/switch.nix lib;
dev = import ./commands/dev.nix lib;
# --- Help text ---
print_help = ''
print_help() {
echo "NixOS CLI Utility -- version 2.1.3"
echo ""
echo "Usage: ncli [command]"
echo ""
echo "System Commands:"
echo " rebuild - Rebuild the NixOS system configuration."
echo " update - Update the flake and rebuild the system."
echo ""
echo "Maintenance Commands:"
echo " cleanup - Clean up old system generations. Can specify a number to keep."
echo " diag - Create a system diagnostic report (saves to ~/diag.txt)."
echo " list-gens - List user and system generations."
echo " trim - Trim filesystems to improve SSD performance."
echo ""
echo "Git Commands:"
echo " commit [msg] - Add all changes and commit with message."
echo " push - Push changes to origin."
echo " pull - Pull latest changes from origin."
echo " status - Show git status."
echo ""
echo "Development Commands:"
echo " dev - Initialize a Nix development environment (flake.nix + direnv)."
echo " dev track - Remove assume-unchanged flag from flake files."
echo " dev untrack - Mark flake files as assume-unchanged in a directory."
echo ""
echo " help - Show this help message."
echo ""
}
'';
in
pkgs.writeShellScriptBin "ncli" ''
#!${pkgs.bash}/bin/bash
set -euo pipefail
# --- Configuration ---
PROJECT="${project}"
HOST="${host}"
BACKUP_FILES_STR="${lib.backupFilesString}"
VERSION="2.2.0"
FLAKE_NIX_PATH="$HOME/$PROJECT/flake.nix"
read -r -a BACKUP_FILES <<< "$BACKUP_FILES_STR"
# --- Read Colors file ---
source ${lib.colorsSource}
# --- Helper Functions ---
${lib.handle_backups}
${lib.handle_build_error}
${lib.print_header}
${lib.print_success}
${lib.print_error}
${lib.print_info}
${print_help}
# --- Main Logic ---
if [ "$#" -eq 0 ]; then
echo "Error: No command provided." >&2
print_help
exit 1
fi
case "$1" in
rebuild)
${rebuild.rebuild_case}
;;
update)
${rebuild.update_case}
;;
cleanup)
${maintenance.cleanup_case}
;;
diag)
${maintenance.diag_case}
;;
list-gens)
${maintenance.list_gens_case}
;;
trim)
${maintenance.trim_case}
;;
home-backups)
${maintenance.home_backups_case}
;;
commit)
${git.commit_case}
;;
push)
${git.push_case}
;;
pull)
${git.pull_case}
;;
status)
${git.status_case}
;;
format)
${git.format_case}
;;
switch)
${switch.switch_case}
;;
dev)
${dev.dev_case}
;;
help)
print_help
;;
*)
echo "Error: Invalid command '$1'" >&2
print_help
exit 1
;;
esac
''

View File

@ -0,0 +1,364 @@
# ncli/commands/dev.nix — dev init / track / untrack
lib: {
dev_case = ''
# Only flake files need assume-unchanged (Nix requires them in the index).
# .envrc and .direnv are handled via .git/info/exclude instead.
DEV_FILES=(flake.nix flake.lock)
DIRENV_LOCAL_FILES=(.envrc .direnv)
_dev_resolve_dir() {
read -rp " Enter target directory [./]: " TARGET_DIR
TARGET_DIR="''${TARGET_DIR:-./}"
if [[ ! -d "$TARGET_DIR" ]]; then
print_error "Directory '$TARGET_DIR' does not exist."
exit 1
fi
TARGET_ABS="$(cd "$TARGET_DIR" && pwd)"
if ! git -C "$TARGET_ABS" rev-parse --git-dir > /dev/null 2>&1; then
print_error "No Git repository found at '$TARGET_ABS'."
exit 1
fi
}
_add_local_excludes() {
local repo_abs="$1"
local git_dir exclude_file
git_dir="$(git -C "$repo_abs" rev-parse --git-dir)"
exclude_file="$git_dir/info/exclude"
mkdir -p "$(dirname "$exclude_file")"
touch "$exclude_file"
for entry in "''${DIRENV_LOCAL_FILES[@]}"; do
if ! grep -qxF "$entry" "$exclude_file" 2>/dev/null; then
echo "$entry" >> "$exclude_file"
print_success "$entry ignored via .git/info/exclude (local only)"
else
print_info "$entry already in .git/info/exclude, skipping."
fi
done
}
_remove_local_excludes() {
local repo_abs="$1"
local git_dir exclude_file tmp_file
git_dir="$(git -C "$repo_abs" rev-parse --git-dir)"
exclude_file="$git_dir/info/exclude"
[[ -f "$exclude_file" ]] || return 0
tmp_file="$(mktemp)"
cp "$exclude_file" "$tmp_file"
for entry in "''${DIRENV_LOCAL_FILES[@]}"; do
if grep -qxF "$entry" "$tmp_file" 2>/dev/null; then
grep -vxF "$entry" "$tmp_file" > "''${tmp_file}.new" || true
mv "''${tmp_file}.new" "$tmp_file"
print_success "$entry removed from .git/info/exclude"
else
print_info "$entry not present in .git/info/exclude, skipping."
fi
done
mv "$tmp_file" "$exclude_file"
}
case "''${2:-init}" in
untrack)
echo ""
echo -e "''${BLUE}--- Dev: Track Files (assume-unchanged) ---''${NOCOLOR}"
echo ""
_dev_resolve_dir
acted=false
for f in "''${DEV_FILES[@]}"; do
full="$TARGET_ABS/$f"
if [[ ! -f "$full" ]]; then
print_info "$f not found in $TARGET_ABS skipping."
continue
fi
if ! git -C "$TARGET_ABS" ls-files --error-unmatch "$f" > /dev/null 2>&1; then
git -C "$TARGET_ABS" add --intent-to-add "$f"
fi
git -C "$TARGET_ABS" update-index --assume-unchanged "$f"
print_success "$f untracked (assume-unchanged)"
acted=true
done
_add_local_excludes "$TARGET_ABS"
if ! $acted; then
print_info "No dev files found in '$TARGET_ABS' to track."
fi
;;
track)
echo ""
echo -e "''${BLUE}--- Dev: Untrack Files (remove assume-unchanged) ---''${NOCOLOR}"
echo ""
_dev_resolve_dir
acted=false
for f in "''${DEV_FILES[@]}"; do
if git -C "$TARGET_ABS" ls-files -v "$f" 2>/dev/null | grep -q "^h "; then
git -C "$TARGET_ABS" update-index --no-assume-unchanged "$f"
print_success "$f tracked (assume-unchanged removed)"
acted=true
else
print_info "$f is not marked assume-unchanged skipping."
fi
done
_remove_local_excludes "$TARGET_ABS"
if ! $acted; then
print_info "No files in '$TARGET_ABS' had the assume-unchanged bit set."
fi
;;
init|*)
SOURCE_FLAKE="$HOME/${lib.project}/other/dev-template.nix"
if [[ ! -f "$SOURCE_FLAKE" ]]; then
print_error "Source flake template not found: $SOURCE_FLAKE"
echo "Please ensure dev-template.nix exists in $HOME/${lib.project}/other/"
exit 1
fi
print_header
# ---- Step 1: Target Directory ----
echo -e "''${YELLOW}Step 1/5: Target Directory''${NOCOLOR}"
echo ""
read -p " Enter target directory [./]: " TARGET_DIR
if [[ -z "$TARGET_DIR" ]]; then
TARGET_DIR="./"
fi
if [[ ! -d "$TARGET_DIR" ]]; then
print_error "Directory '$TARGET_DIR' does not exist. Exiting."
exit 1
fi
print_success "Target directory: $TARGET_DIR"
echo ""
# ---- Check for existing flake ----
if [[ -f "$TARGET_DIR/flake.nix" ]]; then
echo ""
print_error "A flake.nix already exists in '$TARGET_DIR'!"
echo ""
read -p " Would you like to just place the .envrc instead? [y/N]: " ENVRC_ONLY
ENVRC_ONLY="''${ENVRC_ONLY:-N}"
if [[ "$ENVRC_ONLY" =~ ^[Yy]$ ]]; then
TARGET_ABS="$(cd "$TARGET_DIR" && pwd)"
echo ""
print_info "Placing .envrc only..."
if ! grep -qxF "use flake" "$TARGET_ABS/.envrc" 2>/dev/null; then
echo "use flake" >> "$TARGET_ABS/.envrc"
print_success ".envrc created at $TARGET_ABS/"
else
print_info ".envrc already contains 'use flake', nothing to do."
fi
echo ""
print_info "Next steps:"
echo " cd $TARGET_DIR"
echo " direnv allow"
echo ""
exit 0
else
print_info "Aborting. No files were changed."
exit 1
fi
fi
# ---- Step 2: Project Name ----
echo -e "''${YELLOW}Step 2/5: Project Name''${NOCOLOR}"
echo ""
read -p " Enter development environment name [devShell]: " PROJECT_NAME
if [[ -z "$PROJECT_NAME" ]]; then
PROJECT_NAME="devShell"
fi
print_success "Project name: $PROJECT_NAME"
echo ""
# ---- Step 3: Select template ----
echo -e "''${YELLOW}Step 3/5: Select Template''${NOCOLOR}"
echo ""
echo " 1) Empty - Basic shell, add packages yourself"
echo " 2) Python - Python 3, pip, venv setup"
echo " 3) Node.js - Node.js, npm"
echo " 4) Rust - Rustc, cargo, rust-analyzer"
echo " 5) Go - Go, gopls, golangci-lint"
echo " 6) C/C++ - GCC, CMake, GDB, pkg-config"
echo " 7) Java - JDK 21, Maven"
echo ""
read -p " Select template [1-7] (default: 1): " TEMPLATE_CHOICE
case "$TEMPLATE_CHOICE" in
2)
TEMPLATE="python3"
PACKAGES="python3 python3Packages.pip python3Packages.virtualenv"
BUILD_INPUTS=""
SHELL_HOOK_EXTRA="
if [ ! -d .venv ]; then
echo 'Creating Python virtual environment...'
python3 -m venv .venv
fi
source .venv/bin/activate
echo 'Python venv activated.'
"
;;
3)
TEMPLATE="node"
PACKAGES="nodejs_22"
BUILD_INPUTS=""
SHELL_HOOK_EXTRA='echo "Node.js $(node --version) ready."'
;;
4)
TEMPLATE="rust"
PACKAGES="rustc cargo rust-analyzer"
BUILD_INPUTS="openssl pkg-config"
SHELL_HOOK_EXTRA='echo "Rust $(rustc --version) ready."'
;;
5)
TEMPLATE="go"
PACKAGES="go gopls golangci-lint"
BUILD_INPUTS=""
SHELL_HOOK_EXTRA='
export GOPATH="$PWD/.gopath"
export PATH="$GOPATH/bin:$PATH"
mkdir -p "$GOPATH"
echo "Go $(go version) ready. GOPATH: $GOPATH"
'
;;
6)
TEMPLATE="cpp"
PACKAGES="gcc gdb cmake gnumake"
BUILD_INPUTS="pkg-config"
SHELL_HOOK_EXTRA='echo "GCC $(gcc --version | head -1) ready."'
;;
7)
TEMPLATE="java"
PACKAGES="jdk21 maven"
BUILD_INPUTS=""
SHELL_HOOK_EXTRA='echo "Java $(java --version | head -1) ready."'
;;
*)
TEMPLATE="empty"
PACKAGES=""
BUILD_INPUTS=""
SHELL_HOOK_EXTRA=""
;;
esac
print_success "Selected template: $TEMPLATE"
echo ""
# ---- Step 4: Copy and modify flake ----
echo -e "''${YELLOW}Step 4/5: Generating flake.nix''${NOCOLOR}"
echo ""
cp "$SOURCE_FLAKE" "$TARGET_DIR/flake.nix"
print_success "Copied flake.nix to $TARGET_DIR/"
sed -i "s|name = \"replaceNameHere\";|name = \"''${PROJECT_NAME}\";|" "$TARGET_DIR/flake.nix"
print_success "Set project name: $PROJECT_NAME"
if [[ -n "$PACKAGES" ]]; then
sed -i "s|# replacePackagesHere|$PACKAGES|" "$TARGET_DIR/flake.nix"
print_success "Added packages: $PACKAGES"
fi
if [[ -n "$BUILD_INPUTS" ]]; then
BUILD_INPUTS_LINE="buildInputs = with pkgs; [ $BUILD_INPUTS ];"
sed -i "s|# replaceBuildInputsHere|$BUILD_INPUTS_LINE|" "$TARGET_DIR/flake.nix"
print_success "Added build inputs: $BUILD_INPUTS"
fi
if [[ -n "$SHELL_HOOK_EXTRA" ]]; then
awk -v hook="$SHELL_HOOK_EXTRA" '/# replaceShellHookHere/ { print hook; next } { print }' \
"$TARGET_DIR/flake.nix" > "$TARGET_DIR/flake.nix.tmp" \
&& mv "$TARGET_DIR/flake.nix.tmp" "$TARGET_DIR/flake.nix"
print_success "Added template-specific shell hook"
fi
# ---- Step 5: Git Integration & .envrc ----
echo -e "''${YELLOW}Step 5/5: Git Integration''${NOCOLOR}"
echo ""
TARGET_ABS="$(cd "$TARGET_DIR" && pwd)"
echo "Creating .envrc for direnv to automatically work!"
if ! grep -qxF "use flake" "$TARGET_ABS/.envrc" 2>/dev/null; then
echo "use flake" >> "$TARGET_ABS/.envrc"
print_success ".envrc created at $TARGET_ABS/"
else
print_info ".envrc already contains 'use flake', skipping."
fi
if git -C "$TARGET_ABS" rev-parse --git-dir > /dev/null 2>&1; then
echo " A Git repository was detected at:"
echo " $(git -C "$TARGET_ABS" rev-parse --show-toplevel)"
echo ""
_add_local_excludes "$TARGET_ABS"
echo ""
echo " Nix flakes require flake.nix (and flake.lock) to be Git-tracked."
echo " This script can stage them as 'assume-unchanged' so Nix sees them,"
echo " but they will NEVER be committed or show up in git status."
echo ""
read -p " Set up flake files as tracked-but-invisible to Git? [y/N]: " GIT_CHOICE
GIT_CHOICE="''${GIT_CHOICE:-N}"
if [[ "$GIT_CHOICE" =~ ^[Yy]$ ]]; then
cat > "$TARGET_ABS/flake.lock" << 'FLAKE_LOCK_EOF'
{
"nodes": {
"root": {}
},
"root": "root",
"version": 7
}
FLAKE_LOCK_EOF
print_success "flake.lock ready (Nix will populate it on first run if empty)"
git -C "$TARGET_ABS" add --intent-to-add flake.nix flake.lock
git -C "$TARGET_ABS" update-index --assume-unchanged flake.nix flake.lock
print_success "flake.nix + flake.lock tracked (assume-unchanged)"
else
print_info "Skipped. You can do this manually later:"
echo ""
echo " git -C \"$TARGET_ABS\" add --intent-to-add flake.nix flake.lock"
echo " git -C \"$TARGET_ABS\" update-index --assume-unchanged flake.nix flake.lock"
echo ""
fi
else
print_info "No Git repository detected skipping Git integration."
echo ""
fi
# ---- Done ----
echo -e "''${GREEN}==============================================''${NOCOLOR}"
echo -e "''${GREEN} Done! Your flake is ready at:''${NOCOLOR}"
echo -e "''${GREEN} $TARGET_DIR/flake.nix''${NOCOLOR}"
echo -e "''${GREEN}==============================================''${NOCOLOR}"
echo ""
print_info "Next steps:"
echo " cd $TARGET_DIR"
echo " direnv allow # Trust the .envrc so direnv auto-activates"
echo " nix develop # Or just: cd out and back in"
echo ""
;;
esac
'';
}

View File

@ -0,0 +1,40 @@
# ncli/commands/git.nix — commit, push, pull, status, format
lib: let
inherit (lib) project;
in {
commit_case = ''
cd "$HOME/${project}" || { echo "Error: Could not change to $HOME/${project}"; exit 1; }
if [ "$#" -lt 2 ]; then
read -p "Enter commit message: " commit_msg
else
shift
commit_msg="$*"
fi
if [ -z "$commit_msg" ]; then
echo "Error: Commit message cannot be empty" >&2
exit 1
fi
git add -A && git commit -m "$commit_msg"
'';
push_case = ''
cd "$HOME/${project}" || { echo "Error: Could not change to $HOME/${project}"; exit 1; }
git push origin $(git branch --show-current)
'';
pull_case = ''
cd "$HOME/${project}" || { echo "Error: Could not change to $HOME/${project}"; exit 1; }
git pull origin $(git branch --show-current)
'';
status_case = ''
cd "$HOME/${project}" || { echo "Error: Could not change to $HOME/${project}"; exit 1; }
git status
'';
format_case = ''
nix fmt .
'';
}

View File

@ -0,0 +1,75 @@
# ncli/commands/maintenance.nix — cleanup, diag, list-gens, trim, home-backups
lib: let
inherit (lib) project;
in {
cleanup_case = ''
echo "Warning! This will remove old generations of your system."
read -p "How many generations to keep (default: all)? " keep_count
if [ -z "$keep_count" ]; then
read -p "This will remove all but the current generation. Continue (y/N)? " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
nh clean all -v
else
echo "Cleanup cancelled."
fi
else
read -p "This will keep the last $keep_count generations. Continue (y/N)? " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
nh clean all -k "$keep_count" -v
else
echo "Cleanup cancelled."
fi
fi
LOG_DIR="$HOME/ncli-cleanup-logs"
mkdir -p "$LOG_DIR"
LOG_FILE="$LOG_DIR/ncli-cleanup-$(date +%Y-%m-%d_%H-%M-%S).log"
echo "Cleaning up old log files..." >> "$LOG_FILE"
find "$LOG_DIR" -type f -mtime +3 -name "*.log" -delete >> "$LOG_FILE" 2>&1
echo "Cleanup process logged to $LOG_FILE"
'';
diag_case = ''
echo "Generating system diagnostic report..."
{
echo "=== NixOS System Diagnostic Report ==="
echo "Generated: $(date)"
echo ""
echo "=== System Information ==="
inxi --full 2>/dev/null || echo "inxi not available"
echo ""
echo "=== Git Status ==="
cd "$HOME/${project}" 2>/dev/null && git status 2>/dev/null || echo "Git status not available"
echo ""
} > "$HOME/diag.txt"
echo "Diagnostic report saved to $HOME/diag.txt"
'';
list_gens_case = ''
echo "--- User Generations ---"
nix-env --list-generations | cat || echo "Could not list user generations."
echo ""
echo "--- System Generations ---"
nix profile history --profile /nix/var/nix/profiles/system | cat || echo "Could not list system generations."
'';
trim_case = ''
echo "Running 'sudo fstrim -v /' may take a few minutes and impact system performance."
read -p "Enter to run now or enter to exit (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
echo "Running fstrim..."
sudo fstrim -v /
echo "fstrim complete."
else
echo "Trim operation cancelled."
fi
'';
home_backups_case = ''
ls -a ~ | grep backup
'';
}

View File

@ -0,0 +1,145 @@
# ncli/commands/rebuild.nix — Rebuild + Update logic
lib: let
inherit (lib) host project handle_backups handle_build_error;
in rec {
# Shared rebuild snippet used by both `rebuild` and `update`
rebuild_logic = ''
handle_backups
geno=$(sudo nix-env --list-generations --profile /nix/var/nix/profiles/system | grep current | awk '{print $1}')
cd "$HOME/${project}" || { echo "Error: Could not change to $HOME/${project}"; exit 1; }
current=""
if [ -f /etc/nixos-tags ]; then
current=$(cat /etc/nixos-tags)
fi
'';
rebuild_case = ''
${rebuild_logic}
echo -e "Starting NixOS rebuild for current host: ${host} on generation: $YELLOW$geno$NOCOLOR"
# Step 1: Build the configuration and safely update the bootloader first
set +e
sudo nixos-rebuild boot --flake .
_rebuild_exit=$?
set -e
if [ "$_rebuild_exit" -eq 0 ]; then
echo " Rebuild and bootloader update finished successfully for ${host}"
# Step 2: Now that boot entries are safe, activate the system live
echo "Activating new configuration..."
sudo /nix/var/nix/profiles/system/bin/switch-to-configuration switch
if [ -n "$current" ]; then
sudo /nix/var/nix/profiles/system/specialisation/"$current"/bin/switch-to-configuration test
else
echo "No specialization tag found, staying on default system."
fi
genn=$(sudo nix-env --list-generations --profile /nix/var/nix/profiles/system | grep current | awk '{print $1}')
echo -e "Running on new generation: $YELLOW $geno $NOCOLOR-> $GREEN$genn$NOCOLOR"
else
( exit "$_rebuild_exit" ); handle_build_error
echo " Rebuild failed for ${host}" >&2
exit 1
fi
'';
update_case = ''
${rebuild_logic}
echo -e "Updating flake and rebuilding system for current host: ${host} on generation: $YELLOW$geno$NOCOLOR"
# --- Selective flake update ---
read -rp "Update [a]ll inputs or [s]elect manually? (a/s): " choice
case "$choice" in
a|A)
echo "Updating all inputs..."
if nix flake update --flake .; then
echo " Flake updated successfully"
else
echo " Flake update failed" >&2
exit 1
fi
;;
s|S)
echo "Fetching available updates (this may take a moment)..."
TEMP_LOCK=$(mktemp)
trap 'rm -f "$TEMP_LOCK"' EXIT
nix flake update --output-lock-file "$TEMP_LOCK" --flake . 2>/dev/null
outdated=$(jq -r --slurpfile new "$TEMP_LOCK" '
.nodes as $old |
$new[0].nodes as $newn |
($old | keys[]) |
select(. != "root") |
select(
($old[.].locked.lastModified // 0) !=
($newn[.].locked.lastModified // 0)
)
' flake.lock)
if [[ -z "$outdated" ]]; then
echo " All inputs are already up to date, skipping flake update."
else
echo
echo "Updates available for:"
printf '%s\n' "$outdated"
echo
echo "Tab to select, Enter to update, Esc to cancel."
selected=$(printf '%s\n' "$outdated" | fzf --multi) || {
echo "No inputs selected, skipping flake update."
selected=""
}
if [[ -n "$selected" ]]; then
if nix flake update --flake . $selected; then
echo " Flake updated successfully"
else
echo " Flake update failed" >&2
exit 1
fi
fi
fi
;;
*)
echo "Invalid choice, skipping flake update."
;;
esac
# --- End selective flake update ---
if [ -n "$current" ]; then
echo "Rebuilding system... Current specialization: $current"
else
echo "Rebuilding system... Staying on current specialization"
fi
# Step 1: Build the configuration and safely update the bootloader first
set +e
sudo nixos-rebuild boot --flake .
_rebuild_exit=$?
set -e
if [ "$_rebuild_exit" -eq 0 ]; then
echo " Update, rebuild and bootloader update finished successfully for ${host}"
# Step 2: Now that boot entries are safe, activate the system live
echo "Activating new configuration..."
sudo /nix/var/nix/profiles/system/bin/switch-to-configuration switch
if [ -n "$current" ]; then
sudo /nix/var/nix/profiles/system/specialisation/"$current"/bin/switch-to-configuration test
else
echo "No specialization tag found, staying on default system."
fi
genn=$(sudo nix-env --list-generations --profile /nix/var/nix/profiles/system | grep current | awk '{print $1}')
echo -e "Running on new generation: $YELLOW $geno $NOCOLOR-> $GREEN$genn$NOCOLOR"
else
( exit "$_rebuild_exit" ); handle_build_error
echo " Update and rebuild failed for ${host}" >&2
exit 1
fi
'';
}

View File

@ -0,0 +1,35 @@
# ncli/commands/switch.nix — Specialization switching
lib: {
switch_case = ''
current=""
if [ -f /etc/nixos-tags ]; then
current=$(cat /etc/nixos-tags)
fi
if [ "$#" -ge 2 ]; then
spec_name="$2"
if [ -n "$current" ]; then
echo "Already on specialization: $current. Cannot switch directly to '$spec_name'. Please reboot or return to default first."
else
if [ -d "/run/current-system/specialisation/$spec_name" ]; then
echo "Switching to specialization: $spec_name"
sudo /run/current-system/specialisation/"$spec_name"/bin/switch-to-configuration test
else
echo "Error: Specialization '$spec_name' not found."
echo "Available specializations:"
ls /run/current-system/specialisation/
fi
fi
else
if [ -n "$current" ]; then
echo "Already on a specialization: $current. To switch, please reboot, or use 'sudo nixos-rebuild switch --flake .' to get back to default, and then switch after."
else
specs=$(ls /run/current-system/specialisation/)
echo "Specializations available:"
echo "$specs"
echo ""
echo "To switch to a specialization, run: 'ncli switch <tag>'"
fi
fi
'';
}

8
modules/ncli/default.nix Normal file
View File

@ -0,0 +1,8 @@
{
pkgs,
host,
backupFiles ? [".config/mimeapps.list.backup"],
project,
...
}:
import ./builder.nix {inherit pkgs host backupFiles project;}

88
modules/ncli/lib.nix Normal file
View File

@ -0,0 +1,88 @@
# ncli/lib.nix — Shared helpers and utilities
{ pkgs, host, project, backupFiles }:
let
backupFilesString = pkgs.lib.strings.concatStringsSep " " backupFiles;
in
{
# --- Injected config ---
inherit pkgs host project backupFiles backupFilesString;
# --- Color / banner source ---
colorsSource = "$HOME/${project}/other/colors.sh";
# --- Backup helper ---
handle_backups = ''
handle_backups() {
echo "Checking for backup files to remove..."
found=0
for file_path in "''${BACKUP_FILES[@]}"; do
full_path="$HOME/$file_path"
if [ -f "$full_path" ]; then
echo "Removing stale backup file: $full_path"
rm "$full_path"
found=1
fi
done
if [ "$found" -eq 0 ]; then
echo "No stale backup files found."
fi
}
'';
# --- OOM / build error handler ---
handle_build_error = ''
handle_build_error() {
local exit_code=$?
if [ "$exit_code" -eq 137 ]; then
echo ""
echo -e "''${RED}''${NOCOLOR}"
echo -e "''${RED} BUILD KILLED Signal 9 (SIGKILL) detected ''${NOCOLOR}"
echo -e "''${RED}''${NOCOLOR}"
echo ""
echo -e "''${YELLOW}What happened:''${NOCOLOR}"
echo " The build process was forcefully terminated by the OS."
echo " This is almost always the Linux kernel OOM killer running out"
echo " of RAM + swap during Nix evaluation or compilation."
echo ""
echo -e "''${YELLOW}Suggested fixes (try in order):''${NOCOLOR}"
echo ""
echo -e " ''${GREEN}1. Reduce parallel jobs''${NOCOLOR} (lowest RAM usage):"
echo " sudo nixos-rebuild switch --flake . --max-jobs 1 --cores 1"
echo ""
echo -e " ''${GREEN}2. Confirm OOM killer fired:''${NOCOLOR}"
echo " journalctl -k --since '5 minutes ago' | grep -i oom"
echo ""
fi
}
'';
# --- Print helpers (used by dev init) ---
print_header = ''
print_header() {
echo ""
echo -e "''${BLUE}==============================================''${NOCOLOR}"
echo -e "''${BLUE} Nix Flake Development Environment Initializer''${NOCOLOR}"
echo -e "''${BLUE}==============================================''${NOCOLOR}"
echo ""
}
'';
print_success = ''
print_success() {
echo -e "''${GREEN}[OK]''${NOCOLOR} $1"
}
'';
print_error = ''
print_error() {
echo -e "''${RED}[ERR]''${NOCOLOR} $1"
}
'';
print_info = ''
print_info() {
echo -e "''${YELLOW}[->]''${NOCOLOR} $1"
}
'';
}

View File

@ -1,5 +1,4 @@
{ {
config,
inputs, inputs,
pkgs, pkgs,
... ...
@ -7,11 +6,7 @@
imports = [ imports = [
]; ];
home-manager.sharedModules = [
./home.nix
];
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
hyprpaper inputs.noctalia.packages.${pkgs.stdenv.hostPlatform.system}.default
]; ];
} }

View File

@ -0,0 +1,9 @@
{inputs, ...}: {
imports = [
inputs.noctalia.homeModules.default
];
programs.noctalia = {
enable = true;
};
}

View File

@ -15,9 +15,15 @@
stylix = { stylix = {
enable = true; enable = true;
autoEnable = false; #So I can choose my programs it targets myself! autoEnable = false; #So I can choose my programs it targets myself!
#image = ../../other/wallpaper2.png; #image = "${inputs.cookiez-assets}/wallpapers/beach-forest.png";
#autoEnable = true; #Auto generate theme based on wallpaper #polarity = "dark"; # "dark" or "light"
base16Scheme = "${pkgs.base16-schemes}/share/themes/dracula.yaml"; base16Scheme = "${pkgs.base16-schemes}/share/themes/dracula.yaml";
#override = {
# base05 = "e0e0e0"; # default text — light grey (no # prefix!)
# base04 = "b0b0b0"; # secondary/muted text
# base06 = "f5f5f5"; # lighter text variant
#};
opacity = { opacity = {
desktop = 0.5; desktop = 0.5;
terminal = 0.9; terminal = 0.9;
@ -43,7 +49,8 @@
plymouth.logoAnimated = true; plymouth.logoAnimated = true;
console.enable = true; #Default console without desktop environment! (NOT KITTY!) console.enable = true; #Default console without desktop environment! (NOT KITTY!)
grub.enable = false; grub.enable = false;
#qt.enable = false; qt.enable = true;
gtk.enable = true;
}; };
}; };
} }

View File

@ -5,6 +5,7 @@
... ...
}: { }: {
imports = [ imports = [
inputs.niri.homeModules.stylix
]; ];
services = { services = {
@ -16,10 +17,9 @@
#firefox = { #firefox = {
# enable = true; # enable = true;
# colorTheme.enable = true; # colorTheme.enable = true;
# profileNames = [ "${username}" ]; # profileNames = ["${username}"];
#}; #};
qt.enable = false; niri.enable = true;
qt.platform = "kde";
#kde.enable = false; #kde.enable = false;
}; };
}; };

View File

@ -1,153 +0,0 @@
{
"layer": "top",
"position": "top",
"modules-left": [
"custom/launcher",
"hyprland/workspaces",
"cpu",
"memory"
],
"modules-center": [
"hyprland/window"
],
"spacing": 4,
"modules-right": [
"tray",
"wireplumber",
"network",
"backlight",
"clock",
"battery",
"custom/power"
],
"backlight": {
"device": "intel_backlight",
"format": "{percent}% {icon}",
"format-icons": ["", ""]
},
"hyprland/workspaces": {
"format": "{name}",
"persistent-workspaces": {
"1": [],
"2": [],
"3": []
}
},
"hyprland/window": {
"icon": false,
"separate-outputs": true,
"format": "{}"
},
"tray": {
"icon-size": 15,
"spacing": 7
},
"clock": {
"format": "{:%H:%M} ",
"format-alt": "{:%A, %B %d, %Y (%R)}",
"tooltip-format": "<tt><small>{calendar}</small></tt>",
"calendar": {
"mode": "year",
"mode-mon-col": 3,
"weeks-pos": "right",
"on-scroll": 1,
"on-click-right": "mode",
"format": {
"months": "<span color='#f5e0dc'><b>{}</b></span>",
"days": "<span color='#cdd6f4'><b>{}</b></span>",
"weeks": "<span color='#fab387'><b>W{}</b></span>",
"weekdays": "<span color='#f5c2e7'><b>{}</b></span>",
"today": "<span color='#cba6f7'><b><u>{}</u></b></span>"
}
},
"actions": {
"on-click-right": "mode",
"on-click-forward": "tz_up",
"on-click-backward": "tz_down",
"on-scroll-up": "shift_up",
"on-scroll-down": "shift_down"
}
},
"cpu": {
"interval": 1,
"format": "CPU {usage:>2}% {icon0}{icon1}{icon2}{icon3}",
"format-icons": [
"▁",
"▂",
"▃",
"▄",
"▅",
"▆",
"▇",
"█"
],
"on-click": "kitty -e btop"
},
"memory": {
"interval": 30,
"format": "MEM {used:0.1f}G/{total:0.1f}G"
},
"network": {
"format": "󰤭 Disabled",
"format-wifi": " ",
"format-ethernet": " 󰈀 ",
"format-disconnected": "⚠",
"tooltip": true,
"tooltip-format": "{ifname}\n{ipaddr}",
"tooltip-format-wifi": "{essid} {ifname}\n{ipaddr}\nstrength: {signalStrength}%",
"on-click": "networkmanager_dmenu"
},
"custom/launcher": {
"format": " 󰣇 ",
"tooltip": false,
"on-click": "wofi -c ~/.config/wofi/config -I"
},
"custom/power": {
"format": "  ",
"on-click": "~/.config/wofi/scripts/power.sh",
"tooltip": false
},
"wireplumber": {
"scroll-step": 10,
"format": "{volume}% {icon} ",
"format-bluetooth": "{icon} {volume}%",
"format-muted": "muted ",
"on-click": "pavucontrol",
"format-icons": {
"headphones": "",
"handsfree": "",
"headset": "",
"phone": "",
"portable": "",
"car": "",
"default": [
"",
"󰓃"
]
}
},
"battery": {
"states": {
"warning": 30,
"critical": 15
},
"format": "{capacity}% {icon}",
"format-charging": "󰂄 {capacity}%",
"format-pluged": "󱟦 {capacity}%",
"format-full": "󰁹 {capacity}%",
"format-icons": [
"󰂎",
"󰁺",
"󰁻",
"󰁼",
"󰁽",
"󰁾",
"󰁿",
"󰂀",
"󰂁",
"󰂂",
"󰁹"
]
}
}

View File

@ -1,4 +0,0 @@
{...}: {
# xdg.configFile."waybar/config.jsonc".source = ./config.jsonc;
# xdg.configFile."waybar/style.css".source = ./style.css;
}

View File

@ -1,167 +0,0 @@
* {
font-family: "JetBrainsMono Nerd Font", sans-serif;
font-size: 13px;
}
window#waybar {
background-color: transparent;
}
window > box {
margin-top: 0px;
margin-left: 10px;
margin-right: 10px;
padding-left: 4px;
padding-right: 4px;
}
#window {
background-color: #202020;
border-radius: 20px;
padding: 8px 12px 8px 8px;
margin: 0px 0;
}
window#waybar.empty #window {
background: rgba(12, 12, 12, 0);
}
.modules-left {
padding: 3px;
}
.modules-right {
padding: 3px;
}
.modules-center {
padding: 3px;
}
#workspaces {
background-color: #202020;
border-radius: 20px;
padding: 4px 4px 4px 6px;
margin: 4px 0;
}
#workspaces button {
min-height: 0;
padding: 0 7px;
margin-right: 2px;
color: #f5e0dc;
}
#workspaces button.urgent {
color: #f5e0dc;
animation-name: blink;
animation-duration: 0.5s;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-direction: alternate;
}
#workspaces button.empty {
color: #cdd6f4;
}
#workspaces button.visible {
color: #89dceb;
}
#workspaces button.active {
color: #fab387;
}
@keyframes blink {
to {
color: #202020;
background-color: #dcf5f3;
}
}
#custom-launcher {
background-color: #202020;
border-radius: 20px;
padding: 8px 8px 8px 4px;
margin: 4px 0;
color: #89dceb;
}
#custom-power {
background-color: #202020;
border-radius: 20px;
padding: 8px 12px 8px 8px;
margin: 4px 0;
}
#cpu {
background-color: #202020;
border-radius: 20px;
padding: 8px 8px 8px 20px;
margin: 4px 0;
color: #f2cdcd;
}
#memory {
background-color: #202020;
border-radius: 20px;
padding: 8px 8px 8px 20px;
margin: 4px 0;
color: #fab387;
}
#wireplumber {
background-color: #202020;
border-radius: 20px;
padding: 8px 8px 8px 20px;
margin: 4px 0;
color: #f9e2af;
}
#wireplumber.muted {
color: #f38ba8;
}
#clock {
background-color: #202020;
border-radius: 20px;
padding: 8px 10px 10px 10px;
margin: 4px 0;
color: #94e2d5;
}
#network {
background-color: #202020;
color: #cdd6f4;
border-radius: 20px;
padding: 8px;
margin: 4px 0;
}
#network.disabled {
color: #f38ba8;
}
#tray {
background-color: #202020;
border-radius: 20px;
padding: 8px 12px 8px 12px;
margin: 4px 0;
}
#battery {
background-color: #202020;
color: #cdd6f4;
border-radius: 20px;
padding: 8px;
margin: 4px 0;
}
#backlight {
background-color: #202020;
color: #cdd6f4;
border-radius: 20px;
padding: 8px;
margin: 4px 0;
}

View File

@ -1,5 +1,6 @@
{ {
config, config,
inputs,
pkgs, pkgs,
username, username,
project, project,
@ -7,31 +8,8 @@
}: { }: {
#To show logs of services run: #To show logs of services run:
#journalctl --user-unit={service-name} --user #journalctl --user-unit={service-name} --user
systemd.user.services.niri-waybar = {
description = "Waybar status bar for Niri";
# "wantedBy" replaces the [Install] section # The Niri Session Cleanup Service
wantedBy = ["graphical-session.target"];
# "partOf" and "after" replace the [Unit] section dependencies
partOf = ["graphical-session.target"];
after = ["graphical-session.target"];
# [Unit] configuration goes here
unitConfig = {
# This checks the environment variable to ensure we are in Niri
ConditionEnvironment = "XDG_CURRENT_DESKTOP=niri";
};
# [Service] configuration goes here
serviceConfig = {
ExecStart = "${pkgs.waybar}/bin/waybar";
Restart = "on-failure";
RestartSec = "1s";
};
};
# 2. The Niri Session Cleanup Service
# This service starts when the graphical session starts, and when it stops, # This service starts when the graphical session starts, and when it stops,
# it forcibly stops the graphical-session.target to ensure a clean state for the next login. # it forcibly stops the graphical-session.target to ensure a clean state for the next login.
systemd.user.services.niri-session-manager = { systemd.user.services.niri-session-manager = {

View File

@ -2,12 +2,12 @@
config, config,
inputs, inputs,
pkgs, pkgs,
system,
... ...
}: { }: {
imports = [ imports = [
./autostart.nix ./autostart.nix
../modules/hyprlock ../modules/hyprlock
../modules/hyprpaper
../modules/stylix ../modules/stylix
]; ];
@ -16,10 +16,8 @@
]; ];
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
#mako
fuzzel
waybar
xwayland-satellite xwayland-satellite
lxsession #Needed for things like gparted
]; ];
programs = { programs = {
@ -33,7 +31,6 @@
#services.xserver.displayManager.sddm.enable = true; #services.xserver.displayManager.sddm.enable = true;
xdg.portal = { xdg.portal = {
#Needed for waybar
enable = true; enable = true;
extraPortals = [pkgs.xdg-desktop-portal-gtk pkgs.xdg-desktop-portal-wlr]; extraPortals = [pkgs.xdg-desktop-portal-gtk pkgs.xdg-desktop-portal-wlr];
config.common.default = "*"; config.common.default = "*";

View File

@ -5,31 +5,13 @@
}: { }: {
imports = [ imports = [
inputs.niri.homeModules.niri inputs.niri.homeModules.niri
../modules/waybar/home.nix ../modules/noctalia/home.nix
]; ];
xdg.configFile."mako/config".text = ''
default-timeout=5000
ignore-timeout=1
'';
programs.niri = { programs.niri = {
package = pkgs.niri; package = pkgs.niri;
enable = true; enable = true;
#xwayland.enable = true;
# config = ''
# binds {
# Super+Return { spawn "kitty"; }
# Super+Space { spawn "fuzzel"; }
# Super+Q { close-window; }
# Super+Left { focus-column-left; }
# Super+Right { focus-column-right; }
# Super+Up { focus-workspace-up; }
# Super+Down { focus-workspace-down; }
# Super+L { spawn "hyprlock"; }
# Super+Shift+E { "quit"; }
# }
# '';
config = '' config = ''
input { input {
keyboard { keyboard {
@ -38,6 +20,10 @@
} }
numlock numlock
} }
mouse {
accel-profile "flat"
accel-speed -0.4
}
} }
prefer-no-csd prefer-no-csd
@ -83,11 +69,8 @@
} }
} }
// spawn-at-startup "waybar" spawn-at-startup "noctalia"
spawn-at-startup "hyprpaper" spawn-at-startup "lxpolkit"
spawn-at-startup "${pkgs.mako}/bin/mako"
// spawn-sh-at-startup "qs -c ~/source/qs/MyAwesomeShell"
hotkey-overlay { hotkey-overlay {
// Uncomment this line to disable the "Important Hotkeys" pop-up at startup. // Uncomment this line to disable the "Important Hotkeys" pop-up at startup.
@ -102,6 +85,11 @@
draw-border-with-background false draw-border-with-background false
} }
// layer-rule {
// match namespace="^awww-daemonbackdrop$"
// place-within-backdrop true
// }
output "eDP-1" { output "eDP-1" {
mode "2880x1920@120.000" mode "2880x1920@120.000"
scale 2 scale 2
@ -111,24 +99,26 @@
binds { binds {
Mod+Shift+Minus { show-hotkey-overlay; } Mod+Shift+Minus { show-hotkey-overlay; }
Mod+Shift+S hotkey-overlay-title="Make a screenshot selection" { spawn-sh "noctalia msg screenshot-region";}
Mod+T hotkey-overlay-title="Open a Terminal: kitty" { spawn "kitty"; } Mod+T hotkey-overlay-title="Open a Terminal: kitty" { spawn "kitty"; }
Mod+D hotkey-overlay-title="Run an Application: fuzzel" { spawn "fuzzel"; } Mod+D hotkey-overlay-title="Run an Application" { spawn-sh "noctalia msg panel-toggle launcher"; }
Super+L hotkey-overlay-title="Lock the Screen: hyprlock" { spawn "hyprlock"; } Super+L hotkey-overlay-title="Lock the Screen" { spawn-sh "noctalia msg session lock"; }
Super+Alt+S allow-when-locked=true hotkey-overlay-title=null { spawn-sh "pkill orca || exec orca"; } Super+Alt+S allow-when-locked=true hotkey-overlay-title=null { spawn-sh "pkill orca || exec orca"; }
XF86AudioRaiseVolume allow-when-locked=true { spawn-sh "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.1+ -l 1.0"; } XF86AudioRaiseVolume allow-when-locked=true { spawn-sh "noctalia msg volume-up"; }
XF86AudioLowerVolume allow-when-locked=true { spawn-sh "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.1-"; } XF86AudioLowerVolume allow-when-locked=true { spawn-sh "noctalia msg volume-down"; }
XF86AudioMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"; } XF86AudioMute allow-when-locked=true { spawn-sh "noctalia msg volume-mute"; }
XF86AudioMicMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"; } XF86AudioMicMute allow-when-locked=true { spawn-sh "noctalia msg mic-mute"; }
XF86AudioPlay allow-when-locked=true { spawn-sh "playerctl play-pause"; } XF86AudioPlay allow-when-locked=true { spawn-sh "playerctl play-pause"; }
XF86AudioStop allow-when-locked=true { spawn-sh "playerctl stop"; } XF86AudioStop allow-when-locked=true { spawn-sh "playerctl stop"; }
XF86AudioPrev allow-when-locked=true { spawn-sh "playerctl previous"; } XF86AudioPrev allow-when-locked=true { spawn-sh "playerctl previous"; }
XF86AudioNext allow-when-locked=true { spawn-sh "playerctl next"; } XF86AudioNext allow-when-locked=true { spawn-sh "playerctl next"; }
XF86MonBrightnessUp allow-when-locked=true { spawn "brightnessctl" "--class=backlight" "set" "+10%"; } XF86MonBrightnessUp allow-when-locked=true { spawn-sh "noctalia msg brightness-up"; }
XF86MonBrightnessDown allow-when-locked=true { spawn "brightnessctl" "--class=backlight" "set" "10%-"; } XF86MonBrightnessDown allow-when-locked=true { spawn-sh "noctalia msg brightness-down"; }
Mod+O repeat=false { toggle-overview; } Mod+O repeat=false { toggle-overview; }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 211 KiB

View File

@ -1,9 +0,0 @@
mkdir -p /var/lib/AccountsService/{icons,users}
cp /home/cookiez/NixOS/other/pfp.png /var/lib/AccountsService/icons/cookiez
echo -e "[User]\nIcon=/var/lib/AccountsService/icons/cookiez\n" > /var/lib/AccountsService/users/cookiez
chown root:root /var/lib/AccountsService/users/cookiez
chmod 0600 /var/lib/AccountsService/users/cookiez
chown root:root /var/lib/AccountsService/icons/cookiez
chmod 0444 /var/lib/AccountsService/icons/cookiez

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 MiB

View File

@ -12,6 +12,11 @@
description = "Automatically start Yakuake"; description = "Automatically start Yakuake";
after = ["graphical-session.target"]; after = ["graphical-session.target"];
wantedBy = ["graphical-session.target"]; wantedBy = ["graphical-session.target"];
unitConfig = {
ConditionEnvironment = "XDG_CURRENT_DESKTOP=KDE";
};
serviceConfig = { serviceConfig = {
ExecStart = ["${pkgs.kdePackages.yakuake}/bin/yakuake"]; ExecStart = ["${pkgs.kdePackages.yakuake}/bin/yakuake"];

View File

@ -1,5 +1,6 @@
{ {
config, config,
inputs,
pkgs, pkgs,
username, username,
project, project,
@ -8,13 +9,12 @@
# Define the custom background package with the correct relative path # Define the custom background package with the correct relative path
background-package = pkgs.stdenvNoCC.mkDerivation { background-package = pkgs.stdenvNoCC.mkDerivation {
name = "background-image"; name = "background-image";
src = ../other/wallpaper4.png; # Place wallpaper.jpg in the same directory as this config file src = "${inputs.cookiez-assets}/wallpapers/forest-cat.png"; # Place wallpaper.jpg in the same directory as this config file
dontUnpack = true; dontUnpack = true;
installPhase = '' installPhase = ''
cp $src $out cp $src $out
''; '';
}; };
plasmaTheme = "desktop"; #Possible values are "laptop" or "desktop" plasmaTheme = "desktop"; #Possible values are "laptop" or "desktop"
powerProfile = "laptop"; #Possible values are "laptop" or "desktop" powerProfile = "laptop"; #Possible values are "laptop" or "desktop"
in { in {
@ -38,8 +38,6 @@ in {
"sddm".serviceConfig.KillMode = "mixed"; "sddm".serviceConfig.KillMode = "mixed";
}; };
programs.gamemode.enable = true;
services = { services = {
xserver = { xserver = {
enable = true; enable = true;
@ -74,7 +72,6 @@ in {
system.activationScripts.script.text = '' system.activationScripts.script.text = ''
source /home/${username}/${project}/other/colors.sh source /home/${username}/${project}/other/colors.sh
source /home/${username}/${project}/other/pfp.sh
''; '';
environment = { environment = {

View File

@ -14,4 +14,7 @@
] ]
++ lib.optionals (plasmaTheme == "laptop") [./settings/laptop.nix] ++ lib.optionals (plasmaTheme == "laptop") [./settings/laptop.nix]
++ lib.optionals (plasmaTheme == "desktop") [./settings/desktop.nix]; ++ lib.optionals (plasmaTheme == "desktop") [./settings/desktop.nix];
#Add the wallpapers to be available to KDE wallpaper settings page
xdg.dataFile."wallpapers/cookiez".source = "${inputs.cookiez-assets}/wallpapers";
} }

View File

@ -123,7 +123,7 @@
}; };
}; };
configFile = { configFile = {
plasmarc.Wallpapers.usersWallpapers = "/home/cookiez/NixOS/other/wallpaper1.png"; plasmarc.Wallpapers.usersWallpapers = "${inputs.cookiez-assets}/wallpapers/pixel-desert.png";
}; };
}; };
}; };