Compare commits

..

2 Commits

Author SHA1 Message Date
f8ee011d27 Attempt to fix custom package format 2025-10-13 14:25:23 -07:00
4a4ea6316d [app-launcher] Add app-launcher to boxy 2025-10-13 14:25:13 -07:00
43 changed files with 135 additions and 1840 deletions

1
.gitignore vendored
View File

@@ -1,2 +1 @@
result result
thoughts

163
flake.lock generated
View File

@@ -3,11 +3,11 @@
"flake-compat": { "flake-compat": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1761588595, "lastModified": 1747046372,
"narHash": "sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4=", "narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=",
"owner": "edolstra", "owner": "edolstra",
"repo": "flake-compat", "repo": "flake-compat",
"rev": "f387cd2afec9419c8ee37694406ca490c3f34ee5", "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -23,11 +23,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1761423376, "lastModified": 1752428473,
"narHash": "sha256-pMy3cnUFfue4vz/y0jx71BfcPGxZf+hk/DtnzWvfU0c=", "narHash": "sha256-IsE7fdAYbRlZuc0H5FtPfhhuHvlxnDGoAxdlnjpVNCU=",
"ref": "refs/heads/main", "ref": "refs/heads/main",
"rev": "a1f695665771841a988afc965526cbf99160cd77", "rev": "1fad66b55144ab6beaecd900172a21ac3c34dc52",
"revCount": 11, "revCount": 10,
"type": "git", "type": "git",
"url": "https://git.johnogle.info/johno/google-cookie-retrieval.git" "url": "https://git.johnogle.info/johno/google-cookie-retrieval.git"
}, },
@@ -43,62 +43,19 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1758463745, "lastModified": 1759172751,
"narHash": "sha256-uhzsV0Q0I9j2y/rfweWeGif5AWe0MGrgZ/3TjpDYdGA=", "narHash": "sha256-E8W8sRXfrvkFW26GuuiWq6QfReU7m5+cngwHuRo/3jc=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "3b955f5f0a942f9f60cdc9cacb7844335d0f21c3", "rev": "12fa8548feefa9a10266ba65152fd1a787cdde8f",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nix-community", "owner": "nix-community",
"ref": "release-25.05",
"repo": "home-manager", "repo": "home-manager",
"type": "github" "type": "github"
} }
}, },
"home-manager-unstable": {
"inputs": {
"nixpkgs": [
"nixpkgs-unstable"
]
},
"locked": {
"lastModified": 1763416652,
"narHash": "sha256-8EBEEvtzQ11LCxpQHMNEBQAGtQiCu/pqP9zSovDSbNM=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "ea164b7c9ccdc2321379c2ff78fd4317b4c41312",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "master",
"repo": "home-manager",
"type": "github"
}
},
"jovian": {
"inputs": {
"nix-github-actions": "nix-github-actions",
"nixpkgs": [
"nixpkgs-unstable"
]
},
"locked": {
"lastModified": 1763223001,
"narHash": "sha256-Hi6XxTJJjKsDrO+D0fYXS88ehCYzQkZlp9qxX1zoM1s=",
"owner": "Jovian-Experiments",
"repo": "Jovian-NixOS",
"rev": "68a1bcc019378272e601558719f82005a80ddab0",
"type": "github"
},
"original": {
"owner": "Jovian-Experiments",
"repo": "Jovian-NixOS",
"type": "github"
}
},
"nix-darwin": { "nix-darwin": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@@ -106,53 +63,30 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1762912391, "lastModified": 1758805352,
"narHash": "sha256-4hpBE7bGd24SfD28rzMdUGXsLsNEYxCCrTipFdoqoNM=", "narHash": "sha256-BHdc43Lkayd+72W/NXRKHzX5AZ+28F3xaUs3a88/Uew=",
"owner": "nix-darwin", "owner": "nix-darwin",
"repo": "nix-darwin", "repo": "nix-darwin",
"rev": "d76299b2cd01837c4c271a7b5186e3d5d8ebd126", "rev": "c48e963a5558eb1c3827d59d21c5193622a1477c",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nix-darwin", "owner": "nix-darwin",
"ref": "nix-darwin-25.05",
"repo": "nix-darwin", "repo": "nix-darwin",
"type": "github" "type": "github"
} }
}, },
"nix-github-actions": {
"inputs": {
"nixpkgs": [
"jovian",
"nixpkgs"
]
},
"locked": {
"lastModified": 1729697500,
"narHash": "sha256-VFTWrbzDlZyFHHb1AlKRiD/qqCJIripXKiCSFS8fAOY=",
"owner": "zhaofengli",
"repo": "nix-github-actions",
"rev": "e418aeb728b6aa5ca8c5c71974e7159c2df1d8cf",
"type": "github"
},
"original": {
"owner": "zhaofengli",
"ref": "matrix-name",
"repo": "nix-github-actions",
"type": "github"
}
},
"nixos-wsl": { "nixos-wsl": {
"inputs": { "inputs": {
"flake-compat": "flake-compat", "flake-compat": "flake-compat",
"nixpkgs": "nixpkgs" "nixpkgs": "nixpkgs"
}, },
"locked": { "locked": {
"lastModified": 1763385941, "lastModified": 1758785683,
"narHash": "sha256-99CBNgyMvg3Zu/hxqixtShevrF4Kfr/qjtizQ6oseVI=", "narHash": "sha256-mRn51IeEBXeNh5a6xNLylk4PKBX0s/QQxgkEbYoPq/w=",
"owner": "nix-community", "owner": "nix-community",
"repo": "NixOS-WSL", "repo": "NixOS-WSL",
"rev": "cc6483354b236c2fc95cc1d4ba1f0f40b7345e69", "rev": "1bfb978f2f6261b6086e04af17f9418e1fe36d70",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -164,11 +98,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1762977756, "lastModified": 1758277210,
"narHash": "sha256-4PqRErxfe+2toFJFgcRKZ0UI9NSIOJa+7RXVtBhy4KE=", "narHash": "sha256-iCGWf/LTy+aY0zFu8q12lK8KuZp7yvdhStehhyX1v8w=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "c5ae371f1a6a7fd27823bc500d9390b38c05fa55", "rev": "8eaee110344796db060382e15d3af0a9fc396e0e",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -178,34 +112,18 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs-unstable": {
"locked": {
"lastModified": 1763283776,
"narHash": "sha256-Y7TDFPK4GlqrKrivOcsHG8xSGqQx3A6c+i7novT85Uk=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "50a96edd8d0db6cc8db57dab6bb6d6ee1f3dc49a",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1763049705, "lastModified": 1759036355,
"narHash": "sha256-A5LS0AJZ1yDPTa2fHxufZN++n8MCmtgrJDtxFxrH4S8=", "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "3acb677ea67d4c6218f33de0db0955f116b7588c", "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nixos", "owner": "nixos",
"ref": "nixos-25.05", "ref": "nixos-unstable",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }
@@ -220,34 +138,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1762784320, "lastModified": 1759157415,
"narHash": "sha256-odsk96Erywk5hs0dhArF38zb7Oe0q6LZ70gXbxAPKno=", "narHash": "sha256-Fg8cOnVoIe0uQ38UpR6XZzRCwDsjjozVwfevW9yCLI0=",
"owner": "nix-community", "owner": "nix-community",
"repo": "plasma-manager", "repo": "plasma-manager",
"rev": "7911a0f8a44c7e8b29d031be3149ee8943144321", "rev": "df5b3e6da631f732c26c6044c7cccb8706b4f479",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "plasma-manager",
"type": "github"
}
},
"plasma-manager-unstable": {
"inputs": {
"home-manager": [
"home-manager-unstable"
],
"nixpkgs": [
"nixpkgs-unstable"
]
},
"locked": {
"lastModified": 1762784320,
"narHash": "sha256-odsk96Erywk5hs0dhArF38zb7Oe0q6LZ70gXbxAPKno=",
"owner": "nix-community",
"repo": "plasma-manager",
"rev": "7911a0f8a44c7e8b29d031be3149ee8943144321",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -260,14 +155,10 @@
"inputs": { "inputs": {
"google-cookie-retrieval": "google-cookie-retrieval", "google-cookie-retrieval": "google-cookie-retrieval",
"home-manager": "home-manager", "home-manager": "home-manager",
"home-manager-unstable": "home-manager-unstable",
"jovian": "jovian",
"nix-darwin": "nix-darwin", "nix-darwin": "nix-darwin",
"nixos-wsl": "nixos-wsl", "nixos-wsl": "nixos-wsl",
"nixpkgs": "nixpkgs_2", "nixpkgs": "nixpkgs_2",
"nixpkgs-unstable": "nixpkgs-unstable", "plasma-manager": "plasma-manager"
"plasma-manager": "plasma-manager",
"plasma-manager-unstable": "plasma-manager-unstable"
} }
} }
}, },

View File

@@ -2,98 +2,41 @@
description = "A very basic flake"; description = "A very basic flake";
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05"; nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable";
nixos-wsl.url = "github:nix-community/NixOS-WSL/main"; nixos-wsl.url = "github:nix-community/NixOS-WSL/main";
nix-darwin = { nix-darwin = {
url = "github:nix-darwin/nix-darwin/nix-darwin-25.05"; url = "github:nix-darwin/nix-darwin";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
home-manager = { home-manager = {
url = "github:nix-community/home-manager/release-25.05"; url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
home-manager-unstable = {
url = "github:nix-community/home-manager/master";
inputs.nixpkgs.follows = "nixpkgs-unstable";
};
plasma-manager = { plasma-manager = {
url = "github:nix-community/plasma-manager"; url = "github:nix-community/plasma-manager";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
inputs.home-manager.follows = "home-manager"; inputs.home-manager.follows = "home-manager";
}; };
plasma-manager-unstable = {
url = "github:nix-community/plasma-manager";
inputs.nixpkgs.follows = "nixpkgs-unstable";
inputs.home-manager.follows = "home-manager-unstable";
};
google-cookie-retrieval = { google-cookie-retrieval = {
url = "git+https://git.johnogle.info/johno/google-cookie-retrieval.git"; url = "git+https://git.johnogle.info/johno/google-cookie-retrieval.git";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
jovian = {
url = "github:Jovian-Experiments/Jovian-NixOS";
inputs.nixpkgs.follows = "nixpkgs-unstable";
};
}; };
outputs = { self, nixpkgs, nixpkgs-unstable, nixos-wsl, ... } @ inputs: let outputs = { self, nixpkgs, nixos-wsl, ... } @ inputs: let
nixosModules = [ nixosModules = [
./roles ./roles
] ++ [ ] ++ [
./roles/jovian-compat.nix
inputs.home-manager.nixosModules.home-manager inputs.home-manager.nixosModules.home-manager
{ {
nixpkgs.overlays = [
(final: prev: {
unstable = import nixpkgs-unstable {
system = prev.system;
config.allowUnfree = true;
};
custom = prev.callPackage ./packages {};
# Compatibility: bitwarden renamed to bitwarden-desktop in unstable
bitwarden-desktop = prev.bitwarden-desktop or prev.bitwarden;
})
];
home-manager.useGlobalPkgs = true; home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true; home-manager.useUserPackages = true;
home-manager.sharedModules = [ home-manager.sharedModules = [
inputs.plasma-manager.homeModules.plasma-manager inputs.plasma-manager.homeManagerModules.plasma-manager
];
home-manager.extraSpecialArgs = {
globalInputs = inputs;
};
}
];
# Modules for unstable-based systems (like nix-deck)
nixosModulesUnstable = [
./roles
] ++ [
inputs.home-manager-unstable.nixosModules.home-manager
inputs.jovian.nixosModules.jovian
{
nixpkgs.overlays = [
(final: prev: {
unstable = import nixpkgs-unstable {
system = prev.system;
config.allowUnfree = true;
};
custom = prev.callPackage ./packages {};
# Compatibility: bitwarden renamed to bitwarden-desktop in unstable
bitwarden-desktop = prev.bitwarden-desktop or prev.bitwarden;
})
];
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.sharedModules = [
inputs.plasma-manager-unstable.homeModules.plasma-manager
]; ];
home-manager.extraSpecialArgs = { home-manager.extraSpecialArgs = {
globalInputs = inputs; globalInputs = inputs;
@@ -105,17 +48,6 @@
] ++ [ ] ++ [
inputs.home-manager.darwinModules.home-manager inputs.home-manager.darwinModules.home-manager
{ {
nixpkgs.overlays = [
(final: prev: {
unstable = import nixpkgs-unstable {
system = prev.system;
config.allowUnfree = true;
};
custom = prev.callPackage ./packages {};
# Compatibility: bitwarden renamed to bitwarden-desktop in unstable
bitwarden-desktop = prev.bitwarden-desktop or prev.bitwarden;
})
];
home-manager.useGlobalPkgs = true; home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true; home-manager.useUserPackages = true;
home-manager.extraSpecialArgs = { home-manager.extraSpecialArgs = {
@@ -191,18 +123,6 @@
]; ];
}; };
# Steam Deck configuration (using unstable for better Jovian compatibility)
nixosConfigurations.nix-deck = nixpkgs-unstable.lib.nixosSystem rec {
system = "x86_64-linux";
modules = nixosModulesUnstable ++ [
./machines/nix-deck/configuration.nix
{
home-manager.users.johno = import ./home/home-desktop.nix;
home-manager.extraSpecialArgs = { inherit system; };
}
];
};
# Darwin/macOS configurations # Darwin/macOS configurations
darwinConfigurations."blkfv4yf49kt7" = inputs.nix-darwin.lib.darwinSystem rec { darwinConfigurations."blkfv4yf49kt7" = inputs.nix-darwin.lib.darwinSystem rec {
system = "aarch64-darwin"; system = "aarch64-darwin";

View File

@@ -1,33 +1,11 @@
{ config, lib, pkgs, globalInputs, system, ... }: { config, lib, pkgs, globalInputs, system, ... }:
let let
leader = "cmd"; # Change this to experiment with different leader keys (e.g., "cmd", "ctrl") customPkgs = pkgs.callPackage ../packages {};
in in
{ {
# Claude Code Package Override for Corporate Work Environment # Provide arguments to role modules
# _module.args = { inherit customPkgs; };
# This overlay overrides the default claude-code package specifically for work environments
# where corporate network restrictions may prevent access to npm registry distributions.
#
# Context:
# - The default claude-code package (used in home environments) fetches from npm registry
# - Corporate firewalls and security policies often block npm registry access
# - Our custom claude-code package uses Google Cloud Storage distribution as a workaround
# - This maintains the same package name across environments while adapting to network constraints
#
# Environment-specific behavior:
# - Home environments: Use standard npm-distributed claude-code package
# - Work environments: Use custom binary-distributed claude-code package from GCS
#
# This approach ensures consistent tooling availability regardless of network environment
# while respecting corporate security policies.
nixpkgs.overlays = [
(final: prev: {
unstable = prev.unstable // {
claude-code = prev.custom.claude-code;
};
})
];
# Home Manager configuration for Darwin work laptop # Home Manager configuration for Darwin work laptop
# Corporate-friendly setup with essential development tools # Corporate-friendly setup with essential development tools
@@ -35,115 +13,28 @@ in
home.homeDirectory = lib.mkForce "/Users/johno"; home.homeDirectory = lib.mkForce "/Users/johno";
home.stateVersion = "24.05"; home.stateVersion = "24.05";
# System packages
home.packages = with pkgs; [
autoraise
google-cloud-sdk
];
# Note: ghostty installed via Homebrew (managed outside of nix)
# Auto-start autoraise on login
launchd.agents.autoraise = {
enable = true;
config = {
ProgramArguments = [
"${pkgs.autoraise}/bin/AutoRaise"
"-pollMillis" "50"
"-delay" "2"
"-focusDelay" "2"
];
RunAtLoad = true;
KeepAlive = true;
};
};
# Auto-start aerospace on login
# NOTE: In 25.11+, this can be simplified to `programs.aerospace.launchd.enable = true`
launchd.agents.aerospace = {
enable = true;
config = {
Program = "${pkgs.aerospace}/Applications/AeroSpace.app/Contents/MacOS/AeroSpace";
RunAtLoad = true;
KeepAlive = true;
StandardOutPath = "/tmp/aerospace.log";
StandardErrorPath = "/tmp/aerospace.err.log";
};
};
# Override Darwin-incompatible settings from base role # Override Darwin-incompatible settings from base role
programs.rbw.settings.pinentry = lib.mkForce pkgs.pinentry_mac; programs.rbw.settings.pinentry = lib.mkForce pkgs.pinentry_mac;
# Disable Home Manager from managing shell RC files programs.bash.initExtra = ''
# topsoil/compost will manage these files instead export NODE_EXTRA_CA_CERTS=/opt/homebrew/etc/ca-certificates/cert.pem
programs.bash.enable = lib.mkForce false; export COREPACK_NPM_REGISTRY=https://global.block-artifacts.com/artifactory/api/npm/square-npm/
programs.zsh.enable = lib.mkForce false; export COREPACK_INTEGRITY_KEYS=0
# Create a local nix integration file that topsoil-managed configs can source export NVM_DIR="$HOME/.nvm"
home.file.".nix-integration.sh" = { [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
text = '' [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
# Source Home Manager session variables (nix paths, environment, etc.) '';
if [ -e /etc/profiles/per-user/johno/etc/profile.d/hm-session-vars.sh ]; then
. /etc/profiles/per-user/johno/etc/profile.d/hm-session-vars.sh
fi
# Setup bash completions from nix profiles programs.zsh.enable = true;
if [[ ! -v BASH_COMPLETION_VERSINFO ]] && [ -n "$NIX_PROFILES" ]; then programs.zsh.initContent = ''
for profile in $NIX_PROFILES; do export NODE_EXTRA_CA_CERTS=/opt/homebrew/etc/ca-certificates/cert.pem
if [ -f "$profile/etc/profile.d/bash_completion.sh" ]; then export COREPACK_NPM_REGISTRY=https://global.block-artifacts.com/artifactory/api/npm/square-npm/
. "$profile/etc/profile.d/bash_completion.sh" export COREPACK_INTEGRITY_KEYS=0
break export NVM_DIR="$HOME/.nvm"
fi [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm
done [ -s "$NVM_DIR/bash_completion" ] && . "$NVM_DIR/bash_completion" # This loads nvm bash_completion
fi '';
# command-not-found handler
command_not_found_handle() {
local p=/nix/var/nix/profiles/per-user/root/channels/nixos/programs.sqlite
if [ -n "$NIX_PROFILES" ]; then
for profile in $NIX_PROFILES; do
if [ -x "$profile/bin/command-not-found" ] && [ -f "$p" ]; then
"$profile/bin/command-not-found" "$@"
return $?
fi
done
fi
echo "$1: command not found" >&2
return 127
}
'';
};
home.file.".nix-integration.zsh" = {
text = ''
# Source Home Manager session variables (nix paths, environment, etc.)
if [ -e /etc/profiles/per-user/johno/etc/profile.d/hm-session-vars.sh ]; then
. /etc/profiles/per-user/johno/etc/profile.d/hm-session-vars.sh
fi
# Setup zsh completions from nix profiles
typeset -U path cdpath fpath manpath
for profile in ''${(z)NIX_PROFILES}; do
fpath+=($profile/share/zsh/site-functions $profile/share/zsh/$ZSH_VERSION/functions $profile/share/zsh/vendor-completions)
done
autoload -U compinit && compinit
# command-not-found handler
command_not_found_handler() {
local p=/nix/var/nix/profiles/per-user/root/channels/nixos/programs.sqlite
if [ -n "$NIX_PROFILES" ]; then
for profile in ''${(z)NIX_PROFILES}; do
if [ -x "$profile/bin/command-not-found" ] && [ -f "$p" ]; then
"$profile/bin/command-not-found" "$@"
return $?
fi
done
fi
echo "$1: command not found" >&2
return 127
}
'';
};
# Keep SSH and Git disabled to avoid conflicts with work environment # Keep SSH and Git disabled to avoid conflicts with work environment
programs.ssh.enable = lib.mkForce false; programs.ssh.enable = lib.mkForce false;
@@ -152,105 +43,8 @@ in
home.shell.enableShellIntegration = true; home.shell.enableShellIntegration = true;
# TODO: Move this to its own role and/or module
programs.aerospace = {
enable = true;
userSettings.mode.main.binding = {
"${leader}-slash" = "layout tiles horizontal vertical";
"${leader}-comma" = "layout accordion horizontal vertical";
"${leader}-shift-q" = "close";
"${leader}-shift-f" = "fullscreen";
"${leader}-h" = "focus left";
"${leader}-j" = "focus down";
"${leader}-k" = "focus up";
"${leader}-l" = "focus right";
"${leader}-shift-h" = "move left";
"${leader}-shift-j" = "move down";
"${leader}-shift-k" = "move up";
"${leader}-shift-l" = "move right";
"${leader}-minus" = "resize smart -50";
"${leader}-equal" = "resize smart +50";
"${leader}-1" = "workspace 1";
"${leader}-2" = "workspace 2";
"${leader}-3" = "workspace 3";
"${leader}-4" = "workspace 4";
"${leader}-5" = "workspace 5";
"${leader}-6" = "workspace 6";
"${leader}-7" = "workspace 7";
"${leader}-8" = "workspace 8";
"${leader}-9" = "workspace 9";
"${leader}-0" = "workspace 10";
"${leader}-shift-1" = "move-node-to-workspace 1";
"${leader}-shift-2" = "move-node-to-workspace 2";
"${leader}-shift-3" = "move-node-to-workspace 3";
"${leader}-shift-4" = "move-node-to-workspace 4";
"${leader}-shift-5" = "move-node-to-workspace 5";
"${leader}-shift-6" = "move-node-to-workspace 6";
"${leader}-shift-7" = "move-node-to-workspace 7";
"${leader}-shift-8" = "move-node-to-workspace 8";
"${leader}-shift-9" = "move-node-to-workspace 9";
"${leader}-shift-0" = "move-node-to-workspace 10";
"${leader}-tab" = "workspace-back-and-forth";
"${leader}-shift-tab" = "move-workspace-to-monitor --wrap-around next";
"${leader}-enter" = ''
exec-and-forget osascript <<'APPLESCRIPT'
tell application "Ghostty"
activate
tell application "System Events"
keystroke "n" using {command down}
end tell
end tell
APPLESCRIPT
'';
"${leader}-shift-enter" = ''
exec-and-forget osascript <<'APPLESCRIPT'
tell application "Google Chrome"
set newWindow to make new window
activate
tell newWindow to set index to 1
end tell
APPLESCRIPT
'';
"${leader}-shift-e" = "exec-and-forget zsh --login -c \"emacsclient -c -n\"";
# Service mode: Deliberate aerospace window management
"${leader}-i" = "mode service";
# Passthrough mode: Temporarily disable aerospace to use macOS shortcuts
# Press Cmd-P, then use any macOS shortcut (like Cmd-K in Slack), then press Cmd-P again to exit
"${leader}-p" = "mode passthrough";
};
# Service mode: For deliberate aerospace window management operations
userSettings.mode.service.binding = {
esc = ["reload-config" "mode main"];
r = ["flatten-workspace-tree" "mode main"]; # reset layout
f = ["layout floating tiling" "mode main"]; # Toggle between floating and tiling layout
backspace = ["close-all-windows-but-current" "mode main"];
"${leader}-shift-h" = ["join-with left" "mode main"];
"${leader}-shift-j" = ["join-with down" "mode main"];
"${leader}-shift-k" = ["join-with up" "mode main"];
"${leader}-shift-l" = ["join-with right" "mode main"];
};
# Passthrough mode: All shortcuts pass through to macOS
# This mode has minimal bindings - just ways to exit back to main mode
userSettings.mode.passthrough.binding = {
esc = "mode main";
"${leader}-p" = "mode main"; # Toggle back with same key (Cmd-P)
};
};
home.roles = { home.roles = {
base.enable = true; base.enable = true;
development = {
enable = true;
allowArbitraryClaudeCodeModelSelection = true;
};
}; };
imports = [ imports = [

View File

@@ -1,6 +1,11 @@
{ pkgs, globalInputs, system, ... }: { pkgs, globalInputs, system, ... }:
let
customPkgs = pkgs.callPackage ../packages {};
in
{ {
# Provide arguments to role modules
_module.args = { inherit customPkgs; };
# Home Manager configuration for full desktop experience # Home Manager configuration for full desktop experience
home.username = "johno"; home.username = "johno";
home.homeDirectory = "/home/johno"; home.homeDirectory = "/home/johno";
@@ -16,7 +21,6 @@
communication.enable = true; communication.enable = true;
sync.enable = true; sync.enable = true;
kdeconnect.enable = true; kdeconnect.enable = true;
kubectl.enable = true;
}; };
targets.genericLinux.enable = true; targets.genericLinux.enable = true;

View File

@@ -1,6 +1,11 @@
{ config, lib, pkgs, globalInputs, system, ... }: { config, lib, pkgs, globalInputs, system, ... }:
let
customPkgs = pkgs.callPackage ../packages {};
in
{ {
# Provide arguments to role modules
_module.args = { inherit customPkgs; };
# Home Manager configuration for compact laptop setups # Home Manager configuration for compact laptop setups
# Optimized for space-constrained environments # Optimized for space-constrained environments
@@ -17,7 +22,6 @@
kdeconnect.enable = true; kdeconnect.enable = true;
media.enable = true; media.enable = true;
sync.enable = true; sync.enable = true;
kubectl.enable = true;
# office.enable = false; # Excluded for storage constraints # office.enable = false; # Excluded for storage constraints
}; };
@@ -33,4 +37,5 @@
./modules/plasma-manager ./modules/plasma-manager
./modules/tmux ./modules/tmux
]; ];
} }

View File

@@ -1,6 +1,11 @@
{ pkgs, globalInputs, system, ... }: { pkgs, globalInputs, system, ... }:
let
customPkgs = pkgs.callPackage ../packages {};
in
{ {
# Provide arguments to role modules
_module.args = { inherit customPkgs; };
# Home Manager configuration for live USB environments # Home Manager configuration for live USB environments
# Minimal setup without persistent services # Minimal setup without persistent services

View File

@@ -1,6 +1,11 @@
{ pkgs, globalInputs, system, ... }: { pkgs, globalInputs, system, ... }:
let
customPkgs = pkgs.callPackage ../packages {};
in
{ {
# Provide arguments to role modules
_module.args = { inherit customPkgs; };
# Home Manager configuration for media center setups # Home Manager configuration for media center setups
# Optimized for living room media consumption and gaming # Optimized for living room media consumption and gaming

View File

@@ -1,18 +1,20 @@
{ config, lib, pkgs, ... }: { config, lib, ... }:
with lib; with lib;
let let
cfg = config.home.i3_sway; cfg = config.home.i3_sway;
i3_cfg = config.xsession.windowManager.i3.config;
shared_config = recursiveUpdate rec { shared_config = recursiveUpdate rec {
modifier = "Mod4"; modifier = "Mod4";
terminal = "ghostty"; terminal = "kitty";
defaultWorkspace = "workspace number 1"; defaultWorkspace = "workspace number 1";
keybindings = { keybindings = {
"${shared_config.modifier}+Return" = "exec ${terminal}"; "${shared_config.modifier}+Return" = "exec ${terminal}";
"${shared_config.modifier}+Shift+q" = "kill"; "${shared_config.modifier}+Shift+q" = "kill";
"${shared_config.modifier}+d" = "exec ${i3_cfg.menu}";
"${shared_config.modifier}+h" = "focus left"; "${shared_config.modifier}+h" = "focus left";
"${shared_config.modifier}+j" = "focus down"; "${shared_config.modifier}+j" = "focus down";
@@ -36,7 +38,7 @@ let
#"${shared_config.modifier}+h" = "split h"; #"${shared_config.modifier}+h" = "split h";
"${shared_config.modifier}+v" = "split v"; "${shared_config.modifier}+v" = "split v";
"${shared_config.modifier}+Shift+f" = "fullscreen toggle"; "${shared_config.modifier}+f" = "fullscreen toggle";
"${shared_config.modifier}+s" = "layout stacking"; "${shared_config.modifier}+s" = "layout stacking";
"${shared_config.modifier}+w" = "layout tabbed"; "${shared_config.modifier}+w" = "layout tabbed";
@@ -87,8 +89,8 @@ let
"${shared_config.modifier}+r" = "mode resize"; "${shared_config.modifier}+r" = "mode resize";
"XF86MonBrightnessUp" = "exec ddcutil setvcp 10 + 5"; "XF86MonBrightnessUp" = "exec brightnessctl s +5%";
"XF86MonBrightnessDown" = "exec ddcutil setvcp 10 - 5"; "XF86MonBrightnessDown" = "exec brightnessctl s 5%-";
}; };
} cfg.extraSharedConfig; } cfg.extraSharedConfig;
in { in {
@@ -105,176 +107,12 @@ in {
}; };
config = { config = {
# i3blocks configuration file
home.file.".config/i3blocks/config".text = ''
# i3blocks config - replicating waybar setup
separator_block_width=15
markup=pango
[disk]
command=df -h / | awk 'NR==2 {print "💾 " $5}'
interval=30
separator=true
[cpu]
command=top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print "🧠 " int(100 - $1) "%"}'
interval=2
separator=true
[memory]
command=free | awk 'NR==2 {printf "🐏 %.0f%%\n", $3*100/$2}'
interval=5
separator=true
[pulseaudio]
command=${pkgs.writeShellScript "i3blocks-pulseaudio" ''
volume=$(pactl get-sink-volume @DEFAULT_SINK@ | grep -Po '\d+%' | head -1)
muted=$(pactl get-sink-mute @DEFAULT_SINK@ | grep -o 'yes')
if [ "$muted" = "yes" ]; then
echo "🔇"
else
vol_num=''${volume%\%}
if [ $vol_num -le 33 ]; then
echo "🔈 $volume"
elif [ $vol_num -le 66 ]; then
echo "🔉 $volume"
else
echo "🔊 $volume"
fi
fi
''}
interval=1
signal=10
separator=true
[backlight]
command=${pkgs.writeShellScript "i3blocks-backlight" ''
if command -v ddcutil &>/dev/null; then
# Handle mouse scroll events
case $BLOCK_BUTTON in
4) ddcutil setvcp 10 + 5 ;; # Scroll up - increase brightness
5) ddcutil setvcp 10 - 5 ;; # Scroll down - decrease brightness
esac
# Display current brightness
brightness=$(ddcutil getvcp 10 2>/dev/null | grep -oP 'current value =\s*\K\d+')
if [ -n "$brightness" ]; then
echo " $brightness%"
fi
fi
''}
interval=5
separator=true
[network]
command=${pkgs.writeShellScript "i3blocks-network" ''
if iwgetid -r &>/dev/null; then
ssid=$(iwgetid -r)
signal=$(grep "^\s*w" /proc/net/wireless | awk '{print int($3 * 100 / 70)}')
echo "📶 $ssid ($signal%)"
else
ip=$(ip -4 addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v '127.0.0.1' | head -1)
if [ -n "$ip" ]; then
echo "🔌 $ip"
else
echo ""
fi
fi
''}
interval=5
separator=true
[battery]
command=${pkgs.writeShellScript "i3blocks-battery" ''
if [ -d /sys/class/power_supply/BAT0 ]; then
capacity=$(cat /sys/class/power_supply/BAT0/capacity)
status=$(cat /sys/class/power_supply/BAT0/status)
if [ "$status" = "Charging" ]; then
echo " $capacity%"
else
echo "🔋 $capacity%"
fi
fi
''}
interval=10
separator=true
[time]
command=date '+%Y-%m-%d %H:%M'
interval=1
separator=false
'';
xsession.windowManager.i3 = let xsession.windowManager.i3 = let
base_i3_config = recursiveUpdate shared_config { base_i3_config = recursiveUpdate shared_config {
bars = [{ keybindings = {
position = "bottom";
statusCommand = "${pkgs.i3blocks}/bin/i3blocks";
trayOutput = "primary"; # Enable system tray on primary output
fonts = {
names = [ "Fira Code" "monospace" ];
size = 11.0;
};
colors = {
background = "#000000";
statusline = "#ffffff";
separator = "#666666";
# Workspace button colors (matching waybar)
focusedWorkspace = {
border = "#285577";
background = "#285577";
text = "#ffffff";
};
activeWorkspace = {
border = "#5f676a";
background = "#5f676a";
text = "#ffffff";
};
inactiveWorkspace = {
border = "#222222";
background = "#222222";
text = "#888888";
};
urgentWorkspace = {
border = "#900000";
background = "#900000";
text = "#ffffff";
};
};
}];
keybindings = shared_config.keybindings // {
"${shared_config.modifier}+d" = "exec rofi -show drun";
"${shared_config.modifier}+Shift+e" = "${shared_config.modifier}+Shift+e" =
"exec i3-nagbar -t warning -m 'Do you want to exit i3?' -b 'Yes' 'i3-msg exit'"; "exec i3-nagbar -t warning -m 'Do you want to exit i3?' -b 'Yes' 'i3-msg exit'";
}; };
startup = [
# GNOME polkit authentication agent
{
command = "/run/current-system/sw/libexec/polkit-gnome-authentication-agent-1";
always = false;
notification = false;
}
# Picom compositor for smooth rendering and no tearing (important for Nvidia)
{
command = "picom --backend glx -b";
always = false;
notification = false;
}
# NetworkManager system tray applet
{
command = "nm-applet";
always = false;
notification = false;
}
# Set wallpaper with feh
{
command = "feh --bg-scale ${../../wallpapers/metroid-samus-returns-kz-3440x1440.jpg}";
always = false;
notification = false;
}
];
}; };
in { in {
enable = true; enable = true;
@@ -283,9 +121,7 @@ in {
wayland.windowManager.sway = let wayland.windowManager.sway = let
base_sway_config = recursiveUpdate shared_config { base_sway_config = recursiveUpdate shared_config {
bars = []; # Disable default bar, use waybar instead keybindings = {
keybindings = shared_config.keybindings // {
"${shared_config.modifier}+d" = "exec wofi --show drun";
"${shared_config.modifier}+Shift+e" = "${shared_config.modifier}+Shift+e" =
"exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit'"; "exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit'";
}; };
@@ -301,158 +137,10 @@ in {
dwt = "enabled"; dwt = "enabled";
}; };
}; };
output = {
"*" = {
bg = "${../../wallpapers/metroid-samus-returns-kz-3440x1440.jpg} fill";
};
};
startup = [
# Launch waybar status bar
{
command = "waybar";
always = false;
}
];
}; };
in { in {
enable = true; enable = true;
config = recursiveUpdate base_sway_config cfg.extraSwayConfig; config = recursiveUpdate base_sway_config cfg.extraSwayConfig;
}; };
programs.waybar = {
enable = true;
systemd.enable = false; # Don't auto-start via systemd - only launch in sway
settings = {
mainBar = {
layer = "top";
position = "bottom";
height = 30;
spacing = 4;
modules-left = [ "sway/workspaces" "sway/mode" ];
modules-center = [ ];
modules-right = [ "disk" "cpu" "memory" "pulseaudio" "backlight" "network" "battery" "tray" "clock" ];
"sway/workspaces" = {
disable-scroll = true;
all-outputs = true;
};
"clock" = {
format = "{:%Y-%m-%d %H:%M}";
tooltip-format = "<tt><small>{calendar}</small></tt>";
calendar = {
mode = "year";
mode-mon-col = 3;
weeks-pos = "right";
on-scroll = 1;
format = {
months = "<span color='#ffead3'><b>{}</b></span>";
days = "<span color='#ecc6d9'><b>{}</b></span>";
weeks = "<span color='#99ffdd'><b>W{}</b></span>";
weekdays = "<span color='#ffcc66'><b>{}</b></span>";
today = "<span color='#ff6699'><b><u>{}</u></b></span>";
};
};
};
"disk" = {
interval = 30;
format = "💾 {percentage_used}%";
path = "/";
tooltip-format = "Used: {used} / {total} ({percentage_used}%)\nFree: {free} ({percentage_free}%)";
};
"cpu" = {
format = "🧠 {usage}%";
tooltip = false;
};
"memory" = {
format = "🐏 {percentage}%";
tooltip-format = "RAM: {used:0.1f}G / {total:0.1f}G";
};
"pulseaudio" = {
format = "{icon} {volume}%";
format-muted = "🔇";
format-icons = {
headphone = "🎧";
default = [ "🔈" "🔉" "🔊" ];
};
on-click = "pavucontrol";
};
"backlight" = {
format = " {percent}%";
tooltip = false;
};
"network" = {
format-wifi = "📶 {essid} ({signalStrength}%)";
format-ethernet = "🔌 {ipaddr}";
format-disconnected = "";
tooltip-format = "{ifname}: {ipaddr}/{cidr}";
};
"battery" = {
states = {
warning = 30;
critical = 15;
};
format = "{icon} {capacity}%";
format-charging = " {capacity}%";
format-icons = [ "🪫" "🔋" "🔋" "🔋" "🔋" ];
};
"tray" = {
spacing = 10;
};
};
};
style = ''
* {
padding: 0 4px;
font-family: "Fira Code", monospace;
font-size: 13px;
}
#workspaces button {
padding: 0 8px;
background-color: #333333;
color: #ffffff;
border: none;
}
#workspaces button.focused {
background-color: #285577;
font-weight: bold;
}
#workspaces button.visible {
background-color: #5f676a;
}
#workspaces button.urgent {
background-color: #900000;
}
'';
};
programs.rofi = {
enable = true;
theme = "solarized";
extraConfig = {
modi = "drun,run,window";
show-icons = true;
drun-display-format = "{name}";
disable-history = false;
hide-scrollbar = true;
display-drun = " Apps";
display-run = " Run";
display-window = " Windows";
sidebar-mode = true;
};
};
}; };
} }

View File

@@ -13,10 +13,10 @@
enable = true; enable = true;
overrideConfig = true; overrideConfig = true;
hotkeys.commands."launch-ghostty" = { hotkeys.commands."launch-konsole" = {
name = "Launch Ghostty"; name = "Launch Konsole";
key = "Meta+Return"; key = "Meta+Return";
command = "ghostty"; command = "konsole";
}; };
shortcuts = { shortcuts = {
@@ -167,12 +167,6 @@
AutoRaiseInterval = 750; # Delay in ms before auto-raise (if enabled) AutoRaiseInterval = 750; # Delay in ms before auto-raise (if enabled)
DelayFocusInterval = 0; # Delay in ms before focus follows mouse DelayFocusInterval = 0; # Delay in ms before focus follows mouse
}; };
# Desktop wallpaper configuration
plasma-localerc.Formats.LANG = "en_US.UTF-8";
# Set wallpaper for all desktops
plasmarc.Wallpapers.usersWallpapers = "${../../wallpapers/metroid-samus-returns-kz-3440x1440.jpg}";
}; };
}; };
} }

View File

@@ -58,11 +58,11 @@ in
programs.ssh = { programs.ssh = {
enable = true; enable = true;
addKeysToAgent = "yes";
matchBlocks = { matchBlocks = {
"nucdeb1" = { "nucdeb1" = {
hostname = "nucdeb1.oglehome"; hostname = "nucdeb1.oglehome";
user = "root"; user = "root";
addKeysToAgent = "yes";
}; };
}; };
}; };

View File

@@ -14,7 +14,7 @@ in
home.packages = [ home.packages = [
# Communication apps # Communication apps
pkgs.element-desktop pkgs.element-desktop
#pkgs.fluffychat #marked insecure as of nixos 25.05 pkgs.fluffychat
pkgs.nextcloud-talk-desktop pkgs.nextcloud-talk-desktop
# For logging back into google chat # For logging back into google chat

View File

@@ -6,7 +6,6 @@
./development ./development
./gaming ./gaming
./kdeconnect ./kdeconnect
./kubectl
./media ./media
./office ./office
./sync ./sync

View File

@@ -13,18 +13,15 @@ in
config = mkIf cfg.enable { config = mkIf cfg.enable {
home.packages = with pkgs; [ home.packages = with pkgs; [
# Desktop applications # Desktop applications
bitwarden-desktop bitwarden
dunst dunst
keepassxc keepassxc
unstable.ghostty kitty
# Desktop utilities # Desktop utilities
feh # Image viewer and wallpaper setter for X11
rofi # Application launcher for X11
solaar # Logitech management software solaar # Logitech management software
waybar waybar
wofi # Application launcher for Wayland wofi
xdg-utils # XDG utilities for opening files/URLs with default applications
# System utilities with GUI components # System utilities with GUI components
(snapcast.override { pulseaudioSupport = true; }) (snapcast.override { pulseaudioSupport = true; })
@@ -40,14 +37,6 @@ in
kdePackages.kaddressbook kdePackages.kaddressbook
kdePackages.kontact kdePackages.kontact
# KDE System components needed for proper integration
kdePackages.kded
kdePackages.systemsettings
kdePackages.kmenuedit
# Desktop menu support
kdePackages.plasma-desktop # Contains applications.menu
# KDE Online Accounts support # KDE Online Accounts support
kdePackages.kaccounts-integration kdePackages.kaccounts-integration
kdePackages.kaccounts-providers kdePackages.kaccounts-providers
@@ -81,79 +70,7 @@ in
enable = true; enable = true;
}; };
# KDE environment variables for proper integration xdg.enable = true;
home.sessionVariables = {
QT_QPA_PLATFORMTHEME = "kde";
KDE_SESSION_VERSION = "6";
};
xdg = {
enable = true;
# Ensure desktop files are made available for discovery
desktopEntries = {}; # This creates the desktop files directory structure
mimeApps = {
enable = true;
associations.added = {
# Ensure associations are properly registered
"text/html" = "firefox.desktop";
"x-scheme-handler/http" = "firefox.desktop";
"x-scheme-handler/https" = "firefox.desktop";
};
defaultApplications = {
# Web browsers
"text/html" = "firefox.desktop";
"x-scheme-handler/http" = "firefox.desktop";
"x-scheme-handler/https" = "firefox.desktop";
"x-scheme-handler/about" = "firefox.desktop";
"x-scheme-handler/unknown" = "firefox.desktop";
# Documents
"application/pdf" = "okular.desktop";
"text/plain" = "kate.desktop";
"text/x-tex" = "kate.desktop";
"text/x-c" = "kate.desktop";
"text/x-python" = "kate.desktop";
"application/x-shellscript" = "kate.desktop";
# Images
"image/png" = "gwenview.desktop";
"image/jpeg" = "gwenview.desktop";
"image/jpg" = "gwenview.desktop";
"image/gif" = "gwenview.desktop";
"image/bmp" = "gwenview.desktop";
"image/tiff" = "gwenview.desktop";
"image/webp" = "gwenview.desktop";
# Archives
"application/zip" = "ark.desktop";
"application/x-tar" = "ark.desktop";
"application/x-compressed-tar" = "ark.desktop";
"application/x-7z-compressed" = "ark.desktop";
"application/x-rar" = "ark.desktop";
# Audio
"audio/mpeg" = "elisa.desktop";
"audio/mp4" = "elisa.desktop";
"audio/flac" = "elisa.desktop";
"audio/ogg" = "elisa.desktop";
"audio/wav" = "elisa.desktop";
# Email
"message/rfc822" = "kmail.desktop";
"x-scheme-handler/mailto" = "kmail.desktop";
# Calendar
"text/calendar" = "korganizer.desktop";
"application/x-vnd.akonadi.calendar.event" = "korganizer.desktop";
};
};
};
# Fix for KDE applications.menu file issue on Plasma 6
# KDE still looks for applications.menu but Plasma 6 renamed it to plasma-applications.menu
xdg.configFile."menus/applications.menu".source = "${pkgs.kdePackages.plasma-workspace}/etc/xdg/menus/plasma-applications.menu";
# Note: modules must be imported at top-level home config # Note: modules must be imported at top-level home config
}; };

View File

@@ -1,93 +1,26 @@
{ config, lib, pkgs, globalInputs, system, ... }: { config, lib, pkgs, customPkgs, globalInputs, system, ... }:
with lib; with lib;
let let
cfg = config.home.roles.development; cfg = config.home.roles.development;
# Fetch the claude-plugins repository
# Update the rev to get newer versions of the commands
claudePluginsRepo = builtins.fetchGit {
url = "https://github.com/jeffh/claude-plugins.git";
# To update: change this to the latest commit hash
# You can find the latest commit at: https://github.com/jeffh/claude-plugins/commits/main
rev = "5e3e4d937162185b6d78c62022cbfd1c8ad42c4c";
ref = "main";
};
in in
{ {
options.home.roles.development = { options.home.roles.development = {
enable = mkEnableOption "Enable development tools and utilities"; enable = mkEnableOption "Enable development tools and utilities";
allowArbitraryClaudeCodeModelSelection = mkOption {
type = types.bool;
default = false;
description = ''
Whether to preserve model specifications in Claude Code humanlayer commands and agents.
When false (default), the model: line is stripped from frontmatter, allowing Claude Code
to use its default model selection.
When true, the model: specifications from the source files are preserved, allowing
commands to specify opus/sonnet/haiku explicitly.
'';
};
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
home.packages = [ home.packages = [
pkgs.unstable.claude-code pkgs.claude-code
pkgs.unstable.claude-code-router pkgs.codex
pkgs.unstable.codex pkgs.goose-cli
# Custom packages # Custom packages
pkgs.custom.tea-rbw customPkgs.tea-rbw
]; ];
# Install Claude Code humanlayer command and agent plugins programs.kubectl-secure.enable = true;
home.activation.claudeCodeCommands = lib.hm.dag.entryAfter ["writeBoundary"] ''
# Clean up old plugin-installed commands and agents to avoid duplicates
rm -f ~/.claude/commands/humanlayer:* 2>/dev/null || true
rm -f ~/.claude/agents/humanlayer:* 2>/dev/null || true
# Create directories if they don't exist
mkdir -p ~/.claude/commands
mkdir -p ~/.claude/agents
# Copy all humanlayer command files and remove model specifications
for file in ${claudePluginsRepo}/humanlayer/commands/*.md; do
if [ -f "$file" ]; then
filename=$(basename "$file" .md)
dest="$HOME/.claude/commands/humanlayer:''${filename}.md"
# Copy file and conditionally remove the "model:" line from frontmatter
${if cfg.allowArbitraryClaudeCodeModelSelection
then "cp \"$file\" \"$dest\""
else "${pkgs.gnused}/bin/sed '/^model:/d' \"$file\" > \"$dest\""
}
fi
done
# Copy all humanlayer agent files and remove model specifications
for file in ${claudePluginsRepo}/humanlayer/agents/*.md; do
if [ -f "$file" ]; then
filename=$(basename "$file" .md)
dest="$HOME/.claude/agents/humanlayer:''${filename}.md"
# Copy file and conditionally remove the "model:" line from frontmatter
${if cfg.allowArbitraryClaudeCodeModelSelection
then "cp \"$file\" \"$dest\""
else "${pkgs.gnused}/bin/sed '/^model:/d' \"$file\" > \"$dest\""
}
fi
done
$DRY_RUN_CMD echo "Claude Code humanlayer commands and agents installed successfully${
if cfg.allowArbitraryClaudeCodeModelSelection
then " (model specifications preserved)"
else " (model selection removed)"
}"
'';
# Note: modules must be imported at top-level home config # Note: modules must be imported at top-level home config
}; };

View File

@@ -1,16 +0,0 @@
{ config, lib, pkgs, globalInputs, system, ... }:
with lib;
let
cfg = config.home.roles.kubectl;
in
{
options.home.roles.kubectl = {
enable = mkEnableOption "Enable management tools for the homelab k3s oglenet cluster";
};
config = mkIf cfg.enable {
programs.kubectl-secure.enable = true;
};
}

View File

@@ -18,10 +18,6 @@ in
delfin delfin
moonlight-qt moonlight-qt
vlc vlc
# Spotify client
# Using unstable version for better authentication support
unstable.ncspot
]; ];
}; };
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 MiB

View File

@@ -24,7 +24,7 @@ with lib;
}; };
kodi = { kodi = {
enable = true; enable = true;
autologin = true; autologin = false;
wayland = true; wayland = true;
}; };
users.enable = true; users.enable = true;

View File

@@ -65,8 +65,6 @@
# Enable NetworkManager for easy wifi setup # Enable NetworkManager for easy wifi setup
networking.networkmanager.enable = true; networking.networkmanager.enable = true;
# Disable wireless networking (conflicts with NetworkManager)
networking.wireless.enable = false;
# Enable SSH daemon for remote access # Enable SSH daemon for remote access
services.openssh = { services.openssh = {

View File

@@ -21,11 +21,6 @@
}; };
nfs-mounts.enable = true; nfs-mounts.enable = true;
printing.enable = true; printing.enable = true;
remote-build.builders = [{
hostName = "zix790prors";
maxJobs = 16;
speedFactor = 3;
}];
spotifyd.enable = true; spotifyd.enable = true;
users = { users = {
enable = true; enable = true;
@@ -42,6 +37,9 @@
networking.hostName = "nix-book"; # Define your hostname. networking.hostName = "nix-book"; # Define your hostname.
# networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant.
boot.kernelPackages = pkgs.linuxPackages_latest;
# Enable networking # Enable networking
networking.networkmanager.enable = true; networking.networkmanager.enable = true;

View File

@@ -1,40 +0,0 @@
{ pkgs, ... }:
{
imports = [
./hardware-configuration.nix
];
roles = {
audio.enable = true;
bluetooth.enable = true;
desktop = {
enable = true;
wayland = true;
gaming.enable = true;
kde = true;
steamos = {
enable = true;
autoStart = true;
desktopSession = "plasma";
};
};
remote-build.builders = [{
hostName = "zix790prors";
maxJobs = 16;
speedFactor = 4; # Prefer remote heavily on Steam Deck
}];
users = {
enable = true;
extraGroups = [ "video" ];
};
};
# Bootloader
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
networking.hostName = "nix-deck";
networking.networkmanager.enable = true;
system.stateVersion = "25.05";
}

View File

@@ -1,51 +0,0 @@
# Hardware configuration for Steam Deck (nix-deck)
# Generated from nixos-generate-config on 2025-11-17
{ config, lib, pkgs, modulesPath, ... }:
{
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
];
# Steam Deck specific hardware configuration (Jovian)
jovian.devices.steamdeck = {
enable = true;
autoUpdate = false; # Set to true if you want automatic firmware updates
};
# Kernel modules detected by nixos-generate-config
boot.initrd.availableKernelModules = [
"nvme"
"xhci_pci"
"usb_storage"
"uas"
"usbhid"
"sd_mod"
"sdhci_pci"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ];
# IMPORTANT: Update these filesystem configurations based on your actual partition layout
# The configuration below is a placeholder - adjust according to how you partitioned the disk
fileSystems."/" = {
device = "/dev/disk/by-label/nixos";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-label/boot";
fsType = "vfat";
};
swapDevices = [{
device = "/swapfile";
size = 8192; # 8GB swap file
}];
# AMD CPU microcode updates
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View File

@@ -19,16 +19,15 @@ with lib;
enable = true; enable = true;
gaming = { gaming = {
enable = true; enable = true;
emulation = true;
}; };
kde = true; kde = true;
sddm = true; sddm = true;
wayland = true; wayland = true;
x11 = true;
}; };
nfs-mounts.enable = true; nfs-mounts.enable = true;
nvidia.enable = true; nvidia.enable = true;
printing.enable = true; printing.enable = true;
remote-build.enableBuilder = true;
users.enable = true; users.enable = true;
virtualisation.enable = true; virtualisation.enable = true;
}; };
@@ -52,15 +51,19 @@ with lib;
hardware.graphics.enable = true; hardware.graphics.enable = true;
hardware.graphics.enable32Bit = true; hardware.graphics.enable32Bit = true;
# Set DP-0 as primary display with 164.90Hz refresh rate
services.xserver.displayManager.sessionCommands = ''
${pkgs.xorg.xrandr}/bin/xrandr --output DP-0 --mode 3440x1440 --rate 164.90 --primary
'';
hardware.nvidia = { hardware.nvidia = {
# Modesetting is required.
modesetting.enable = true; modesetting.enable = true;
# Enable the Nvidia settings menu,
# accessible via `nvidia-settings`.
nvidiaSettings = true; nvidiaSettings = true;
# Optionally, you may need to select the appropriate driver version for your specific GPU.
package = pkgs.linuxPackages.nvidiaPackages.stable; package = pkgs.linuxPackages.nvidiaPackages.stable;
# Use open source kernel modules (recommended for RTX/GTX 16xx and newer)
# Set to false if you have an older GPU
open = true; open = true;
# For gaming performance # For gaming performance

View File

@@ -7,7 +7,6 @@ import subprocess
import sys import sys
from http.server import BaseHTTPRequestHandler, HTTPServer from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import urlparse from urllib.parse import urlparse
import psutil
# Configure logging # Configure logging
logging.basicConfig( logging.basicConfig(
@@ -22,60 +21,6 @@ ALLOWED_APPS = {
'kodi': 'kodi' 'kodi': 'kodi'
} }
def is_app_running(app_name):
"""Check if an application is already running, returns (is_running, pid)"""
command = ALLOWED_APPS.get(app_name)
if not command:
return False, None
logger.debug(f"Looking for processes related to app '{app_name}' (command: '{command}')")
for proc in psutil.process_iter(['name', 'cmdline', 'pid']):
try:
proc_name = proc.info['name']
cmdline = proc.info['cmdline'] or []
logger.debug(f"Checking process PID {proc.info['pid']}: name='{proc_name}', cmdline={cmdline}")
# Check multiple patterns for the application:
# 1. Process name exactly matches command
# 2. Process name contains the command (e.g., "kodi.bin" contains "kodi")
# 3. Command line starts with the command
# 4. Command line contains the wrapped version (e.g., ".kodi-wrapped")
# 5. Any command line argument ends with the command executable
matches = False
match_reason = ""
if proc_name == command:
matches = True
match_reason = f"exact process name match: '{proc_name}'"
elif command in proc_name:
matches = True
match_reason = f"process name contains command: '{proc_name}' contains '{command}'"
elif cmdline and cmdline[0] == command:
matches = True
match_reason = f"exact cmdline match: '{cmdline[0]}'"
elif cmdline and cmdline[0].endswith('/' + command):
matches = True
match_reason = f"cmdline path ends with command: '{cmdline[0]}'"
elif cmdline and any(f'.{command}-wrapped' in arg for arg in cmdline):
matches = True
match_reason = f"wrapped command in cmdline: {cmdline}"
elif cmdline and any(f'{command}.bin' in arg for arg in cmdline):
matches = True
match_reason = f"binary command in cmdline: {cmdline}"
if matches:
logger.info(f"Found running {app_name} process: PID {proc.info['pid']} ({match_reason})")
return True, proc.info['pid']
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
continue
logger.debug(f"No running process found for {app_name}")
return False, None
class AppLauncherHandler(BaseHTTPRequestHandler): class AppLauncherHandler(BaseHTTPRequestHandler):
def log_message(self, format, *args): def log_message(self, format, *args):
logger.info(format % args) logger.info(format % args)
@@ -111,22 +56,6 @@ class AppLauncherHandler(BaseHTTPRequestHandler):
command = ALLOWED_APPS[app_name] command = ALLOWED_APPS[app_name]
# Check if app is already running
is_running, existing_pid = is_app_running(app_name)
if is_running:
logger.info(f"Application {app_name} is already running (PID: {existing_pid}), skipping launch")
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
response = {
'status': 'success',
'message': f'{app_name} is already running',
'pid': existing_pid,
'already_running': True
}
self.wfile.write(json.dumps(response).encode())
return
try: try:
# Launch the application in the background # Launch the application in the background
# Ensure we have the proper environment for GUI apps # Ensure we have the proper environment for GUI apps
@@ -147,8 +76,7 @@ class AppLauncherHandler(BaseHTTPRequestHandler):
response = { response = {
'status': 'success', 'status': 'success',
'message': f'Successfully launched {app_name}', 'message': f'Successfully launched {app_name}',
'pid': process.pid, 'pid': process.pid
'already_running': False
} }
self.wfile.write(json.dumps(response).encode()) self.wfile.write(json.dumps(response).encode())

View File

@@ -1,10 +1,5 @@
{ pkgs }: { pkgs }:
let
python = pkgs.python3.withPackages (ps: with ps; [
psutil
]);
in
pkgs.writeShellScriptBin "app-launcher-server" '' pkgs.writeShellScriptBin "app-launcher-server" ''
exec ${python}/bin/python3 ${./app-launcher-server.py} "$@" exec ${pkgs.python3}/bin/python3 ${./app-launcher-server.py} "$@"
'' ''

View File

@@ -1,116 +0,0 @@
# claude-cli
Custom Nix package for Claude Code CLI.
## Why This Package Exists
The official `claude-code` package in nixpkgs tries to fetch from npm registry, which is blocked by Block's corporate security (Cloudflare Teams dependency confusion protection). This custom package fetches directly from Anthropic's Google Cloud Storage distribution, bypassing the npm registry entirely.
## Updating to a New Version
### Automated Update (Recommended)
Run the update script to automatically fetch and update to the latest version:
```bash
cd packages/claude-cli
./update.sh
```
The script will:
- Fetch the latest version from Homebrew cask
- Update version and all SHA256 hashes in default.nix
- Show you what changed
For a dry-run to see what would change:
```bash
./update.sh --dry-run
```
After the script completes, follow the "Test the Build" steps below.
### Manual Update
If you prefer to update manually, or if the automated script fails:
#### 1. Find the Latest Version and Hashes
Check the Homebrew cask formula for the latest version info:
```bash
curl -s "https://raw.githubusercontent.com/Homebrew/homebrew-cask/HEAD/Casks/c/claude-code.rb" | head -50
```
This will show:
- The latest `version` number
- SHA256 hashes for all platforms (`arm64`, `x86_64`, `x86_64_linux`, `arm64_linux`)
#### 2. Update default.nix
Edit `default.nix` and update:
1. The `version` variable (line 9):
```nix
version = "2.0.51"; # Update this
```
2. All four platform sha256 hashes in the `srcs` attribute set (lines 11-27):
```nix
aarch64-darwin = {
sha256 = "..."; # Update from Homebrew cask "arm:" value
};
x86_64-darwin = {
sha256 = "..."; # Update from Homebrew cask "x86_64:" value
};
x86_64-linux = {
sha256 = "..."; # Update from Homebrew cask "x86_64_linux:" value
};
aarch64-linux = {
sha256 = "..."; # Update from Homebrew cask "arm64_linux:" value
};
```
#### 3. Test the Build
Before committing, test that the package builds successfully:
```bash
NIXPKGS_ALLOW_UNFREE=1 nix-build -E 'with import <nixpkgs> { config.allowUnfree = true; }; callPackage ./packages/claude-cli {}'
```
Verify the version:
```bash
./result/bin/claude --version
```
Clean up the test build:
```bash
rm result
```
#### 4. Deploy
Commit your changes and rebuild:
```bash
git add packages/claude-cli/
git commit -m "claude-cli: Update to version X.Y.Z"
darwin-rebuild switch --flake .#blkfv4yf49kt7
```
## Alternative: Automated Hash Fetching
If you prefer to fetch hashes automatically, you can use `nix-prefetch-url`:
```bash
# For macOS ARM64 (your current platform)
nix-prefetch-url "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/VERSION/darwin-arm64/claude"
# For other platforms, replace VERSION and adjust the platform string:
# darwin-x64, linux-x64, linux-arm64
```
This will download the file and output the SHA256 hash.

View File

@@ -1,60 +0,0 @@
{ lib
, stdenv
, fetchurl
, autoPatchelfHook
}:
let
version = "2.0.53";
srcs = {
aarch64-darwin = {
url = "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/${version}/darwin-arm64/claude";
sha256 = "28c3ad73a20f3ae7ab23efa24d45a9791ccbe071284f1622d4e5e2b89c4a15b7";
};
x86_64-darwin = {
url = "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/${version}/darwin-x64/claude";
sha256 = "a27f7b75a51514658640432a0afec8be130673eb7dbecc9a4d742527dd85d29a";
};
x86_64-linux = {
url = "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/${version}/linux-x64/claude";
sha256 = "9c4cc19e207fb6bf7ea140a1580d5ed0dd0a481af471f23614d5a140a4abf1c6";
};
aarch64-linux = {
url = "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/${version}/linux-arm64/claude";
sha256 = "a5d4044034f3b63c38379bc2dd4067a4dd3c8ec48965ba8e66e3623774a93b72";
};
};
src = srcs.${stdenv.hostPlatform.system} or (throw "Unsupported system: ${stdenv.hostPlatform.system}");
in stdenv.mkDerivation {
pname = "claude-code";
inherit version;
src = fetchurl {
inherit (src) url sha256;
};
dontUnpack = true;
dontBuild = true;
nativeBuildInputs = lib.optionals stdenv.isLinux [ autoPatchelfHook ];
installPhase = ''
runHook preInstall
install -Dm755 $src $out/bin/claude
runHook postInstall
'';
meta = with lib; {
description = "Terminal-based AI coding assistant from Anthropic";
homepage = "https://www.anthropic.com/claude-code";
license = licenses.unfree;
maintainers = [ ];
platforms = [ "aarch64-darwin" "x86_64-darwin" "x86_64-linux" "aarch64-linux" ];
mainProgram = "claude";
};
}

View File

@@ -1,34 +0,0 @@
{ lib
, buildNpmPackage
, fetchurl
, nodejs_18
}:
buildNpmPackage {
pname = "claude-cli";
version = "0.2.65";
src = fetchurl {
url = "https://registry.npmjs.org/@anthropic-ai/claude-code/-/claude-code-0.2.65.tgz";
sha256 = "0wwaqq7k9p5aw4vqhfpdgf3da09x64q55wibqaprk6kjvn130i92";
};
npmDepsHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; # Will be updated after first build
nodejs = nodejs_18;
# Don't run npm audit or other network operations during build
npmConfigHook = ''
npm config set audit false
npm config set fund false
'';
meta = with lib; {
description = "Terminal-based AI coding assistant from Anthropic (npm distribution)";
homepage = "https://www.anthropic.com/claude-code";
license = licenses.unfree;
maintainers = [ ];
platforms = platforms.all;
mainProgram = "claude";
};
}

View File

@@ -1,132 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
DRY_RUN=false
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
--dry-run|-n)
DRY_RUN=true
shift
;;
--help|-h)
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Options:"
echo " --dry-run, -n Show what would be updated without making changes"
echo " --help, -h Show this help message"
exit 0
;;
*)
echo "Unknown option: $1"
echo "Use --help for usage information"
exit 1
;;
esac
done
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
CASK_URL="https://raw.githubusercontent.com/Homebrew/homebrew-cask/HEAD/Casks/c/claude-code.rb"
NIX_FILE="$(dirname "$0")/default.nix"
echo "Fetching latest claude-code version from Homebrew cask..."
# Fetch the cask file
CASK_CONTENT=$(curl -fsSL "$CASK_URL")
# Extract version (format: version "X.Y.Z")
NEW_VERSION=$(echo "$CASK_CONTENT" | grep -m1 'version' | sed -E 's/.*version "([^"]+)".*/\1/')
# Extract SHA256 hashes (be specific to match sha256 lines only)
SHA_ARM=$(echo "$CASK_CONTENT" | grep 'sha256 arm:' | sed -E 's/.*"([a-f0-9]{64})".*/\1/')
SHA_X86_64=$(echo "$CASK_CONTENT" | grep 'x86_64:' | sed -E 's/.*"([a-f0-9]{64})".*/\1/')
SHA_X86_64_LINUX=$(echo "$CASK_CONTENT" | grep 'x86_64_linux:' | sed -E 's/.*"([a-f0-9]{64})".*/\1/')
SHA_ARM64_LINUX=$(echo "$CASK_CONTENT" | grep 'arm64_linux:' | sed -E 's/.*"([a-f0-9]{64})".*/\1/')
# Get current version
CURRENT_VERSION=$(grep -m1 'version = ' "$NIX_FILE" | sed -E 's/.*version = "([^"]+)".*/\1/')
# Validate extracted data
if [ -z "$NEW_VERSION" ] || [ -z "$SHA_ARM" ] || [ -z "$SHA_X86_64" ] || [ -z "$SHA_X86_64_LINUX" ] || [ -z "$SHA_ARM64_LINUX" ]; then
echo -e "${RED}Error: Failed to extract all required values from Homebrew cask${NC}"
echo "Version: $NEW_VERSION"
echo "ARM: $SHA_ARM"
echo "x86_64: $SHA_X86_64"
echo "x86_64_linux: $SHA_X86_64_LINUX"
echo "arm64_linux: $SHA_ARM64_LINUX"
exit 1
fi
# Check if update is needed
if [ "$CURRENT_VERSION" = "$NEW_VERSION" ]; then
echo -e "${GREEN}Already up to date: $CURRENT_VERSION${NC}"
exit 0
fi
echo -e "${YELLOW}Updating from $CURRENT_VERSION to $NEW_VERSION${NC}"
if [ "$DRY_RUN" = true ]; then
echo -e "${YELLOW}DRY RUN - No changes will be made${NC}"
echo ""
echo "Would update:"
echo " Version: $CURRENT_VERSION -> $NEW_VERSION"
echo " aarch64-darwin SHA: $SHA_ARM"
echo " x86_64-darwin SHA: $SHA_X86_64"
echo " x86_64-linux SHA: $SHA_X86_64_LINUX"
echo " aarch64-linux SHA: $SHA_ARM64_LINUX"
exit 0
fi
# Update version
sed -i.tmp "s/version = \".*\";/version = \"$NEW_VERSION\";/" "$NIX_FILE"
# Update SHA256 hashes using awk for more reliable parsing
awk -v sha_arm="$SHA_ARM" -v sha_x86="$SHA_X86_64" -v sha_x86_linux="$SHA_X86_64_LINUX" -v sha_arm_linux="$SHA_ARM64_LINUX" '
/aarch64-darwin = {/ { in_arm = 1 }
/x86_64-darwin = {/ { in_x86 = 1 }
/x86_64-linux = {/ { in_x86_linux = 1 }
/aarch64-linux = {/ { in_arm_linux = 1 }
/};/ {
in_arm = 0
in_x86 = 0
in_x86_linux = 0
in_arm_linux = 0
}
/sha256 = / {
if (in_arm) {
sub(/sha256 = ".*";/, "sha256 = \"" sha_arm "\";")
} else if (in_x86) {
sub(/sha256 = ".*";/, "sha256 = \"" sha_x86 "\";")
} else if (in_x86_linux) {
sub(/sha256 = ".*";/, "sha256 = \"" sha_x86_linux "\";")
} else if (in_arm_linux) {
sub(/sha256 = ".*";/, "sha256 = \"" sha_arm_linux "\";")
}
}
{ print }
' "$NIX_FILE" > "$NIX_FILE.new"
mv "$NIX_FILE.new" "$NIX_FILE"
# Clean up temp files
rm -f "$NIX_FILE.tmp"
echo -e "${GREEN}Successfully updated to version $NEW_VERSION${NC}"
echo ""
echo "Updated SHA256 hashes:"
echo " aarch64-darwin: $SHA_ARM"
echo " x86_64-darwin: $SHA_X86_64"
echo " x86_64-linux: $SHA_X86_64_LINUX"
echo " aarch64-linux: $SHA_ARM64_LINUX"
echo ""
echo "Next steps:"
echo " 1. Review changes: git diff $NIX_FILE"
echo " 2. Test build: NIXPKGS_ALLOW_UNFREE=1 nix-build -E 'with import <nixpkgs> { config.allowUnfree = true; }; callPackage ./packages/claude-code {}'"
echo " 3. Verify version: ./result/bin/claude --version"
echo " 4. Commit: git add $NIX_FILE && git commit -m 'claude-code: Update to version $NEW_VERSION'"

View File

@@ -3,5 +3,4 @@
vulkanHDRLayer = pkgs.callPackage ./vulkan-hdr-layer {}; vulkanHDRLayer = pkgs.callPackage ./vulkan-hdr-layer {};
tea-rbw = pkgs.callPackage ./tea-rbw {}; tea-rbw = pkgs.callPackage ./tea-rbw {};
app-launcher-server = pkgs.callPackage ./app-launcher-server {}; app-launcher-server = pkgs.callPackage ./app-launcher-server {};
claude-code = pkgs.callPackage ./claude-code {};
} }

View File

@@ -15,7 +15,6 @@ in
environment.etc."bashrc".enable = false; environment.etc."bashrc".enable = false;
environment.etc."zshrc".enable = false; environment.etc."zshrc".enable = false;
environment.etc."zshenv".enable = false; environment.etc."zshenv".enable = false;
environment.etc."zprofile".enable = false;
# Create .local files with nix environment setup # Create .local files with nix environment setup
environment.etc."bash.local".text = '' environment.etc."bash.local".text = ''
@@ -45,41 +44,6 @@ in
time.timeZone = "America/Los_Angeles"; time.timeZone = "America/Los_Angeles";
# System preferences
system.defaults = {
# Custom keyboard shortcuts
CustomUserPreferences = {
"com.apple.symbolichotkeys" = {
AppleSymbolicHotKeys = {
# Screenshot - Capture entire screen (Cmd+Ctrl+3)
"28" = {
enabled = true;
value = {
parameters = [ 51 20 1310720 ];
type = "standard";
};
};
# Screenshot - Capture selected portion (Cmd+Ctrl+4)
"30" = {
enabled = true;
value = {
parameters = [ 52 21 1310720 ];
type = "standard";
};
};
# Screenshot - Show screenshot toolbar (Cmd+Ctrl+5)
"184" = {
enabled = true;
value = {
parameters = [ 53 23 1310720 ];
type = "standard";
};
};
};
};
};
};
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
git git
glances glances

View File

@@ -12,7 +12,6 @@ with lib;
./nfs-mounts ./nfs-mounts
./nvidia ./nvidia
./printing ./printing
./remote-build
./spotifyd ./spotifyd
./users ./users
./virtualisation ./virtualisation

View File

@@ -11,6 +11,7 @@ with lib;
kde = mkOption { type = types.bool; default = false; description = "Enable KDE."; }; kde = mkOption { type = types.bool; default = false; description = "Enable KDE."; };
gaming = { gaming = {
enable = mkOption { type = types.bool; default = false; description = "Enable gaming support."; }; enable = mkOption { type = types.bool; default = false; description = "Enable gaming support."; };
emulation = mkOption { type = types.bool; default = false; description = "Enable emulation support."; };
}; };
sddm = mkOption { type = types.bool; default = false; description = "Enable SDDM greeter."; }; sddm = mkOption { type = types.bool; default = false; description = "Enable SDDM greeter."; };
}; };
@@ -22,6 +23,5 @@ with lib;
./kde.nix ./kde.nix
./programs.nix ./programs.nix
./sddm.nix ./sddm.nix
./steamos.nix
]; ];
} }

View File

@@ -12,20 +12,15 @@ in
steam steam
lutris lutris
moonlight moonlight
# Emulators
dolphin-emu
dolphin-emu-primehack
retroarch-full
ryubing
]; ];
# TODO: Remove me once dolphin-emu and dolphin-emu-primehack update
# dependencies to mbedtls from mbedtls_2 (which is currently)
# unmaintained
nixpkgs.config.permittedInsecurePackages = [ "mbedtls-2.28.10" ];
warnings = [ # Possibly other gaming specific services or settings
"Using insecure mbedtls-2.28.10 for Dolphin Emu - check for updates regularly" })
(mkIf (cfg.enable && cfg.gaming.emulation) {
environment.systemPackages = with pkgs; [
ryubing
dolphin-emu
]; ];
}) })
]; ];

