[
  {
    "path": ".envrc",
    "content": "watch_file dev/flake.nix\nuse flake ./dev --override-input nixos-unified .\n"
  },
  {
    "path": ".github/workflows/ci.yaml",
    "content": "name: \"CI\"\non:\n  push:\n    branches:\n      - master\njobs:\n  website-upload:\n    runs-on: ubuntu-latest\n    if: github.ref == 'refs/heads/master'\n    steps:\n      - uses: actions/checkout@v4\n      - uses: nixbuild/nix-quick-install-action@v33\n      - name: Build docs\n        run: |\n          cd doc && nix build\n      - name: Upload artifact\n        uses: actions/upload-pages-artifact@v3\n        with:\n          path: doc/result\n\n  website-deploy:\n    runs-on: ubuntu-latest\n    if: github.ref == 'refs/heads/master'\n    needs: website-upload\n    environment:\n      name: github-pages\n      url: ${{ steps.deployment.outputs.page_url }}\n    # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages\n    permissions:\n      contents: read\n      pages: write\n      id-token: write\n    # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.\n    # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.\n    concurrency:\n      group: \"pages\"\n      cancel-in-progress: false\n    steps:\n      - name: Deploy to GitHub Pages\n        id: deployment\n        uses: actions/deploy-pages@v4\n"
  },
  {
    "path": ".gitignore",
    "content": "result\n/.direnv\n"
  },
  {
    "path": ".vscode/extensions.json",
    "content": "{\n    \"recommendations\": [\n        \"bbenoist.nix\",\n        \"b4dm4n.nixpkgs-fmt\",\n        \"jnoortheen.nix-ide\",\n        \"mattn.lisp\",\n        \"mkhl.direnv\",\n        \"thenuprojectcontributors.vscode-nushell-lang\"\n    ]\n}"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n    \"editor.defaultFormatter\": \"B4dM4n.nixpkgs-fmt\",\n    \"editor.formatOnSave\": true,\n    \"editor.formatOnType\": true\n}"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2023 Sridhar Ratnakumar\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "[![project chat](https://img.shields.io/badge/zulip-join_chat-brightgreen.svg)](https://nixos.zulipchat.com/#narrow/stream/413948-nixos)\n[![Naiveté Compass of Mood](https://img.shields.io/badge/naïve-FF10F0)](https://compass.naivete.me/ \"This project follows the 'Naiveté Compass of Mood'\")\n\n# nixos-unified\n\n[**nixos-unified**](https://github.com/srid/nixos-unified) is a\n[flake-parts](https://flake.parts/) module to unify [NixOS] + [nix-darwin] +\n[home-manager] configuration in a single flake, while providing a consistent\ninterface at DX and UX level.\n\n[NixOS]: https://nixos.org/\n[nix-darwin]: https://github.com/LnL7/nix-darwin\n[home-manager]: https://github.com/nix-community/home-manager\n\nFor motivation, see https://nixos-unified.org/#why\n\n[home-manager]: https://github.com/nix-community/home-manager\n\n## Getting Started\n\nhttps://nixos-unified.org/start.html\n\n## Examples\n\nhttps://nixos-unified.org/examples.html\n\n## Discussion\n\nTo discuss the project, post in [our Zulip](https://nixos.zulipchat.com/#narrow/stream/413948-nixos) or in [Github Discussions](https://github.com/srid/nixos-unified/discussions).\n"
  },
  {
    "path": "activate/activate.nu",
    "content": "use std log\nuse std assert\n\nuse nixos-unified.nu getData  # This module is generated in Nix\n\nlet CURRENT_HOSTNAME = (hostname -s | str trim)\nlet data = getData\n\n# Get all the data associated with a host\n#\n# Presently, this only deals with nixosConfigurations and darwinConfigurations.\n# But we should also incorporate home-manager configurations.\ndef get_host_data [ host: string ] {\n    if $host not-in $data.nixos-unified-configs {\n        log error $\"Host '($host)' not found in flake. Available hosts=($data.nixos-unified-configs | columns)\"\n        exit 1\n    }\n    $data.nixos-unified-configs\n        | get $host\n        | insert \"host\" $host\n        | insert \"flake\" $\"($data.cleanFlake)#($host)\"\n}\n\n# Parse \"[srid@]example\" into { user: \"srid\", host: \"example\" }\n#\n# localhost hosts are ignored (null'ified)\ndef parseFlakeOutputRef [ spec: string ] {\n    let parts = $spec | split row \"@\"\n    let handleLocalhost = {|h| if $h == \"localhost\" { null } else { $h } }\n    if ($parts | length) == 1 {\n        { user: null host: (do $handleLocalhost $parts.0) }\n    } else {\n        { user: $parts.0 host: (do $handleLocalhost $parts.1) }\n    }\n}\n\n# Activate system or home configuration\n#\n# The ref should match the name of the corresponding nixosConfigurations, darwinConfigurations or homeConfigurations attrkey. \"localhost\" is an exception, which will use the current host.\ndef main [\n  ref: string = \"localhost\", # Hostname or username (if containing `@`) to activate\n  --dry-run # Dry run (don't actually activate)\n] {\n    let spec = parseFlakeOutputRef $ref\n    if $spec.user != null {\n        activate_home $spec.user $spec.host --dry-run=$dry_run\n    } else {\n        let host = if ($spec.host | is-empty) { $CURRENT_HOSTNAME } else { $spec.host }\n        let hostData = get_host_data $host\n        activate_system $hostData --dry-run=$dry_run\n    }\n}\n\ndef activate_home [ user: string, host: string, --dry-run ] {\n    if (($host | is-empty) or ($host == $CURRENT_HOSTNAME)) {\n        activate_home_local $user $host --dry-run=$dry_run\n    } else {\n        activate_home_remote_ssh $user $host --dry-run=$dry_run\n    }\n}\n\ndef activate_home_local [ user: string, host: string, --dry-run ] {\n    let name = $\"($user)\" + (if ($host | is-empty) { \"\" } else { \"@\" + $host })\n    let extraArgs = if $dry_run { [\"--dry-run\"] } else { [] }\n    log info $\"Activating home configuration ($name) (ansi purple)locally(ansi reset)\"\n    log info $\"(ansi blue_bold)>>>(ansi reset) home-manager switch ($extraArgs | str join) --flake ($data.cleanFlake)#($name)\"\n    home-manager switch ...$extraArgs -b (date now | format date \"nixos-unified.%Y-%m-%d-%H:%M:%S.bak\") --flake $\"($data.cleanFlake)#($name)\"\n}\n\ndef activate_home_remote_ssh [ user: string, host: string, --dry-run ] {\n    let name = $\"($user)@($host)\"\n    let sshTarget = $\"($user)@($host)\"\n    log info $\"Activating home configuration ($name) (ansi purple_reverse)remotely(ansi reset) on ($sshTarget)\"\n\n    # Copy the flake to the remote host.\n    nix_copy $data.cleanFlake $\"ssh-ng://($sshTarget)\"\n\n    # We re-run this activation script, but on the remote host (where it will invoke activate_home_local).\n    log info $'(ansi blue_bold)>>>(ansi reset) ssh -t ($sshTarget) nix --extra-experimental-features '\"nix-command flakes\"' run $\"($data.cleanFlake)#activate\" -- ($name) --dry-run=($dry_run)'\n    ssh -t $sshTarget nix --extra-experimental-features '\"nix-command flakes\"' run $\"($data.cleanFlake)#activate\" -- ($name) --dry-run=($dry_run)\n}\n\ndef activate_system [ hostData: record, --dry-run=false ] {\n    log info $\"(ansi grey)currentSystem=($data.system) currentHost=(ansi green_bold)($CURRENT_HOSTNAME)(ansi grey) targetHost=(ansi green_reverse)($hostData.host)(ansi reset)(ansi grey) hostData=($hostData)(ansi reset)\"\n\n    if ($CURRENT_HOSTNAME == $hostData.host) {\n        # Since the user asked to activate current host, do so.\n        activate_system_local $hostData --dry-run=$dry_run\n    } else {\n        # Remote activation request, so copy the flake and the necessary inputs\n        # and then activate over SSH.\n        if $hostData.sshTarget == null {\n            log error $\"sshTarget not found in host data for ($hostData.host). Add `nixos-unified.sshTarget = \\\"user@hostname\\\";` to your configuration.\"\n            exit 1\n        }\n        activate_system_remote_ssh $hostData --dry-run=$dry_run\n    }\n}\n\ndef activate_system_local [ hostData: record, --dry-run=false ] {\n    log info $\"Activating (ansi purple)locally(ansi reset)\"\n    let darwin = $hostData.outputs.system in [\"aarch64-darwin\" \"x86_64-darwin\"]\n    if $darwin {\n        let subcommand = if $dry_run { \"build\" } else { \"switch\" }\n        log info $\"(ansi blue_bold)>>>(ansi reset) sudo darwin-rebuild ($subcommand) --flake ($hostData.flake) ($hostData.outputs.nixArgs | str join)\"\n        sudo darwin-rebuild $subcommand --flake $hostData.flake ...$hostData.outputs.nixArgs\n    } else {\n        let subcommand = if $dry_run { \"dry-activate\" } else { \"switch\" }\n        if $hostData.localPrivilegeMode == \"sudo-nixos-rebuild\" {\n            let nixosRebuild = \"/run/current-system/sw/bin/nixos-rebuild\"\n            log info $\"(ansi blue_bold)>>>(ansi reset) sudo ($nixosRebuild) ($subcommand) --flake ($hostData.flake) ($hostData.outputs.nixArgs | str join)\"\n            sudo $nixosRebuild $subcommand --flake $hostData.flake ...$hostData.outputs.nixArgs\n        } else {\n            log info $\"(ansi blue_bold)>>>(ansi reset) nixos-rebuild ($subcommand) --flake ($hostData.flake) ($hostData.outputs.nixArgs | str join) --sudo\"\n            nixos-rebuild $subcommand --flake $hostData.flake ...$hostData.outputs.nixArgs --sudo\n        }\n    }\n}\n\ndef activate_system_remote_ssh [ hostData: record, --dry-run=false ] {\n    log info $\"Activating (ansi purple_reverse)remotely(ansi reset) on ($hostData.sshTarget)\"\n\n    # Copy the flake and the necessary inputs to the remote host.\n    nix_copy $data.cleanFlake $\"ssh-ng://($hostData.sshTarget)\"\n    $hostData.outputs.overrideInputs | transpose key value | each { |input|\n        nix_copy $input.value $\"ssh-ng://($hostData.sshTarget)\"\n    }\n\n    # We re-run this activation script, but on the remote host (where it will invoke activate_system_local).\n    log info $'(ansi blue_bold)>>>(ansi reset) ssh -t ($hostData.sshTarget) nix --extra-experimental-features '\"nix-command flakes\"' run ($hostData.outputs.nixArgs | str join) $\"($data.cleanFlake)#activate\" -- ($hostData.host) --dry-run=($dry_run)'\n    ssh -t $hostData.sshTarget nix --extra-experimental-features '\"nix-command flakes\"' run ...$hostData.outputs.nixArgs $\"($data.cleanFlake)#activate\" -- ($hostData.host) --dry-run=($dry_run)\n}\n\ndef nix_copy [ src: string dst: string ] {\n    log info $\"(ansi blue_bold)>>>(ansi reset) nix --extra-experimental-features \\\"nix-command flakes\\\" copy ($src) --to ($dst)\"\n    nix --extra-experimental-features \"nix-command flakes\" copy $src --to $dst\n}\n"
  },
  {
    "path": "activate/default.nix",
    "content": "{ self, inputs', pkgs, lib, system, ... }:\n\nlet\n  nixosFlakeNuModule =\n    let\n      # Workaround https://github.com/NixOS/nix/issues/8752\n      cleanFlake = lib.cleanSourceWith {\n        name = \"nixos-unified-activate-flake\";\n        src = self;\n      };\n      nixos-unified-configs = lib.mapAttrs (name: value: value.config.nixos-unified) (self.nixosConfigurations or { } // self.darwinConfigurations or { });\n      data = {\n        nixos-unified-configs = nixos-unified-configs;\n        system = system;\n        cleanFlake = cleanFlake;\n      };\n      dataFile = pkgs.writeTextFile {\n        name = \"nixos-unified-activate-data\";\n        text = ''\n          ${builtins.toJSON data}\n        '';\n      };\n    in\n    pkgs.writeTextFile {\n      name = \"nixos-unified.nu\";\n      text = ''\n        export def getData [] {\n          open ${dataFile} | from json\n        }\n      '';\n    };\n  nu = import ./nu.nix { inherit pkgs; };\nin\nnu.writeNushellApplication {\n  name = \"activate\";\n  scriptDir = ./.;\n  meta = {\n    mainProgram = \"activate.nu\";\n    description = \"Activate NixOS/nix-darwin/home-manager configurations\";\n  };\n  runtimeInputs =\n    # TODO: better way to check for nix-darwin availability\n    lib.optionals (pkgs.stdenv.isDarwin && lib.hasAttr \"nix-darwin\" inputs') [\n      inputs'.nix-darwin.packages.default # Provides darwin-rebuild\n    ] ++ lib.optionals (lib.hasAttr \"home-manager\" inputs') [\n      inputs'.home-manager.packages.default # Provides home-manager\n    ] ++ [\n      pkgs.nixos-rebuild\n      pkgs.hostname\n    ];\n  extraBuildCommand = ''\n    cp ${nixosFlakeNuModule} nixos-unified.nu\n  '';\n}\n"
  },
  {
    "path": "activate/nu.nix",
    "content": "# Nix support for working Nushell scripts\n#\n# TODO: Migrate to this once merged,\n# https://github.com/DeterminateSystems/nuenv/pull/27\n{ pkgs, ... }:\n{\n  # Like writeShellApplication but for Nushell scripts\n  #\n  # This function likely should be improved for general use.\n  writeNushellApplication =\n    { name\n    , runtimeInputs ? [ ]\n    , scriptDir\n    , extraBuildCommand ? \"\"\n    , meta\n    }:\n    let\n      nixNuModule = pkgs.writeTextFile {\n        name = \"nix.nu\";\n        text = ''\n          use std *\n          let bins = '${builtins.toJSON (builtins.map (p: \"${p}/bin\") runtimeInputs)}' | from json\n          log debug $\"Adding runtime inputs to PATH: ($bins)\"\n          if $bins != [] {\n            path add ...$bins\n          }\n        '';\n      };\n    in\n    pkgs.runCommand name\n      {\n        inherit meta;\n      } ''\n      mkdir -p $out/bin\n      cp ${scriptDir}/*.nu $out/bin/\n      chmod -R a+w $out/bin\n      cd $out/bin\n      rm -f ${meta.mainProgram}\n      echo \"#!${pkgs.nushell}/bin/nu\" >> ${meta.mainProgram}\n      cat ${nixNuModule} >> ${meta.mainProgram}\n      cat ${scriptDir}/${meta.mainProgram} >> ${meta.mainProgram}\n      chmod a+x ${meta.mainProgram}\n      ${extraBuildCommand}\n    '';\n\n}\n"
  },
  {
    "path": "dev/flake.nix",
    "content": "{\n  inputs = {\n    nixpkgs.url = \"github:nixos/nixpkgs/nixpkgs-unstable\";\n    flake-parts.url = \"github:hercules-ci/flake-parts\";\n    flake-root.url = \"github:srid/flake-root\";\n    treefmt-nix.url = \"github:numtide/treefmt-nix\";\n    nixos-unified.url = \"github:srid/nixos-unified\";\n  };\n  outputs = inputs@{ nixpkgs, flake-parts, ... }:\n    flake-parts.lib.mkFlake { inherit inputs; } {\n      systems = nixpkgs.lib.systems.flakeExposed;\n      imports = [\n        inputs.flake-root.flakeModule\n        inputs.treefmt-nix.flakeModule\n      ];\n      perSystem = { pkgs, lib, config, ... }: {\n        treefmt.config = {\n          projectRoot = inputs.haskell-flake;\n          projectRootFile = \"README.md\";\n          programs.nixpkgs-fmt.enable = true;\n        };\n        devShells.default = pkgs.mkShell {\n          # cf. https://community.flake.parts/haskell-flake/devshell#composing-devshells\n          inputsFrom = [\n            config.treefmt.build.devShell\n          ];\n          packages = with pkgs; [\n            just\n            nixd\n          ];\n          shellHook = ''\n            echo\n            echo \"🍎🍎 Run 'just <recipe>' to get started\"\n            just\n          '';\n        };\n      };\n    };\n}\n"
  },
  {
    "path": "doc/.gitignore",
    "content": "/book\n/result\n"
  },
  {
    "path": "doc/examples.md",
    "content": "---\norder: 10\n---\n\n# Examples\n\n- <https://github.com/juspay/nixos-unified-template>\n- <https://github.com/srid/nixos-config>\n- <https://github.com/nammayatri/ci>\n"
  },
  {
    "path": "doc/flake.nix",
    "content": "{\n  inputs = {\n    emanote.url = \"github:srid/emanote\";\n    emanote.inputs.emanote-template.follows = \"\";\n    nixpkgs.follows = \"emanote/nixpkgs\";\n    flake-parts.follows = \"emanote/flake-parts\";\n  };\n\n  outputs = inputs@{ self, flake-parts, nixpkgs, ... }:\n    flake-parts.lib.mkFlake { inherit inputs; } {\n      systems = [ \"x86_64-linux\" \"aarch64-darwin\" ];\n      imports = [ inputs.emanote.flakeModule ];\n      perSystem = { self', pkgs, system, ... }: {\n        emanote = {\n          sites.\"default\" = {\n            layers = [{ path = ./.; pathString = \".\"; }];\n            extraConfig.template = {\n              baseUrl = \"/\";\n              urlStrategy = \"pretty\";\n            };\n          };\n        };\n      };\n    };\n}\n"
  },
  {
    "path": "doc/guide/activate.md",
    "content": "---\norder: 2\n---\n\n\n# Activation\n\n`nixos-unified` provides an `.#activate` flake app that can be used in place of `nixos-rebuild switch` (if using NixOS),`darwin-rebuild switch` (if using `nix-darwin`) or `home-manager switch` (if using home-manager)\n\nIn addition, it can remotely activate the system over SSH (see further below).\n\n## Activating NixOS or nix-darwin configurations {#system}\n\n\nIn order to activate a system configuration for the current host (`$HOSTNAME`), run:\n\n```sh\nnix run .#activate\n```\n\n### Passwordless local NixOS activation {#passwordless-local-nixos}\n\nBy default, local NixOS activation runs `nixos-rebuild switch --sudo`, so\n`nixos-rebuild` decides when to invoke `sudo` for privileged steps.\n\nIf you want sudoers to match a single command, configure the target host to run\n`nixos-rebuild` itself through sudo:\n\n```nix\n{\n  nixos-unified.localPrivilegeMode = \"sudo-nixos-rebuild\";\n}\n```\n\nThis makes the activator run `/run/current-system/sw/bin/nixos-rebuild` via\nsudo. Add a narrowly scoped sudoers rule for the user and command you use for\nactivation:\n\n```nix\n{\n  security.sudo.extraRules = [\n    {\n      users = [ \"myuser\" ];\n      commands = [\n        {\n          command = \"/run/current-system/sw/bin/nixos-rebuild switch *\";\n          options = [ \"NOPASSWD\" ];\n        }\n      ];\n    }\n  ];\n}\n```\n\n> [!TIP]\n> Usually, you'd make this your default package, so as to be able to use `nix run`. In `flake.nix`:\n>\n> ```nix\n> # In perSystem\n> {\n>     packages.default = self'.packages.activate\n> }\n> ```\n\n## Activating home configuration {#home}\n\nIf you are on a non-NixOS Linux (or on macOS but you do not use nix-darwin), you will have a home-manager configuration. Suppose, you have it stored in `legacyPackages.homeConfigurations.\"myuser\"` (where `myuser` matches `$USER`), you can activate that by running:\n\n```sh\nnix run .#activate $USER@\n```\n\n> [!NOTE]\n> The activate app will activate the home-manager configuration if the argument contains a `@` (separating user and the optional hostname). The above command has no hostname, indicating that we are activating for the local host.\n\n> [!NOTE]\n> The activate app will move your existing dotfiles out of the way with a timestamped backup extension. For example, your existing `~/.zshrc` will be backed up in `~/.zshrc.nixos-unified.2025-01-15-22:29:54.bak`.\n\n### Per-host home configurations {#home-perhost}\n\nYou may also have separate home configurations for each machine, such as `legacyPackages.homeConfigurations.\"myuser@myhost\"`. These can be activated using:\n\n```sh\nnix run .#activate $USER@$HOSTNAME\n```\n\nThis will activate the home-manager configuration for the specified host over SSH (see below).\n\n## Remote Activation {#remote}\n\n`nixos-unified` acts as a lightweight alternative to the various deployment tools such as `deploy-rs` and `colmena`. The `.#activate` app takes the hostname as an argument and supports remote activation for both system configurations (NixOS/nix-darwin) and home-manager configurations.\n\n### Remote System Activation {#remote-system}\n\nFor NixOS or nix-darwin configurations, set the `nixos-unified.sshTarget` option in your configuration:\n\n```nix\n{\n    nixos-unified.sshTarget = \"myuser@myhost\";\n}\n```\n\nThen, you will be able to run the following to deploy to `myhost` from any machine:\n\n```sh\nnix run .#activate myhost\n```\n\n### Remote Home-Manager Activation {#remote-home}\n\nFor home-manager configurations, remote activation works by specifying the user and hostname:\n\n```sh\nnix run .#activate myuser@myhost\n```\n\nThis will:\n1. Copy the flake and necessary inputs to the remote host via SSH\n2. Run the home-manager activation remotely on the target machine\n\n> [!NOTE]\n> Remote home-manager activation uses the `user@host` format for the SSH connection, where the user is extracted from the configuration name and the host is the target machine.\n\n### Non-goals\n\nRemote activation doesn't seek to replace other deployment tools, and as such doesn't provide features like rollbacks. It is meant for simple deployment use cases.\n\n> [!NOTE]\n> It is possible however that `nixos-unified` can grow to support more sophisticated deployment capabilities\n"
  },
  {
    "path": "doc/guide/autowiring.md",
    "content": "---\norder: 5\n---\n\n# Autowiring\n\nAn optional **autowiring** module is provided that will scan the directory structure and wire up the appropriate flake outputs automatically without you having to do it manually.\n\nA ready demonstration is available in [nixos-unified-template](https://github.com/juspay/nixos-unified-template) as well as [srid/nixos-config](https://github.com/srid/nixos-config). In the latter, you will notice the following directory structure:\n\n```\n❮ lsd --tree --depth 1 configurations modules overlays packages\n📁 configurations\n├── 📁 darwin\n├── 📁 home\n└── 📁 nixos\n📁 modules\n├── 📁 darwin\n├── 📁 flake\n├── 📁 home\n└── 📁 nixos\n📁 overlays\n└── ❄️ default.nix\n📁 packages\n├── ❄️ git-squash.nix\n├── ❄️ sshuttle-via.nix\n└── 📁 twitter-convert\n```\n\nEach of these are wired to the corresponding flake output, as indicated in the below table:\n\n| Directory                                 | Flake Output                                                |\n| ----------------------------------------- | ----------------------------------------------------------- |\n| `configurations/nixos/foo.nix`[^default]  | `nixosConfigurations.foo`                                   |\n| `configurations/darwin/foo.nix`[^default] | `darwinConfigurations.foo`                                  |\n| `configurations/home/foo.nix`[^default]   | `legacyPackages.${system}.homeConfigurations.foo`[^hm-pkgs] |\n| `modules/nixos/foo.nix`                   | `nixosModules.foo`                                          |\n| `modules/darwin/foo.nix`                  | `darwinModules.foo`                                         |\n| `modules/flake/foo.nix`                   | `flakeModules.foo`                                          |\n| `overlays/foo.nix`                        | `overlays.foo`                                              |\n| `packages/foo.nix`                        | `packages.${system}.foo`[^packages]                         |\n\n## flake-parts\n\nAutowiring is also provided if you use just flake-parts, via the `lib.mkFlake` function. In your top-level flake.nix, you only need to define your `outputs` as follows:\n\n```nix\n{\n  inputs = ...;\n  outputs = inputs:\n    inputs.nixos-unified.lib.mkFlake\n      { inherit inputs; root = ./.; };\n}\n```\n\nThis will,\n\n- Auto-import flake-parts modules under either `./nix/modules/flake` or `./modules/flake` (whichever exists)\n- Use a sensible default for `systems` which can be overriden.\n- Pass `root` as top-level module args, as a non-recursive way of referring to the path of the flake (without needing `inputs.self`).\n\nSee [srid/haskell-template's flake.nix](https://github.com/srid/haskell-template/blob/master/flake.nix) for a ready example. For another example, see [this emanote PR](https://github.com/srid/emanote/pull/558).\n\n## Package Autowiring Example\n\nThe `packages/` directory allows you to define custom packages that will be automatically wired as flake outputs. Here's an example project structure:\n\n```\n❮ lsd --tree --depth 2 packages\n📁 packages\n├── ❄️ hello-world.nix\n└── 📁 complex-app\n    └── ❄️ default.nix\n```\n\nEach package file should export a function compatible with `pkgs.callPackage`. Here are two examples:\n\n**packages/hello-world.nix** - Simple shell script package:\n```nix\n{ lib, writeShellApplication }:\n\nwriteShellApplication {\n  name = \"hello-world\";\n  text = ''\n    echo \"Hello from my autowired package!\"\n    echo \"Args: $*\"\n  '';\n  meta = {\n    description = \"A simple hello world script\";\n    license = lib.licenses.mit;\n  };\n}\n```\n\n**packages/complex-app/default.nix** - Directory-based package:\n```nix\n{ lib, stdenv, makeWrapper }:\n\nstdenv.mkDerivation {\n  pname = \"complex-app\";\n  version = \"1.0.0\";\n\n  src = ./.;\n\n  nativeBuildInputs = [ makeWrapper ];\n\n  installPhase = ''\n    mkdir -p $out/bin\n    cp app.sh $out/bin/complex-app\n    chmod +x $out/bin/complex-app\n  '';\n\n  meta = {\n    description = \"A more complex application\";\n    license = lib.licenses.gpl3;\n    platforms = lib.platforms.unix;\n  };\n}\n```\n\nAfter defining these packages, they become available in your flake outputs:\n\n```bash\n# Build and run packages\nnix build .#hello-world\nnix run .#complex-app\n\n# List all autowired packages\nnix flake show | grep packages\n```\n\nThe packages will appear as:\n- `packages.${system}.hello-world`\n- `packages.${system}.complex-app`\n\n[^default]: This path could as well be `configurations/nixos/foo/default.nix`. Likewise for other output types.\n\n[^hm-pkgs]: Why `legacyPackages`? Because, creating a home-manager configuration [requires `pkgs`](https://github.com/srid/nixos-unified/blob/47a26bc9118d17500bbe0c4adb5ebc26f776cc36/nix/modules/flake-parts/lib.nix#L97). See <https://github.com/nix-community/home-manager/issues/3075>\n\n[^packages]: Package files should export a function that can be called with `callPackage`. The autowiring system automatically calls `pkgs.callPackage` on each package file, making them available as `packages.${system}.{name}` in your flake outputs.\n"
  },
  {
    "path": "doc/guide/outputs.md",
    "content": "---\norder: 4\n---\n\n# Flake Outputs\n\nImporting the `nixos-unified` flake-parts module will autowire the following flake outputs in your flake:\n\n| Name                                   | Description                                                                                   |\n| -------------------------------------- | --------------------------------------------------------------------------------------------- |\n| **`nixos-unified.lib`**                | Functions `mkLinuxSystem`, `mkMacosSystem` and `mkHomeConfiguration`                          |\n| **`packages.update`**                  | Flake app to update key flake inputs                                                          |\n| [**`packages.activate`**](activate.md) | Flake app to build & activate the system (locally or remotely over SSH) or home configuration |\n\nIn addition, all of your NixOS/nix-darwin/home-manager modules implicitly receive the following `specialArgs`:\n\n- `flake@{self, inputs, config}` (`config` is from flake-parts)\n- `rosettaPkgs` (if on darwin)\n"
  },
  {
    "path": "doc/guide/specialArgs.md",
    "content": "---\norder: 3\n---\n\n# Module Arguments\n\nEach of your NixOS, nix-darwin and home-manager modules implicitly receive a [`specialArgs`](https://nixos.asia/en/nix-modules) called `flake`.\n\nThe components of this `flake` attrset are:\n\n| Name | Description |\n| ---- | ----------- |\n| `inputs` | The `inputs` of your flake; `inputs.self` referring to the flake itself |\n| `config` | The flake-parts perSystem `config` |\n\n[Here](https://github.com/srid/nixos-config/blob/a420e5f531172aef753b07a411de8e254207f5c6/modules/darwin/default.nix#L2-L5) is an example of how these can be used:\n\n```nix\n{ flake, pkgs, lib, ... }:\nlet\n  inherit (flake) config inputs;\n  inherit (inputs) self;\nin\n{\n  imports = [\n    # Reference a flake input directly from a nix-darwin module\n    inputs.agenix.darwinModules.default\n  ];\n\n  # Reference an arbitrary flake-parts config\n  home-manager.users.${config.me.username} = { };\n}\n```\n\nWhile the above example uses a nix-darwin module, you can do the same on NixOS or home-manager modules.\n"
  },
  {
    "path": "doc/guide/templates.md",
    "content": "---\norder: 1\n---\n\n# Flake Templates\n\nWe provide four templates, depending on your needs:\n\n## Available templates\n\nYou can easily initialize one of our templates using [Omnix](https://omnix.page/om/init.html)[^no-omnix]:\n\n[^no-omnix]: If you do not use Omnix, you must use `nix flake init`, and manually change the template values such as username and hostname.\n\n### NixOS only {#nixos}\n\nNixOS configuration only, with [home-manager]\n\n```sh\nnix --accept-flake-config run github:juspay/omnix -- \\\n  init -o ~/nix-config github:srid/nixos-unified#linux\n```\n\n### macOS only {#macos}\n\n[nix-darwin] configuration only, with [home-manager]\n\n```sh\nnix --accept-flake-config run github:juspay/omnix -- \\\n  init -o ~/nix-config github:srid/nixos-unified#macos\n```\n\n### Home only {#home}\n\n[home-manager] configuration only (useful if you use other Linux distros or do not have admin access to the machine)\n\n```bash\nnix --accept-flake-config run github:juspay/omnix -- \\\n  init -o ~/nix-config github:srid/nixos-unified#home\n```\n\n## After initializing the template\n\nRun `nix run .#activate` (`nix run .#activate $USER@` if you are using the last template, \"Home only\") to activate the configuration.\n\n- on macOS, if you get an error about `/etc/nix/nix.conf`, run:\n  ```sh\n  sudo mv /etc/nix/nix.conf /etc/nix/nix.conf.before-nix-darwin\n  nix --extra-experimental-features \"nix-command flakes\" run .#activate\n  ```\n- on macOS, if you had used Determinate Systems nix-installer, you may want to [uninstall that Nix](https://github.com/LnL7/nix-darwin/issues/931#issuecomment-2075596824), such that we use the one provided by nix-darwin,\n  ```sh\n  sudo -i nix-env --uninstall nix\n  ```\n\n[^intel]: If you are on an Intel Mac, also change `nixpkgs.hostPlatform` accordingly.\n\n[home-manager]: https://github.com/nix-community/home-manager\n\n[nix-darwin]: https://github.com/LnL7/nix-darwin\n"
  },
  {
    "path": "doc/guide.md",
    "content": "\n# Guide\n\n- [[templates]]#\n- [[activate]]#\n- [[specialArgs]]#\n- [[outputs]]#\n- [[autowiring]]#"
  },
  {
    "path": "doc/history.md",
    "content": "---\norder: 100\n---\n\n# Release history\n\n## Unreleased\n\n- autoWiring of flake outputs & `mkFlake`\n- activate script\n  - add `--dry-run` (#104)\n  - Remote activation support for home-manager configurations (#143)\n- home-manager\n  - More unique backup filenames (#97)\n  - Add a default `home.homeDirectory` based on the user's username (#117)\n- Remove use of deprecated alias `--update-input` of `nix flake update`\n- Use `sudo` when activating with nix-darwin (#130)\n- Add an opt-in local NixOS activation mode that runs `nixos-rebuild` itself through `sudo`\n- Fix `nix copy` command for legacy NixOS systems by adding experimental features flag (#138)\n- Switch to runCommand since runCommandNoCC is dropped in newer nixpkgs (#147)\n\n## 0.2.0 (2024-10-03)\n\nInitial release, branched from `nixos-flake`\n"
  },
  {
    "path": "doc/howto.md",
    "content": "# HOWTO\n\n## Creating shared configuration {#config}\n\nYou may want to share certain configuration (such as username or email) across multiple modules. Here is how you can do it:\n\n1. Create a flake-parts module to hold the config schema. For example, [`config-module.nix`](https://github.com/juspay/nixos-unified-template/blob/9eeeb6c1ab4287ac0a37a22e72f053a3de82ddbc/modules/flake/config-module.nix)\n1. Define your configuration in your config file. For example, [`config.nix`](https://github.com/juspay/nixos-unified-template/blob/9eeeb6c1ab4287ac0a37a22e72f053a3de82ddbc/modules/flake/config.nix).\n1. Use your configuration from any of NixOS/ nix-darwin/ home-manager modules through `flake` [[specialArgs|specialArgs]], specifically `flake.config`. For example, see [here](https://github.com/juspay/nixos-unified-template/blob/9eeeb6c1ab4287ac0a37a22e72f053a3de82ddbc/modules/home/git.nix#L3)."
  },
  {
    "path": "doc/index.md",
    "content": "---\nshort-title: nixos-unified\ntemplate:\n  sidebar:\n    collapsed: true\nemanote:\n  folder-folgezettel: false\n---\n\n# nixos-unified\n\n[**nixos-unified**](https://github.com/srid/nixos-unified) is a [flake-parts](https://flake.parts/) module to unify [NixOS] + [nix-darwin] + [home-manager] configuration in a single flake, while providing a consistent interface at DX and UX level.\n\n[NixOS]: https://nixos.org/\n[nix-darwin]: https://github.com/LnL7/nix-darwin\n[home-manager]: https://github.com/nix-community/home-manager\n\n## Why?\n\nnixos-unified provides the following features:\n\n- **One-click activation & deployment**\n  - [[activate]]: An `.#activate` flake app that works uniformly on [NixOS], [nix-darwin] and [home-manager].\n    - [[activate#remote|Remote Activation]]: `.#activate` can also *remotely* activate machines (be it macOS or NixOS) over SSH, thus acting as a simple alternative to deployment tools like `deploy-rs` and `colmena`.\n  - Also: an `.#update` flake app to update the primary inputs (which can be overriden)\n- **Seamless access to top-level flake**\n  - All [NixOS]/ [nix-darwin]/ [home-manager] modules receive [[specialArgs|specialArgs]] which includes all the information in the top-level flake.\n    - This enables those modules to be aware of the flake inputs, for instance.\n- **Sensible defaults**\n  - Sensible defaults for [home-manager]/ [nix-darwin]/ and [NixOS] configurations ([\\#75](https://github.com/srid/nixos-unified/pull/75)).\n- **Autowiring** of flake outputs\n  - [[autowiring]]: An optional module that will scan the directory structure and wire up the appropriate flake outputs automatically without you having to do it manually.\n\n## Getting Started\n\nSee: [[start]].\n"
  },
  {
    "path": "doc/index.yaml",
    "content": "# Emanote configuration for nixos-unified documentation\n# Ref: https://github.com/srid/emanote/blob/master/emanote/default/index.yaml\n\ntemplate:\n  editBaseUrl: https://github.com/srid/nixos-unified/edit/master/doc\n  # List of available colors: https://tailwindcss.com/docs/customizing-colors#default-color-palette\n  theme: lime\n  sidebar:\n    collapsed: false\n  urlStrategy: pretty\n\npage:\n  siteTitle: \"nixos-unified\"\n  siteUrl: https://nixos-unified.org\n"
  },
  {
    "path": "doc/mod.just",
    "content": "default:\n  @just --list doc\n\n# Run mdbook live server\nrun:\n  nix run\n\n# Build the static site\nbuild:\n  nix build\n"
  },
  {
    "path": "doc/start.md",
    "content": "---\norder: -100\n---\n\n# Getting Started\n\nPick your desired operating system and follow the below instructions.\n\n> [!TIP]\n> Checkout [nixos-unified-template](https://github.com/juspay/nixos-unified-template) for the quickest way to get started.\n\n## NixOS\n\n1. [Install NixOS w/ Flakes enabled](https://nixos.asia/en/nixos-tutorial)\n1. Convert your `flake.nix` to using `nixos-unified` using the [NixOS only template](guide/templates.md) as reference.\n\n## non-NixOS Linux\n\nIf you use other Linux distros like Ubuntu, you may use just `home-manager`.\n\n1. [Install Nix](https://nixos.asia/en/install)\n1. Use the [HOME only template](guide/templates.md)\n\n## macOS\n\n1. [Install Nix](https://nixos.asia/en/install)\n1. Use the [macOS only template](guide/templates.md)\n"
  },
  {
    "path": "examples/home/flake.nix",
    "content": "{\n  inputs = {\n    # Principle inputs (updated by `nix run .#update`)\n    nixpkgs.url = \"github:nixos/nixpkgs/nixos-unstable\";\n    home-manager.url = \"github:nix-community/home-manager\";\n    home-manager.inputs.nixpkgs.follows = \"nixpkgs\";\n\n    flake-parts.url = \"github:hercules-ci/flake-parts\";\n    nixos-unified.url = \"github:srid/nixos-unified\";\n  };\n\n  outputs = inputs@{ self, ... }:\n    inputs.flake-parts.lib.mkFlake { inherit inputs; } {\n      systems = [ \"x86_64-linux\" \"aarch64-linux\" \"aarch64-darwin\" \"x86_64-darwin\" ];\n      imports = [\n        inputs.nixos-unified.flakeModules.default\n      ];\n\n      perSystem = { pkgs, ... }:\n        let\n          myUserName = \"john\";\n        in\n        {\n          legacyPackages.homeConfigurations.${myUserName} =\n            self.nixos-unified.lib.mkHomeConfiguration\n              pkgs\n              ({ pkgs, ... }: {\n                imports = [ self.homeModules.default ];\n                home.username = myUserName;\n                home.stateVersion = \"24.11\";\n              });\n        };\n\n      flake = {\n        # All home-manager configurations are kept here.\n        homeModules.default = { pkgs, ... }: {\n          imports = [ ];\n          programs = {\n            git.enable = true;\n            starship.enable = true;\n            bash.enable = true;\n          };\n        };\n      };\n    };\n}\n"
  },
  {
    "path": "examples/linux/flake.nix",
    "content": "{\n  inputs = {\n    # Principle inputs (updated by `nix run .#update`)\n    nixpkgs.url = \"github:nixos/nixpkgs/nixos-unstable\";\n    home-manager.url = \"github:nix-community/home-manager\";\n    home-manager.inputs.nixpkgs.follows = \"nixpkgs\";\n\n    flake-parts.url = \"github:hercules-ci/flake-parts\";\n    nixos-unified.url = \"github:srid/nixos-unified\";\n  };\n\n  outputs = inputs@{ self, ... }:\n    inputs.flake-parts.lib.mkFlake { inherit inputs; } {\n      systems = [ \"x86_64-linux\" \"aarch64-linux\" ];\n      imports = [ inputs.nixos-unified.flakeModules.default ];\n\n      flake =\n        let\n          myUserName = \"john\";\n        in\n        {\n          # Configurations for Linux (NixOS) machines\n          nixosConfigurations.\"example1\" =\n            self.nixos-unified.lib.mkLinuxSystem\n              { home-manager = true; }\n              {\n                nixpkgs.hostPlatform = \"x86_64-linux\";\n                imports = [\n                  # Your machine's configuration.nix goes here\n                  ({ pkgs, ... }: {\n                    # TODO: Put your /etc/nixos/hardware-configuration.nix here\n                    boot.loader.grub.device = \"nodev\";\n                    fileSystems.\"/\" = { device = \"/dev/disk/by-label/nixos\"; fsType = \"btrfs\"; };\n                    users.users.${myUserName}.isNormalUser = true;\n                    system.stateVersion = \"23.05\";\n                  })\n                  # Setup home-manager in NixOS config\n                  {\n                    home-manager.users.${myUserName} = {\n                      imports = [ self.homeModules.default ];\n                      home.stateVersion = \"24.11\";\n                    };\n                  }\n                ];\n              };\n\n          # home-manager configuration goes here.\n          homeModules.default = { pkgs, ... }: {\n            imports = [ ];\n            programs.git.enable = true;\n            programs.starship.enable = true;\n            programs.bash.enable = true;\n          };\n        };\n    };\n}\n"
  },
  {
    "path": "examples/macos/flake.nix",
    "content": "{\n  inputs = {\n    # Principle inputs (updated by `nix run .#update`)\n    nixpkgs.url = \"github:nixos/nixpkgs/nixos-unstable\";\n    nix-darwin.url = \"github:lnl7/nix-darwin/master\";\n    nix-darwin.inputs.nixpkgs.follows = \"nixpkgs\";\n    home-manager.url = \"github:nix-community/home-manager\";\n    home-manager.inputs.nixpkgs.follows = \"nixpkgs\";\n\n    flake-parts.url = \"github:hercules-ci/flake-parts\";\n    nixos-unified.url = \"github:srid/nixos-unified\";\n  };\n\n  outputs = inputs@{ self, ... }:\n    inputs.flake-parts.lib.mkFlake { inherit inputs; } {\n      systems = [ \"aarch64-darwin\" \"x86_64-darwin\" ];\n      imports = [ inputs.nixos-unified.flakeModules.default ];\n\n      flake =\n        let\n          myUserName = \"john\";\n        in\n        {\n          # Configurations for macOS machines\n          darwinConfigurations.\"example1\" =\n            self.nixos-unified.lib.mkMacosSystem\n              { home-manager = true; }\n              {\n                nixpkgs.hostPlatform = \"aarch64-darwin\";\n                imports = [\n                  # Your nix-darwin configuration goes here\n                  ({ pkgs, ... }: {\n                    # https://github.com/nix-community/home-manager/issues/4026#issuecomment-1565487545\n                    users.users.${myUserName}.home = \"/Users/${myUserName}\";\n\n                    security.pam.services.sudo_local.touchIdAuth = true;\n\n                    # Used for backwards compatibility, please read the changelog before changing.\n                    # $ darwin-rebuild changelog\n                    system.stateVersion = 6;\n                  })\n                  # Setup home-manager in nix-darwin config\n                  {\n                    home-manager.users.${myUserName} = {\n                      imports = [ self.homeModules.default ];\n                      home.stateVersion = \"24.11\";\n                    };\n                  }\n                ];\n              };\n\n          # home-manager configuration goes here.\n          homeModules.default = { pkgs, ... }: {\n            imports = [ ];\n            programs.git.enable = true;\n            programs.starship.enable = true;\n            programs.zsh.enable = true;\n          };\n        };\n    };\n}\n"
  },
  {
    "path": "flake.nix",
    "content": "{\n  outputs = _: rec {\n    flakeModules = {\n      default = ./nix/modules/flake-parts;\n      autoWire = ./nix/modules/flake-parts/autowire.nix;\n    };\n    # For backwards compat only\n    flakeModule = flakeModules.default;\n\n    # Like flake-parts mkFlake, but auto-imports modules/flake-parts, consistent with autowiring feature.\n    #\n    # Looks under either nix/modules/flake-parts or modules/flake-parts for modules to import. `systems` is set to a default value. `root` is passed as top-level module args (as distinct from `inputs.self` the use of which can lead to infinite recursion).\n    lib.mkFlake =\n      { inputs\n      , root\n      , systems ? [ \"x86_64-linux\" \"x86_64-darwin\" \"aarch64-linux\" \"aarch64-darwin\" ]\n      , specialArgs ? { }\n      }:\n      inputs.flake-parts.lib.mkFlake { inherit inputs specialArgs; } {\n        inherit systems;\n        _module.args = { inherit root; };\n        imports =\n          let\n            # Patterns to search in order\n            candidates = [\n              # These correspond to `flakeModules.*`\n              \"nix/modules/flake\"\n              \"modules/flake\"\n              # Just for backwards compatbility\n              \"nix/modules/flake-parts\"\n              \"modules/flake-parts\"\n            ];\n            getModulesUnderFirst = cs: with builtins;\n              if cs == [ ] then throw \"None of these paths exist: ${toString candidates}\"\n              else if pathExists \"${root}/${head cs}\"\n              then\n                map (fn: \"${root}/${head cs}/${fn}\") (attrNames (readDir (root + /${head cs})))\n              else getModulesUnderFirst (tail cs);\n          in\n          getModulesUnderFirst candidates;\n      };\n\n    templates =\n      let\n        tmplPath = path: builtins.path { inherit path; filter = path: _: baseNameOf path != \"test.sh\"; };\n      in\n      {\n        linux = {\n          description = \"nixos-unified template for NixOS configuration.nix\";\n          path = tmplPath ./examples/linux;\n        };\n        macos = {\n          description = \"nixos-unified template for nix-darwin configuration\";\n          path = tmplPath ./examples/macos;\n        };\n        home = {\n          description = \"nixos-unified template for home-manager configuration\";\n          path = tmplPath ./examples/home;\n        };\n      };\n\n    om = {\n      templates = rec {\n        home = {\n          template = templates.home;\n          params = [\n            {\n              name = \"username\";\n              description = \"The $USER to apply home-manager configuration on\";\n              placeholder = \"john\";\n            }\n          ];\n        };\n\n        macos = {\n          template = templates.macos;\n          params = home.params ++ [\n            {\n              name = \"hostname\";\n              description = \"Hostname of the machine\";\n              placeholder = \"example1\";\n            }\n          ];\n        };\n\n        linux = {\n          template = templates.linux;\n          inherit (macos) params;\n        };\n      };\n    };\n  };\n}\n"
  },
  {
    "path": "justfile",
    "content": "# Documentation targets\nmod doc\n\ndefault:\n    @just --list\n\n# Run CI locally\nci:\n    om ci --extra-access-tokens \"github.com=$(gh auth token)\"\n\n# Auto-format the Nix files in project tree\nfmt:\n    treefmt\n"
  },
  {
    "path": "nix/modules/configurations/default.nix",
    "content": "# A NixOS/nix-darwin module to specify nixos-unified metadata for configurations.\n#\n# FIXME: Using this module in home-manager leads to `error: infinite recursion\n# encountered` on `id = x: x`\n{ flake, config, lib, ... }:\nlet\n  inherit (flake) inputs;\nin\n{\n  options = {\n    nixos-unified = {\n      sshTarget = lib.mkOption {\n        type = lib.types.nullOr lib.types.str;\n        default = null;\n        description = ''\n          SSH target for this system configuration.\n        '';\n      };\n      overrideInputs = lib.mkOption {\n        type = lib.types.listOf lib.types.str;\n        default = [ ];\n        description = ''\n          List of flake inputs to override when deploying or activating.\n        '';\n      };\n      localPrivilegeMode = lib.mkOption {\n        type = lib.types.enum [ \"nixos-rebuild-sudo\" \"sudo-nixos-rebuild\" ];\n        default = \"nixos-rebuild-sudo\";\n        description = ''\n          How local NixOS activation obtains root privileges.\n\n          `nixos-rebuild-sudo` runs `nixos-rebuild` as the calling user with\n          `--sudo`, letting nixos-rebuild invoke sudo for privileged steps.\n\n          `sudo-nixos-rebuild` runs `nixos-rebuild` itself via sudo. This is\n          useful when sudoers should allow passwordless activation by matching a\n          single `nixos-rebuild` command.\n        '';\n      };\n      outputs = {\n        system = lib.mkOption {\n          type = lib.types.str;\n          readOnly = true;\n          default = config.nixpkgs.hostPlatform.system;\n          description = ''\n            System to activate.\n          '';\n        };\n        overrideInputs = lib.mkOption {\n          type = lib.types.attrsOf lib.types.path;\n          readOnly = true;\n          default = lib.foldl' (acc: x: acc // { \"${x}\" = inputs.${x}; }) { } config.nixos-unified.overrideInputs;\n        };\n        nixArgs = lib.mkOption {\n          type = lib.types.listOf lib.types.str;\n          readOnly = true;\n          default = (builtins.concatMap\n            (name: [\n              \"--override-input\"\n              \"${name}\"\n              \"${inputs.${name}}\"\n            ])\n            # TODO: Use `outputs.overrideInputs` instead.\n            config.nixos-unified.overrideInputs);\n          description = ''\n            Arguments to pass to `nix`\n          '';\n        };\n      };\n    };\n  };\n}\n"
  },
  {
    "path": "nix/modules/flake-parts/autowire.nix",
    "content": "{ self, lib, ... }:\n{\n  config =\n    let\n      # Combine mapAttrs' and filterAttrs\n      #\n      # f can return null if the attribute should be filtered out.\n      mapAttrsMaybe = f: attrs:\n        lib.pipe attrs [\n          (lib.mapAttrsToList f)\n          (builtins.filter (x: x != null))\n          builtins.listToAttrs\n        ];\n      forAllNixFiles = dir: f:\n        if builtins.pathExists dir then\n          lib.pipe dir [\n            builtins.readDir\n            (mapAttrsMaybe (fn: type:\n              if type == \"regular\" then\n                let name = lib.removeSuffix \".nix\" fn; in\n                if name != fn then\n                  lib.nameValuePair name (f \"${dir}/${fn}\")\n                else\n                  null\n              else if type == \"directory\" && builtins.pathExists \"${dir}/${fn}/default.nix\" then\n                lib.nameValuePair fn (f \"${dir}/${fn}\")\n              else\n                null\n            ))\n          ] else { };\n    in\n    {\n      flake = {\n        darwinConfigurations =\n          forAllNixFiles \"${self}/configurations/darwin\"\n            (fn: self.nixos-unified.lib.mkMacosSystem { home-manager = true; } fn);\n\n        nixosConfigurations =\n          forAllNixFiles \"${self}/configurations/nixos\"\n            (fn: self.nixos-unified.lib.mkLinuxSystem { home-manager = true; } fn);\n\n        darwinModules =\n          forAllNixFiles \"${self}/modules/darwin\"\n            (fn: fn);\n\n        nixosModules =\n          forAllNixFiles \"${self}/modules/nixos\"\n            (fn: fn);\n\n        homeModules =\n          forAllNixFiles \"${self}/modules/home\"\n            (fn: fn);\n\n        overlays =\n          forAllNixFiles \"${self}/overlays\"\n            (fn: import fn self.nixos-unified.lib.specialArgsFor.common);\n      };\n\n      perSystem = { pkgs, ... }: {\n        legacyPackages.homeConfigurations =\n          forAllNixFiles \"${self}/configurations/home\"\n            (fn: self.nixos-unified.lib.mkHomeConfiguration pkgs fn);\n\n        packages =\n          forAllNixFiles \"${self}/packages\"\n            (fn: pkgs.callPackage fn { });\n      };\n    };\n}\n"
  },
  {
    "path": "nix/modules/flake-parts/default.nix",
    "content": "{\n  imports = [\n    ./packages.nix\n    ./lib.nix\n  ];\n}\n"
  },
  {
    "path": "nix/modules/flake-parts/lib.nix",
    "content": "{ self, inputs, config, lib, ... }:\nlet\n  specialArgsFor = rec {\n    common = {\n      flake = { inherit self inputs config; };\n    };\n    nixos = common;\n    darwin = common // {\n      rosettaPkgs = import inputs.nixpkgs { system = \"x86_64-darwin\"; };\n    };\n  };\n\n  nixosModules = {\n    # Linux home-manager module\n    home-manager = {\n      imports = [\n        inputs.home-manager.nixosModules.home-manager\n        {\n          home-manager.useGlobalPkgs = true;\n          home-manager.useUserPackages = true;\n          home-manager.extraSpecialArgs = specialArgsFor.nixos;\n          home-manager.sharedModules = [ homeModules.common ];\n        }\n      ];\n    };\n\n    # Common and useful setting across all platforms\n    common = { lib, ... }: {\n      nix = {\n        settings = {\n          # Use all CPU cores\n          max-jobs = lib.mkDefault \"auto\";\n          # Duh\n          experimental-features = lib.mkDefault \"nix-command flakes\";\n        };\n      };\n    };\n  };\n\n  homeModules = {\n    common = { config, pkgs, ... }: {\n      # Sensible default for `home.homeDirectory`\n      home.homeDirectory = lib.mkDefault \"/${if pkgs.stdenv.isDarwin then \"Users\" else \"home\"}/${config.home.username}\";\n\n      # For macOS, $PATH must contain these.\n      home.sessionPath = lib.mkIf pkgs.stdenv.isDarwin [\n        \"/etc/profiles/per-user/$USER/bin\" # To access home-manager binaries\n        \"/nix/var/nix/profiles/system/sw/bin\" # To access nix-darwin binaries\n        \"/usr/local/bin\" # Some macOS GUI programs install here\n      ];\n    };\n  };\n\n  darwinModules = {\n    # macOS home-manager module\n    home-manager = {\n      imports = [\n        inputs.home-manager.darwinModules.home-manager\n        {\n          home-manager.useGlobalPkgs = true;\n          home-manager.useUserPackages = true;\n          home-manager.extraSpecialArgs = specialArgsFor.darwin;\n          home-manager.sharedModules = [ homeModules.common ];\n        }\n      ];\n    };\n  };\nin\n{\n  config = {\n    flake = {\n      nixos-unified.lib = {\n        inherit specialArgsFor;\n\n        mkLinuxSystem = { home-manager ? false }: mod: inputs.nixpkgs.lib.nixosSystem {\n          # Arguments to pass to all modules.\n          specialArgs = specialArgsFor.nixos;\n          modules = [\n            ../configurations\n            nixosModules.common\n            mod\n          ] ++ lib.optional home-manager nixosModules.home-manager;\n        };\n\n        mkMacosSystem = { home-manager ? false }: mod: inputs.nix-darwin.lib.darwinSystem {\n          specialArgs = specialArgsFor.darwin;\n          modules = [\n            ../configurations\n            nixosModules.common\n            mod\n          ] ++ lib.optional home-manager darwinModules.home-manager;\n        };\n\n        mkHomeConfiguration = pkgs: mod: inputs.home-manager.lib.homeManagerConfiguration {\n          inherit pkgs; # cf. https://github.com/nix-community/home-manager/issues/3075\n          extraSpecialArgs = specialArgsFor.common;\n          modules = [\n            homeModules.common\n            mod\n          ];\n        };\n      };\n    };\n  };\n}\n"
  },
  {
    "path": "nix/modules/flake-parts/packages.nix",
    "content": "{ self, flake-parts-lib, lib, ... }:\nlet\n  inherit (flake-parts-lib)\n    mkPerSystemOption;\n  inherit (lib)\n    types;\nin\n{\n  options.perSystem = mkPerSystemOption ({ config, inputs', pkgs, system, ... }: {\n    options.nixos-unified = lib.mkOption {\n      default = { };\n      type = types.submodule {\n        options = {\n          primary-inputs = lib.mkOption {\n            type = types.listOf types.str;\n            default = [ \"nixpkgs\" \"home-manager\" \"nix-darwin\" ];\n            description = ''\n              List of flake inputs to update when running `nix run .#update`.\n            '';\n          };\n        };\n      };\n    };\n    config.packages = lib.filterAttrs (_: v: v != null) {\n      update =\n        let\n          inputs = config.nixos-unified.primary-inputs;\n        in\n        pkgs.writeShellApplication {\n          name = \"update-main-flake-inputs\";\n          meta.description = \"Update the primary flake inputs\";\n          text = ''\n            nix flake update${lib.foldl' (acc: x: acc + \" \" + x) \"\" inputs}\n          '';\n        };\n\n      # Activate the given (system or home) configuration\n      activate = import ../../../activate { inherit self inputs' pkgs lib system; };\n    };\n  });\n}\n"
  },
  {
    "path": "vira.hs",
    "content": "-- CI configuration <https://vira.nixos.asia/>\n\\ctx pipeline ->\n  let\n    isMaster = ctx.branch == \"master\"\n    nu = [(\"nixos-unified\", \".\")]\n  in pipeline\n     { build.systems =\n        [ \"x86_64-linux\"\n        , \"aarch64-darwin\"\n        ]\n     , build.flakes =\n         [ \"./doc\" { overrideInputs = nu }\n         , \"./examples/macos\" { overrideInputs = nu }\n         , \"./examples/home\" { overrideInputs = nu }\n         , \"./examples/linux\" { overrideInputs = nu }\n         ]\n     , signoff.enable = True\n     , cache.url = if isMaster then Just \"https://cache.nixos.asia/oss\" else Nothing\n     }\n"
  }
]