This commit is contained in:
2025-12-07 17:25:31 +00:00
parent 3370e9856a
commit 621e38aa79
62 changed files with 2425 additions and 2370 deletions

View File

@@ -1 +1 @@
indentation = "TwoSpaces" indentation = "Tabs"

272
flake.nix
View File

@@ -1,144 +1,148 @@
{ {
description = "Configuration for my macOS laptops and NixOS server"; description = "Configuration for my macOS laptops and NixOS server";
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
flake-parts.url = "github:hercules-ci/flake-parts"; flake-parts.url = "github:hercules-ci/flake-parts";
sops-nix = { sops-nix = {
url = "github:Mic92/sops-nix"; url = "github:Mic92/sops-nix";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
home-manager = { home-manager = {
url = "github:nix-community/home-manager"; url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
darwin = { darwin = {
url = "github:LnL7/nix-darwin/master"; url = "github:LnL7/nix-darwin/master";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
nix-homebrew.url = "github:zhaofengli-wip/nix-homebrew"; nix-homebrew.url = "github:zhaofengli-wip/nix-homebrew";
homebrew-core = { homebrew-core = {
url = "github:homebrew/homebrew-core"; url = "github:homebrew/homebrew-core";
flake = false; flake = false;
}; };
homebrew-cask = { homebrew-cask = {
url = "github:homebrew/homebrew-cask"; url = "github:homebrew/homebrew-cask";
flake = false; flake = false;
}; };
nixvim.url = "github:nix-community/nixvim"; nixvim.url = "github:nix-community/nixvim";
zjstatus.url = "github:dj95/zjstatus"; zjstatus.url = "github:dj95/zjstatus";
nix-ai-tools.url = "github:numtide/nix-ai-tools"; nix-ai-tools.url = "github:numtide/nix-ai-tools";
beads.url = "github:steveyegge/beads"; beads.url = "github:steveyegge/beads";
tangled = { tangled = {
url = "git+https://tangled.org/tangled.org/core"; url = "git+https://tangled.org/tangled.org/core";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
disko = { disko = {
url = "github:nix-community/disko"; url = "github:nix-community/disko";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
}; };
outputs = inputs @ {flake-parts, ...}: outputs = inputs @ {flake-parts, ...}:
flake-parts.lib.mkFlake {inherit inputs;} ( flake-parts.lib.mkFlake {inherit inputs;} (
let let
constants = import ./lib/constants.nix; constants = import ./lib/constants.nix;
user = constants.user; user = constants.user;
darwinHosts = ["chidi" "jason"]; darwinHosts = ["chidi" "jason"];
nixosHosts = ["michael" "tahani"]; nixosHosts = ["michael" "tahani"];
overlays = import ./overlays {inherit inputs;}; overlays = import ./overlays {inherit inputs;};
in { in {
systems = [ systems = [
"x86_64-linux" "x86_64-linux"
"aarch64-darwin" "aarch64-darwin"
]; ];
flake.darwinConfigurations = inputs.nixpkgs.lib.genAttrs darwinHosts ( flake.darwinConfigurations =
hostname: inputs.nixpkgs.lib.genAttrs darwinHosts (
inputs.darwin.lib.darwinSystem { hostname:
system = "aarch64-darwin"; inputs.darwin.lib.darwinSystem {
specialArgs = { system = "aarch64-darwin";
inherit inputs user hostname constants; specialArgs = {
}; inherit inputs user hostname constants;
modules = [ };
inputs.home-manager.darwinModules.home-manager modules = [
inputs.nix-homebrew.darwinModules.nix-homebrew inputs.home-manager.darwinModules.home-manager
{ inputs.nix-homebrew.darwinModules.nix-homebrew
nixpkgs.overlays = overlays; {
nixpkgs.overlays = overlays;
nix-homebrew = { nix-homebrew = {
inherit user; inherit user;
enable = true; enable = true;
taps = { taps = {
"homebrew/homebrew-core" = inputs.homebrew-core; "homebrew/homebrew-core" = inputs.homebrew-core;
"homebrew/homebrew-cask" = inputs.homebrew-cask; "homebrew/homebrew-cask" = inputs.homebrew-cask;
}; };
mutableTaps = true; mutableTaps = true;
}; };
} }
./hosts/${hostname} ./hosts/${hostname}
]; ];
} }
); );
flake.nixosConfigurations = inputs.nixpkgs.lib.genAttrs nixosHosts ( flake.nixosConfigurations =
hostname: inputs.nixpkgs.lib.genAttrs nixosHosts (
inputs.nixpkgs.lib.nixosSystem { hostname:
system = "x86_64-linux"; inputs.nixpkgs.lib.nixosSystem {
specialArgs = { system = "x86_64-linux";
inherit inputs user hostname constants; specialArgs = {
}; inherit inputs user hostname constants;
modules = [ };
inputs.home-manager.nixosModules.home-manager modules = [
{ inputs.home-manager.nixosModules.home-manager
nixpkgs.overlays = overlays; {
} nixpkgs.overlays = overlays;
./hosts/${hostname} }
]; ./hosts/${hostname}
} ];
); }
);
perSystem = { perSystem = {
pkgs, pkgs,
system, system,
inputs', inputs',
... ...
}: let }: let
mkApp = name: { mkApp = name: {
type = "app"; type = "app";
program = "${(pkgs.writeShellScriptBin name '' program = "${(pkgs.writeShellScriptBin name ''
PATH=${pkgs.git}/bin:$PATH PATH=${pkgs.git}/bin:$PATH
echo "Running ${name} for ${system}" echo "Running ${name} for ${system}"
exec ${inputs.self}/apps/${system}/${name} "$@" exec ${inputs.self}/apps/${system}/${name} "$@"
'')}/bin/${name}"; '')}/bin/${name}";
}; };
appNames = [ appNames = [
"apply" "apply"
"build" "build"
"build-switch" "build-switch"
"rollback" "rollback"
]; ];
in { in {
devShells.default = pkgs.mkShell { devShells.default =
nativeBuildInputs = with pkgs; [ pkgs.mkShell {
bashInteractive nativeBuildInputs = with pkgs; [
git bashInteractive
age git
age-plugin-yubikey age
]; age-plugin-yubikey
shellHook = ''export EDITOR=nvim''; ];
}; shellHook = ''export EDITOR=nvim'';
};
apps = builtins.listToAttrs ( apps =
map (n: { builtins.listToAttrs (
name = n; map (n: {
value = mkApp n; name = n;
}) value = mkApp n;
appNames })
); appNames
}; );
flake.overlays = overlays; };
} flake.overlays = overlays;
); }
);
} }

View File

@@ -1,27 +1,27 @@
{ {
pkgs, pkgs,
user, user,
... ...
}: { }: {
imports = [ imports = [
../../modules/darwin ../../modules/darwin
]; ];
networking.hostName = "chidi"; networking.hostName = "chidi";
networking.computerName = "Chidi"; networking.computerName = "Chidi";
services.syncthing.settings.folders = { services.syncthing.settings.folders = {
"Projects/Work" = { "Projects/Work" = {
path = "/Users/${user}/Projects/Work"; path = "/Users/${user}/Projects/Work";
devices = ["tahani" "chidi"]; devices = ["tahani" "chidi"];
}; };
}; };
home-manager.users.${user} = { home-manager.users.${user} = {
programs.git.settings.user.email = "christoph@tuist.dev"; programs.git.settings.user.email = "christoph@tuist.dev";
}; };
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
slack slack
]; ];
} }

View File

@@ -1,36 +1,36 @@
{user, ...}: { {user, ...}: {
imports = [ imports = [
../../modules/darwin ../../modules/darwin
]; ];
networking.hostName = "jason"; networking.hostName = "jason";
networking.computerName = "Jason"; networking.computerName = "Jason";
services.syncthing.settings.folders = { services.syncthing.settings.folders = {
"Projects/Personal" = { "Projects/Personal" = {
path = "/Users/${user}/Projects/Personal"; path = "/Users/${user}/Projects/Personal";
devices = ["tahani" "jason"]; devices = ["tahani" "jason"];
}; };
}; };
sops.age.keyFile = "/Users/${user}/.config/sops/age/keys.txt"; sops.age.keyFile = "/Users/${user}/.config/sops/age/keys.txt";
sops.secrets = { sops.secrets = {
jason-syncthing-cert = { jason-syncthing-cert = {
sopsFile = ../../secrets/jason-syncthing-cert; sopsFile = ../../secrets/jason-syncthing-cert;
format = "binary"; format = "binary";
owner = user; owner = user;
path = "/Users/${user}/.config/syncthing/cert.pem"; path = "/Users/${user}/.config/syncthing/cert.pem";
}; };
jason-syncthing-key = { jason-syncthing-key = {
sopsFile = ../../secrets/jason-syncthing-key; sopsFile = ../../secrets/jason-syncthing-key;
format = "binary"; format = "binary";
owner = user; owner = user;
path = "/Users/${user}/.config/syncthing/key.pem"; path = "/Users/${user}/.config/syncthing/key.pem";
}; };
}; };
home-manager.users.${user} = { home-manager.users.${user} = {
programs.git.settings.user.email = "christoph@schmatzler.com"; programs.git.settings.user.email = "christoph@schmatzler.com";
}; };
} }

View File

@@ -22,7 +22,7 @@
}; };
}; };
networking.firewall.allowedTCPPorts = [ 80 443 ]; networking.firewall.allowedTCPPorts = [80 443];
services.caddy = { services.caddy = {
enable = true; enable = true;

View File

@@ -1,112 +1,112 @@
{ {
config, config,
hostname, hostname,
user, user,
... ...
}: { }: {
imports = [ imports = [
../../modules/nixos ../../modules/nixos
]; ];
services.adguardhome = { services.adguardhome = {
enable = true; enable = true;
port = 10000; port = 10000;
settings = { settings = {
dns = { dns = {
upstream_dns = [ upstream_dns = [
"1.1.1.1" "1.1.1.1"
"1.0.0.1" "1.0.0.1"
]; ];
}; };
filtering = { filtering = {
protection_enabled = true; protection_enabled = true;
filtering_enabled = true; filtering_enabled = true;
safe_search = { safe_search = {
enabled = false; enabled = false;
}; };
}; };
}; };
}; };
virtualisation.docker = { virtualisation.docker = {
enable = true; enable = true;
}; };
services.openssh = { services.openssh = {
enable = true; enable = true;
settings = { settings = {
PermitRootLogin = "prohibit-password"; PermitRootLogin = "prohibit-password";
PasswordAuthentication = false; PasswordAuthentication = false;
}; };
}; };
fileSystems."/" = { fileSystems."/" = {
device = "/dev/disk/by-label/NIXROOT"; device = "/dev/disk/by-label/NIXROOT";
fsType = "ext4"; fsType = "ext4";
}; };
fileSystems."/boot" = { fileSystems."/boot" = {
device = "/dev/disk/by-label/NIXBOOT"; device = "/dev/disk/by-label/NIXBOOT";
fsType = "vfat"; fsType = "vfat";
}; };
networking = { networking = {
hostName = hostname; hostName = hostname;
useDHCP = false; useDHCP = false;
interfaces.eno1.ipv4.addresses = [ interfaces.eno1.ipv4.addresses = [
{ {
address = "192.168.1.10"; address = "192.168.1.10";
prefixLength = 24; prefixLength = 24;
} }
]; ];
defaultGateway = "192.168.1.1"; defaultGateway = "192.168.1.1";
nameservers = ["1.1.1.1"]; nameservers = ["1.1.1.1"];
firewall = { firewall = {
enable = true; enable = true;
trustedInterfaces = ["eno1" "tailscale0"]; trustedInterfaces = ["eno1" "tailscale0"];
allowedUDPPorts = [config.services.tailscale.port]; allowedUDPPorts = [config.services.tailscale.port];
allowedTCPPorts = [22 5555]; allowedTCPPorts = [22 5555];
checkReversePath = "loose"; checkReversePath = "loose";
}; };
}; };
sops.secrets = { sops.secrets = {
tahani-syncthing-cert = { tahani-syncthing-cert = {
sopsFile = ../../secrets/tahani-syncthing-cert; sopsFile = ../../secrets/tahani-syncthing-cert;
format = "binary"; format = "binary";
owner = user; owner = user;
path = "/home/${user}/.config/syncthing/cert.pem"; path = "/home/${user}/.config/syncthing/cert.pem";
}; };
tahani-syncthing-key = { tahani-syncthing-key = {
sopsFile = ../../secrets/tahani-syncthing-key; sopsFile = ../../secrets/tahani-syncthing-key;
format = "binary"; format = "binary";
owner = user; owner = user;
path = "/home/${user}/.config/syncthing/key.pem"; path = "/home/${user}/.config/syncthing/key.pem";
}; };
}; };
services.syncthing.settings.folders = { services.syncthing.settings.folders = {
"Projects/Personal" = { "Projects/Personal" = {
path = "/home/${user}/Projects/Personal"; path = "/home/${user}/Projects/Personal";
devices = ["tahani" "jason"]; devices = ["tahani" "jason"];
}; };
"Projects/Work" = { "Projects/Work" = {
path = "/home/${user}/Projects/Work"; path = "/home/${user}/Projects/Work";
devices = ["tahani" "chidi"]; devices = ["tahani" "chidi"];
}; };
}; };
services.gitea = { services.gitea = {
enable = true; enable = true;
settings = { settings = {
server = { server = {
DOMAIN = "git.tahani"; DOMAIN = "git.tahani";
HTTP_PORT = 8380; HTTP_PORT = 8380;
}; };
}; };
}; };
home-manager.users.${user} = { home-manager.users.${user} = {
programs.git.settings.user.email = "christoph@schmatzler.com"; programs.git.settings.user.email = "christoph@schmatzler.com";
}; };
} }

View File

@@ -1,14 +1,14 @@
{ {
user = "cschmatzler"; user = "cschmatzler";
sshKeys = [ sshKeys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHfRZQ+7ejD3YHbyMTrV0gN1Gc0DxtGgl5CVZSupo5ws" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHfRZQ+7ejD3YHbyMTrV0gN1Gc0DxtGgl5CVZSupo5ws"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL/I+/2QT47raegzMIyhwMEPKarJP/+Ox9ewA4ZFJwk/" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL/I+/2QT47raegzMIyhwMEPKarJP/+Ox9ewA4ZFJwk/"
]; ];
stateVersions = { stateVersions = {
darwin = 6; darwin = 6;
nixos = "25.11"; nixos = "25.11";
homeManager = "25.11"; homeManager = "25.11";
}; };
} }

View File

@@ -1,8 +1,8 @@
{pkgs}: {pkgs}:
pkgs.writeShellScriptBin "open-project" '' pkgs.writeShellScriptBin "open-project" ''
TARGET=$(fd -t d --exact-depth 1 . $HOME/Projects | TARGET=$(fd -t d --exact-depth 1 . $HOME/Projects |
sed "s~$HOME/Projects/~~" | sed "s~$HOME/Projects/~~" |
fzf --prompt "project > ") fzf --prompt "project > ")
zellij run -i -- /${pkgs.fish}/bin/fish -c "cd $HOME/Projects/$TARGET; fish" zellij run -i -- /${pkgs.fish}/bin/fish -c "cd $HOME/Projects/$TARGET; fish"
'' ''

View File

@@ -1,33 +1,33 @@
{pkgs, ...}: { {pkgs, ...}: {
programs.fish.enable = true; programs.fish.enable = true;
nixpkgs = { nixpkgs = {
config = { config = {
allowUnfree = true; allowUnfree = true;
}; };
}; };
nix = { nix = {
package = pkgs.nix; package = pkgs.nix;
settings = { settings = {
trusted-users = [ trusted-users = [
"@admin" "@admin"
]; ];
substituters = [ substituters = [
"https://nix-community.cachix.org" "https://nix-community.cachix.org"
"https://cache.nixos.org" "https://cache.nixos.org"
]; ];
trusted-public-keys = [ trusted-public-keys = [
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
]; ];
}; };
gc = { gc = {
automatic = true; automatic = true;
options = "--delete-older-than 30d"; options = "--delete-older-than 30d";
}; };
extraOptions = '' extraOptions = ''
experimental-features = nix-command flakes experimental-features = nix-command flakes
''; '';
}; };
} }

View File

@@ -1,10 +1,11 @@
{pkgs}: let {pkgs}: let
wallpaper = pkgs.fetchurl { wallpaper =
url = "https://misc-assets.raycast.com/wallpapers/bright-rain.png"; pkgs.fetchurl {
sha256 = "sha256-wQT4I2X3gS6QFsEb7MdRsn4oX7FNkflukXPGMFbJZ10="; url = "https://misc-assets.raycast.com/wallpapers/bright-rain.png";
}; sha256 = "sha256-wQT4I2X3gS6QFsEb7MdRsn4oX7FNkflukXPGMFbJZ10=";
};
in in
pkgs.writeShellScriptBin "set-wallpaper-script" '' pkgs.writeShellScriptBin "set-wallpaper-script" ''
set -e set -e
/usr/bin/osascript -e "tell application \"Finder\" to set desktop picture to POSIX file \"${wallpaper}\"" /usr/bin/osascript -e "tell application \"Finder\" to set desktop picture to POSIX file \"${wallpaper}\""
'' ''

View File

@@ -1,79 +1,79 @@
{ {
config, config,
constants, constants,
inputs, inputs,
pkgs, pkgs,
user, user,
... ...
}: { }: {
imports = [ imports = [
../core.nix ../core.nix
../syncthing.nix ../syncthing.nix
../tailscale.nix ../tailscale.nix
./dock ./dock
./homebrew.nix ./homebrew.nix
./syncthing.nix ./syncthing.nix
./system.nix ./system.nix
inputs.sops-nix.darwinModules.sops inputs.sops-nix.darwinModules.sops
]; ];
system = { system = {
primaryUser = user; primaryUser = user;
stateVersion = constants.stateVersions.darwin; stateVersion = constants.stateVersions.darwin;
}; };
nix = { nix = {
settings.trusted-users = ["@admin" "${user}"]; settings.trusted-users = ["@admin" "${user}"];
gc.interval = { gc.interval = {
Weekday = 0; Weekday = 0;
Hour = 2; Hour = 2;
Minute = 0; Minute = 0;
}; };
}; };
users.users.${user} = { users.users.${user} = {
name = "${user}"; name = "${user}";
home = "/Users/${user}"; home = "/Users/${user}";
isHidden = false; isHidden = false;
shell = pkgs.fish; shell = pkgs.fish;
}; };
home-manager = { home-manager = {
useGlobalPkgs = true; useGlobalPkgs = true;
users.${user} = { users.${user} = {
pkgs, pkgs,
config, config,
lib, lib,
... ...
}: { }: {
_module.args = {inherit user constants inputs;}; _module.args = {inherit user constants inputs;};
imports = [ imports = [
inputs.nixvim.homeModules.nixvim inputs.nixvim.homeModules.nixvim
../home/default.nix ../home/default.nix
./home/default.nix ./home/default.nix
]; ];
fonts.fontconfig.enable = true; fonts.fontconfig.enable = true;
}; };
}; };
local = { local = {
dock = { dock = {
enable = true; enable = true;
username = user; username = user;
entries = [ entries = [
{path = "/Applications/Helium.app/";} {path = "/Applications/Helium.app/";}
{path = "${config.users.users.${user}.home}/Applications/Home Manager Apps/Ghostty.app/";} {path = "${config.users.users.${user}.home}/Applications/Home Manager Apps/Ghostty.app/";}
{path = "/System/Applications/Calendar.app/";} {path = "/System/Applications/Calendar.app/";}
{path = "/System/Applications/Mail.app/";} {path = "/System/Applications/Mail.app/";}
{path = "/System/Applications/Notes.app/";} {path = "/System/Applications/Notes.app/";}
{path = "/System/Applications/Music.app/";} {path = "/System/Applications/Music.app/";}
{path = "/System/Applications/System Settings.app/";} {path = "/System/Applications/System Settings.app/";}
{ {
path = "${config.users.users.${user}.home}/Downloads"; path = "${config.users.users.${user}.home}/Downloads";
section = "others"; section = "others";
options = "--sort name --view grid --display stack"; options = "--sort name --view grid --display stack";
} }
]; ];
}; };
}; };
} }

View File

@@ -1,104 +1,110 @@
{ {
config, config,
pkgs, pkgs,
lib, lib,
... ...
}: }:
with lib; let with lib; let
cfg = config.local.dock; cfg = config.local.dock;
inherit (pkgs) stdenv dockutil; inherit (pkgs) stdenv dockutil;
in { in {
options = { options = {
local.dock = { local.dock = {
enable = mkOption { enable =
description = "Enable dock"; mkOption {
default = stdenv.isDarwin; description = "Enable dock";
example = false; default = stdenv.isDarwin;
}; example = false;
};
entries = mkOption { entries =
description = "Entries on the Dock"; mkOption {
type = with types; description = "Entries on the Dock";
listOf (submodule { type = with types;
options = { listOf (submodule {
path = lib.mkOption {type = str;}; options = {
section = lib.mkOption { path = lib.mkOption {type = str;};
type = str; section =
default = "apps"; lib.mkOption {
}; type = str;
options = lib.mkOption { default = "apps";
type = str; };
default = ""; options =
}; lib.mkOption {
}; type = str;
}); default = "";
readOnly = true; };
}; };
});
readOnly = true;
};
username = mkOption { username =
description = "Username to apply the dock settings to"; mkOption {
type = types.str; description = "Username to apply the dock settings to";
}; type = types.str;
}; };
}; };
};
config = mkIf cfg.enable ( config =
let mkIf cfg.enable (
normalize = path: let
if hasSuffix ".app" path normalize = path:
then path + "/" if hasSuffix ".app" path
else path; then path + "/"
entryURI = path: else path;
"file://" entryURI = path:
+ ( "file://"
builtins.replaceStrings + (
[ builtins.replaceStrings
" " [
"!" " "
"\"" "!"
"#" "\""
"$" "#"
"%" "$"
"&" "%"
"'" "&"
"(" "'"
")" "("
] ")"
[ ]
"%20" [
"%21" "%20"
"%22" "%21"
"%23" "%22"
"%24" "%23"
"%25" "%24"
"%26" "%25"
"%27" "%26"
"%28" "%27"
"%29" "%28"
] "%29"
(normalize path) ]
); (normalize path)
wantURIs = concatMapStrings (entry: "${entryURI entry.path}\n") cfg.entries; );
createEntries = wantURIs = concatMapStrings (entry: "${entryURI entry.path}\n") cfg.entries;
concatMapStrings ( createEntries =
entry: "${dockutil}/bin/dockutil --no-restart --add '${entry.path}' --section ${entry.section} ${entry.options}\n" concatMapStrings (
) entry: "${dockutil}/bin/dockutil --no-restart --add '${entry.path}' --section ${entry.section} ${entry.options}\n"
cfg.entries; )
in { cfg.entries;
system.activationScripts.postActivation.text = '' in {
echo >&2 "Setting up the Dock for ${cfg.username}..." system.activationScripts.postActivation.text = ''
su ${cfg.username} -s /bin/sh <<'USERBLOCK' echo >&2 "Setting up the Dock for ${cfg.username}..."
haveURIs="$(${dockutil}/bin/dockutil --list | ${pkgs.coreutils}/bin/cut -f2)" su ${cfg.username} -s /bin/sh <<-'USERBLOCK'
if ! diff -wu <(echo -n "$haveURIs") <(echo -n '${wantURIs}') >&2 ; then haveURIs="$(${dockutil}/bin/dockutil --list | ${pkgs.coreutils}/bin/cut -f2)"
echo >&2 "Resetting Dock." if ! diff -wu <(echo -n "$haveURIs") <(echo -n '${wantURIs}') >&2 ; then
${dockutil}/bin/dockutil --no-restart --remove all echo >&2 "Resetting Dock."
${createEntries} ${dockutil}/bin/dockutil --no-restart --remove all
killall Dock ${createEntries}
else killall Dock
echo >&2 "Dock setup complete." else
fi echo >&2 "Dock setup complete."
USERBLOCK fi
''; USERBLOCK
} '';
); }
);
} }

View File

@@ -1,21 +1,22 @@
{ {
pkgs, pkgs,
lib, lib,
... ...
}: let }: let
setWallpaperScript = import ../bin/wallpaper.nix {inherit pkgs;}; setWallpaperScript = import ../bin/wallpaper.nix {inherit pkgs;};
in { in {
imports = [ imports = [
./ghostty.nix ./ghostty.nix
]; ];
home = { home = {
packages = pkgs.callPackage ../packages.nix {}; packages = pkgs.callPackage ../packages.nix {};
activation = { activation = {
"setWallpaper" = lib.hm.dag.entryAfter ["revealHomeLibraryDirectory"] '' "setWallpaper" =
echo "[+] Setting wallpaper" lib.hm.dag.entryAfter ["revealHomeLibraryDirectory"] ''
${setWallpaperScript}/bin/set-wallpaper-script echo "[+] Setting wallpaper"
''; ${setWallpaperScript}/bin/set-wallpaper-script
}; '';
}; };
};
} }

View File

@@ -1,22 +1,22 @@
{pkgs, ...}: { {pkgs, ...}: {
programs.ghostty = { programs.ghostty = {
enable = true; enable = true;
package = pkgs.ghostty-bin; package = pkgs.ghostty-bin;
settings = { settings = {
command = "${pkgs.fish}/bin/fish"; command = "${pkgs.fish}/bin/fish";
theme = "Catppuccin Latte"; theme = "Catppuccin Latte";
window-padding-x = 12; window-padding-x = 12;
window-padding-y = 3; window-padding-y = 3;
window-padding-balance = true; window-padding-balance = true;
font-family = "TX-02 SemiCondensed"; font-family = "TX-02 SemiCondensed";
font-size = 16.5; font-size = 16.5;
cursor-style = "block"; cursor-style = "block";
mouse-hide-while-typing = true; mouse-hide-while-typing = true;
mouse-scroll-multiplier = 1.25; mouse-scroll-multiplier = 1.25;
shell-integration = "detect"; shell-integration = "detect";
shell-integration-features = "no-cursor"; shell-integration-features = "no-cursor";
clipboard-read = "allow"; clipboard-read = "allow";
clipboard-write = "allow"; clipboard-write = "allow";
}; };
}; };
} }

View File

@@ -1,10 +1,10 @@
{ {
homebrew = { homebrew = {
enable = true; enable = true;
casks = [ casks = [
"helium-browser" "helium-browser"
"pearcleaner" "pearcleaner"
"tidal" "tidal"
]; ];
}; };
} }

View File

@@ -1,10 +1,10 @@
{pkgs}: {pkgs}:
with pkgs; [ with pkgs; [
_1password-gui _1password-gui
dockutil dockutil
mas mas
raycast raycast
tailscale tailscale
# whatsapp-for-mac # whatsapp-for-mac
xcodes xcodes
] ]

View File

@@ -1,396 +1,437 @@
{ {
config, config,
lib, lib,
pkgs, pkgs,
... ...
}: }:
with lib; let with lib; let
cfg = config.services.syncthing; cfg = config.services.syncthing;
settingsFormat = pkgs.formats.json {}; settingsFormat = pkgs.formats.json {};
cleanedConfig = converge (filterAttrsRecursive (_: v: v != null && v != {})) cfg.settings; cleanedConfig = converge (filterAttrsRecursive (_: v: v != null && v != {})) cfg.settings;
isUnixGui = (builtins.substring 0 1 cfg.guiAddress) == "/"; isUnixGui = (builtins.substring 0 1 cfg.guiAddress) == "/";
curlAddressArgs = path: curlAddressArgs = path:
if isUnixGui if isUnixGui
then "--unix-socket ${cfg.guiAddress} http://.${path}" then "--unix-socket ${cfg.guiAddress} http://.${path}"
else "${cfg.guiAddress}${path}"; else "${cfg.guiAddress}${path}";
devices = mapAttrsToList (_: device: device // {deviceID = device.id;}) cfg.settings.devices; devices = mapAttrsToList (_: device: device // {deviceID = device.id;}) cfg.settings.devices;
anyAutoAccept = builtins.any (dev: dev.autoAcceptFolders) devices; anyAutoAccept = builtins.any (dev: dev.autoAcceptFolders) devices;
folders = mapAttrsToList (_: folder: folders =
folder mapAttrsToList (_: folder:
// { folder
devices = let // {
folderDevices = folder.devices; devices = let
in folderDevices = folder.devices;
map ( in
device: map (
if builtins.isString device device:
then {deviceId = cfg.settings.devices.${device}.id;} if builtins.isString device
else if builtins.isAttrs device then {deviceId = cfg.settings.devices.${device}.id;}
then {deviceId = cfg.settings.devices.${device.name}.id;} // device else if builtins.isAttrs device
else throw "Invalid type for devices in folder; expected list or attrset." then {deviceId = cfg.settings.devices.${device.name}.id;} // device
) else throw "Invalid type for devices in folder; expected list or attrset."
folderDevices; )
}) (filterAttrs (_: folder: folder.enable) cfg.settings.folders); folderDevices;
}) (filterAttrs (_: folder: folder.enable) cfg.settings.folders);
jq = "${pkgs.jq}/bin/jq"; jq = "${pkgs.jq}/bin/jq";
updateConfig = pkgs.writers.writeBash "merge-syncthing-config" ( updateConfig =
'' pkgs.writers.writeBash "merge-syncthing-config" (
set -efu ''
umask 0077 set -efu
umask 0077
curl() { curl() {
while while
! ${pkgs.libxml2}/bin/xmllint \ ! ${pkgs.libxml2}/bin/xmllint \
--xpath 'string(configuration/gui/apikey)' \ --xpath 'string(configuration/gui/apikey)' \
${cfg.configDir}/config.xml \ ${cfg.configDir}/config.xml \
>"$TMPDIR/api_key" >"$TMPDIR/api_key"
do sleep 1; done do sleep 1; done
(printf "X-API-Key: "; cat "$TMPDIR/api_key") >"$TMPDIR/headers" (printf "X-API-Key: "; cat "$TMPDIR/api_key") >"$TMPDIR/headers"
${pkgs.curl}/bin/curl -sSLk -H "@$TMPDIR/headers" \ ${pkgs.curl}/bin/curl -sSLk -H "@$TMPDIR/headers" \
--retry 1000 --retry-delay 1 --retry-all-errors \ --retry 1000 --retry-delay 1 --retry-all-errors \
"$@" "$@"
} }
'' ''
+ (lib.pipe { + (lib.pipe {
devs = { devs = {
new_conf_IDs = map (v: v.id) devices; new_conf_IDs = map (v: v.id) devices;
GET_IdAttrName = "deviceID"; GET_IdAttrName = "deviceID";
override = cfg.overrideDevices; override = cfg.overrideDevices;
conf = devices; conf = devices;
baseAddress = curlAddressArgs "/rest/config/devices"; baseAddress = curlAddressArgs "/rest/config/devices";
}; };
dirs = { dirs = {
new_conf_IDs = map (v: v.id) folders; new_conf_IDs = map (v: v.id) folders;
GET_IdAttrName = "id"; GET_IdAttrName = "id";
override = cfg.overrideFolders; override = cfg.overrideFolders;
conf = folders; conf = folders;
baseAddress = curlAddressArgs "/rest/config/folders"; baseAddress = curlAddressArgs "/rest/config/folders";
}; };
} [ } [
(mapAttrs ( (mapAttrs (
conf_type: s: conf_type: s:
lib.pipe s.conf [ lib.pipe s.conf [
(map ( (map (
new_cfg: let new_cfg: let
jsonPreSecretsFile = pkgs.writeTextFile { jsonPreSecretsFile =
name = "${conf_type}-${new_cfg.id}-conf-pre-secrets.json"; pkgs.writeTextFile {
text = builtins.toJSON new_cfg; name = "${conf_type}-${new_cfg.id}-conf-pre-secrets.json";
}; text = builtins.toJSON new_cfg;
injectSecretsJqCmd = };
{ injectSecretsJqCmd =
"devs" = "${jq} ."; {
"dirs" = let "devs" = "${jq} .";
folder = new_cfg; "dirs" = let
devicesWithSecrets = lib.pipe folder.devices [ folder = new_cfg;
(lib.filter (device: (builtins.isAttrs device) && device ? encryptionPasswordFile)) devicesWithSecrets =
(map (device: { lib.pipe folder.devices [
deviceId = device.deviceId; (lib.filter (device: (builtins.isAttrs device) && device ? encryptionPasswordFile))
variableName = "secret_${builtins.hashString "sha256" device.encryptionPasswordFile}"; (map (device: {
secretPath = device.encryptionPasswordFile; deviceId = device.deviceId;
})) variableName = "secret_${builtins.hashString "sha256" device.encryptionPasswordFile}";
]; secretPath = device.encryptionPasswordFile;
jqUpdates = }))
map (device: '' ];
.devices[] |= ( jqUpdates =
if .deviceId == "${device.deviceId}" then map (device: ''
del(.encryptionPasswordFile) | .devices[] |= (
.encryptionPassword = ''$${device.variableName} if .deviceId == "${device.deviceId}" then
else del(.encryptionPasswordFile) |
. .encryptionPassword = ''$${device.variableName}
end else
) .
'') end
devicesWithSecrets; )
jqRawFiles = map (device: "--rawfile ${device.variableName} ${lib.escapeShellArg device.secretPath}") devicesWithSecrets; '')
in "${jq} ${lib.concatStringsSep " " jqRawFiles} ${lib.escapeShellArg (lib.concatStringsSep "|" (["."] ++ jqUpdates))}"; devicesWithSecrets;
}.${ jqRawFiles = map (device: "--rawfile ${device.variableName} ${lib.escapeShellArg device.secretPath}") devicesWithSecrets;
conf_type in "${jq} ${lib.concatStringsSep " " jqRawFiles} ${lib.escapeShellArg (lib.concatStringsSep "|" (["."] ++ jqUpdates))}";
}; }.${
in '' conf_type
${injectSecretsJqCmd} ${jsonPreSecretsFile} | curl --json @- -X POST ${s.baseAddress} };
'' in ''
)) ${injectSecretsJqCmd} ${jsonPreSecretsFile} | curl --json @- -X POST ${s.baseAddress}
(lib.concatStringsSep "\n") ''
] ))
+ lib.optionalString s.override '' (lib.concatStringsSep "\n")
stale_${conf_type}_ids="$(curl -X GET ${s.baseAddress} | ${jq} \ ]
--argjson new_ids ${lib.escapeShellArg (builtins.toJSON s.new_conf_IDs)} \ + lib.optionalString s.override ''
--raw-output \ stale_${conf_type}_ids="$(curl -X GET ${s.baseAddress} | ${jq} \
'[.[].${s.GET_IdAttrName}] - $new_ids | .[]' --argjson new_ids ${lib.escapeShellArg (builtins.toJSON s.new_conf_IDs)} \
)" --raw-output \
for id in ''${stale_${conf_type}_ids}; do '[.[].${s.GET_IdAttrName}] - $new_ids | .[]'
>&2 echo "Deleting stale device: $id" )"
curl -X DELETE ${s.baseAddress}/$id for id in ''${stale_${conf_type}_ids}; do
done >&2 echo "Deleting stale device: $id"
'' curl -X DELETE ${s.baseAddress}/$id
)) done
builtins.attrValues ''
(lib.concatStringsSep "\n") ))
]) builtins.attrValues
+ (lib.pipe cleanedConfig [ (lib.concatStringsSep "\n")
builtins.attrNames ])
(lib.subtractLists ["folders" "devices"]) + (lib.pipe cleanedConfig [
(map (subOption: '' builtins.attrNames
curl -X PUT -d ${lib.escapeShellArg (builtins.toJSON cleanedConfig.${subOption})} ${curlAddressArgs "/rest/config/${subOption}"} (lib.subtractLists ["folders" "devices"])
'')) (map (subOption: ''
(lib.concatStringsSep "\n") curl -X PUT -d ${lib.escapeShellArg (builtins.toJSON cleanedConfig.${subOption})} ${curlAddressArgs "/rest/config/${subOption}"}
]) ''))
+ '' (lib.concatStringsSep "\n")
if curl ${curlAddressArgs "/rest/config/restart-required"} | ])
${jq} -e .requiresRestart > /dev/null; then + ''
curl -X POST ${curlAddressArgs "/rest/system/restart"} if curl ${curlAddressArgs "/rest/config/restart-required"} |
fi ${jq} -e .requiresRestart > /dev/null; then
'' curl -X POST ${curlAddressArgs "/rest/system/restart"}
); fi
''
);
in { in {
options = { options = {
services.syncthing = { services.syncthing = {
enable = mkEnableOption "Syncthing, a self-hosted open-source alternative to Dropbox and Bittorrent Sync"; enable = mkEnableOption "Syncthing, a self-hosted open-source alternative to Dropbox and Bittorrent Sync";
cert = mkOption { cert =
type = types.nullOr types.str; mkOption {
default = null; type = types.nullOr types.str;
description = "Path to the cert.pem file, which will be copied into Syncthing's configDir."; default = null;
}; description = "Path to the cert.pem file, which will be copied into Syncthing's configDir.";
};
key = mkOption { key =
type = types.nullOr types.str; mkOption {
default = null; type = types.nullOr types.str;
description = "Path to the key.pem file, which will be copied into Syncthing's configDir."; default = null;
}; description = "Path to the key.pem file, which will be copied into Syncthing's configDir.";
};
overrideDevices = mkOption { overrideDevices =
type = types.bool; mkOption {
default = true; type = types.bool;
description = "Whether to delete the devices which are not configured via the devices option."; default = true;
}; description = "Whether to delete the devices which are not configured via the devices option.";
};
overrideFolders = mkOption { overrideFolders =
type = types.bool; mkOption {
default = !anyAutoAccept; type = types.bool;
description = "Whether to delete the folders which are not configured via the folders option."; default = !anyAutoAccept;
}; description = "Whether to delete the folders which are not configured via the folders option.";
};
settings = mkOption { settings =
type = types.submodule { mkOption {
freeformType = settingsFormat.type; type =
options = { types.submodule {
options = mkOption { freeformType = settingsFormat.type;
default = {}; options = {
description = "The options element contains all other global configuration options"; options =
type = types.submodule { mkOption {
freeformType = settingsFormat.type; default = {};
options = { description = "The options element contains all other global configuration options";
localAnnounceEnabled = mkOption { type =
type = types.nullOr types.bool; types.submodule {
default = null; freeformType = settingsFormat.type;
description = "Whether to send announcements to the local LAN."; options = {
}; localAnnounceEnabled =
globalAnnounceEnabled = mkOption { mkOption {
type = types.nullOr types.bool; type = types.nullOr types.bool;
default = null; default = null;
description = "Whether to send announcements to the global discovery servers."; description = "Whether to send announcements to the local LAN.";
}; };
relaysEnabled = mkOption { globalAnnounceEnabled =
type = types.nullOr types.bool; mkOption {
default = null; type = types.nullOr types.bool;
description = "When true, relays will be connected to and potentially used for device to device connections."; default = null;
}; description = "Whether to send announcements to the global discovery servers.";
urAccepted = mkOption { };
type = types.nullOr types.int; relaysEnabled =
default = null; mkOption {
description = "Whether the user has accepted to submit anonymous usage data."; type = types.nullOr types.bool;
}; default = null;
}; description = "When true, relays will be connected to and potentially used for device to device connections.";
}; };
}; urAccepted =
mkOption {
type = types.nullOr types.int;
default = null;
description = "Whether the user has accepted to submit anonymous usage data.";
};
};
};
};
devices = mkOption { devices =
default = {}; mkOption {
description = "Peers/devices which Syncthing should communicate with."; default = {};
type = types.attrsOf (types.submodule ({name, ...}: { description = "Peers/devices which Syncthing should communicate with.";
freeformType = settingsFormat.type; type =
options = { types.attrsOf (types.submodule ({name, ...}: {
name = mkOption { freeformType = settingsFormat.type;
type = types.str; options = {
default = name; name =
description = "The name of the device."; mkOption {
}; type = types.str;
id = mkOption { default = name;
type = types.str; description = "The name of the device.";
description = "The device ID."; };
}; id =
autoAcceptFolders = mkOption { mkOption {
type = types.bool; type = types.str;
default = false; description = "The device ID.";
description = "Automatically create or share folders that this device advertises at the default path."; };
}; autoAcceptFolders =
}; mkOption {
})); type = types.bool;
}; default = false;
description = "Automatically create or share folders that this device advertises at the default path.";
};
};
}));
};
folders = mkOption { folders =
default = {}; mkOption {
description = "Folders which should be shared by Syncthing."; default = {};
type = types.attrsOf (types.submodule ({name, ...}: { description = "Folders which should be shared by Syncthing.";
freeformType = settingsFormat.type; type =
options = { types.attrsOf (types.submodule ({name, ...}: {
enable = mkOption { freeformType = settingsFormat.type;
type = types.bool; options = {
default = true; enable =
description = "Whether to share this folder."; mkOption {
}; type = types.bool;
path = mkOption { default = true;
type = types.str; description = "Whether to share this folder.";
default = name; };
description = "The path to the folder which should be shared."; path =
}; mkOption {
id = mkOption { type = types.str;
type = types.str; default = name;
default = name; description = "The path to the folder which should be shared.";
description = "The ID of the folder. Must be the same on all devices."; };
}; id =
label = mkOption { mkOption {
type = types.str; type = types.str;
default = name; default = name;
description = "The label of the folder."; description = "The ID of the folder. Must be the same on all devices.";
}; };
type = mkOption { label =
type = types.enum ["sendreceive" "sendonly" "receiveonly" "receiveencrypted"]; mkOption {
default = "sendreceive"; type = types.str;
description = "Controls how the folder is handled by Syncthing."; default = name;
}; description = "The label of the folder.";
devices = mkOption { };
type = types.listOf (types.oneOf [ type =
types.str mkOption {
(types.submodule { type = types.enum ["sendreceive" "sendonly" "receiveonly" "receiveencrypted"];
freeformType = settingsFormat.type; default = "sendreceive";
options = { description = "Controls how the folder is handled by Syncthing.";
name = mkOption { };
type = types.str; devices =
description = "The name of a device defined in the devices option."; mkOption {
}; type =
encryptionPasswordFile = mkOption { types.listOf (types.oneOf [
type = types.nullOr types.path; types.str
default = null; (types.submodule {
description = "Path to encryption password file."; freeformType = settingsFormat.type;
}; options = {
}; name =
}) mkOption {
]); type = types.str;
default = []; description = "The name of a device defined in the devices option.";
description = "The devices this folder should be shared with."; };
}; encryptionPasswordFile =
}; mkOption {
})); type = types.nullOr types.path;
}; default = null;
}; description = "Path to encryption password file.";
}; };
default = {}; };
description = "Extra configuration options for Syncthing."; })
}; ]);
default = [];
description = "The devices this folder should be shared with.";
};
};
}));
};
};
};
default = {};
description = "Extra configuration options for Syncthing.";
};
guiAddress = mkOption { guiAddress =
type = types.str; mkOption {
default = "127.0.0.1:8384"; type = types.str;
description = "The address to serve the web interface at."; default = "127.0.0.1:8384";
}; description = "The address to serve the web interface at.";
};
user = mkOption { user =
type = types.str; mkOption {
default = "syncthing"; type = types.str;
description = "The user to run Syncthing as."; default = "syncthing";
}; description = "The user to run Syncthing as.";
};
group = mkOption { group =
type = types.str; mkOption {
default = "syncthing"; type = types.str;
description = "The group to run Syncthing under."; default = "syncthing";
}; description = "The group to run Syncthing under.";
};
dataDir = mkOption { dataDir =
type = types.path; mkOption {
default = "/var/lib/syncthing"; type = types.path;
description = "The path where synchronised directories will exist."; default = "/var/lib/syncthing";
}; description = "The path where synchronised directories will exist.";
};
configDir = mkOption { configDir =
type = types.path; mkOption {
default = cfg.dataDir + "/.config/syncthing"; type = types.path;
description = "The path where the settings and keys will exist."; default = cfg.dataDir + "/.config/syncthing";
}; description = "The path where the settings and keys will exist.";
};
openDefaultPorts = mkOption { openDefaultPorts =
type = types.bool; mkOption {
default = false; type = types.bool;
description = "Whether to open the default ports in the firewall (not applicable on Darwin)."; default = false;
}; description = "Whether to open the default ports in the firewall (not applicable on Darwin).";
};
package = mkPackageOption pkgs "syncthing" {}; package = mkPackageOption pkgs "syncthing" {};
}; };
}; };
config = mkIf cfg.enable { config =
assertions = [ mkIf cfg.enable {
{ assertions = [
assertion = !(cfg.overrideFolders && anyAutoAccept); {
message = "services.syncthing.overrideFolders will delete auto-accepted folders from the configuration, creating path conflicts."; assertion = !(cfg.overrideFolders && anyAutoAccept);
} message = "services.syncthing.overrideFolders will delete auto-accepted folders from the configuration, creating path conflicts.";
]; }
];
environment.systemPackages = [cfg.package]; environment.systemPackages = [cfg.package];
launchd.user.agents.syncthing = { launchd.user.agents.syncthing = {
serviceConfig = { serviceConfig = {
ProgramArguments = [ ProgramArguments = [
"${cfg.package}/bin/syncthing" "${cfg.package}/bin/syncthing"
"--no-browser" "--no-browser"
"--gui-address=${ "--gui-address=${
if isUnixGui if isUnixGui
then "unix://" then "unix://"
else "" else ""
}${cfg.guiAddress}" }${cfg.guiAddress}"
"--config=${cfg.configDir}" "--config=${cfg.configDir}"
"--data=${cfg.configDir}" "--data=${cfg.configDir}"
]; ];
EnvironmentVariables = { EnvironmentVariables = {
STNORESTART = "yes"; STNORESTART = "yes";
STNOUPGRADE = "yes"; STNOUPGRADE = "yes";
}; };
KeepAlive = true; KeepAlive = true;
RunAtLoad = true; RunAtLoad = true;
ProcessType = "Background"; ProcessType = "Background";
StandardOutPath = "${cfg.configDir}/syncthing.log"; StandardOutPath = "${cfg.configDir}/syncthing.log";
StandardErrorPath = "${cfg.configDir}/syncthing.log"; StandardErrorPath = "${cfg.configDir}/syncthing.log";
}; };
}; };
launchd.user.agents.syncthing-init = mkIf (cleanedConfig != {}) { launchd.user.agents.syncthing-init =
serviceConfig = { mkIf (cleanedConfig != {}) {
ProgramArguments = ["${updateConfig}"]; serviceConfig = {
RunAtLoad = true; ProgramArguments = ["${updateConfig}"];
KeepAlive = false; RunAtLoad = true;
ProcessType = "Background"; KeepAlive = false;
StandardOutPath = "${cfg.configDir}/syncthing-init.log"; ProcessType = "Background";
StandardErrorPath = "${cfg.configDir}/syncthing-init.log"; StandardOutPath = "${cfg.configDir}/syncthing-init.log";
}; StandardErrorPath = "${cfg.configDir}/syncthing-init.log";
}; };
};
system.activationScripts.syncthing = mkIf (cfg.cert != null || cfg.key != null) '' system.activationScripts.syncthing =
echo "Setting up Syncthing certificates..." mkIf (cfg.cert != null || cfg.key != null) ''
mkdir -p ${cfg.configDir} echo "Setting up Syncthing certificates..."
${optionalString (cfg.cert != null) '' mkdir -p ${cfg.configDir}
cp ${toString cfg.cert} ${cfg.configDir}/cert.pem ${optionalString (cfg.cert != null) ''
chmod 644 ${cfg.configDir}/cert.pem cp ${toString cfg.cert} ${cfg.configDir}/cert.pem
''} chmod 644 ${cfg.configDir}/cert.pem
${optionalString (cfg.key != null) '' ''}
cp ${toString cfg.key} ${cfg.configDir}/key.pem ${optionalString (cfg.key != null) ''
chmod 600 ${cfg.configDir}/key.pem cp ${toString cfg.key} ${cfg.configDir}/key.pem
''} chmod 600 ${cfg.configDir}/key.pem
''; ''}
}; '';
};
} }

View File

@@ -1,32 +1,32 @@
{ {
system.defaults = { system.defaults = {
NSGlobalDomain = { NSGlobalDomain = {
# null equals "Light" # null equals "Light"
AppleInterfaceStyle = null; AppleInterfaceStyle = null;
AppleShowAllExtensions = true; AppleShowAllExtensions = true;
ApplePressAndHoldEnabled = false; ApplePressAndHoldEnabled = false;
KeyRepeat = 2; KeyRepeat = 2;
InitialKeyRepeat = 15; InitialKeyRepeat = 15;
"com.apple.mouse.tapBehavior" = 1; "com.apple.mouse.tapBehavior" = 1;
"com.apple.sound.beep.volume" = 0.0; "com.apple.sound.beep.volume" = 0.0;
"com.apple.sound.beep.feedback" = 0; "com.apple.sound.beep.feedback" = 0;
}; };
dock = { dock = {
autohide = true; autohide = true;
show-recents = false; show-recents = false;
launchanim = true; launchanim = true;
orientation = "bottom"; orientation = "bottom";
tilesize = 60; tilesize = 60;
}; };
finder = { finder = {
_FXShowPosixPathInTitle = false; _FXShowPosixPathInTitle = false;
}; };
trackpad = { trackpad = {
Clicking = true; Clicking = true;
TrackpadThreeFingerDrag = true; TrackpadThreeFingerDrag = true;
}; };
}; };
} }

View File

@@ -1,15 +1,15 @@
{ {
programs.atuin = { programs.atuin = {
enable = true; enable = true;
enableFishIntegration = true; enableFishIntegration = true;
flags = [ flags = [
"--disable-up-arrow" "--disable-up-arrow"
]; ];
settings = { settings = {
style = "compact"; style = "compact";
inline_height = 0; inline_height = 0;
show_help = false; show_help = false;
show_tabs = false; show_tabs = false;
}; };
}; };
} }

View File

@@ -1,5 +1,5 @@
{ {
programs.zsh = { programs.zsh = {
enable = true; enable = true;
}; };
} }

View File

@@ -1,20 +1,21 @@
{pkgs, ...}: { {pkgs, ...}: {
programs.bat = { programs.bat = {
enable = true; enable = true;
config = { config = {
theme = "Catppuccin Latte"; theme = "Catppuccin Latte";
pager = "ov"; pager = "ov";
}; };
themes = { themes = {
"Catppuccin Latte" = { "Catppuccin Latte" = {
src = pkgs.fetchFromGitHub { src =
owner = "catppuccin"; pkgs.fetchFromGitHub {
repo = "bat"; owner = "catppuccin";
rev = "6810349b28055dce54076712fc05fc68da4b8ec0"; repo = "bat";
sha256 = "lJapSgRVENTrbmpVyn+UQabC9fpV1G1e+CdlJ090uvg="; rev = "6810349b28055dce54076712fc05fc68da4b8ec0";
}; sha256 = "lJapSgRVENTrbmpVyn+UQabC9fpV1G1e+CdlJ090uvg=";
file = "themes/Catppuccin Latte.tmTheme"; };
}; file = "themes/Catppuccin Latte.tmTheme";
}; };
}; };
};
} }

View File

@@ -1,36 +1,36 @@
{ {
pkgs, pkgs,
constants, constants,
inputs, inputs,
... ...
}: { }: {
imports = [ imports = [
./atuin.nix ./atuin.nix
./bash.nix ./bash.nix
./bat.nix ./bat.nix
./direnv.nix ./direnv.nix
./eza.nix ./eza.nix
./fish.nix ./fish.nix
./fzf.nix ./fzf.nix
./git.nix ./git.nix
./jjui.nix ./jjui.nix
./jujutsu.nix ./jujutsu.nix
./lazygit.nix ./lazygit.nix
./mise.nix ./mise.nix
./neovim ./neovim
./opencode.nix ./opencode.nix
./ripgrep.nix ./ripgrep.nix
./ssh.nix ./ssh.nix
./starship.nix ./starship.nix
./zellij.nix ./zellij.nix
./zoxide.nix ./zoxide.nix
./zsh.nix ./zsh.nix
]; ];
programs.home-manager.enable = true; programs.home-manager.enable = true;
home = { home = {
packages = pkgs.callPackage ../packages.nix {inherit inputs;}; packages = pkgs.callPackage ../packages.nix {inherit inputs;};
stateVersion = constants.stateVersions.homeManager; stateVersion = constants.stateVersions.homeManager;
}; };
} }

View File

@@ -1,6 +1,6 @@
{ {
programs.direnv = { programs.direnv = {
enable = true; enable = true;
nix-direnv.enable = true; nix-direnv.enable = true;
}; };
} }

View File

@@ -1,6 +1,6 @@
{ {
programs.eza = { programs.eza = {
enable = true; enable = true;
enableFishIntegration = true; enableFishIntegration = true;
}; };
} }

View File

@@ -1,54 +1,54 @@
{ {
programs.fish = { programs.fish = {
enable = true; enable = true;
functions = { functions = {
open_project = '' open_project = ''
set -l base "$HOME/Projects" set -l base "$HOME/Projects"
set -l choice (fd -t d -d 1 -a . "$base/Personal" "$base/Work" \ set -l choice (fd -t d -d 1 -a . "$base/Personal" "$base/Work" \
| string replace -r -- "^$base/" "" \ | string replace -r -- "^$base/" "" \
| fzf --prompt "project > ") | fzf --prompt "project > ")
test -n "$choice"; and cd "$base/$choice" test -n "$choice"; and cd "$base/$choice"
''; '';
}; };
interactiveShellInit = '' interactiveShellInit = ''
set fish_greeting set fish_greeting
set fish_color_normal 4c4f69 set fish_color_normal 4c4f69
set fish_color_command 1e66f5 set fish_color_command 1e66f5
set fish_color_param dd7878 set fish_color_param dd7878
set fish_color_keyword d20f39 set fish_color_keyword d20f39
set fish_color_quote 40a02b set fish_color_quote 40a02b
set fish_color_redirection ea76cb set fish_color_redirection ea76cb
set fish_color_end fe640b set fish_color_end fe640b
set fish_color_comment 8c8fa1 set fish_color_comment 8c8fa1
set fish_color_error d20f39 set fish_color_error d20f39
set fish_color_gray 9ca0b0 set fish_color_gray 9ca0b0
set fish_color_selection --background=ccd0da set fish_color_selection --background=ccd0da
set fish_color_search_match --background=ccd0da set fish_color_search_match --background=ccd0da
set fish_color_option 40a02b set fish_color_option 40a02b
set fish_color_operator ea76cb set fish_color_operator ea76cb
set fish_color_escape e64553 set fish_color_escape e64553
set fish_color_autosuggestion 9ca0b0 set fish_color_autosuggestion 9ca0b0
set fish_color_cancel d20f39 set fish_color_cancel d20f39
set fish_color_cwd df8e1d set fish_color_cwd df8e1d
set fish_color_user 179299 set fish_color_user 179299
set fish_color_host 1e66f5 set fish_color_host 1e66f5
set fish_color_host_remote 40a02b set fish_color_host_remote 40a02b
set fish_color_status d20f39 set fish_color_status d20f39
set fish_pager_color_progress 9ca0b0 set fish_pager_color_progress 9ca0b0
set fish_pager_color_prefix ea76cb set fish_pager_color_prefix ea76cb
set fish_pager_color_completion 4c4f69 set fish_pager_color_completion 4c4f69
set fish_pager_color_description 9ca0b0 set fish_pager_color_description 9ca0b0
set -gx LS_COLORS "$(vivid generate catppuccin-latte)" set -gx LS_COLORS "$(vivid generate catppuccin-latte)"
set -gx COLORTERM truecolor set -gx COLORTERM truecolor
set -gx COLORFGBG "15;0" set -gx COLORFGBG "15;0"
set -gx TERM_BACKGROUND light set -gx TERM_BACKGROUND light
for mode in default insert for mode in default insert
bind --mode $mode \cp open_project bind --mode $mode \cp open_project
end end
''; '';
}; };
} }

View File

@@ -1,24 +1,24 @@
{ {
programs.fzf = { programs.fzf = {
enable = true; enable = true;
enableFishIntegration = true; enableFishIntegration = true;
}; };
home.sessionVariables = { home.sessionVariables = {
FZF_DEFAULT_OPTS = '' FZF_DEFAULT_OPTS = ''
--bind=alt-k:up,alt-j:down --bind=alt-k:up,alt-j:down
--expect=tab,enter --expect=tab,enter
--layout=reverse --layout=reverse
--delimiter='\t' --delimiter='\t'
--with-nth=1 --with-nth=1
--preview-window='border-rounded' --prompt=' ' --marker=' ' --pointer=' ' --preview-window='border-rounded' --prompt=' ' --marker=' ' --pointer=' '
--separator='' --scrollbar='' --layout='reverse' --separator='' --scrollbar='' --layout='reverse'
--color=bg+:#CCD0DA,bg:#EFF1F5,spinner:#DC8A78,hl:#D20F39 --color=bg+:#CCD0DA,bg:#EFF1F5,spinner:#DC8A78,hl:#D20F39
--color=fg:#4C4F69,header:#D20F39,info:#8839EF,pointer:#DC8A78 --color=fg:#4C4F69,header:#D20F39,info:#8839EF,pointer:#DC8A78
--color=marker:#7287FD,fg+:#4C4F69,prompt:#8839EF,hl+:#D20F39 --color=marker:#7287FD,fg+:#4C4F69,prompt:#8839EF,hl+:#D20F39
--color=selected-bg:#BCC0CC --color=selected-bg:#BCC0CC
--color=border:#9CA0B0,label:#4C4F69 --color=border:#9CA0B0,label:#4C4F69
''; '';
}; };
} }

View File

@@ -1,211 +1,211 @@
{...}: let {...}: let
name = "Christoph Schmatzler"; name = "Christoph Schmatzler";
in { in {
programs.git = { programs.git = {
enable = true; enable = true;
ignores = ["*.swp"]; ignores = ["*.swp"];
settings = { settings = {
user.name = name; user.name = name;
init.defaultBranch = "main"; init.defaultBranch = "main";
core = { core = {
editor = "vim"; editor = "vim";
autocrlf = "input"; autocrlf = "input";
pager = "delta"; pager = "delta";
}; };
pull.rebase = true; pull.rebase = true;
rebase.autoStash = true; rebase.autoStash = true;
interactive.diffFilter = "delta --color-only"; interactive.diffFilter = "delta --color-only";
delta = { delta = {
navigate = true; navigate = true;
line-numbers = true; line-numbers = true;
syntax-theme = "GitHub"; syntax-theme = "GitHub";
side-by-side = true; side-by-side = true;
pager = "less -FRX"; pager = "less -FRX";
}; };
pager = { pager = {
diff = "delta"; diff = "delta";
log = "delta"; log = "delta";
show = "delta"; show = "delta";
}; };
}; };
lfs = { lfs = {
enable = true; enable = true;
}; };
}; };
home.shellAliases = { home.shellAliases = {
g = "git"; g = "git";
ga = "git add"; ga = "git add";
gaa = "git add --all"; gaa = "git add --all";
gapa = "git add --patch"; gapa = "git add --patch";
gau = "git add --update"; gau = "git add --update";
gav = "git add --verbose"; gav = "git add --verbose";
gap = "git apply"; gap = "git apply";
gapt = "git apply --3way"; gapt = "git apply --3way";
gb = "git branch"; gb = "git branch";
gba = "git branch --all"; gba = "git branch --all";
gbd = "git branch --delete"; gbd = "git branch --delete";
gbD = "git branch --delete --force"; gbD = "git branch --delete --force";
gbl = "git blame -w"; gbl = "git blame -w";
gbnm = "git branch --no-merged"; gbnm = "git branch --no-merged";
gbr = "git branch --remote"; gbr = "git branch --remote";
gbs = "git bisect"; gbs = "git bisect";
gbsb = "git bisect bad"; gbsb = "git bisect bad";
gbsg = "git bisect good"; gbsg = "git bisect good";
gbsn = "git bisect new"; gbsn = "git bisect new";
gbso = "git bisect old"; gbso = "git bisect old";
gbsr = "git bisect reset"; gbsr = "git bisect reset";
gbss = "git bisect start"; gbss = "git bisect start";
gc = "git commit --verbose"; gc = "git commit --verbose";
gca = "git commit --verbose --all"; gca = "git commit --verbose --all";
gcam = "git commit --all --message"; gcam = "git commit --all --message";
gcas = "git commit --all --signoff"; gcas = "git commit --all --signoff";
gcasm = "git commit --all --signoff --message"; gcasm = "git commit --all --signoff --message";
gcb = "git checkout -b"; gcb = "git checkout -b";
gcB = "git checkout -B"; gcB = "git checkout -B";
gcf = "git config --list"; gcf = "git config --list";
gclean = "git clean --interactive -d"; gclean = "git clean --interactive -d";
gcl = "git clone --recurse-submodules"; gcl = "git clone --recurse-submodules";
gclf = "git clone --recursive --shallow-submodules --filter=blob:none --also-filter-submodules"; gclf = "git clone --recursive --shallow-submodules --filter=blob:none --also-filter-submodules";
gcm = "git checkout main"; gcm = "git checkout main";
gcmsg = "git commit --message"; gcmsg = "git commit --message";
gcn = "git commit --verbose --no-edit"; gcn = "git commit --verbose --no-edit";
gco = "git checkout"; gco = "git checkout";
gcor = "git checkout --recurse-submodules"; gcor = "git checkout --recurse-submodules";
gcount = "git shortlog --summary --numbered"; gcount = "git shortlog --summary --numbered";
gcp = "git cherry-pick"; gcp = "git cherry-pick";
gcpa = "git cherry-pick --abort"; gcpa = "git cherry-pick --abort";
gcpc = "git cherry-pick --continue"; gcpc = "git cherry-pick --continue";
gcs = "git commit --gpg-sign"; gcs = "git commit --gpg-sign";
gcss = "git commit --gpg-sign --signoff"; gcss = "git commit --gpg-sign --signoff";
gcssm = "git commit --gpg-sign --signoff --message"; gcssm = "git commit --gpg-sign --signoff --message";
gcsm = "git commit --signoff --message"; gcsm = "git commit --signoff --message";
gd = "git diff"; gd = "git diff";
gdca = "git diff --cached"; gdca = "git diff --cached";
gdcw = "git diff --cached --word-diff"; gdcw = "git diff --cached --word-diff";
gds = "git diff --staged"; gds = "git diff --staged";
gdw = "git diff --word-diff"; gdw = "git diff --word-diff";
gdt = "git diff-tree --no-commit-id --name-only -r"; gdt = "git diff-tree --no-commit-id --name-only -r";
gdup = "git diff @{upstream}"; gdup = "git diff @{upstream}";
gf = "git fetch"; gf = "git fetch";
gfa = "git fetch --all --tags --prune"; gfa = "git fetch --all --tags --prune";
gfo = "git fetch origin"; gfo = "git fetch origin";
gfg = "git ls-files | grep"; gfg = "git ls-files | grep";
gg = "git gui citool"; gg = "git gui citool";
gga = "git gui citool --amend"; gga = "git gui citool --amend";
ggpull = "git pull origin \"$(git branch --show-current)\""; ggpull = "git pull origin \"$(git branch --show-current)\"";
ggpush = "git push origin \"$(git branch --show-current)\""; ggpush = "git push origin \"$(git branch --show-current)\"";
ggsup = "git branch --set-upstream-to=origin/$(git branch --show-current)"; ggsup = "git branch --set-upstream-to=origin/$(git branch --show-current)";
ghh = "git help"; ghh = "git help";
gignore = "git update-index --assume-unchanged"; gignore = "git update-index --assume-unchanged";
gignored = "git ls-files -v | grep \"^[[:lower:]]\""; gignored = "git ls-files -v | grep \"^[[:lower:]]\"";
gl = "git pull"; gl = "git pull";
glg = "git log --stat"; glg = "git log --stat";
glgp = "git log --stat --patch"; glgp = "git log --stat --patch";
glgg = "git log --graph"; glgg = "git log --graph";
glgga = "git log --graph --decorate --all"; glgga = "git log --graph --decorate --all";
glgm = "git log --graph --max-count=10"; glgm = "git log --graph --max-count=10";
glo = "git log --oneline --decorate"; glo = "git log --oneline --decorate";
glog = "git log --oneline --decorate --graph"; glog = "git log --oneline --decorate --graph";
gloga = "git log --oneline --decorate --graph --all"; gloga = "git log --oneline --decorate --graph --all";
glol = "git log --graph --pretty=\"%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset\""; glol = "git log --graph --pretty=\"%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset\"";
glola = "git log --graph --pretty=\"%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset\" --all"; glola = "git log --graph --pretty=\"%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset\" --all";
glols = "git log --graph --pretty=\"%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset\" --stat"; glols = "git log --graph --pretty=\"%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset\" --stat";
glod = "git log --graph --pretty=\"%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ad) %C(bold blue)<%an>%Creset\""; glod = "git log --graph --pretty=\"%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ad) %C(bold blue)<%an>%Creset\"";
glods = "git log --graph --pretty=\"%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ad) %C(bold blue)<%an>%Creset\" --date=short"; glods = "git log --graph --pretty=\"%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ad) %C(bold blue)<%an>%Creset\" --date=short";
gluc = "git pull upstream $(git branch --show-current)"; gluc = "git pull upstream $(git branch --show-current)";
glum = "git pull upstream main"; glum = "git pull upstream main";
gm = "git merge"; gm = "git merge";
gma = "git merge --abort"; gma = "git merge --abort";
gmc = "git merge --continue"; gmc = "git merge --continue";
gms = "git merge --squash"; gms = "git merge --squash";
gmff = "git merge --ff-only"; gmff = "git merge --ff-only";
gmtl = "git mergetool --no-prompt"; gmtl = "git mergetool --no-prompt";
gmtlvim = "git mergetool --no-prompt --tool=vimdiff"; gmtlvim = "git mergetool --no-prompt --tool=vimdiff";
gmum = "git merge upstream/main"; gmum = "git merge upstream/main";
gmom = "git merge origin/main"; gmom = "git merge origin/main";
gp = "git push"; gp = "git push";
gpd = "git push --dry-run"; gpd = "git push --dry-run";
gpf = "git push --force-with-lease"; gpf = "git push --force-with-lease";
gpod = "git push origin --delete"; gpod = "git push origin --delete";
gpoat = "git push origin --all && git push origin --tags"; gpoat = "git push origin --all && git push origin --tags";
gpr = "git pull --rebase"; gpr = "git pull --rebase";
gpra = "git pull --rebase --autostash"; gpra = "git pull --rebase --autostash";
gprav = "git pull --rebase --autostash -v"; gprav = "git pull --rebase --autostash -v";
gprom = "git pull --rebase origin main"; gprom = "git pull --rebase origin main";
gpromi = "git pull --rebase=interactive origin main"; gpromi = "git pull --rebase=interactive origin main";
gprv = "git pull --rebase -v"; gprv = "git pull --rebase -v";
gprum = "git pull --rebase upstream main"; gprum = "git pull --rebase upstream main";
gprumi = "git pull --rebase=interactive upstream main"; gprumi = "git pull --rebase=interactive upstream main";
gpsup = "git push --set-upstream origin $(git branch --show-current)"; gpsup = "git push --set-upstream origin $(git branch --show-current)";
gpsupf = "git push --set-upstream origin $(git branch --show-current) --force-with-lease"; gpsupf = "git push --set-upstream origin $(git branch --show-current) --force-with-lease";
gpv = "git push --verbose"; gpv = "git push --verbose";
gpu = "git push upstream"; gpu = "git push upstream";
gr = "git remote"; gr = "git remote";
gra = "git remote add"; gra = "git remote add";
grb = "git rebase"; grb = "git rebase";
grba = "git rebase --abort"; grba = "git rebase --abort";
grbc = "git rebase --continue"; grbc = "git rebase --continue";
grbd = "git rebase develop"; grbd = "git rebase develop";
grbi = "git rebase --interactive"; grbi = "git rebase --interactive";
grbm = "git rebase main"; grbm = "git rebase main";
grbo = "git rebase --onto"; grbo = "git rebase --onto";
grbom = "git rebase origin/main"; grbom = "git rebase origin/main";
grbs = "git rebase --skip"; grbs = "git rebase --skip";
grbum = "git rebase upstream/main"; grbum = "git rebase upstream/main";
grev = "git revert"; grev = "git revert";
greva = "git revert --abort"; greva = "git revert --abort";
grevc = "git revert --continue"; grevc = "git revert --continue";
grf = "git reflog"; grf = "git reflog";
grh = "git reset"; grh = "git reset";
grhh = "git reset --hard"; grhh = "git reset --hard";
grhk = "git reset --keep"; grhk = "git reset --keep";
grhs = "git reset --soft"; grhs = "git reset --soft";
grm = "git rm"; grm = "git rm";
grmc = "git rm --cached"; grmc = "git rm --cached";
grmv = "git remote rename"; grmv = "git remote rename";
groh = "git reset origin/$(git branch --show-current) --hard"; groh = "git reset origin/$(git branch --show-current) --hard";
grrm = "git remote remove"; grrm = "git remote remove";
grs = "git restore"; grs = "git restore";
grset = "git remote set-url"; grset = "git remote set-url";
grss = "git restore --source"; grss = "git restore --source";
grst = "git restore --staged"; grst = "git restore --staged";
grt = "cd \"$(git rev-parse --show-toplevel || echo .)\""; grt = "cd \"$(git rev-parse --show-toplevel || echo .)\"";
gru = "git reset --"; gru = "git reset --";
grup = "git remote update"; grup = "git remote update";
grv = "git remote --verbose"; grv = "git remote --verbose";
gsb = "git status --short --branch"; gsb = "git status --short --branch";
gsh = "git show"; gsh = "git show";
gsi = "git submodule init"; gsi = "git submodule init";
gsps = "git show --pretty=short --show-signature"; gsps = "git show --pretty=short --show-signature";
gss = "git status --short"; gss = "git status --short";
gst = "git status"; gst = "git status";
gsta = "git stash push"; gsta = "git stash push";
gstaa = "git stash apply"; gstaa = "git stash apply";
gstall = "git stash --all"; gstall = "git stash --all";
gstc = "git stash clear"; gstc = "git stash clear";
gstd = "git stash drop"; gstd = "git stash drop";
gstl = "git stash list"; gstl = "git stash list";
gstp = "git stash pop"; gstp = "git stash pop";
gsts = "git stash show --patch"; gsts = "git stash show --patch";
gstu = "git stash push --include-untracked"; gstu = "git stash push --include-untracked";
gsu = "git submodule update"; gsu = "git submodule update";
gsw = "git switch"; gsw = "git switch";
gswc = "git switch --create"; gswc = "git switch --create";
gswd = "git switch develop"; gswd = "git switch develop";
gswm = "git switch main"; gswm = "git switch main";
gta = "git tag --annotate"; gta = "git tag --annotate";
gts = "git tag --sign"; gts = "git tag --sign";
gtv = "git tag | sort -V"; gtv = "git tag | sort -V";
gunignore = "git update-index --no-assume-unchanged"; gunignore = "git update-index --no-assume-unchanged";
gunwip = "git rev-list --max-count=1 --format=\"%s\" HEAD | grep -q \"\\--wip--\" && git reset HEAD~1"; gunwip = "git rev-list --max-count=1 --format=\"%s\" HEAD | grep -q \"\\--wip--\" && git reset HEAD~1";
gwch = "git whatchanged -p --abbrev-commit --pretty=medium"; gwch = "git whatchanged -p --abbrev-commit --pretty=medium";
gwipe = "git reset --hard && git clean --force -df"; gwipe = "git reset --hard && git clean --force -df";
gwt = "git worktree"; gwt = "git worktree";
gwta = "git worktree add"; gwta = "git worktree add";
gwtls = "git worktree list"; gwtls = "git worktree list";
gwtmv = "git worktree move"; gwtmv = "git worktree move";
gwtrm = "git worktree remove"; gwtrm = "git worktree remove";
gwip = "git add -A; git rm $(git ls-files --deleted) 2> /dev/null; git commit --no-verify --no-gpg-sign --message \"--wip-- [skip ci]\""; gwip = "git add -A; git rm $(git ls-files --deleted) 2> /dev/null; git commit --no-verify --no-gpg-sign --message \"--wip-- [skip ci]\"";
}; };
} }

View File

@@ -1,5 +1,5 @@
{ {
programs.jjui = { programs.jjui = {
enable = true; enable = true;
}; };
} }

View File

@@ -1,27 +1,27 @@
{ {
programs.jujutsu = { programs.jujutsu = {
enable = true; enable = true;
settings = { settings = {
user = { user = {
name = "Christoph Schmatzler"; name = "Christoph Schmatzler";
email = "christoph@schmatzler.com"; email = "christoph@schmatzler.com";
}; };
diff = { diff = {
tool = "delta"; tool = "delta";
}; };
ui = { ui = {
default-command = "status"; default-command = "status";
diff-formatter = ":git"; diff-formatter = ":git";
pager = ["delta" "--pager" "less -FRX"]; pager = ["delta" "--pager" "less -FRX"];
diff-editor = ["nvim" "-c" "DiffEditor $left $right $output"]; diff-editor = ["nvim" "-c" "DiffEditor $left $right $output"];
}; };
aliases = { aliases = {
tug = ["bookmark" "move" "--from" "closest_bookmark(@-)" "--to" "@-"]; tug = ["bookmark" "move" "--from" "closest_bookmark(@-)" "--to" "@-"];
retrunk = ["rebase" "-d" "trunk()"]; retrunk = ["rebase" "-d" "trunk()"];
}; };
revset-aliases = { revset-aliases = {
"closest_bookmark(to)" = "heads(::to & bookmarks())"; "closest_bookmark(to)" = "heads(::to & bookmarks())";
}; };
}; };
}; };
} }

View File

@@ -1,58 +1,58 @@
{ {
programs.lazygit = { programs.lazygit = {
enable = true; enable = true;
settings = { settings = {
git = { git = {
commit.signOff = true; commit.signOff = true;
pagers = [ pagers = [
{ {
delta = { delta = {
colorArg = "always"; colorArg = "always";
pager = "DELTA_FEATURES=decorations delta --light --paging=never --line-numbers --hyperlinks --hyperlinks-file-link-format=\"lazygit-edit://{path}:{line}\""; pager = "DELTA_FEATURES=decorations delta --light --paging=never --line-numbers --hyperlinks --hyperlinks-file-link-format=\"lazygit-edit://{path}:{line}\"";
}; };
} }
]; ];
}; };
gui = { gui = {
authorColors = { authorColors = {
"*" = "#7287fd"; "*" = "#7287fd";
}; };
theme = { theme = {
activeBorderColor = [ activeBorderColor = [
"#8839ef" "#8839ef"
"bold" "bold"
]; ];
inactiveBorderColor = [ inactiveBorderColor = [
"#6c6f85" "#6c6f85"
]; ];
optionsTextColor = [ optionsTextColor = [
"#1e66f5" "#1e66f5"
]; ];
selectedLineBgColor = [ selectedLineBgColor = [
"#ccd0da" "#ccd0da"
]; ];
cherryPickedCommitBgColor = [ cherryPickedCommitBgColor = [
"#bcc0cc" "#bcc0cc"
]; ];
cherryPickedCommitFgColor = [ cherryPickedCommitFgColor = [
"#8839ef" "#8839ef"
]; ];
defaultFgColor = [ defaultFgColor = [
"#4c4f69" "#4c4f69"
]; ];
searchingActiveBorderColor = [ searchingActiveBorderColor = [
"#df8e1d" "#df8e1d"
]; ];
unstagedChangesColor = [ unstagedChangesColor = [
"#d20f39" "#d20f39"
]; ];
}; };
}; };
}; };
}; };
home.shellAliases = { home.shellAliases = {
lg = "lazygit"; lg = "lazygit";
}; };
} }

View File

@@ -1,10 +1,10 @@
{ {
programs.mise = { programs.mise = {
enable = true; enable = true;
enableFishIntegration = true; enableFishIntegration = true;
enableZshIntegration = true; enableZshIntegration = true;
settings = { settings = {
auto_install = false; auto_install = false;
}; };
}; };
} }

View File

@@ -1,34 +1,34 @@
{ {
programs.nixvim = { programs.nixvim = {
autoGroups = { autoGroups = {
Christoph = {}; Christoph = {};
}; };
autoCmd = [ autoCmd = [
{ {
event = "BufWritePre"; event = "BufWritePre";
group = "Christoph"; group = "Christoph";
pattern = "*"; pattern = "*";
command = "%s/\\s\\+$//e"; command = "%s/\\s\\+$//e";
} }
{ {
event = "BufReadPost"; event = "BufReadPost";
group = "Christoph"; group = "Christoph";
pattern = "*"; pattern = "*";
command = "normal zR"; command = "normal zR";
} }
{ {
event = "FileReadPost"; event = "FileReadPost";
group = "Christoph"; group = "Christoph";
pattern = "*"; pattern = "*";
command = "normal zR"; command = "normal zR";
} }
{ {
event = "FileType"; event = "FileType";
group = "Christoph"; group = "Christoph";
pattern = "*.ex,*.exs,*.heex"; pattern = "*.ex,*.exs,*.heex";
command = "setlocal expandtab tabstop=2 shiftwidth=2 softtabstop=2"; command = "setlocal expandtab tabstop=2 shiftwidth=2 softtabstop=2";
} }
]; ];
}; };
} }

View File

@@ -1,37 +1,37 @@
{ {
imports = [ imports = [
./autocmd.nix ./autocmd.nix
./mappings.nix ./mappings.nix
./options.nix ./options.nix
./plugins/blink-cmp.nix ./plugins/blink-cmp.nix
./plugins/conform.nix ./plugins/conform.nix
./plugins/copilot.nix ./plugins/copilot.nix
./plugins/grug-far.nix ./plugins/grug-far.nix
./plugins/harpoon.nix ./plugins/harpoon.nix
./plugins/hunk.nix ./plugins/hunk.nix
./plugins/lsp.nix ./plugins/lsp.nix
./plugins/mini.nix ./plugins/mini.nix
./plugins/oil.nix ./plugins/oil.nix
./plugins/toggleterm.nix ./plugins/toggleterm.nix
./plugins/treesitter.nix ./plugins/treesitter.nix
]; ];
programs.nixvim = { programs.nixvim = {
enable = true; enable = true;
defaultEditor = true; defaultEditor = true;
luaLoader.enable = true; luaLoader.enable = true;
colorschemes.catppuccin = { colorschemes.catppuccin = {
enable = true; enable = true;
settings = { settings = {
flavour = "latte"; flavour = "latte";
}; };
}; };
extraConfigLua = '' extraConfigLua = ''
vim.ui.select = MiniPick.ui_select vim.ui.select = MiniPick.ui_select
''; '';
}; };
home.shellAliases = { home.shellAliases = {
v = "nvim"; v = "nvim";
}; };
} }

View File

@@ -1,235 +1,235 @@
{ {
programs.nixvim.keymaps = [ programs.nixvim.keymaps = [
# clipboard - OSC52 yank and paste # clipboard - OSC52 yank and paste
{ {
mode = ["n" "v"]; mode = ["n" "v"];
key = "<leader>y"; key = "<leader>y";
action = ''"+y''; action = ''"+y'';
options.desc = "Yank to system clipboard (OSC52)"; options.desc = "Yank to system clipboard (OSC52)";
} }
# e - explore/edit # e - explore/edit
{ {
mode = "n"; mode = "n";
key = "<leader>ef"; key = "<leader>ef";
action = ":lua require('oil').open()<CR>"; action = ":lua require('oil').open()<CR>";
options.desc = "File directory"; options.desc = "File directory";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>er"; key = "<leader>er";
action = ":lua require('grug-far').open()<CR>"; action = ":lua require('grug-far').open()<CR>";
options.desc = "Search and replace"; options.desc = "Search and replace";
} }
# f - find # f - find
{ {
mode = "n"; mode = "n";
key = "<leader>f/"; key = "<leader>f/";
action = ":Pick history scope='/'<CR>"; action = ":Pick history scope='/'<CR>";
options.desc = "'/' history"; options.desc = "'/' history";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>f:"; key = "<leader>f:";
action = ":Pick history scope=':'<CR>"; action = ":Pick history scope=':'<CR>";
options.desc = "':' history"; options.desc = "':' history";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>fa"; key = "<leader>fa";
action = ":Pick git_hunks scope='staged'<CR>"; action = ":Pick git_hunks scope='staged'<CR>";
options.desc = "Added hunks (all)"; options.desc = "Added hunks (all)";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>fA"; key = "<leader>fA";
action = ":Pick git_hunks path='%' scope='staged'<CR>"; action = ":Pick git_hunks path='%' scope='staged'<CR>";
options.desc = "Added hunks (buffer)"; options.desc = "Added hunks (buffer)";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>fb"; key = "<leader>fb";
action = ":Pick buffers<CR>"; action = ":Pick buffers<CR>";
options.desc = "Buffers"; options.desc = "Buffers";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>fd"; key = "<leader>fd";
action = ":Pick diagnostic scope='all'<CR>"; action = ":Pick diagnostic scope='all'<CR>";
options.desc = "Diagnostic (workspace)"; options.desc = "Diagnostic (workspace)";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>fD"; key = "<leader>fD";
action = ":Pick diagnostic scope='current'<CR>"; action = ":Pick diagnostic scope='current'<CR>";
options.desc = "Diagnostic (buffer)"; options.desc = "Diagnostic (buffer)";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>ff"; key = "<leader>ff";
action = ":Pick files<CR>"; action = ":Pick files<CR>";
options.desc = "Search files"; options.desc = "Search files";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>fg"; key = "<leader>fg";
action = ":Pick grep_live<CR>"; action = ":Pick grep_live<CR>";
options.desc = "Grep"; options.desc = "Grep";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>fm"; key = "<leader>fm";
action = ":Pick git_hunks<CR>"; action = ":Pick git_hunks<CR>";
options.desc = "Modified hunks (all)"; options.desc = "Modified hunks (all)";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>fM"; key = "<leader>fM";
action = ":Pick git_hunks path='%'<CR>"; action = ":Pick git_hunks path='%'<CR>";
options.desc = "Modified hunks (buffer)"; options.desc = "Modified hunks (buffer)";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>fr"; key = "<leader>fr";
action = ":Pick lsp scope='references'<CR>"; action = ":Pick lsp scope='references'<CR>";
options.desc = "References (LSP)"; options.desc = "References (LSP)";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>fs"; key = "<leader>fs";
action = ":Pick lsp scope='workspace_symbol'<CR>"; action = ":Pick lsp scope='workspace_symbol'<CR>";
options.desc = "Symbols (LSP, workspace)"; options.desc = "Symbols (LSP, workspace)";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>fS"; key = "<leader>fS";
action = ":Pick lsp scope='document_symbol'<CR>"; action = ":Pick lsp scope='document_symbol'<CR>";
options.desc = "Symbols (LSP, buffer)"; options.desc = "Symbols (LSP, buffer)";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>fv"; key = "<leader>fv";
action = ":Pick visit_paths cwd=\"\"<CR>"; action = ":Pick visit_paths cwd=\"\"<CR>";
options.desc = "Visit paths (all)"; options.desc = "Visit paths (all)";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>fV"; key = "<leader>fV";
action = ":Pick visit_paths<CR>"; action = ":Pick visit_paths<CR>";
options.desc = "Visit paths (cwd)"; options.desc = "Visit paths (cwd)";
} }
# g - git # g - git
{ {
mode = "n"; mode = "n";
key = "<leader>gd"; key = "<leader>gd";
action = ":DiffviewOpen<CR>"; action = ":DiffviewOpen<CR>";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>gg"; key = "<leader>gg";
action.__raw = '' action.__raw = ''
function() function()
require('toggleterm.terminal').Terminal:new({ cmd = 'jjui', direction = 'float' }):toggle() require('toggleterm.terminal').Terminal:new({ cmd = 'jjui', direction = 'float' }):toggle()
end end
''; '';
options.desc = "jjui"; options.desc = "jjui";
} }
# l - lsp/formatter # l - lsp/formatter
{ {
mode = "n"; mode = "n";
key = "<leader>la"; key = "<leader>la";
action = ":lua vim.lsp.buf.code_action()<CR>"; action = ":lua vim.lsp.buf.code_action()<CR>";
options.desc = "Actions"; options.desc = "Actions";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>ld"; key = "<leader>ld";
action = ":lua vim.diagnostic.open_float({ severity = { min = vim.diagnostic.severity.HINT } })<CR>"; action = ":lua vim.diagnostic.open_float({ severity = { min = vim.diagnostic.severity.HINT } })<CR>";
options.desc = "Diagnostics popup"; options.desc = "Diagnostics popup";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>lf"; key = "<leader>lf";
action = ":lua require('conform').format({ lsp_fallback = true })<CR>"; action = ":lua require('conform').format({ lsp_fallback = true })<CR>";
options.desc = "Format"; options.desc = "Format";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>li"; key = "<leader>li";
action = ":lua vim.lsp.buf.hover()<CR>"; action = ":lua vim.lsp.buf.hover()<CR>";
options.desc = "Information"; options.desc = "Information";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>lj"; key = "<leader>lj";
action = ":lua vim.diagnostic.goto_next()<CR>"; action = ":lua vim.diagnostic.goto_next()<CR>";
options.desc = "Next diagnostic"; options.desc = "Next diagnostic";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>lk"; key = "<leader>lk";
action = ":lua vim.diagnostic.goto_prev()<CR>"; action = ":lua vim.diagnostic.goto_prev()<CR>";
options.desc = "Prev diagnostic"; options.desc = "Prev diagnostic";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>lr"; key = "<leader>lr";
action = ":lua vim.lsp.buf.rename()<CR>"; action = ":lua vim.lsp.buf.rename()<CR>";
options.desc = "Rename"; options.desc = "Rename";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>lR"; key = "<leader>lR";
action = ":lua vim.lsp.buf.references()<CR>"; action = ":lua vim.lsp.buf.references()<CR>";
options.desc = "References"; options.desc = "References";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>ls"; key = "<leader>ls";
action = ":lua vim.lsp.buf.definition()<CR>"; action = ":lua vim.lsp.buf.definition()<CR>";
options.desc = "Source definition"; options.desc = "Source definition";
} }
# other # other
{ {
mode = "n"; mode = "n";
key = "<leader>j"; key = "<leader>j";
action = ":lua require('mini.jump2d').start(require('mini.jump2d').builtin_opts.query)<CR>"; action = ":lua require('mini.jump2d').start(require('mini.jump2d').builtin_opts.query)<CR>";
options.desc = "Jump to character"; options.desc = "Jump to character";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>a"; key = "<leader>a";
action = ":lua require('harpoon'):list():add()<CR>"; action = ":lua require('harpoon'):list():add()<CR>";
options.desc = "Add harpoon"; options.desc = "Add harpoon";
} }
{ {
mode = "n"; mode = "n";
key = "<C-e>"; key = "<C-e>";
action = ":lua require('harpoon').ui:toggle_quick_menu(require('harpoon'):list())<CR>"; action = ":lua require('harpoon').ui:toggle_quick_menu(require('harpoon'):list())<CR>";
options.desc = "Toggle harpoon quick menu"; options.desc = "Toggle harpoon quick menu";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>1"; key = "<leader>1";
action = ":lua require('harpoon'):list():select(1)<CR>"; action = ":lua require('harpoon'):list():select(1)<CR>";
options.desc = "Go to harpoon 1"; options.desc = "Go to harpoon 1";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>2"; key = "<leader>2";
action = ":lua require('harpoon'):list():select(2)<CR>"; action = ":lua require('harpoon'):list():select(2)<CR>";
options.desc = "Go to harpoon 2"; options.desc = "Go to harpoon 2";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>3"; key = "<leader>3";
action = ":lua require('harpoon'):list():select(3)<CR>"; action = ":lua require('harpoon'):list():select(3)<CR>";
options.desc = "Go to harpoon 3"; options.desc = "Go to harpoon 3";
} }
{ {
mode = "n"; mode = "n";
key = "<leader>4"; key = "<leader>4";
action = ":lua require('harpoon'):list():select(4)<CR>"; action = ":lua require('harpoon'):list():select(4)<CR>";
options.desc = "Go to harpoon 4"; options.desc = "Go to harpoon 4";
} }
]; ];
} }

View File

@@ -1,17 +1,17 @@
{ {
programs.nixvim = { programs.nixvim = {
globals = { globals = {
clipboard = "osc52"; clipboard = "osc52";
}; };
opts = { opts = {
expandtab = false; expandtab = false;
tabstop = 2; tabstop = 2;
ignorecase = true; ignorecase = true;
list = false; list = false;
mouse = ""; mouse = "";
relativenumber = true; relativenumber = true;
shiftwidth = 2; shiftwidth = 2;
smartcase = true; smartcase = true;
}; };
}; };
} }

View File

@@ -1,17 +1,17 @@
{ {
programs.nixvim.plugins.blink-cmp = { programs.nixvim.plugins.blink-cmp = {
enable = true; enable = true;
settings = { settings = {
signature.enabled = true; signature.enabled = true;
completion = { completion = {
accept = { accept = {
auto_brackets = { auto_brackets = {
enabled = true; enabled = true;
semantic_token_resolution.enabled = false; semantic_token_resolution.enabled = false;
}; };
}; };
documentation.auto_show = true; documentation.auto_show = true;
}; };
}; };
}; };
} }

View File

@@ -1,14 +1,14 @@
{ {
programs.nixvim.plugins.conform-nvim = { programs.nixvim.plugins.conform-nvim = {
enable = true; enable = true;
settings = { settings = {
format_on_save = {}; format_on_save = {};
formatters_by_ft = { formatters_by_ft = {
nix = ["alejandra"]; nix = ["alejandra"];
javascript = ["prettier"]; javascript = ["prettier"];
typescript = ["prettier"]; typescript = ["prettier"];
vue = ["prettier"]; vue = ["prettier"];
}; };
}; };
}; };
} }

View File

@@ -1,15 +1,15 @@
{ {
programs.nixvim.plugins.copilot-lua = { programs.nixvim.plugins.copilot-lua = {
enable = true; enable = true;
settings = { settings = {
panel.enabled = false; panel.enabled = false;
suggestion = { suggestion = {
enabled = true; enabled = true;
auto_trigger = true; auto_trigger = true;
keymap = { keymap = {
accept = "<Tab>"; accept = "<Tab>";
}; };
}; };
}; };
}; };
} }

View File

@@ -1,7 +1,7 @@
{ {
programs.nixvim.plugins = { programs.nixvim.plugins = {
grug-far = { grug-far = {
enable = true; enable = true;
}; };
}; };
} }

View File

@@ -1,7 +1,7 @@
{ {
programs.nixvim.plugins = { programs.nixvim.plugins = {
harpoon = { harpoon = {
enable = true; enable = true;
}; };
}; };
} }

View File

@@ -1,7 +1,7 @@
{ {
programs.nixvim.plugins = { programs.nixvim.plugins = {
hunk = { hunk = {
enable = true; enable = true;
}; };
}; };
} }

View File

@@ -1,15 +1,15 @@
{ {
programs.nixvim.plugins = { programs.nixvim.plugins = {
lsp = { lsp = {
enable = true; enable = true;
inlayHints = true; inlayHints = true;
servers = { servers = {
nil_ls.enable = true; nil_ls.enable = true;
cssls.enable = true; cssls.enable = true;
dockerls.enable = true; dockerls.enable = true;
yamlls.enable = true; yamlls.enable = true;
vtsls.enable = true; vtsls.enable = true;
}; };
}; };
}; };
} }

View File

@@ -1,157 +1,157 @@
{ {
programs.nixvim.plugins.mini = { programs.nixvim.plugins.mini = {
enable = true; enable = true;
modules = { modules = {
ai = { ai = {
custom_textobjects = { custom_textobjects = {
B.__raw = "require('mini.extra').gen_ai_spec.buffer()"; B.__raw = "require('mini.extra').gen_ai_spec.buffer()";
F.__raw = "require('mini.ai').gen_spec.treesitter({ a = '@function.outer', i = '@function.inner' })"; F.__raw = "require('mini.ai').gen_spec.treesitter({ a = '@function.outer', i = '@function.inner' })";
}; };
}; };
align = {}; align = {};
basics = { basics = {
options = { options = {
basic = true; basic = true;
extra_ui = true; extra_ui = true;
}; };
mappings = { mappings = {
basic = false; basic = false;
}; };
autocommands = { autocommands = {
basic = true; basic = true;
}; };
}; };
bracketed = {}; bracketed = {};
clue = { clue = {
clues.__raw = '' clues.__raw = ''
{ {
{ mode = 'n', keys = '<Leader>e', desc = '+Explore/+Edit' }, { mode = 'n', keys = '<Leader>e', desc = '+Explore/+Edit' },
{ mode = 'n', keys = '<Leader>f', desc = '+Find' }, { mode = 'n', keys = '<Leader>f', desc = '+Find' },
{ mode = 'n', keys = '<Leader>g', desc = '+Git' }, { mode = 'n', keys = '<Leader>g', desc = '+Git' },
{ mode = 'n', keys = '<Leader>l', desc = '+LSP' }, { mode = 'n', keys = '<Leader>l', desc = '+LSP' },
{ mode = 'x', keys = '<Leader>l', desc = '+LSP' }, { mode = 'x', keys = '<Leader>l', desc = '+LSP' },
require("mini.clue").gen_clues.builtin_completion(), require("mini.clue").gen_clues.builtin_completion(),
require("mini.clue").gen_clues.g(), require("mini.clue").gen_clues.g(),
require("mini.clue").gen_clues.marks(), require("mini.clue").gen_clues.marks(),
require("mini.clue").gen_clues.registers(), require("mini.clue").gen_clues.registers(),
require("mini.clue").gen_clues.windows({ submode_resize = true }), require("mini.clue").gen_clues.windows({ submode_resize = true }),
require("mini.clue").gen_clues.z(), require("mini.clue").gen_clues.z(),
} }
''; '';
triggers = [ triggers = [
{ {
mode = "n"; mode = "n";
keys = "<Leader>"; keys = "<Leader>";
} }
{ {
mode = "x"; mode = "x";
keys = "<Leader>"; keys = "<Leader>";
} }
{ {
mode = "n"; mode = "n";
keys = "["; keys = "[";
} }
{ {
mode = "n"; mode = "n";
keys = "]"; keys = "]";
} }
{ {
mode = "x"; mode = "x";
keys = "["; keys = "[";
} }
{ {
mode = "x"; mode = "x";
keys = "]"; keys = "]";
} }
{ {
mode = "i"; mode = "i";
keys = "<C-x>"; keys = "<C-x>";
} }
{ {
mode = "n"; mode = "n";
keys = "g"; keys = "g";
} }
{ {
mode = "x"; mode = "x";
keys = "g"; keys = "g";
} }
{ {
mode = "n"; mode = "n";
keys = "\""; keys = "\"";
} }
{ {
mode = "x"; mode = "x";
keys = "\""; keys = "\"";
} }
{ {
mode = "i"; mode = "i";
keys = "<C-r>"; keys = "<C-r>";
} }
{ {
mode = "c"; mode = "c";
keys = "<C-r>"; keys = "<C-r>";
} }
{ {
mode = "n"; mode = "n";
keys = "<C-w>"; keys = "<C-w>";
} }
{ {
mode = "n"; mode = "n";
keys = "z"; keys = "z";
} }
{ {
mode = "x"; mode = "x";
keys = "z"; keys = "z";
} }
{ {
mode = "n"; mode = "n";
keys = "'"; keys = "'";
} }
{ {
mode = "n"; mode = "n";
keys = "`"; keys = "`";
} }
{ {
mode = "x"; mode = "x";
keys = "'"; keys = "'";
} }
{ {
mode = "x"; mode = "x";
keys = "`"; keys = "`";
} }
]; ];
}; };
comment = {}; comment = {};
diff = {}; diff = {};
extra = {}; extra = {};
git = {}; git = {};
icons = {}; icons = {};
indentscope = { indentscope = {
settings = { settings = {
symbol = "|"; symbol = "|";
}; };
}; };
jump = {}; jump = {};
jump2d = { jump2d = {
settings = { settings = {
spotter.__raw = "require('mini.jump2d').gen_spotter.pattern('[^%s%p]+')"; spotter.__raw = "require('mini.jump2d').gen_spotter.pattern('[^%s%p]+')";
labels = "asdfghjkl"; labels = "asdfghjkl";
view = { view = {
dim = true; dim = true;
n_steps_ahead = 2; n_steps_ahead = 2;
}; };
}; };
}; };
move = {}; move = {};
pairs = {}; pairs = {};
pick = {}; pick = {};
starter = {}; starter = {};
statusline = {}; statusline = {};
surround = {}; surround = {};
trailspace = {}; trailspace = {};
visits = {}; visits = {};
}; };
mockDevIcons = true; mockDevIcons = true;
}; };
} }

View File

@@ -1,27 +1,27 @@
{ {
programs.nixvim.plugins.oil = { programs.nixvim.plugins.oil = {
enable = true; enable = true;
settings = { settings = {
keymaps = { keymaps = {
"<C-r>" = "actions.refresh"; "<C-r>" = "actions.refresh";
"<leader>qq" = "actions.close"; "<leader>qq" = "actions.close";
}; };
skip_confirm_for_simple_edits = true; skip_confirm_for_simple_edits = true;
constrain_cursor = "editable"; constrain_cursor = "editable";
default_file_explorer = true; default_file_explorer = true;
view_options = { view_options = {
show_hidden = true; show_hidden = true;
}; };
win_options = { win_options = {
concealcursor = "ncv"; concealcursor = "ncv";
conceallevel = 3; conceallevel = 3;
cursorcolumn = false; cursorcolumn = false;
foldcolumn = "0"; foldcolumn = "0";
list = false; list = false;
signcolumn = "no"; signcolumn = "no";
spell = false; spell = false;
wrap = false; wrap = false;
}; };
}; };
}; };
} }

View File

@@ -1,20 +1,20 @@
{ {
programs.nixvim.plugins.toggleterm = { programs.nixvim.plugins.toggleterm = {
enable = true; enable = true;
settings = { settings = {
open_mapping = null; open_mapping = null;
direction = "float"; direction = "float";
float_opts = { float_opts = {
border = "curved"; border = "curved";
winblend = 3; winblend = 3;
}; };
size = 20; size = 20;
hide_numbers = true; hide_numbers = true;
shade_terminals = true; shade_terminals = true;
shading_factor = 2; shading_factor = 2;
start_in_insert = true; start_in_insert = true;
close_on_exit = true; close_on_exit = true;
shell = "fish"; shell = "fish";
}; };
}; };
} }

View File

@@ -1,21 +1,21 @@
{pkgs, ...}: { {pkgs, ...}: {
programs.nixvim.plugins.treesitter = { programs.nixvim.plugins.treesitter = {
enable = true; enable = true;
settings = { settings = {
highlight.enable = true; highlight.enable = true;
indent.enable = true; indent.enable = true;
}; };
grammarPackages = with pkgs.vimPlugins.nvim-treesitter.builtGrammars; [ grammarPackages = with pkgs.vimPlugins.nvim-treesitter.builtGrammars; [
bash bash
elixir elixir
fish fish
heex heex
json json
nix nix
toml toml
typescript typescript
vue vue
yaml yaml
]; ];
}; };
} }

View File

@@ -1,23 +1,23 @@
{ {
inputs, inputs,
pkgs, pkgs,
... ...
}: { }: {
programs.opencode = { programs.opencode = {
enable = true; enable = true;
package = inputs.nix-ai-tools.packages.${pkgs.system}.opencode; package = inputs.nix-ai-tools.packages.${pkgs.system}.opencode;
settings = { settings = {
theme = "catppuccin"; theme = "catppuccin";
instructions = [ instructions = [
"CLAUDE.md" "CLAUDE.md"
"AGENT.md" "AGENT.md"
"AGENTS.md" "AGENTS.md"
]; ];
formatter = { formatter = {
mix = { mix = {
disabled = true; disabled = true;
}; };
}; };
}; };
}; };
} }

View File

@@ -1,21 +1,21 @@
{ {
programs.ripgrep = { programs.ripgrep = {
enable = true; enable = true;
arguments = [ arguments = [
"--max-columns=150" "--max-columns=150"
"--max-columns-preview" "--max-columns-preview"
"--smart-case" "--smart-case"
"--colors=column:none" "--colors=column:none"
"--colors=column:fg:4" "--colors=column:fg:4"
"--colors=column:style:underline" "--colors=column:style:underline"
"--colors=line:none" "--colors=line:none"
"--colors=line:fg:4" "--colors=line:fg:4"
"--colors=match:none" "--colors=match:none"
"--colors=match:bg:0" "--colors=match:bg:0"
"--colors=match:fg:6" "--colors=match:fg:6"
"--colors=path:none" "--colors=path:none"
"--colors=path:fg:14" "--colors=path:fg:14"
"--colors=path:style:bold" "--colors=path:style:bold"
]; ];
}; };
} }

View File

@@ -1,25 +1,25 @@
{ {
pkgs, pkgs,
lib, lib,
user, user,
... ...
}: { }: {
programs.ssh = { programs.ssh = {
enable = true; enable = true;
enableDefaultConfig = false; enableDefaultConfig = false;
includes = [ includes = [
(lib.mkIf pkgs.stdenv.hostPlatform.isLinux "/home/${user}/.ssh/config_external") (lib.mkIf pkgs.stdenv.hostPlatform.isLinux "/home/${user}/.ssh/config_external")
(lib.mkIf pkgs.stdenv.hostPlatform.isDarwin "/Users/${user}/.ssh/config_external") (lib.mkIf pkgs.stdenv.hostPlatform.isDarwin "/Users/${user}/.ssh/config_external")
]; ];
matchBlocks = { matchBlocks = {
"*" = {}; "*" = {};
"github.com" = { "github.com" = {
identitiesOnly = true; identitiesOnly = true;
identityFile = [ identityFile = [
(lib.mkIf pkgs.stdenv.hostPlatform.isLinux "/home/${user}/.ssh/id_ed25519") (lib.mkIf pkgs.stdenv.hostPlatform.isLinux "/home/${user}/.ssh/id_ed25519")
(lib.mkIf pkgs.stdenv.hostPlatform.isDarwin "/Users/${user}/.ssh/id_ed25519") (lib.mkIf pkgs.stdenv.hostPlatform.isDarwin "/Users/${user}/.ssh/id_ed25519")
]; ];
}; };
}; };
}; };
} }

View File

@@ -1,45 +1,45 @@
{ {
programs.starship = { programs.starship = {
enable = true; enable = true;
enableFishIntegration = true; enableFishIntegration = true;
settings = { settings = {
add_newline = true; add_newline = true;
command_timeout = 2000; command_timeout = 2000;
format = "[$directory$\{custom.jj}]($style)$character"; format = "[$directory$\{custom.jj}]($style)$character";
character = { character = {
error_symbol = "[ ](bold #e64553)"; error_symbol = "[ ](bold #e64553)";
success_symbol = "[](bold #40a02b)[](bold #df8e1d)[](bold #dc8a78)"; success_symbol = "[](bold #40a02b)[](bold #df8e1d)[](bold #dc8a78)";
}; };
directory = { directory = {
truncation_length = 2; truncation_length = 2;
truncation_symbol = "/"; truncation_symbol = "/";
repo_root_style = "bold cyan"; repo_root_style = "bold cyan";
repo_root_format = "[$repo_root]($repo_root_style)[$path]($style)[$read_only]($read_only_style) "; repo_root_format = "[$repo_root]($repo_root_style)[$path]($style)[$read_only]($read_only_style) ";
}; };
custom.jj = { custom.jj = {
command = '' command = ''
jj log --revisions @ --no-graph --ignore-working-copy --color always --limit 1 --template ' jj log --revisions @ --no-graph --ignore-working-copy --color always --limit 1 --template '
separate(" ", separate(" ",
change_id.shortest(4), change_id.shortest(4),
bookmarks, bookmarks,
"|", "|",
concat( concat(
if(conflict, "💥"), if(conflict, "💥"),
if(divergent, "🚧"), if(divergent, "🚧"),
if(hidden, "👻"), if(hidden, "👻"),
if(immutable, "🔒"), if(immutable, "🔒"),
), ),
raw_escape_sequence("\x1b[1;32m") ++ if(empty, "(empty)"), raw_escape_sequence("\x1b[1;32m") ++ if(empty, "(empty)"),
raw_escape_sequence("\x1b[1;32m") ++ coalesce( raw_escape_sequence("\x1b[1;32m") ++ coalesce(
truncate_end(29, description.first_line(), ""), truncate_end(29, description.first_line(), ""),
"(no description set)", "(no description set)",
) ++ raw_escape_sequence("\x1b[0m"), ) ++ raw_escape_sequence("\x1b[0m"),
) )
' '
''; '';
when = "jj --ignore-working-copy root"; when = "jj --ignore-working-copy root";
symbol = "🥋"; symbol = "🥋";
}; };
}; };
}; };
} }

View File

@@ -1,60 +1,60 @@
{ {
lib, lib,
pkgs, pkgs,
... ...
}: { }: {
programs.zellij = programs.zellij =
{ {
enable = true; enable = true;
settings = { settings = {
theme = "catppuccin-latte"; theme = "catppuccin-latte";
default_layout = "default"; default_layout = "default";
default_shell = "${pkgs.fish}/bin/fish"; default_shell = "${pkgs.fish}/bin/fish";
pane_frames = false; pane_frames = false;
show_startup_tips = false; show_startup_tips = false;
show_release_notes = false; show_release_notes = false;
}; };
} }
// lib.optionalAttrs pkgs.stdenv.isLinux { // lib.optionalAttrs pkgs.stdenv.isLinux {
enableFishIntegration = true; enableFishIntegration = true;
}; };
xdg.configFile."zellij/layouts/default.kdl".text = '' xdg.configFile."zellij/layouts/default.kdl".text = ''
layout { layout {
default_tab_template { default_tab_template {
pane split_direction="vertical" { pane split_direction="vertical" {
pane pane
} }
pane size=1 borderless=true { pane size=1 borderless=true {
plugin location="file:${pkgs.zjstatus}/bin/zjstatus.wasm" { plugin location="file:${pkgs.zjstatus}/bin/zjstatus.wasm" {
hide_frame_for_single_pane "true" hide_frame_for_single_pane "true"
format_left "{mode}#[fg=#1e66f5,bg=#eff1f5,bold] {session}#[bg=#eff1f5] {tabs}" format_left "{mode}#[fg=#1e66f5,bg=#eff1f5,bold] {session}#[bg=#eff1f5] {tabs}"
format_right "{datetime}" format_right "{datetime}"
format_space "#[bg=#eff1f5]" format_space "#[bg=#eff1f5]"
mode_normal "#[fg=#eff1f5,bg=#1e66f5] " mode_normal "#[fg=#eff1f5,bg=#1e66f5] "
mode_locked "#[fg=#eff1f5,bg=#fe640b] L " mode_locked "#[fg=#eff1f5,bg=#fe640b] L "
mode_tab "#[fg=#eff1f5,bg=#40a02b] T " mode_tab "#[fg=#eff1f5,bg=#40a02b] T "
mode_pane "#[fg=#eff1f5,bg=#8839ef] P " mode_pane "#[fg=#eff1f5,bg=#8839ef] P "
mode_session "#[fg=#eff1f5,bg=#04a5e5] S " mode_session "#[fg=#eff1f5,bg=#04a5e5] S "
mode_resize "#[fg=#eff1f5,bg=#df8e1d] R " mode_resize "#[fg=#eff1f5,bg=#df8e1d] R "
mode_move "#[fg=#eff1f5,bg=#ea76cb] M " mode_move "#[fg=#eff1f5,bg=#ea76cb] M "
mode_search "#[fg=#eff1f5,bg=#d20f39] S " mode_search "#[fg=#eff1f5,bg=#d20f39] S "
tab_normal "#[fg=#acb0be,bg=#eff1f5] {index} {name} {fullscreen_indicator}{sync_indicator}{floating_indicator}" tab_normal "#[fg=#acb0be,bg=#eff1f5] {index} {name} {fullscreen_indicator}{sync_indicator}{floating_indicator}"
tab_active "#[fg=#eff1f5,bg=#1e66f5,bold,underline] {index} {name} {fullscreen_indicator}{sync_indicator}{floating_indicator}" tab_active "#[fg=#eff1f5,bg=#1e66f5,bold,underline] {index} {name} {fullscreen_indicator}{sync_indicator}{floating_indicator}"
tab_fullscreen_indicator " " tab_fullscreen_indicator " "
tab_sync_indicator " " tab_sync_indicator " "
tab_floating_indicator "󰉈 " tab_floating_indicator "󰉈 "
datetime "#[fg=#4c4f69,bg=#eff1f5] {format} " datetime "#[fg=#4c4f69,bg=#eff1f5] {format} "
datetime_format "%A, %d %b %Y %H:%M" datetime_format "%A, %d %b %Y %H:%M"
datetime_timezone "Europe/Berlin" datetime_timezone "Europe/Berlin"
} }
} }
} }
} }
''; '';
} }