View File

@@ -16,22 +16,5 @@ in
programs.dconf.enable = true; programs.dconf.enable = true;
services.gnome.gnome-keyring.enable = true; services.gnome.gnome-keyring.enable = true;
programs.kdeconnect.enable = true; programs.kdeconnect.enable = true;
# XDG Desktop Portal for default application handling in non-KDE environments
xdg.portal = {
enable = true;
extraPortals = with pkgs; [
kdePackages.xdg-desktop-portal-kde # For KDE application integration
xdg-desktop-portal-gtk # Fallback for GTK applications
];
config = {
common = {
default = "kde";
};
i3 = {
default = ["kde" "gtk"];
};
};
};
}; };
} }

View File

@@ -1,51 +0,0 @@
{ lib, config, pkgs, ... }:
with lib;
let
cfg = config.roles.desktop;
in
{
options.roles.desktop.steamos = {
enable = mkEnableOption "SteamOS (Jovian) configuration";
autoStart = mkOption {
type = types.bool;
default = false;
description = "Automatically start Steam Deck UI on boot";
};
user = mkOption {
type = types.str;
default = "johno";
description = "User to run Steam as";
};
desktopSession = mkOption {
type = types.nullOr types.str;
default = null;
description = "Desktop session to launch when switching to Desktop Mode";
};
enableDeckyLoader = mkOption {
type = types.bool;
default = true;
description = "Enable Decky Loader plugin system";
};
};
config = mkIf (cfg.enable && cfg.steamos.enable) {
jovian.steam = {
enable = true;
autoStart = cfg.steamos.autoStart;
user = cfg.steamos.user;
desktopSession = cfg.steamos.desktopSession;
};
jovian.decky-loader.enable = cfg.steamos.enableDeckyLoader;
environment.systemPackages = with pkgs; [
maliit-keyboard
];
};
}

