Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Release 26.11

This is the current unstable branch and the information in this section is therefore not final.

Highlights

This release has the following notable changes:

  • fzf shell integrations now source packaged scripts instead of running fzf to generate them. Custom programs.fzf.package values must include the integration scripts under share/fzf for the enabled shells. Wrappers must preserve that directory alongside the executable, or use the default package, which already includes these files.

  • The programs.uv module can now install uv-managed Python versions and tools through the new programs.uv.python.versions, programs.uv.python.default, and programs.uv.tool.packages options. Unpinned entries track the latest release on each activation while pinned ones stay put, and programs.uv.python.prune / programs.uv.tool.prune make the managed set fully declarative by removing versions and tools that are no longer listed.

  • On Darwin, Home Manager launchd agents now support launchd.agents.name.domain to choose either the user’s GUI or background launchd domain. Agents use the GUI domain by default. Set the domain to user for agents that should run without an active graphical login session.

  • The services.voxtype.enable daemon now starts as part of graphical-session.target instead of default.target. Starting after the compositor owns its GPU render node lets Vulkan-accelerated whisper builds detect their device. Previously, a daemon that started before the render node existed fell back to CPU and never recovered until it was restarted manually.

  • XSuspender now uses services.xsuspender.settings for freeform INI configuration. Move services.xsuspender.defaults to services.xsuspender.settings.Default and services.xsuspender.rules to services.xsuspender.settings.<name>. Use snake_case keys such as suspend_delay instead of suspendDelay.

    Deprecated aliases warn and preserve old defaults, including legacy function reads, in legacy sections and Default. These defaults have option-default priority, so ordinary assignments override them. Settings-only sections inherit from Default at runtime, then use native defaults. To preserve old behavior, set suspend_delay to 5 and only_on_battery to false, rather than 10 and true.

    Without legacy options, empty settings leave the configuration file unmanaged. If you configured both services.xsuspender.defaults and services.xsuspender.rules.Default, consolidate them under services.xsuspender.settings.Default. They now merge instead of the rule replacing the entire defaults section.

  • Notmuch now uses programs.notmuch.settings for native INI configuration. Deprecated options warn and map to settings, for example search.excludeTags to settings.search.exclude_tags. Home Manager no longer writes values notmuch already defaults to (new.tags, new.ignore, maildir.synchronize_flags); new.ignore order may differ.

    programs.notmuch.extraConfig no longer overwrites other definitions. Definitions follow module priorities: forced values win, lists concatenate, and ordinary scalar or string/list collisions fail. Use a list for extraConfig.new.ignore when mbsync, lieer, or mujmap contributes patterns. lib.mkForce on extraConfig replaces definitions in named sections. Section-level lib.mkDefault loses to sections Home Manager or sync modules define: database, new, search, and user. Null settings are omitted.

  • TWMN now uses services.twmn.settings for freeform INI configuration. Legacy options emit migration warnings. Move native options and extraConfig values into settings, resolving duplicate definitions. Enabling the service without configuration no longer creates a config file. Settings-only configurations use TWMN’s native defaults; see the option documentation for compatibility limits and preserving previous defaults.

  • Move programs.openstackclient.clouds to programs.openstackclient.cloudsSettings.clouds, and move programs.openstackclient.publicClouds to programs.openstackclient.cloudsPublicSettings.public-clouds. The old options remain as deprecated aliases and emit warnings.

  • Astroid now uses programs.astroid.settings for JSON configuration. Move programs.astroid.extraConfig into settings; replace externalEditor = "command" with settings.editor.cmd = "command" and settings.editor.external_editor = "true". Both old options warn; per-account astroid.extraConfig is unchanged. Home Manager no longer writes a full default configuration; Astroid’s built-in defaults match it except editor.markdown_processor, now cmark. Set settings.editor.markdown_processor = "marked" to keep marked. Without astroid accounts or settings, no config file is written.

    externalEditor merges at ordinary priority: differing ordinary editor keys conflict; lib.mkForce wins. Priorities on extraConfig sections apply as a unit. lib.mkForce on such a section drops its generated keys; lib.mkDefault loses for sections Home Manager defines. Prefer per-key priorities. Replacing a generated section with a non-object value requires lib.mkForce.

  • Grobi now uses services.grobi.settings for its complete JSON configuration. Move services.grobi.executeAfter to services.grobi.settings.execute_after and services.grobi.rules to services.grobi.settings.rules. The deprecated aliases preserve list order and definition priorities. The generated JSON is now pretty-printed.

  • Borgmatic backups now use programs.borgmatic.backups.name.settings for native YAML settings. Deprecated options warn with the backup name and move to their snake_case keys, such as retention.keepDaily to settings.keep_daily. Repository strings become { path = "..."; }, and each section’s extraConfig moves directly into settings. location.excludeHomeManagerSymlinks remains available.

    Legacy configurations without overlapping keys keep their generated YAML, except that null check frequencies are now omitted. Overlapping extraConfig keys no longer take the last section’s value. Distinct scalars at the same priority conflict and lists concatenate, so resolve overlaps in settings. Backups no longer need exactly one of sourceDirectories and patterns, which allows native patterns and database-only backups. repositories is still required.

  • programs.github-copilot-cli.settings is now written to settings.json instead of config.json, since Copilot CLI 1.0.35 and later keep user settings there and replace a linked config.json. The old link is removed on activation if it still points to a Home Manager generation; a regular state file is left alone. If Copilot CLI already created a regular settings.json from the old config.json, remove it before switching or enable programs.github-copilot-cli.mutableSettings to merge into it. With nonempty immutable settings, byte-identical files become managed links; differing files use normal collision and backup handling. Trusted folders in settings are no longer written, because Copilot CLI keeps them in its own state; declare them with programs.github-copilot-cli.trustedFolders instead.

  • Vicinae now requires version 0.17.0 or later. Legacy JSON themes and the vicinae.json configuration file are no longer supported. Replace programs.vicinae.useLayerShell with programs.vicinae.settings.launcher_window.layer_shell.enabled.

  • Mise’s mutable configuration switch is now programs.mise.mutableSettings. The former programs.mise.enableMutableConfig remains a deprecated alias. Defaults and configuration behavior are unchanged.

  • Option aliases, value conversions, and other compatibility code that had warned for at least one stable release were removed. Unless noted otherwise, configurations that still use the old options now fail to evaluate with an error that names the replacement. Options inside submodules, namely the lieer account options, the i3 and Sway config.focus.forceWrapping options, and i3’s config.startup.*.workspace, fail as unknown options instead. Update them as follows:

    • Core:

      • The home-manager command no longer looks for configurations in $XDG_CONFIG_HOME/nixpkgs or ~/.nixpkgs. Move them to $XDG_CONFIG_HOME/home-manager, or pass their path explicitly.
      • Setting nixpkgs.config or nixpkgs.overlays while home-manager.useGlobalPkgs is enabled is now an error instead of a warning.
      • Set qt.platformTheme.name = "gtk2" instead of qt.useGtkTheme = true, and qt.platformTheme.name instead of a string qt.platformTheme. Replace the kde6 theme name with kde. The gnome theme name no longer installs qgnomeplatform; use adwaita, or set qt.platformTheme.package yourself. Neither name is checked any more, so old values are used as given without a warning.
      • Replace i18n.inputMethod.enabled with i18n.inputMethod.type and i18n.inputMethod.enable = true. fcitx, removed in 23.05, is no longer an accepted i18n.inputMethod.type; use fcitx5.
      • Replace fonts.fontconfig.enableProfileFonts with fonts.fontconfig.enable, xdg.userDirs.publishShare with xdg.userDirs.publicShare, specialization with specialisation, targets.genericLinux.extraXdgDataDirs with xdg.systemDirs.data, nixGL with targets.genericLinux.nixGL, and nix.gc.frequency with nix.gc.dates.
      • The lib.xdg.mimeAssociations function was removed; use xdg.mimeApps.defaultApplicationPackages.
      • launchd.agents.<name>.config.ProgramArguments values containing a literal &amp; no longer warn. Home Manager escapes plist values itself, so write & instead.
    • Services:

      • In xsession.windowManager.i3.config and wayland.windowManager.sway.config, fonts and bars.*.fonts must be attribute sets. Replace focus.forceWrapping = true with focus.wrapping = "force" for i3 or "yes" for Sway, and i3 startup.*.workspace with assigns. Replace wayland.windowManager.sway.systemdIntegration with wayland.windowManager.sway.systemd.enable.
      • Replace services.kanshi.profiles and services.kanshi.extraConfig with the ordered list services.kanshi.settings. Turn each named profile into a list entry with profile.name set to its former attribute name and its other options under profile, and rewrite raw extraConfig as structured entries or put it in a file referenced by an include entry. Keep those entries after the profiles to preserve the previous order.
      • Replace services.hyprsunset.transitions with native profiles in services.hyprsunset.settings.profile, such as [ { time = "21:00"; temperature = 5000; } ]. Rewrite each transition using the profile fields time, temperature, gamma, and identity; Home Manager no longer creates per-transition systemd timers or runs their hyprctl requests.
      • Move the removed top-level services.mako options into services.mako.settings. Single-word names such as font and width stay the same; camelCase names such as backgroundColor and defaultTimeout become background-color and default-timeout.
      • Move services.redshift.brightness.day and brightness.night to services.redshift.settings.redshift.brightness-day and brightness-night, and the Gammastep options to services.gammastep.settings.general.brightness-day and brightness-night.
      • Replace services.screen-locker.xssLockExtraOptions, xautolockExtraOptions, and enableDetectSleep with services.screen-locker.xss-lock.extraOptions, xautolock.extraOptions, and xautolock.detectSleep.
      • Replace services.picom.opacityRule with services.picom.opacityRules, programs.wpaperd with services.wpaperd, and services.gpg-agent.pinentryPackage with services.gpg-agent.pinentry.package.
    • Git and diff tools:

      • Move programs.git.userName, userEmail, and aliases to programs.git.settings.user.name, settings.user.email, and settings.alias, programs.git.extraConfig to programs.git.settings, and programs.git.signing.gpgPath to programs.git.signing.signer.
      • Move the programs.git.delta, diff-highlight, diff-so-fancy, difftastic, patdiff, and riff options to programs.<tool>, with these exceptions. The diff-so-fancy markEmptyLines, changeHunkIndicators, stripLeadingSymbols, useUnicodeRuler, and rulerWidth options, under either programs.git.diff-so-fancy or programs.diff-so-fancy, move to programs.diff-so-fancy.settings. programs.git.difftastic.background, color, context, and display move to programs.difftastic.options, and programs.git.difftastic.enableAsDifftool = true becomes programs.difftastic.git.mode = "both". The old enable options also turned on Git integration, so set programs.<tool>.enableGitIntegration = true (for difftastic, programs.difftastic.git.enable = true) explicitly.
      • Replace programs.gh.aliases, editor, and gitProtocol with programs.gh.settings.aliases, settings.editor, and settings.git_protocol, and programs.gh.enableGitCredentialHelper with programs.gh.gitCredentialHelper.enable. programs.gh.settings no longer declares aliases, editor, and git_protocol with defaults, so the generated config.yml omits them unless they are set, and gh uses its own defaults.
    • Shell and terminal programs:

      • Replace programs.zsh.initExtra with programs.zsh.initContent, initExtraFirst with initContent wrapped in lib.mkBefore, and initExtraBeforeCompInit with initContent wrapped in lib.mkOrder 550. Replace enableAutosuggestions, enableSyntaxHighlighting, and zproof with autosuggestion.enable, syntaxHighlighting.enable, and zprof. Relative programs.zsh.dotDir and programs.zsh.history.path values are now rejected; use absolute paths.
      • Replace programs.bash.enableAutojump with programs.autojump.enable, programs.direnv.enableNixDirenvIntegration with programs.direnv.nix-direnv.enable, and the top-level programs.ssh options, such as forwardAgent and controlPath, with the native directives under programs.ssh.settings."*".
      • Combine programs.go.goPath and extraGoPaths, in that order, into programs.go.env.GOPATH, and move goBin to programs.go.env.GOBIN and goPrivate to programs.go.env.GOPRIVATE. The old path options were relative to the home directory, so write absolute paths such as "${config.home.homeDirectory}/go".
      • Replace programs.k9s.skin, hotkey, and plugin with programs.k9s.skins.skin, hotKeys, and plugins. Nested alias, plugin, and k9s.views keys no longer warn; move their contents directly under programs.k9s.aliases, plugins, and views.
      • Replace programs.kitty.theme with programs.kitty.themeFile, using the theme’s file name without .conf rather than its display name. For example, "Space Gray Eighties" becomes "SpaceGray_Eighties".
      • Replace programs.mcfly.enableFuzzySearch with programs.mcfly.fuzzySearchFactor, using 2 for true and 0 for false, and programs.less.keys with programs.less.config.
      • Use programs.eza instead of programs.exa, and "auto" or null instead of a Boolean programs.eza.icons. programs.bat.themes and programs.bat.syntaxes accept only { src; file; } attribute sets. Move programs.broot.modal, verbs, and skin to programs.broot.settings.
      • programs.keychain.agents and programs.keychain.inheritType were removed, because keychain 2.9.0 no longer supports them.
    • Applications:

      • For programs.firefox and the other Firefox-based browsers, add pkgs.gnome-browser-connector to nativeMessagingHosts instead of setting enableGnomeExtensions, and drop vendorPath. Put bookmarks under bookmarks.settings with bookmarks.force = true.
      • Firefox search engines are now referenced only by id, such as ddg or google. Display names such as "DuckDuckGo" in search.default, search.privateDefault, search.order, and the search.engines keys are no longer converted and are written unchanged. For custom search engines, use icon or numeric iconMapObj keys: iconURL, iconUpdateURL, hasPreferredIcon, and JSON iconMapObj keys are no longer checked or converted and are written unchanged. Engines marked isAppProvided = true still ignore icon fields.
      • Move programs.vscode.enableUpdateCheck, enableExtensionUpdateCheck, userSettings, userTasks, userMcp, keybindings, extensions, languageSnippets, and globalSnippets to programs.vscode.profiles.default, and replace programs.vscode.immutableExtensionsDir with the inverse programs.vscode.mutableExtensionsDir.
      • programs.vim.plugins accepts only packages, and programs.helix.languages only an attribute set, with the language list under language. programs.neomutt.binds.*.map and programs.neomutt.macros.*.map accept only lists.
      • Replace programs.msmtp.extraConfig with programs.msmtp.configContent wrapped in lib.mkBefore, and programs.msmtp.extraAccounts with configContent wrapped in lib.mkAfter, so they stay before and after the generated accounts.
      • Under accounts.email.accounts.<name>.lieer, replace dropNonExistingLabels, ignoreTagsRemote, ignoreTagsLocal, timeout, and replaceSlashWithDot with settings.drop_non_existing_label, settings.ignore_remote_labels, settings.ignore_tags, settings.timeout, and settings.replace_slash_with_dot.
      • Replace programs.rtorrent.settings with programs.rtorrent.extraConfig. programs.thunderbird.darwinSetupWarning was removed.
      • Replace programs.anki.sync.passwordFile with programs.anki.profiles."User 1".sync.keyFile.
      • programs.ashell now requires ashell 0.5.0 or later and always writes ashell/config.toml; it no longer generates ashell.yml for older versions, and programs.ashell.settings no longer accepts null. camelCase keys in programs.ashell.settings are no longer converted and are written as given, where ashell ignores them; use the upstream snake_case names.
      • programs.hyprpanel.settings.theme.name no longer warns; put theme contents directly under programs.hyprpanel.settings.theme.