View File

@@ -1,6 +1,6 @@
{ {
programs.zoxide = { programs.zoxide = {
enable = true; enable = true;
enableFishIntegration = true; enableFishIntegration = true;
}; };
} }

View File

@@ -1,5 +1,5 @@
{ {
programs.zsh = { programs.zsh = {
enable = true; enable = true;
}; };
} }

View File

@@ -1,81 +1,81 @@
{ {
pkgs, pkgs,
inputs, inputs,
user, user,
constants, constants,
... ...
}: { }: {
imports = [ imports = [
../core.nix ../core.nix
../syncthing.nix ../syncthing.nix
../tailscale.nix ../tailscale.nix
inputs.sops-nix.nixosModules.sops inputs.sops-nix.nixosModules.sops
]; ];
security.sudo.enable = true; security.sudo.enable = true;
system.stateVersion = constants.stateVersions.nixos; system.stateVersion = constants.stateVersions.nixos;
time.timeZone = "UTC"; time.timeZone = "UTC";
nix = { nix = {
settings.trusted-users = ["${user}"]; settings.trusted-users = ["${user}"];
gc.dates = "weekly"; gc.dates = "weekly";
nixPath = ["nixos-config=/home/${user}/.local/share/src/nixos-config:/etc/nixos"]; nixPath = ["nixos-config=/home/${user}/.local/share/src/nixos-config:/etc/nixos"];
}; };
boot = { boot = {
loader = { loader = {
systemd-boot = { systemd-boot = {
enable = true; enable = true;
configurationLimit = 42; configurationLimit = 42;
}; };
efi.canTouchEfiVariables = true; efi.canTouchEfiVariables = true;
}; };
initrd.availableKernelModules = [ initrd.availableKernelModules = [
"xhci_pci" "xhci_pci"
"ahci" "ahci"
"nvme" "nvme"
"usbhid" "usbhid"
"usb_storage" "usb_storage"
"sd_mod" "sd_mod"
]; ];
kernelPackages = pkgs.linuxPackages_latest; kernelPackages = pkgs.linuxPackages_latest;
}; };
users.users = { users.users = {
${user} = { ${user} = {
isNormalUser = true; isNormalUser = true;
home = "/home/${user}"; home = "/home/${user}";
extraGroups = [ extraGroups = [
"wheel" "wheel"
"sudo" "sudo"
"network" "network"
"systemd-journal" "systemd-journal"
"docker" "docker"
]; ];
shell = pkgs.fish; shell = pkgs.fish;
openssh.authorizedKeys.keys = constants.sshKeys; openssh.authorizedKeys.keys = constants.sshKeys;
}; };
root = { root = {
openssh.authorizedKeys.keys = constants.sshKeys; openssh.authorizedKeys.keys = constants.sshKeys;
}; };
}; };
home-manager = { home-manager = {
useGlobalPkgs = true; useGlobalPkgs = true;
users.${user} = { users.${user} = {
pkgs, pkgs,
config, config,
lib, lib,
... ...
}: { }: {
_module.args = {inherit user constants inputs;}; _module.args = {inherit user constants inputs;};
imports = [ imports = [
inputs.nixvim.homeModules.nixvim inputs.nixvim.homeModules.nixvim
../home/default.nix ../home/default.nix
./home/default.nix ./home/default.nix
]; ];
}; };
}; };
} }