View File

@@ -12,27 +12,8 @@ in
windowManager.i3 = { windowManager.i3 = {
enable = true; enable = true;
extraPackages = with pkgs; [ extraPackages = with pkgs; [ dmenu i3status i3lock ];
dmenu
i3status
i3lock
polkit_gnome # GNOME polkit authentication agent (more stable with i3)
picom # Compositor for smooth rendering (important for Nvidia)
networkmanagerapplet # NetworkManager system tray applet
ddcutil # DDC/CI monitor control for brightness
];
}; };
}; };
# Enable DDC/CI support for monitor brightness control
boot.kernelModules = [ "i2c-dev" ];
# Add ddcutil udev rules and user permissions
hardware.i2c.enable = true;
# Install ddcutil system-wide
environment.systemPackages = with pkgs; [
ddcutil
];
}; };
} }

View File

@@ -1,64 +0,0 @@
{ lib, config, ... }:
# Minimal Jovian compatibility layer for NixOS stable (25.05)
# Defines only the Jovian options used by roles/desktop/steamos.nix
# No actual implementation - just option definitions to prevent evaluation errors
# REMOVE THIS FILE when all systems are on NixOS 25.11+ or unstable
with lib;
let
nixosVersion = config.system.nixos.release;
isCompatibleVersion = versionOlder nixosVersion "25.11";
in
{
options.jovian = {
steam = {
enable = mkEnableOption "Steam (jovian-compat stub)";
autoStart = mkOption {
type = types.bool;
default = false;
description = "Auto-start Steam (jovian-compat stub)";
};
user = mkOption {
type = types.str;
default = "user";
description = "Steam user (jovian-compat stub)";
};
desktopSession = mkOption {
type = types.nullOr types.str;
default = null;
description = "Desktop session (jovian-compat stub)";
};
};
decky-loader = {
enable = mkEnableOption "Decky Loader (jovian-compat stub)";
};
};
config = mkMerge [
{
assertions = [
{
assertion = isCompatibleVersion;
message = ''
The Jovian compatibility shim (roles/jovian-compat.nix) is only needed for NixOS 25.05 and earlier.
You are running NixOS ${nixosVersion}.
Please remove 'roles/jovian-compat.nix' from your flake.nix nixosModules list.
'';
}
];
}
# No config implementation - these options do nothing on stable systems
# steamos role is only enabled on nix-deck which uses unstable anyway
(mkIf config.jovian.steam.enable {
warnings = [
"Jovian is enabled but you're using the compatibility stub. This won't work correctly. Use NixOS unstable for Jovian support."
];
})
];
}

