`--arg/--argstr` and home-manager without flakes

Hi all, I’m trying to run a standalone home manager (without flakes) and am trying to pass in arguments from home-manager switch. I’m doing this by naming them in the top-level attribute set (e.g. { config, pkgs, lib, userName, ...}, using them like home.username = userName;, and passing them like home-manager switch -f ~/home.nix --argstr userName "$USER". When I do this, I get an error like error: attribute 'userName' missing. What am I doing wrong?

You need extraSpecialArgs. i.e.

home-manager switch --arg extraSpecialArgs '{ userName = "poopypants" }'

This seems entirely reasonable, but it’s not working and I’m getting similar errors.

My invocation:

home-manager switch -f ~/home.nix --arg extraSpecialArgs '{ userName = "'"$USER"'"; homeDirectory = "'"$HOME"'"; isContainer = true; }'

The top of my file:

{ config, pkgs, lib, userName , homeDirectory , isContainer ? false, ... }:

{



  home.username = userName;
  home.homeDirectory = homeDirectory;
  ...
}

and the errors:

57.92 error:
57.92        … while evaluating the attribute 'activationPackage'
57.92          at /nix/store/87makzcfs5qcjr08hgjq2bwp5kk4q9sz-home-manager-25.05.tar.gz/home-manager/modules/default.nix:62:7:
57.92            61|
57.92            62|       activationPackage = module.config.home.activationPackage;
57.92              |       ^
57.92            63|
57.92 
57.92        … while evaluating a branch condition
57.92          at /nix/store/p2i18gpldgzjq0vkdgb2r5qnsd5z2fcf-nixpkgs/nixpkgs/lib/lists.nix:142:18:
57.92           141|       len = length list;
57.92           142|       fold' = n: if n == len then nul else op (elemAt list n) (fold' (n + 1));
57.92              |                  ^
57.92           143|     in
57.9
[2025-06-07T18:46:48.411Z] 2 
57.92        … while evaluating the option `assertions':
57.92 
57.92        … while evaluating definitions from `/nix/store/87makzcfs5qcjr08hgjq2bwp5kk4q9sz-home-manager-25.05.tar.gz/home-manager/modules/systemd.nix':
57.92 
57.92        … while evaluating the option `home.username':
57.92 
57.92        … while evaluating definitions from `/home/vscode/home.nix':
57.92 
57.92        … while evaluating the module argument `userName' in "/home/vscode/home.nix":
57.92 
57.92        (stack trace truncated; use '--show-trace' to show the full, detailed trace)
57.92 
57.92        error: attribute 'userName' missing
57.92        at /nix/store/p2i18gpldgzjq0vkdgb2r5qnsd5z2fcf-nixpkgs/nixpkgs/lib/modules.nix:652:66:
57.92           651|       extraArgs = mapAttrs (
57.92           652|         name: _: addErrorContext (context name) (args.${name} or config._module.args.${name})
57.92              |                                                                  ^
57.92           653|  
[2025-06-07T18:46:48.412Z]      ) (functionArgs f);

I have to apologise I was running from memory. I don’t actual think this is possible because reading the help implies the arguments are actually being passed to home-manager.nix which doesn’t expose extraSpecialArgs afaict. If you are willing to enable the nix command cli and use nh then it is possible to do this. Pulled from my shell history (rather than my memory):

nh home switch -f '<home-manager/modules>' -- --arg configuration ~/.config/home-manager/home.nix --arg pkgs 'import <nixpkgs> {}' --arg extraSpecialArgs '{ hostname = "lamorna"; }'

If you do go that route you’ll also need to watch out for this if you are running unstable: Regression 4.0.3 -> 4.1.0 Flakes required when not using flakes · Issue #305 · nix-community/nh · GitHub

I really do love nh though, so consider it! You get nom hooked up for free!

EDIT: looking at home-manager.nix more carefully it might be that confAttr does the business for you in a round-about way, as it seems like it allows you to pick an attribute off an attribute set as your specific configuration, which would allow per-host customisation. It obviously doesn’t push args into modules BUT you could achieve that by using _modules.args if you wanted to go that route.

This seems like it might be the right move, thank you! If I were to try to figure out what on earth flakes are and how to use them, would there be any built-in way to pass in arguments from the command line?

I know this kinda flies in the face of the whole nix philosophy of course-- just to give you some idea of my broader purpose, I’m trying to create a home manager configuration to use across all my computers and containers to have some shell and editor configuration and some command line utilities installed without getting in the way of whatever development environment I’m putting it on top of. For the record, I am prepared to deal with the inevitable dynamic linking issues! I want to be able to pass in some flags when building/switching to determine what parts of the config are enabled. If there’s a simpler way to do this I’d appreciate the knowledge!

flakes don’t take input arguments. Instead flakes have multiple outputs and you choose which output you build on the flake cli. Effectively it would look a lot like the --arg confAttr way of doing things.