View File

@@ -1,5 +1,5 @@
{pkgs, ...}: { {pkgs, ...}: {
home = { home = {
packages = pkgs.callPackage ../packages.nix {}; packages = pkgs.callPackage ../packages.nix {};
}; };
} }

View File

@@ -1,6 +1,6 @@
{pkgs}: {pkgs}:
with pkgs; [ with pkgs; [
gcc15 gcc15
lm_sensors lm_sensors
ghostty.terminfo ghostty.terminfo
] ]

View File

@@ -1,43 +1,43 @@
{ {
pkgs, pkgs,
inputs, inputs,
... ...
}: }:
with pkgs; [ with pkgs; [
inputs.beads.packages.${pkgs.system}.default inputs.beads.packages.${pkgs.system}.default
inputs.nix-ai-tools.packages.${pkgs.system}.amp inputs.nix-ai-tools.packages.${pkgs.system}.amp
(callPackage ./bin/open-project.nix {}) (callPackage ./bin/open-project.nix {})
age age
alejandra alejandra
ast-grep ast-grep
bun bun
delta delta
devenv devenv
dig dig
docker docker
docker-compose docker-compose
fastfetch fastfetch
fd fd
gh gh
git git
gnumake gnumake
gnupg gnupg
hledger hledger
htop htop
hyperfine hyperfine
jq jq
killall killall
lsof lsof
nurl nurl
openssh openssh
postgresql_17 postgresql_17
sd sd
sops sops
sqlite sqlite
tokei tokei
tree tree
tree-sitter tree-sitter
unzip unzip
vivid vivid
zip zip
] ]