View File

@@ -4,6 +4,7 @@ with lib;
let let
cfg = config.roles.kodi; cfg = config.roles.kodi;
customPkgs = pkgs.callPackage ../../packages {};
in in
{ {
options.roles.kodi = { options.roles.kodi = {
@@ -53,7 +54,7 @@ in
kodiPkg kodiPkg
wget wget
firefox firefox
] ++ optional cfg.appLauncherServer.enable pkgs.custom.app-launcher-server; ] ++ optional cfg.appLauncherServer.enable customPkgs.app-launcher-server;
programs.kdeconnect.enable = true; programs.kdeconnect.enable = true;
@@ -64,7 +65,7 @@ in
after = [ "graphical-session.target" ]; after = [ "graphical-session.target" ];
serviceConfig = { serviceConfig = {
Type = "simple"; Type = "simple";
ExecStart = "${pkgs.custom.app-launcher-server}/bin/app-launcher-server ${toString cfg.appLauncherServer.port}"; ExecStart = "${customPkgs.app-launcher-server}/bin/app-launcher-server ${toString cfg.appLauncherServer.port}";
Restart = "always"; Restart = "always";
RestartSec = "5s"; RestartSec = "5s";
Environment = [ Environment = [
@@ -74,10 +75,13 @@ in
}; };
}; };
services.displayManager = mkIf cfg.autologin { services = if cfg.autologin then {
autoLogin.enable = true; displayManager = {
autoLogin.user = "kodi"; autoLogin.enable = true;
defaultSession = "plasma"; autoLogin.user = "kodi";
}; defaultSession = "kodi";
sessionData.autologinSession = "plasma";
};
} else {};
}; };
} }

