/ flake.nix
flake.nix
1 { 2 description = "Zenbook NixOS — Goose + Ralph + MCP"; 3 4 inputs = { 5 nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"; 6 nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable"; 7 flake-parts.url = "github:hercules-ci/flake-parts"; 8 llm-agents.url = "github:numtide/llm-agents.nix"; 9 llama-cpp.url = "github:ggml-org/llama.cpp"; 10 home-manager = { 11 url = "github:nix-community/home-manager"; 12 inputs.nixpkgs.follows = "nixpkgs-unstable"; 13 }; 14 }; 15 16 outputs = inputs@{ self, flake-parts, ... }: 17 let 18 system = "x86_64-linux"; 19 unstable = import inputs.nixpkgs-unstable { 20 inherit system; 21 config = { 22 allowUnfree = true; 23 cudaSupport = true; 24 cudaCapabilities = [ "7.5" ]; 25 }; 26 }; 27 lib = unstable.lib; 28 homeUser = "user"; 29 homeDir = "/home/${homeUser}"; 30 ralphConfigPath = "${homeDir}/.config/ralph-orchestrator/config.yml"; 31 secretspecFilePath = "${homeDir}/.config/secretspec/secretspec.toml"; 32 systemReportPath = "${homeDir}/.cache/zenbook/post-switch-report.txt"; 33 llamaCuda = inputs.llama-cpp.packages.${system}.cuda.overrideAttrs (prevAttrs: { 34 buildInputs = (prevAttrs.buildInputs or []) ++ [ unstable.openssl ]; 35 nativeBuildInputs = (prevAttrs.nativeBuildInputs or []) ++ [ unstable.pkg-config ]; 36 cmakeFlags = (prevAttrs.cmakeFlags or []) ++ [ "-DLLAMA_OPENSSL=ON" ]; 37 }); 38 ralphUnwrapped = unstable.rustPlatform.buildRustPackage rec { 39 pname = "ralph-orchestrator"; 40 version = "2.9.0"; 41 src = unstable.fetchFromGitHub { 42 owner = "mikeyobrien"; 43 repo = "ralph-orchestrator"; 44 rev = "v${version}"; 45 hash = "sha256-ptNKdHBUj84ArO/K/jrXazqy1t0bDPHKWFkrrkUTY9s="; 46 }; 47 cargoLock.lockFile = "${src}/Cargo.lock"; 48 cargoBuildFlags = [ "--package=ralph-cli" ]; 49 doCheck = false; 50 }; 51 gooseUnwrapped = unstable.stdenv.mkDerivation { 52 pname = "goose"; 53 version = "1.29.1"; 54 src = unstable.fetchurl { 55 url = "https://github.com/block/goose/releases/download/v1.29.1/goose-x86_64-unknown-linux-gnu.tar.bz2"; 56 hash = "sha256-cWQVSAhhI7z3zxN9nSRyOuFvMmM/7ShpM1FahTtZRY8="; 57 }; 58 sourceRoot = "."; 59 dontBuild = true; 60 dontConfigure = true; 61 nativeBuildInputs = [ unstable.autoPatchelfHook unstable.gnutar ]; 62 buildInputs = [ unstable.openssl unstable.gcc.cc.lib ]; 63 installPhase = "install -Dm755 goose $out/bin/goose"; 64 }; 65 searchMcp = unstable.rustPlatform.buildRustPackage rec { 66 pname = "search-mcp"; 67 version = "0.1.0"; 68 src = unstable.fetchFromGitHub { 69 owner = "pdaxt"; 70 repo = "search-mcp"; 71 rev = "v${version}"; 72 hash = "sha256-QmYmm7isUaARUrb8KR+Zz/R5wlgs84+VZ6rEuIf67So="; 73 }; 74 cargoLock.lockFile = "${src}/Cargo.lock"; 75 doCheck = false; 76 }; 77 wildLinker = unstable.rustPlatform.buildRustPackage rec { 78 pname = "wild"; 79 version = "unstable-2026-04-02"; 80 src = unstable.fetchFromGitHub { 81 owner = "wild-linker"; 82 repo = "wild"; 83 rev = "9a7ad7c"; 84 hash = "sha256-Ef2A6YON5N9GsapHg0Tvidig5Fn2kZxHo9NdqzEA6vk="; 85 }; 86 cargoLock.lockFile = "${src}/Cargo.lock"; 87 doCheck = false; 88 }; 89 nuMcp = unstable.stdenv.mkDerivation { 90 pname = "nu-mcp"; 91 version = "0.7.1"; 92 src = unstable.fetchurl { 93 url = "https://github.com/ck3mp3r/nu-mcp/releases/download/v0.7.1/nu-mcp-0.7.1-x86_64-linux.tgz"; 94 hash = "sha256-aEk+i5KQTH8IZzvEmaiGF/yR2my3pmVgBs2NQYGUfEE="; 95 }; 96 sourceRoot = "bin"; 97 dontBuild = true; 98 dontConfigure = true; 99 dontPatchELF = true; 100 dontStrip = true; 101 dontFixup = true; 102 nativeBuildInputs = [ unstable.autoPatchelfHook ]; 103 buildInputs = [ unstable.openssl unstable.gcc.cc.lib ]; 104 installPhase = '' 105 mkdir -p $out/bin 106 cp -f nu-mcp $out/bin/nu-mcp 107 chmod +x $out/bin/nu-mcp 108 ''; 109 }; 110 llmsFetchMcp = unstable.stdenv.mkDerivation rec { 111 pname = "llms-fetch-mcp"; 112 version = "0.1.7"; 113 src = unstable.fetchurl { 114 url = "https://github.com/Crazytieguy/llms-fetch-mcp/releases/download/v${version}/llms-fetch-mcp-x86_64-unknown-linux-gnu.tar.xz"; 115 hash = "sha256-9twZnUkmCdP6RoJ8N8JSaZqrWJIJhRAZDm38cbud9Ug="; 116 }; 117 nativeBuildInputs = [ unstable.autoPatchelfHook unstable.patchelf ]; 118 buildInputs = [ 119 unstable.openssl 120 unstable.gcc.cc.lib 121 unstable.glibc 122 unstable.stdenv.cc.libc 123 ]; 124 dontBuild = true; 125 dontStrip = true; 126 installPhase = '' 127 mkdir -p "$TMPDIR/extract" 128 tar -xJf $src -C "$TMPDIR/extract" --strip-components=1 129 install -Dm755 "$TMPDIR/extract/llms-fetch-mcp" $out/bin/llms-fetch-mcp 130 ''; 131 postFixup = '' 132 autoPatchelf $out/bin/llms-fetch-mcp || true 133 patchelf --set-interpreter ${unstable.glibc}/lib/ld-linux-x86-64.so.2 \ 134 $out/bin/llms-fetch-mcp || true 135 ''; 136 }; 137 gooseEnvironmentExports = lib.concatStringsSep "\n" ( 138 lib.mapAttrsToList (name: value: "export ${name}=${lib.escapeShellArg (toString value)}") { 139 GOOSE_PROVIDER = "custom_z.ai"; 140 GOOSE_MODEL = "glm-5-turbo"; 141 GOOSE_TEMPERATURE = "0.2"; 142 GOOSE_MAX_TURNS = "250"; 143 GOOSE_MODE = "auto"; 144 GOOSE_CONTEXT_STRATEGY = "summarize"; 145 GOOSE_AUTO_COMPACT_THRESHOLD = "0.6"; 146 GOOSE_SUBAGENT_MAX_TURNS = "50"; 147 GOOSE_DISABLE_SESSION_NAMING = "true"; 148 GOOSE_TELEMETRY_ENABLED = "false"; 149 GOOSE_DISABLE_TELEMETRY = "1"; 150 GOOSE_DISABLE_KEYRING = "1"; 151 GOOSE_SHELL = "${unstable.bashInteractive}/bin/bash"; 152 } 153 ); 154 goose = unstable.writeShellScriptBin "goose" '' 155 set -euo pipefail 156 export SHELL="${unstable.bashInteractive}/bin/bash" 157 ${gooseEnvironmentExports} 158 export PATH="${lib.makeBinPath [ nuMcp searchMcp llmsFetchMcp ]}:$PATH" 159 exec ${unstable.secretspec}/bin/secretspec run -- ${gooseUnwrapped}/bin/goose "$@" 160 ''; 161 ralph = unstable.writeShellScriptBin "ralph" '' 162 set -euo pipefail 163 ${gooseEnvironmentExports} 164 export PATH="${lib.makeBinPath [ goose ]}:$PATH" 165 if [ "''${1:-}" = "run" ]; then 166 shift 167 exec ${ralphUnwrapped}/bin/ralph run --no-tui "$@" 168 fi 169 exec ${ralphUnwrapped}/bin/ralph "$@" 170 ''; 171 agentTools = unstable.writeShellApplication { 172 name = "agent-tools"; 173 runtimeInputs = [ 174 unstable.git 175 unstable.findutils 176 unstable.coreutils 177 unstable.nix 178 unstable.home-manager 179 unstable.secretspec 180 ]; 181 text = '' 182 set -euo pipefail 183 IFS=$'\n\t' 184 skillsRoot="${homeDir}/.config/agents/skills" 185 temporaryDirectory="" 186 printUsage() { 187 printf 'Usage: agent-tools init-secrets|setup-skills|prune\n' 188 } 189 cleanupTemporaryDirectory() { 190 [ -n "''${temporaryDirectory:-}" ] && [ -d "''${temporaryDirectory:-}" ] && rm -rf "$temporaryDirectory" 191 } 192 initializeSecrets() { 193 secretspec set Z_API_KEY 194 secretspec set BRAVE_API_KEY 195 printf 'Secrets stored. Run: goose\n' 196 } 197 setupSkills() { 198 temporaryDirectory="$(mktemp -d)" 199 trap cleanupTemporaryDirectory EXIT 200 git clone --depth 1 https://github.com/protagonist-fy/low-level-dev-skills.git "$temporaryDirectory" 201 mkdir -p "$skillsRoot" 202 find "$temporaryDirectory/skills" -type f -name SKILL.md -print | while IFS= read -r file; do 203 skillName="$(basename "$(dirname "$file")")" 204 mkdir -p "$skillsRoot/$skillName" 205 cp -f "$file" "$skillsRoot/$skillName/SKILL.md" 206 done 207 printf 'Skills ready.\n' 208 } 209 pruneSystem() { 210 nix-collect-garbage -d && sudo nix-collect-garbage -d 211 home-manager expire-generations '-30 days' 212 sudo nixos-rebuild boot --flake "${homeDir}/base#nixos" 213 } 214 case "''${1:-}" in 215 init-secrets) initializeSecrets ;; 216 setup-skills) setupSkills ;; 217 prune) pruneSystem ;; 218 -h|--help) printUsage ;; 219 *) printUsage >&2; exit 1 ;; 220 esac 221 ''; 222 }; 223 systemReport = unstable.writeShellApplication { 224 name = "system-report"; 225 runtimeInputs = [ 226 unstable.coreutils 227 unstable.findutils 228 unstable.gnugrep 229 unstable.which 230 unstable.git 231 unstable.nix 232 unstable.home-manager 233 unstable.sccache 234 unstable.cargo 235 unstable.rustc 236 unstable.nodejs 237 unstable.bat 238 unstable.mpv 239 unstable.qbittorrent 240 unstable.telegram-desktop 241 unstable.brightnessctl 242 unstable.wl-clipboard 243 unstable.brave 244 unstable.ghostty 245 unstable.podman 246 unstable.openssl 247 unstable.clang 248 unstable.radicle-desktop 249 unstable.secretspec 250 unstable.nushell 251 goose 252 ralph 253 nuMcp 254 searchMcp 255 llmsFetchMcp 256 wildLinker 257 ]; 258 text = '' 259 set -euo pipefail 260 export PATH="/run/current-system/sw/bin:/run/opengl-driver/bin:$PATH" 261 mkdir -p "$(dirname "${systemReportPath}")" 262 probeCommand() { 263 local label="$1" 264 local commandName="$2" 265 local mode="$3" 266 if ! command -v "$commandName" >/dev/null 2>&1; then 267 echo "MISSING: $label ($commandName)" 268 return 0 269 fi 270 case "$mode" in 271 version) "$commandName" --version >/dev/null 2>&1 || "$commandName" -V >/dev/null 2>&1 || true ;; 272 help) "$commandName" --help >/dev/null 2>&1 || "$commandName" -h >/dev/null 2>&1 || true ;; 273 exec) "$commandName" >/dev/null 2>&1 || true ;; 274 esac 275 echo "OK: $label" 276 } 277 { 278 echo "================ SYSTEM VERIFY ================" 279 echo "User: ''${USER:-unknown} | Host: $(uname -n) | Generated: $(date -Is)" 280 echo "RALPH_CONFIG path: ${ralphConfigPath}" 281 echo "SECRETSPEC_FILE path: ${secretspecFilePath}" 282 echo "Report file: ${systemReportPath}" 283 echo "----------------------------------------------" 284 echo "== Core CLI checks ==" 285 probeCommand bash bash version 286 probeCommand goose goose version 287 probeCommand ralph ralph version 288 probeCommand nu-mcp nu-mcp version 289 probeCommand search-mcp search-mcp version 290 probeCommand llms-fetch-mcp llms-fetch-mcp version 291 probeCommand wild wild version 292 probeCommand secretspec secretspec version 293 probeCommand nushell nu version 294 probeCommand git git version 295 probeCommand nix nix version 296 probeCommand home-manager home-manager version 297 probeCommand sccache sccache version 298 probeCommand cargo cargo version 299 probeCommand rustc rustc version 300 probeCommand node node version 301 probeCommand bat bat version 302 probeCommand mpv mpv version 303 probeCommand qbittorrent qbittorrent version 304 probeCommand telegram-desktop telegram-desktop version 305 probeCommand brightnessctl brightnessctl version 306 probeCommand wl-copy wl-copy help 307 probeCommand brave-browser brave-browser version 308 probeCommand ghostty ghostty version 309 echo "== Capability checks ==" 310 probeCommand podman podman version 311 probeCommand openssl openssl version 312 probeCommand clang clang version 313 if [ -d "${homeDir}/.config/agents/skills" ]; then 314 echo "OK: skills directory exists" 315 find "${homeDir}/.config/agents/skills" -maxdepth 2 -type f -name SKILL.md | sort || true 316 else 317 echo "WARN: skills directory missing — run: agent-tools setup-skills" 318 fi 319 if command -v nvidia-smi >/dev/null 2>&1; then 320 nvidia-smi -L >/dev/null 2>&1 && echo "OK: nvidia-smi GPU visibility" \ 321 || echo "WARN: nvidia-smi exists but GPU query failed" 322 else 323 echo "WARN: nvidia-smi not found; NVIDIA capability not verified" 324 fi 325 echo "==============================================" 326 } | tee "${systemReportPath}" 327 ''; 328 }; 329 sessionEnvironment = { 330 RALPH_QUIET = "1"; 331 NO_COLOR = "1"; 332 RALPH_CONFIG = ralphConfigPath; 333 SECRETSPEC_FILE = secretspecFilePath; 334 RUSTC_WRAPPER = "sccache"; 335 SCCACHE_DIR = "${homeDir}/.cache/sccache"; 336 SCCACHE_CACHE_SIZE = "500G"; 337 NIXOS_OZONE_WL = "1"; 338 QT_QPA_PLATFORM = "wayland"; 339 }; 340 gooseExtensions = 341 let 342 makePlatformExtension = name: displayName: enabled: description: { 343 name = name; 344 value = { 345 type = "platform"; 346 bundled = true; 347 available_tools = []; 348 name = name; 349 display_name = displayName; 350 enabled = enabled; 351 description = description; 352 }; 353 }; 354 makeStdioExtension = commandName: displayName: enabled: description: environmentKeys: { 355 name = commandName; 356 value = { 357 type = "stdio"; 358 cmd = commandName; 359 args = []; 360 envs = {}; 361 env_keys = environmentKeys; 362 timeout = 300; 363 bundled = false; 364 available_tools = []; 365 enabled = enabled; 366 description = description; 367 name = commandName; 368 display_name = displayName; 369 }; 370 }; 371 in 372 builtins.listToAttrs [ 373 (makePlatformExtension "developer" "Developer" true "Write and edit files, execute shell commands") 374 (makePlatformExtension "orchestrator" "Orchestrator" true "Manage agent sessions") 375 (makePlatformExtension "extensionmanager" "Extension Manager" true "Enable extension management tools") 376 (makePlatformExtension "summarize" "Summarize" true "Summarize files/directories via LLM") 377 (makePlatformExtension "analyze" "Analyze" true "Analyze code structure with tree-sitter") 378 (makePlatformExtension "todo" "Todo" true "Maintain a todo list across turns") 379 (makePlatformExtension "summon" "Summon" true "Delegate tasks to subagents") 380 (makePlatformExtension "apps" "Apps" true "Create and manage custom Goose apps") 381 (makePlatformExtension "code_execution" "Code Mode" true "Execute tool calls through code interpreter") 382 (makePlatformExtension "chatrecall" "Chat Recall" false "Search past conversations") 383 (makePlatformExtension "tom" "Top Of Mind" false "Inject custom context") 384 (makeStdioExtension "search-mcp" "Brave Search" true "AI-native web search via Brave" [ "BRAVE_API_KEY" ]) 385 (makeStdioExtension "llms-fetch-mcp" "LLMs Fetch" true "Fetch and process web content" []) 386 (makeStdioExtension "nu-mcp" "Nushell MCP" true "MCP server for Nushell integration" []) 387 ]; 388 userHomeModule = { lib, config, ... }: { 389 home.username = homeUser; 390 home.homeDirectory = homeDir; 391 home.stateVersion = "25.11"; 392 home.enableNixpkgsReleaseCheck = false; 393 home.sessionVariables = sessionEnvironment; 394 home.packages = [ 395 unstable.wl-clipboard 396 unstable.brightnessctl 397 unstable.home-manager 398 unstable.openssl 399 unstable.mpv 400 unstable.telegram-desktop 401 unstable.bat 402 unstable.devenv 403 unstable.nodejs 404 unstable.secretspec 405 unstable.qbittorrent 406 unstable.sccache 407 llamaCuda 408 wildLinker 409 nuMcp 410 searchMcp 411 llmsFetchMcp 412 goose 413 ralph 414 agentTools 415 systemReport 416 inputs.llm-agents.packages.${system}.gemini-cli 417 ]; 418 xdg.configFile."secretspec/config.toml".source = 419 (unstable.formats.toml {}).generate "ss-config.toml" { 420 defaults = { 421 provider = "keyring"; 422 profile = "default"; 423 }; 424 }; 425 xdg.configFile."secretspec/secretspec.toml".source = 426 (unstable.formats.toml {}).generate "secretspec.toml" { 427 project = { 428 name = homeUser; 429 revision = "1.0"; 430 }; 431 profiles.default = { 432 Z_API_KEY = { 433 description = "Z.ai API key"; 434 required = true; 435 }; 436 BRAVE_API_KEY = { 437 description = "Brave Search API key"; 438 required = true; 439 }; 440 }; 441 }; 442 xdg.configFile."goose/config.yaml".source = 443 (unstable.formats.yaml {}).generate "goose-config.yaml" { 444 extensions = gooseExtensions; 445 }; 446 xdg.configFile."goose/custom_providers/custom_z.ai.json".source = 447 (unstable.formats.json {}).generate "custom_z.ai.json" { 448 name = "custom_z.ai"; 449 engine = "anthropic"; 450 display_name = "Z.ai"; 451 description = "Custom Z.ai provider"; 452 api_key_env = "Z_API_KEY"; 453 base_url = "https://api.z.ai/api/anthropic"; 454 supports_streaming = true; 455 requires_auth = true; 456 models = [ 457 { 458 name = "glm-5-turbo"; 459 context_limit = 128000; 460 } 461 { 462 name = "glm-4.7"; 463 context_limit = 128000; 464 } 465 ]; 466 }; 467 xdg.configFile."ralph-orchestrator/config.yml".source = 468 (unstable.formats.yaml {}).generate "ralph-config.yml" { 469 event_loop = { 470 completion_promise = "LOOP_COMPLETE"; 471 max_iterations = 400; 472 max_runtime_seconds = 43200; 473 max_consecutive_failures = 10; 474 idle_timeout_secs = 0; 475 checkpoint_interval = 5; 476 }; 477 cli = { 478 backend = "custom"; 479 command = "goose"; 480 args = [ "run" "--quiet" "--no-session" "--max-tool-repetitions" "100" ]; 481 prompt_mode = "arg"; 482 prompt_flag = "--text"; 483 idle_timeout_secs = 0; 484 pty_mode = false; 485 }; 486 core = { 487 specs_dir = "./specs/"; 488 guardrails = [ 489 "Define every feature with Gherkin specification first." 490 "Start each loop with fresh context." 491 "Never loop in setup." 492 "Finish the real task." 493 "Save all learnings to memory." 494 "Commit after each finished step." 495 "Run full verification." 496 "All tests must pass before LOOP_COMPLETE." 497 ]; 498 }; 499 memories = { 500 enabled = true; 501 inject = "auto"; 502 budget = 3500; 503 }; 504 tasks = { 505 enabled = true; 506 }; 507 features = { 508 parallel = false; 509 auto_merge = false; 510 preflight = { 511 enabled = true; 512 strict = false; 513 }; 514 }; 515 skills = { 516 enabled = true; 517 dirs = [ "${homeDir}/.config/agents/skills" ]; 518 }; 519 }; 520 xdg.configFile."cargo/config.toml".source = 521 (unstable.formats.toml {}).generate "cargo-config.toml" { 522 build."rustc-wrapper" = "sccache"; 523 target."x86_64-unknown-linux-gnu" = { 524 linker = "clang"; 525 rustflags = [ "-Clink-arg=--ld-path=wild" ]; 526 }; 527 }; 528 xdg.configFile."mimeapps.list".force = true; 529 services.radicle.node = { 530 enable = true; 531 lazy = { 532 enable = true; 533 exitIdleTime = "30min"; 534 }; 535 }; 536 programs.radicle = { 537 enable = true; 538 settings = { 539 publicExplorer = "https://app.radicle.xyz/nodes/$host/$rid$path"; 540 preferredSeeds = [ 541 "z6MkrLMMsiPWUcNPHcRajuMi9mDfYckSoJyPwwnknocNYPm7@iris.radicle.xyz:8776" 542 "z6MkrLMMsiPWUcNPHcRajuMi9mDfYckSoJyPwwnknocNYPm7@irisradizskwweumpydlj4oammoshkxxjur3ztcmo7cou5emc6s5lfid.onion:8776" 543 "z6Mkmqogy2qEM2ummccUthFEaaHvyYmYBYh3dbe9W4ebScxo@rosa.radicle.xyz:8776" 544 "z6Mkmqogy2qEM2ummccUthFEaaHvyYmYBYh3dbe9W4ebScxo@rosarad5bxgdlgjnzzjygnsxrwxmoaj4vn7xinlstwglxvyt64jlnhyd.onion:8776" 545 ]; 546 web.pinned.repositories = []; 547 cli.hints = true; 548 node = { 549 alias = "cognitive-singularity"; 550 listen = []; 551 peers.type = "dynamic"; 552 connect = []; 553 externalAddresses = []; 554 network = "main"; 555 log = "INFO"; 556 relay = "auto"; 557 limits = { 558 routingMaxSize = 1000; 559 routingMaxAge = 604800; 560 gossipMaxAge = 1209600; 561 fetchConcurrency = 1; 562 maxOpenFiles = 4096; 563 rate.inbound = { 564 fillRate = 5.0; 565 capacity = 1024; 566 }; 567 rate.outbound = { 568 fillRate = 10.0; 569 capacity = 2048; 570 }; 571 connection = { 572 inbound = 128; 573 outbound = 16; 574 }; 575 fetchPackReceive = "500.0 MiB"; 576 }; 577 workers = 8; 578 seedingPolicy.default = "block"; 579 }; 580 }; 581 }; 582 programs.direnv = { 583 enable = true; 584 nix-direnv.enable = true; 585 enableNushellIntegration = true; 586 }; 587 programs.gpg = { 588 enable = true; 589 homedir = "${config.home.homeDirectory}/.gnupg"; 590 mutableKeys = true; 591 mutableTrust = true; 592 settings.default-key = "306A63FF178E18B466462D9DE5BEE3A77A0751E5"; 593 }; 594 services.gpg-agent = { 595 enable = true; 596 defaultCacheTtl = 1800; 597 maxCacheTtl = 3600; 598 enableSshSupport = true; 599 pinentry.package = unstable.pinentry-gnome3; 600 enableBashIntegration = true; 601 }; 602 programs.git = { 603 enable = true; 604 lfs.enable = true; 605 ignores = [ 606 ".ralph/" 607 ".llms-fetch-mcp/" 608 ]; 609 settings = { 610 core.excludesFile = "~/.config/git/ignore"; 611 user = { 612 name = "Cognitive Singularity"; 613 email = "cognitive-singularity@tutamail.com"; 614 }; 615 init.defaultBranch = "main"; 616 pull.rebase = true; 617 signing = { 618 signByDefault = true; 619 key = "306A63FF178E18B466462D9DE5BEE3A77A0751E5"; 620 format = "openpgp"; 621 }; 622 }; 623 }; 624 programs.dircolors = { 625 enable = true; 626 enableNushellIntegration = true; 627 }; 628 programs.helix = { 629 enable = true; 630 defaultEditor = true; 631 settings = { 632 theme = "base16_default"; 633 editor = { 634 line-number = "relative"; 635 mouse = true; 636 cursor-shape = { 637 insert = "bar"; 638 normal = "block"; 639 }; 640 }; 641 keys.normal = { 642 "A-s" = ":write"; 643 "A-q" = ":quit"; 644 "ret" = "open_below"; 645 "C-j" = ":bn"; 646 "C-k" = ":bp"; 647 }; 648 keys.insert = { 649 "A-s" = [ "normal_mode" ":write" ]; 650 "A-q" = [ "normal_mode" ":quit" ]; 651 }; 652 }; 653 }; 654 programs.nushell = { 655 enable = true; 656 package = unstable.nushell; 657 settings = { 658 show_banner = false; 659 use_ansi_coloring = true; 660 table = { 661 mode = "none"; 662 index_mode = "never"; 663 }; 664 }; 665 environmentVariables = sessionEnvironment; 666 shellAliases = { 667 sp = "brightnessctl --device='asus_screenpad'"; 668 ss = "secretspec"; 669 sx = "secretspec check"; 670 sr = "secretspec run --"; 671 hm = "home-manager switch --flake ${homeDir}/base#user --show-trace"; 672 ns = "sudo nixos-rebuild switch --flake ${homeDir}/base#nixos --show-trace"; 673 init-secrets = "${agentTools}/bin/agent-tools init-secrets"; 674 setup-skills = "${agentTools}/bin/agent-tools setup-skills"; 675 prune = "${agentTools}/bin/agent-tools prune"; 676 report-system = "${systemReport}/bin/system-report"; 677 g = "git clone"; 678 }; 679 extraConfig = '' 680 def join-words [parts: list<string>] { 681 $parts | str join " " 682 } 683 def ralph-run-basic [...text: string] { 684 if ($text | is-empty) { 685 ^ralph run 686 } else { 687 ^ralph run -p (join-words $text) 688 } 689 } 690 def ralph-run-with-hat [hat: string, ...text: string] { 691 if ($text | is-empty) { 692 ^ralph run -H $hat 693 } else { 694 ^ralph run -H $hat -p (join-words $text) 695 } 696 } 697 def ralph-plan-shortcut [...text: string] { 698 if ($text | is-empty) { 699 ^ralph plan 700 } else { 701 ^ralph plan (join-words $text) 702 } 703 } 704 def r [...text: string] { ralph-run-basic ...$text } 705 def r0 [...text: string] { ralph-run-basic ...$text } 706 def ra [...text: string] { ralph-run-with-hat "builtin:autoresearch" ...$text } 707 def rc [...text: string] { ralph-run-with-hat "builtin:code-assist" ...$text } 708 def rd [...text: string] { ralph-run-with-hat "builtin:debug" ...$text } 709 def rp [...text: string] { ralph-run-with-hat "builtin:pdd-to-code-assist" ...$text } 710 def rr [...text: string] { ralph-run-with-hat "builtin:research" ...$text } 711 def rv [...text: string] { ralph-run-with-hat "builtin:review" ...$text } 712 def pl [...text: string] { ralph-plan-shortcut ...$text } 713 def skills-list [] { 714 let skillsRoot = $"($env.HOME)/.config/agents/skills" 715 if ($skillsRoot | path exists) { 716 ^find $skillsRoot -type f -name SKILL.md | sort 717 } else { 718 print $"Skills directory missing: ($skillsRoot)" 719 } 720 } 721 def skills-debug [] { 722 let skillsRoot = $"($env.HOME)/.config/agents/skills" 723 print "=== SKILLS DIRECTORY ===" 724 print $skillsRoot 725 if ($skillsRoot | path exists) { 726 ls $skillsRoot 727 } else { 728 print "Missing" 729 } 730 print "" 731 print "=== SKILL MANIFESTS ===" 732 if ($skillsRoot | path exists) { 733 ^find $skillsRoot -type f -name SKILL.md | sort 734 } 735 } 736 ''; 737 }; 738 programs.brave = { 739 enable = true; 740 package = unstable.brave; 741 }; 742 programs.ghostty = { 743 enable = true; 744 package = unstable.ghostty; 745 settings = { 746 theme = "Ghostty Default Style Dark"; 747 background = "000000"; 748 }; 749 enableBashIntegration = true; 750 systemd.enable = true; 751 }; 752 xdg.mimeApps = { 753 enable = true; 754 defaultApplications = { 755 "text/html" = [ "brave-browser.desktop" ]; 756 "x-scheme-handler/http" = [ "brave-browser.desktop" ]; 757 "x-scheme-handler/https" = [ "brave-browser.desktop" ]; 758 "x-scheme-handler/about" = [ "brave-browser.desktop" ]; 759 "x-scheme-handler/unknown" = [ "brave-browser.desktop" ]; 760 }; 761 }; 762 home.activation.systemReport = lib.hm.dag.entryAfter [ "writeBoundary" ] '' 763 echo "" 764 echo "================ SYSTEM VERIFY ================" 765 echo "User: $USER" 766 echo "RALPH_CONFIG path: ${ralphConfigPath}" 767 echo "SECRETSPEC_FILE path: ${secretspecFilePath}" 768 echo "Report file: ${systemReportPath}" 769 echo "----------------------------------------------" 770 ${systemReport}/bin/system-report || true 771 echo "==============================================" 772 echo "" 773 ''; 774 }; 775 in 776 flake-parts.lib.mkFlake { inherit inputs; } { 777 systems = [ system ]; 778 flake = { 779 homeConfigurations.user = inputs.home-manager.lib.homeManagerConfiguration { 780 pkgs = unstable; 781 extraSpecialArgs = { inherit unstable; }; 782 modules = [ userHomeModule ]; 783 }; 784 nixosConfigurations.nixos = inputs.nixpkgs.lib.nixosSystem { 785 inherit system; 786 specialArgs = { inherit unstable; }; 787 modules = [ 788 ./hardware-configuration.nix 789 inputs.home-manager.nixosModules.home-manager 790 ({ config, pkgs, unstable, ... }: { 791 nix.package = unstable.nixVersions.latest; 792 nix.gc = { 793 automatic = true; 794 dates = "weekly"; 795 options = "--delete-older-than 30d"; 796 }; 797 nix.optimise.automatic = true; 798 nix.settings = { 799 experimental-features = [ "nix-command" "flakes" "pipe-operators" "ca-derivations" ]; 800 auto-optimise-store = true; 801 builders-use-substitutes = true; 802 download-buffer-size = 524288000; 803 trusted-users = [ "root" "@wheel" ]; 804 cores = 8; 805 max-jobs = 2; 806 sandbox = true; 807 substituters = [ 808 "https://cache.nixos.org" 809 "https://cache.nixos-cuda.org" 810 "https://cache.flox.dev" 811 "https://nix-community.cachix.org" 812 "https://llama-cpp.cachix.org" 813 "https://cuda-maintainers.cachix.org" 814 ]; 815 trusted-public-keys = [ 816 "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" 817 "cache.nixos-cuda.org:74DUi4Ye579gUqzH4ziL9IyiJBlDpMRn9MBN8oNan9M=" 818 "flox-cache-public-1:7F4OyH7ZCnFhcze3fJdfyXYLQw/aV7GEed86nQ7IsOs=" 819 "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" 820 "llama-cpp.cachix.org-1:H75X+w83wUKTIPSO1KWy9ADUrzThyGs8P5tmAbkWhQc=" 821 "cuda-maintainers.cachix.org-1:0dq3bujKpuEPMCX6U4WylrUDZ9JyUG0VpVZa7CNfq5E=" 822 ]; 823 }; 824 nixpkgs.config.allowUnfree = true; 825 boot.loader.systemd-boot.enable = true; 826 boot.loader.efi.canTouchEfiVariables = true; 827 services.xserver.enable = true; 828 services.xserver.videoDrivers = [ "nvidia" ]; 829 services.displayManager.gdm.enable = true; 830 services.desktopManager.gnome.enable = true; 831 services.gnome.gnome-keyring.enable = true; 832 hardware.graphics.enable = true; 833 hardware.nvidia = { 834 modesetting.enable = true; 835 open = false; 836 powerManagement.enable = true; 837 package = config.boot.kernelPackages.nvidiaPackages.production; 838 prime = { 839 offload.enable = true; 840 offload.enableOffloadCmd = true; 841 intelBusId = "PCI:0:2:0"; 842 nvidiaBusId = "PCI:1:0:0"; 843 }; 844 }; 845 hardware.nvidia-container-toolkit.enable = true; 846 networking.hostName = "nixos"; 847 networking.networkmanager.enable = true; 848 time.timeZone = "Europe/Warsaw"; 849 i18n.defaultLocale = "en_US.UTF-8"; 850 security.rtkit.enable = true; 851 services.pipewire = { 852 enable = true; 853 alsa.enable = true; 854 pulse.enable = true; 855 }; 856 virtualisation.podman = { 857 enable = true; 858 dockerSocket.enable = true; 859 defaultNetwork.settings.dns_enabled = true; 860 }; 861 environment.shells = [ unstable.nushell ]; 862 users.users.user = { 863 isNormalUser = true; 864 shell = unstable.nushell; 865 extraGroups = [ "networkmanager" "wheel" "video" "render" "podman" ]; 866 }; 867 environment.systemPackages = [ 868 unstable.wl-clipboard 869 unstable.brightnessctl 870 unstable.home-manager 871 unstable.openssl 872 ]; 873 home-manager = { 874 backupFileExtension = "backup"; 875 useGlobalPkgs = true; 876 useUserPackages = true; 877 extraSpecialArgs = { inherit unstable; }; 878 users.user = userHomeModule; 879 }; 880 system.stateVersion = "25.11"; 881 }) 882 ]; 883 }; 884 }; 885 }; 886 }