View File

@@ -1,43 +1,43 @@
{ {
pkgs, pkgs,
inputs, inputs,
... ...
}: }:
with pkgs; [ with pkgs; [
inputs.beads.packages.${pkgs.system}.default inputs.beads.packages.${pkgs.system}.default
inputs.nix-ai-tools.packages.${pkgs.system}.amp inputs.nix-ai-tools.packages.${pkgs.system}.amp
(callPackage ./bin/open-project.nix {}) (callPackage ./bin/open-project.nix {})
age age
alejandra alejandra
ast-grep ast-grep
bun bun
delta delta
devenv devenv
dig dig
docker docker
docker-compose docker-compose
hledger hledger
fastfetch fastfetch
fd fd
gh gh
git git
gnumake gnumake
gnupg gnupg
htop htop
hyperfine hyperfine
jq jq
killall killall
lsof lsof
nurl nurl
openssh openssh
postgresql_17 postgresql_17
sd sd
sops sops
sqlite sqlite
tokei tokei
tree tree
tree-sitter tree-sitter
unzip unzip
vivid vivid
zip zip
] ]

View File

@@ -1,53 +1,53 @@
{ {
user, user,
pkgs, pkgs,
... ...
}: let }: let
isDarwin = pkgs.stdenv.isDarwin; isDarwin = pkgs.stdenv.isDarwin;
homeDir = homeDir =
if isDarwin if isDarwin
then "/Users/${user}" then "/Users/${user}"
else "/home/${user}"; else "/home/${user}";
group = group =
if isDarwin if isDarwin
then "staff" then "staff"
else "users"; else "users";
in { in {
services.syncthing = { services.syncthing = {
enable = true; enable = true;
openDefaultPorts = !isDarwin; openDefaultPorts = !isDarwin;
dataDir = "${homeDir}/.local/share/syncthing"; dataDir = "${homeDir}/.local/share/syncthing";
configDir = "${homeDir}/.config/syncthing"; configDir = "${homeDir}/.config/syncthing";
user = "${user}"; user = "${user}";
group = group; group = group;
guiAddress = "0.0.0.0:8384"; guiAddress = "0.0.0.0:8384";
overrideFolders = true; overrideFolders = true;
overrideDevices = true; overrideDevices = true;
settings = { settings = {
devices = { devices = {
"tahani" = { "tahani" = {
id = "6B7OZZF-TEAMUGO-FBOELXP-Z4OY7EU-5ZHLB5T-V6Z3UDB-Q2DYR43-QBYW6QM"; id = "6B7OZZF-TEAMUGO-FBOELXP-Z4OY7EU-5ZHLB5T-V6Z3UDB-Q2DYR43-QBYW6QM";
addresses = ["tcp://tahani:22000"]; addresses = ["tcp://tahani:22000"];
}; };
"jason" = { "jason" = {
id = "42II2VO-QYPJG26-ZS3MB2I-AOPVZ67-JJNSE76-U54CO5Y-634A5OG-ECU4YQA"; id = "42II2VO-QYPJG26-ZS3MB2I-AOPVZ67-JJNSE76-U54CO5Y-634A5OG-ECU4YQA";
addresses = ["tcp://jason:22000"]; addresses = ["tcp://jason:22000"];
}; };
"chidi" = { "chidi" = {
id = "N7W6SUT-QO6J4BE-T3Y65SM-OFGYGNV-TGYBJPX-JVN4Z72-AENZ247-KWXOQA6"; id = "N7W6SUT-QO6J4BE-T3Y65SM-OFGYGNV-TGYBJPX-JVN4Z72-AENZ247-KWXOQA6";
addresses = ["tcp://chidi:22000"]; addresses = ["tcp://chidi:22000"];
}; };
}; };
folders = { folders = {
"nixos-config" = { "nixos-config" = {
path = "${homeDir}/nixos-config"; path = "${homeDir}/nixos-config";
devices = ["tahani" "jason" "chidi"]; devices = ["tahani" "jason" "chidi"];
}; };
}; };
options.globalAnnounceEnabled = false; options.globalAnnounceEnabled = false;
}; };
}; };
} }