View File

@@ -26,11 +26,5 @@ in
model = "everywhere"; model = "everywhere";
}]; }];
hardware.printers.ensureDefaultPrinter = "MFC-L8900CDW_series"; hardware.printers.ensureDefaultPrinter = "MFC-L8900CDW_series";
# Fix ensure-printers service to wait for network availability
systemd.services.ensure-printers = {
after = [ "cups.service" "network-online.target" ];
wants = [ "cups.service" "network-online.target" ];
};
}; };
} }

View File

@@ -1,132 +0,0 @@
{ lib, config, pkgs, ... }:
with lib;
let
cfg = config.roles.remote-build;
in
{
options.roles.remote-build = {
enableBuilder = mkOption {
type = types.bool;
default = false;
description = "Enable this machine as a remote build host for other machines";
};
builderUser = mkOption {
type = types.str;
default = "nix-builder";
description = "User account for remote builders to connect as";
};
builders = mkOption {
type = types.listOf (types.submodule {
options = {
hostName = mkOption {
type = types.str;
description = "Hostname or IP address of the build machine";
};
systems = mkOption {
type = types.listOf types.str;
default = [ "x86_64-linux" ];
description = "Supported systems";
};
maxJobs = mkOption {
type = types.int;
default = 8;
description = "Maximum number of parallel build jobs";
};
speedFactor = mkOption {
type = types.int;
default = 2;
description = "Speed factor compared to local building (higher = prefer remote)";
};
supportedFeatures = mkOption {
type = types.listOf types.str;
default = [ "nixos-test" "benchmark" "big-parallel" "kvm" ];
description = "Supported build features";
};
sshUser = mkOption {
type = types.str;
default = "nix-builder";
description = "SSH user for connecting to the builder";
};
sshKey = mkOption {
type = types.nullOr types.path;
default = null;
description = "Path to SSH private key for authentication";
};
};
});
default = [];
description = "List of remote build machines to use";
};
fallbackToLocalBuild = mkOption {
type = types.bool;
default = true;
description = "Fallback to local building if remote builders are unavailable";
};
};
config = mkMerge [
# Builder host configuration
(mkIf cfg.enableBuilder {
# Create dedicated builder user
users.users.${cfg.builderUser} = {
isSystemUser = true;
group = cfg.builderUser;
description = "Nix remote build user";
home = "/var/lib/${cfg.builderUser}";
createHome = true;
shell = pkgs.bashInteractive;
openssh.authorizedKeys.keyFiles = []; # Will be populated by client machines
};
users.groups.${cfg.builderUser} = {};
# Ensure home directory has correct permissions
systemd.tmpfiles.rules = [
"d /var/lib/${cfg.builderUser} 0700 ${cfg.builderUser} ${cfg.builderUser} -"
];
# Allow builder user to perform builds
nix.settings.trusted-users = [ cfg.builderUser ];
# Allow remote builds
services.openssh.enable = true;
# Ensure nix-daemon is accessible
nix.settings.allowed-users = [ "*" ];
})
# Client configuration (machines using remote builders)
(mkIf (cfg.builders != []) {
nix.buildMachines = map (builder: {
hostName = builder.hostName;
systems = builder.systems;
maxJobs = builder.maxJobs;
speedFactor = builder.speedFactor;
supportedFeatures = builder.supportedFeatures;
sshUser = builder.sshUser;
sshKey = builder.sshKey;
}) cfg.builders;
nix.distributedBuilds = true;
# Use substitutes from remote builders
nix.extraOptions = ''
builders-use-substitutes = true
'';
# Fallback to local build if remote unavailable
nix.settings.fallback = cfg.fallbackToLocalBuild;
})
];
}