State Version Changes

The state version in this release includes the changes below. These changes are only active if the home.stateVersion option is set to “26.11” or later.

  • programs.nushell.loadSessionVariables defaults to true from home.stateVersion = "26.11". Nushell loads the Home Manager session environment at startup and, when used as a NixOS or nix-darwin module, the system environment too. This makes Home Manager manage env.nu; migrate independently managed contents to programs.nushell.envFile or programs.nushell.extraEnv, or disable the option. Earlier state versions retain the old behavior and emit an evaluation warning until programs.nushell.loadSessionVariables is explicitly set.

  • On Darwin, the default value of programs.firefox.configPath changes from Library/Application Support/Firefox to Library/Application Support/org.nixos.firefox when programs.firefox.package is not null. Explicit configPath values remain unchanged. Users with a home.stateVersion earlier than "26.11" should set programs.firefox.configPath = "Library/Application Support/org.nixos.firefox"; explicitly. Before changing configPath, quit Firefox and move your data from ~/Library/Application Support/Firefox to ~/Library/Application Support/org.nixos.firefox.

  • From home.stateVersion = "26.11", notmuch no longer defaults search.exclude_tags to deleted;spam, and it sets database.path only when an email account is enabled. Earlier versions keep both defaults. To retain them when upgrading, set programs.notmuch.settings.search.exclude_tags = [ "deleted" "spam" ]; and, without email accounts, set programs.notmuch.settings.database.path to the mail directory, previously accounts.email.maildirBasePath.

  • The KDL options under programs.zellij will now correctly escape backslashes in string values. For example, the Nix string "\\" will now correctly generate the KDL string "\\". Previously, this would have generated "\", which is invalid KDL. The following options are affected:

    • programs.zellij.settings
    • programs.zellij.themes
    • programs.zellij.layouts
  • The KDL options under programs.zellij will now escape tabs in string values. For example, the Nix string "\t" (corresponding to a single tab) will now generate the KDL string "\t". Previously, this would have generated "<tab>" (where <tab> denotes a literal tab character). The following options are affected:

    • programs.zellij.settings
    • programs.zellij.themes
    • programs.zellij.layouts
  • The default value of programs.claude-code.configDir changes from ~/.claude to ${config.xdg.configHome}/claude when home.preferXdgDirectories is enabled. Existing Claude Code data in ~/.claude is not migrated automatically. Move it to the new directory before upgrading, or preserve the previous location by setting programs.claude-code.configDir = "${config.home.homeDirectory}/.claude".