View File

@@ -1,14 +1,14 @@
{ {
lib, lib,
pkgs, pkgs,
... ...
}: { }: {
services.tailscale = services.tailscale =
{ {
enable = true; enable = true;
} }
// lib.optionalAttrs pkgs.stdenv.isLinux { // lib.optionalAttrs pkgs.stdenv.isLinux {
openFirewall = true; openFirewall = true;
useRoutingFeatures = "server"; useRoutingFeatures = "server";
}; };
} }

View File

@@ -1,17 +1,18 @@
{inputs}: let {inputs}: let
dir = builtins.readDir ./.; dir = builtins.readDir ./.;
overlayNames = builtins.sort builtins.lessThan (builtins.filter ( overlayNames =
name: builtins.sort builtins.lessThan (builtins.filter (
name name:
!= "default.nix" name
&& dir.${name} == "regular" != "default.nix"
&& builtins.match ".*\\.nix" name != null && dir.${name} == "regular"
) (builtins.attrNames dir)); && builtins.match ".*\\.nix" name != null
overlayPath = name: ) (builtins.attrNames dir));
builtins.toPath "${builtins.toString ./.}/${name}"; overlayPath = name:
loadOverlay = name: let builtins.toPath "${builtins.toString ./.}/${name}";
overlayModule = import (overlayPath name); loadOverlay = name: let
in overlayModule = import (overlayPath name);
overlayModule {inherit inputs;}; in
overlayModule {inherit inputs;};
in in
map loadOverlay overlayNames map loadOverlay overlayNames

View File

@@ -1,3 +1,3 @@
{inputs}: final: prev: { {inputs}: final: prev: {
zjstatus = inputs.zjstatus.packages.${prev.system}.default; zjstatus = inputs.zjstatus.packages.${prev.system}.default;
} }