Compare commits

...

202 Commits

Author SHA1 Message Date
Robert Helgesson
4fee4bd14b ghostty: reload service on configuration change 2026-01-07 17:22:44 -05:00
Austin Horstman
c068188a8e tests: output store path even for success
Useful when trying to double check the contents of a test directory even
when the tests are passing. ie: stub a test and see the stuff you want
to assert/validate.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-07 13:50:01 -05:00
Austin Horstman
bdaa374383 tests/hyprpaper: update basic configuration
Show the newer format and test the proper generation of config.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-07 11:07:21 -05:00
Austin Horstman
d28cc9f4a6 hyprpaper: add monitor importantPrefix
New config requires monitor at top of generated block.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-07 10:56:09 -05:00
Austin Horstman
a97b0a0999 hyprland: add note about xwayland option
Add small blurb about how the option works and recommends settings

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-07 10:48:08 -05:00
Austin Horstman
a4a571c2d6 Revert "hyprland: dont recompile when disabling xwayland"
This reverts commit c91dbdf61a.
2026-01-07 10:48:08 -05:00
Sefa Eyeoglu
aea57993a8 direnv: make Fish integration read-write
As https://github.com/NixOS/nixpkgs/pull/475992 is merged, we can make
this option read-write.

Depends-on: https://github.com/NixOS/nixpkgs/pull/475992

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2026-01-07 14:22:49 +01:00
home-manager-ci[bot]
1c7be243ea flake.lock: Update
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/c0b0e0fddf73fd517c3471e546c0df87a42d53f4?narHash=sha256-coBu0ONtFzlwwVBzmjacUQwj3G%2BlybcZ1oeNSQkgC0M%3D' (2025-12-28)
  → 'github:NixOS/nixpkgs/9f0c42f8bc7151b8e7e5840fb3bd454ad850d8c5?narHash=sha256-UWYqmD7JFBEDBHWYcqE6s6c77pWdcU/i%2BbwD6XxMb8A%3D' (2026-01-05)
2026-01-07 14:06:45 +01:00
James Hobson
93da26b426 xmonad: removed buildScriptPackages and cleaned up
From the code-review, buildScriptPackages was deemed unnecessary and so
has been removed. The ghc package with dependencies was not needed when
building without a custom build script so this build dependency has been
made contingent on the presence of a custom build script. The install
command is used instead of cp and chmod. Finally, an example has been
added for the documentation.
2026-01-07 13:31:23 +01:00
James Hobson
0d3183953c xmonad: Added buildScript and buildScriptPackages
If you need to change ghc args, or maybe want to use cabal or stack to
build xmonad, a way of doing this is write a script called build which
overrides xmonad's default build behaviour.

This patch adds two extra (optional) config options to xmonad:
- buildScript, a path to said build script
- buildScriptPackages, any additional dependencies it may need
2026-01-07 13:31:23 +01:00
Robert Helgesson
4e8b7bef66 ghostty: prevent service restarts
Stopping or restarting the service will destroy open Ghostty sessions,
potentially disrupting work. This change ensures that we leave the
existing service untouched.

Fixes #8485
2026-01-06 23:26:04 +01:00
Benedikt Rips
6e94d8157c keepassxc: point to the default upstream branch 2026-01-06 22:08:42 +01:00
Benedikt Rips
6e3931c01f keepassxc: add note about error message in the GUI 2026-01-06 22:08:42 +01:00
N4CH723HR3R
c91dbdf61a hyprland: dont recompile when disabling xwayland
xwayland can be disabled in the settings without recompiling hyprland
2026-01-06 22:07:12 +01:00
Timothy Gallion
38e187fd2f podman-linux: fix tests expected results and modules
Update the expected results to match changes in the podman generator
and fix not importing the podman stub overlay with module import
behind `mkIf` introduced in #6905.
2026-01-06 13:35:00 +01:00
Robert Helgesson
9bfca5b3a7 tree-wide: remove redundant platform checks
In the code base, there are lots of configurations locally guarded by
`stdenv.hostPlatform.is(Darwin|Linux)` despite the targeted options
already being guarded. Examples for these targeted options are:

- `systemd.user.*`: globally guarded by `systemd.user.enable`.
- `launchd.*`: globally guarded by `launchd.enable`.
- `lib.hm.darwin.assertInterval`: only effective on Darwin.

These local guards are an antipattern since they weaken the global
guards. Furthermore, they hamper readability. This series of commits
remove instances of these local guards.
2026-01-06 13:13:38 +01:00
leiserfg
bfaba198af vicinae: use simpler raycast extension in the test
This avoids npm issues.
2026-01-06 09:37:09 +01:00
Robert Helgesson
b1421bdfe5 i18n: merge changes from weblate 2026-01-06 09:32:20 +01:00
sternenseemann
4cd7ae4cd4 neovim: builtins.groupBy -> lib.groupBy
lib.groupBy is an alias for builtins.groupBy which should be
preferred, as it also has a compatibility shim in case the Nix
implementation doesn't have the builtin function.
2026-01-06 09:22:28 +01:00
Anderson Torres
e43f7c3321 treewide: remove AndersonTorres from maintainers. 2026-01-06 09:17:04 +01:00
Benedikt Rips
6841643203 yubikey-agent: remove redundant platform checks 2026-01-05 23:10:04 +01:00
Benedikt Rips
a755d94ab0 xdg: remove redundant platform checks 2026-01-05 23:10:04 +01:00
Benedikt Rips
33fe25dbe5 ssh-agent: remove redundant platform checks 2026-01-05 23:10:04 +01:00
Benedikt Rips
337d3602c0 restic: remove redundant platform checks 2026-01-05 23:10:04 +01:00
Benedikt Rips
5d814af6af pueue: remove redundant platform checks 2026-01-05 23:10:03 +01:00
Benedikt Rips
787784fb6f ollama: remove redundant platform checks 2026-01-05 23:10:03 +01:00
Benedikt Rips
2379f704b0 nix-gc: remove redundant platform checks 2026-01-05 23:10:03 +01:00
Benedikt Rips
a26335db1b nh: remove redundant platform checks 2026-01-05 23:10:03 +01:00
Benedikt Rips
d016674f6a mpd: remove redundant platform checks 2026-01-05 23:10:03 +01:00
Benedikt Rips
c2d3a75ebe home-manager-auto-expire: remove redundant platform checks 2026-01-05 23:10:03 +01:00
Benedikt Rips
93af99ec02 gpg-agent: remove redundant platform checks 2026-01-05 23:10:03 +01:00
Benedikt Rips
c8b68aafed git-sync: remove redundant platform checks 2026-01-05 23:10:03 +01:00
Benedikt Rips
bca7415de4 emacs: remove redundant platform checks 2026-01-05 23:10:03 +01:00
Benedikt Rips
d070d83048 colima: remove redundant platform checks 2026-01-05 23:10:03 +01:00
Benedikt Rips
048104c098 clipse: remove redundant platform checks 2026-01-05 23:10:02 +01:00
Benedikt Rips
af894fbbc7 borgmatic: remove redundant platform checks 2026-01-05 23:10:02 +01:00
Benedikt Rips
53084c95ce atuin: remove redundant platform checks 2026-01-05 23:08:11 +01:00
Robert Helgesson
a65c04965c gpg: update key hash in test
Fixes #8478
2026-01-05 14:29:03 +01:00
Noah765
c4eabb884b hyprpaper: update settings example
The configuration format changed in v0.8.0, which is available on nixpkgs.
2026-01-05 10:52:37 +01:00
June Stepp
156b698b75 anki: fix answerKeys of length one 2026-01-05 10:51:38 +01:00
Hoang Nguyen
9d1c71f390 gpg: add dirmngrSettings and gpgsmSettings options 2026-01-05 10:34:11 +01:00
Hoang Nguyen
47e195783e gpg: remove obsolete default values in the settings
- charset option doesn't exist. The correct option name is display-charset.
- fixed-list-mode option is always used and thus obsolete since GNUPG 2.0.10.
- use-agent is a dummy option. gpg will always requires the agent.
2026-01-05 10:34:11 +01:00
Benedikt Rips
f894bc4ffd ssh-agent: improve handling of SSH_AUTH_SOCK variable
Specifically, only preserve `$SSH_AUTH_SOCK` when it points to a
forwarded agent.
2026-01-04 20:52:35 +01:00
Benedikt Rips
73f5a5ecc9 ssh-agent: fix Nushell's check for emptiness
Previously, it would not succeed if `$env.SSH_AUTH_SOCK` is set to an
empty string.
2026-01-04 20:52:35 +01:00
Naïm Camille Favier
7d5927b63c xfconf: fix package 2026-01-04 12:26:39 +01:00
Ivan Isakov
8f7d6bacb6 launchd: Restore errexit after setting up launchd agents
At the beginning of the setup script `errexit` is disabled, but never
properly enabled again at the end. This causes potential issues/errors
in activation scripts following `setupLaunchAgents` to go unnoticed,
since the build doesn't actually fail.
2026-01-04 11:30:04 +01:00
Alex Martens
12cc14271b hyprshell: fix broken links 2026-01-04 09:32:19 +01:00
Benedikt Rips
c211298f7e tree-wide: use lib.hm.assertions.assertPlatform 2026-01-04 09:31:10 +01:00
Tim Kleinschmidt
1cfa305fba opencode: add agent skills support
Adds support for OpenCode Agent Skills by managing skill definitions
under "/opencode/skill/<name>/SKILL.md" via `programs.opencode.skills`.

Documentation: https://opencode.ai/docs/skills/
2026-01-03 11:47:20 +01:00
Tim Kleinschmidt
3e87b442b5 opencode: update docs
.config is already part of $XDG_CONFIG_HOME
2026-01-03 11:47:20 +01:00
leiserfg
99a037de18 vicinae: fix settings example 2026-01-03 11:31:39 +01:00
Robert Helgesson
3b3164dfe3 zsh: avoid escaping showing up in dotDir docs 2026-01-03 11:29:29 +01:00
Robert Helgesson
bc43546503 docs: turn option references into links 2026-01-03 11:29:29 +01:00
Aguirre Matteo
78a8fae57f yt-dlp: remove redundant extraConfig test 2026-01-03 11:23:26 +01:00
Aguirre Matteo
b558d54215 yt-dlp: allow multiple declarations of the same option 2026-01-03 11:23:26 +01:00
Robert Helgesson
9ef24320f1 emacs: remove unnecessary rec 2026-01-03 11:10:00 +01:00
Vladislav
18f9d668aa anki: fix UI scale configuration
Use `numbers.between 1.0 2.0` for the UI scale type to match Anki's
actual behavior where ProfileManager.uiScale clamps values below 1.0
to 1.0.
2026-01-03 10:49:37 +01:00
bandithedoge
2f06b72606 mpd: set network settings as environment variables
https://mpd.readthedocs.io/en/stable/client.html#connecting-to-mpd

These environment variables are picked up by, amongst others, clients
based on libmpdclient:

- 2a42a10067/src/settings.c (L108)
- 2a42a10067/src/settings.c (L135)
2026-01-02 23:05:42 +01:00
PerchunPak
d4e4d5cfa3 lib: make toHyprconf support strings and attrs in sections
Adds support for

    section = [
      "abc"
      { a = 123; }
    ];

Which gets generated to

    section=abc

    section {
      a=123
    }

This is very useful with the new windowrule syntax, where you can
create anonymous window rules as strings and named rules as attribute
sets. See <https://wiki.hypr.land/Configuring/Window-Rules/>.
2026-01-02 15:56:43 +01:00
Austin Horstman
e4e78a2cbe tests/linux-wallpaperengine: add execstart test
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-30 08:22:50 -06:00
Austin Horstman
ae1ea768ef linux-wallpaperengine: misc cleanup
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-30 08:22:50 -06:00
Austin Horstman
365cbc13c4 linux-wallpaperengine: fix ExecStart command
Make sure to properly separate command args.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-30 08:22:50 -06:00
teto
d99b4ca5de meli: support jmap
Enabled when flavor == fastmail.com
2025-12-29 23:55:10 +01:00
teto
64f4dadb80 neovim: fix extraLuaConfig example
reported by bruno
2025-12-29 16:00:00 -06:00
Austin Horstman
7a7b43c723 treewide: drop foo-dogsquared
Removed in https://github.com/NixOS/nixpkgs/pull/472804

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-28 22:03:17 -06:00
home-manager-ci[bot]
a84cccefd4 flake.lock: Update
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/3e2499d5539c16d0d173ba53552a4ff8547f4539?narHash=sha256-QEhk0eXgyIqTpJ/ehZKg9IKS7EtlWxF3N7DXy42zPfU%3D' (2025-12-25)
  → 'github:NixOS/nixpkgs/c0b0e0fddf73fd517c3471e546c0df87a42d53f4?narHash=sha256-coBu0ONtFzlwwVBzmjacUQwj3G%2BlybcZ1oeNSQkgC0M%3D' (2025-12-28)
2025-12-28 22:03:17 -06:00
teto
9d32c214db neovim: let user insert snippets in init.lua
It is a common complaint for users that they can't insert their own code
where they want in the init.lua.
2025-12-29 01:51:32 +01:00
leiserfg
87785ddbc7 vicinae: Add tests for old vicinae version 2025-12-28 17:17:29 -06:00
leiserfg
113b155fe8 vicinae: Update to post 0.17 settings 2025-12-28 17:17:29 -06:00
teto
398bc87bc8 neovim: refactor to get rid of makeNeovimConfig 2025-12-28 20:13:09 +01:00
home-manager-ci[bot]
3613abcbd7 flake.lock: Update
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/a6531044f6d0bef691ea18d4d4ce44d0daa6e816?narHash=sha256-3xY8CZ4rSnQ0NqGhMKAy5vgC%2B2IVK0NoVEzDoOh4DA4%3D' (2025-12-21)
  → 'github:NixOS/nixpkgs/3e2499d5539c16d0d173ba53552a4ff8547f4539?narHash=sha256-QEhk0eXgyIqTpJ/ehZKg9IKS7EtlWxF3N7DXy42zPfU%3D' (2025-12-25)
2025-12-28 10:30:53 -06:00
Austin Horstman
d7e794fe12 tests/anyrun: add empty css test
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-28 10:29:55 -06:00
Austin Horstman
8969535f1c anyrun: default extraCss to null
Prevent creating a file when not configured.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-28 10:29:55 -06:00
teto
80cca72314 meli: support account specific settings
also assert when overriding accounts. I had overriden settings when
testing this module, forgot about it and then wondered why my email
accounts were ignored.
2025-12-28 16:49:26 +01:00
Austin Horstman
d2e0458d65 zsh: don't suggest stateVersion update
Generally best to avoid telling normal users to adjust their
stateVersion to avoid other home-manager module logic changes based on
stateVersion.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-27 18:30:08 -06:00
Austin Horstman
b3ae822959 tests/zsh: add xdg dotDir tests
Verify we respect xdg.enable behavior when placing files.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-27 17:58:46 -06:00
Austin Horstman
d761c0ce89 news: add zsh dotDir default change
Default has changed to respect `xdg.enable`. Let user's know in case it
affects them surprisingly.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-27 17:58:46 -06:00
Austin Horstman
f84f474c1b zsh: respect xdg.enable for dotDir
Make sure we actually respect a user's `xdg.enable` preference.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-27 17:58:46 -06:00
Austin Horstman
ea6dfabe3c tests/zsh: add more test cases for dotdir
Adds tests for various dotDir configurations including trailing slashes
and spaces.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-27 17:58:46 -06:00
Austin Horstman
5432dc5bc4 zsh: fix dotDir path normalization and quoting
Fixes issue where dotDir with trailing slash caused failures.
Refactors lib.nix to use raw paths internally, fixing issues with spaces
in paths.
Updates history.path logic to correctly handle raw absolute paths.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-27 17:58:46 -06:00
Bruno BELANYI
bec08ef6e3 programs/ssh: DRY address/port options
The end goal is to hoist the forwarded path assertion directly into this
module rather than the top-level.
2025-12-27 15:12:05 -06:00
Sandro Marques
4067ca1ffb easyeffects: Fix race condition on Wayland session startup
Add systemd service ordering dependencies to prevent EasyEffects from
starting before the Wayland compositor is ready.

**Problem:** EasyEffects would crash during login with "Failed to create
wl_display (No such file or directory)" if started before the Wayland
display server was fully initialized.

**Solution:** Declaring the "After" property ensures EasyEffects waits
for the graphical session to be fully ready. The "PartOf" properly stops
EasyEffects when logging out. Got the tip from
https://github.com/wwmm/easyeffects/issues/1310.

Tested on NixOS 25.11 (Xantusia, 20251223.76701a1) and Home Manager 25.11
(0999ed8) with GNOME 49 on Wayland.
2025-12-27 12:56:02 -06:00
Oliver Geneser
2d36a6de2f ssh: add kexAlgorithms to matchBlocks
This commit adds the option to add kexAlgorithms as an matchBlock
option with updated test case.
2025-12-27 16:54:14 +01:00
Heitor Augusto
91cdb0e2d5 nixGL: patch systemd and d-bus services references 2025-12-25 11:16:13 -06:00
home-manager-ci[bot]
7eca7f7081 flake.lock: Update
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/c6245e83d836d0433170a16eb185cefe0572f8b8?narHash=sha256-G/WVghka6c4bAzMhTwT2vjLccg/awmHkdKSd2JrycLc%3D' (2025-12-18)
  → 'github:NixOS/nixpkgs/a6531044f6d0bef691ea18d4d4ce44d0daa6e816?narHash=sha256-3xY8CZ4rSnQ0NqGhMKAy5vgC%2B2IVK0NoVEzDoOh4DA4%3D' (2025-12-21)
2025-12-23 23:24:11 -06:00
Austin Horstman
20728df08f release/25.11: add darwin copy apps change
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-23 16:36:16 -06:00
Austin Horstman
af3c24de76 release/25.05: add git signing format change
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-23 16:36:16 -06:00
Austin Horstman
624c7e80fb release/23.05: add swaylock stateVersion change
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-23 16:36:16 -06:00
home-manager-ci[bot]
9c790e687e maintainers: update all-maintainers.nix
Automated update of the master maintainers list combining:
- Home Manager specific maintainers from modules/lib/maintainers.nix
- Nixpkgs maintainers referenced in Home Manager modules

**Added:** 0 maintainers
**Removed:** 0 maintainers
**Total:** 282 → 282 maintainers

Generated by: lib/python/generate-all-maintainers.py
2025-12-23 13:45:25 -06:00
Austin Horstman
527ad07e66 tests/radicle: stub radicle-node
Failing build is blocking CI, test only verifies generated config.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-22 01:11:39 -06:00
home-manager-ci[bot]
57a02fd7d9 flake.lock: Update
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/1306659b587dc277866c7b69eb97e5f07864d8c4?narHash=sha256-KJ2wa/BLSrTqDjbfyNx70ov/HdgNBCBBSQP3BIzKnv4%3D' (2025-12-15)
  → 'github:NixOS/nixpkgs/c6245e83d836d0433170a16eb185cefe0572f8b8?narHash=sha256-G/WVghka6c4bAzMhTwT2vjLccg/awmHkdKSd2JrycLc%3D' (2025-12-18)
2025-12-22 01:11:39 -06:00
aleksana
3fe66908e0 television: fix keybindings 2025-12-21 23:41:33 -06:00
Austin Horstman
61fcc9de76 tests/neovim: add test to catch config eval
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-20 19:55:46 -06:00
Austin Horstman
7b73a6e98f neovim: fix eval
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-20 19:51:30 -06:00
Austin Horstman
4dc3c91c50 neovim: remove deprecated type coercion for extraXPackages
3 years old, no need to keep around.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-20 17:11:31 -06:00
Austin Horstman
a7d6bba358 neovim: remove old removal options
3-4 years old, no need to keep around.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-20 17:11:31 -06:00
Austin Horstman
bdb807dc28 neovim: modernize
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-20 17:11:31 -06:00
Austin Horstman
0a583021ea tests/neovim: add wrapper args test
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-20 17:11:31 -06:00
Austin Horstman
ab01ea24b2 neovim: add missing wrapper args
Add support for extraName, autowrapRuntimeDeps, waylandSupport, and
withPerl options in the neovim module. These options are passed to the
neovim wrapper to allow for more granular configuration.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-20 17:11:31 -06:00
Austin Horstman
c764a377a0 gemini-cli: fix settings example
Supposed to represent the settigns to pass in, not the generated json.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-20 17:11:06 -06:00
Austin Horstman
28b3622b80 tests/gemini-cli: verify defaultModel behavior
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-20 17:11:06 -06:00
Austin Horstman
c848303f1e gemini-cli: don't force GEMINI_MODEL
Default to null so user's can opt in to using this variable that will
override configurations.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-20 17:11:06 -06:00
Austin Horstman
bb35f07cc9 tests/claude-code: add rules tests
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-19 13:19:35 -06:00
Austin Horstman
9bf54edf10 claude-code: add rules support
Support the `rules` directory for modular memory files.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-19 13:19:35 -06:00
Benedikt Rips
89c9508bbe ssh-agent: set $SSH_AUTH_SOCK in non-interactive shells
Since PR #8099, the module sets `$SSH_AUTH_SOCK` through shells' options
for interactive shell initialization instead of
`home.sessionVariablesExtra`. The replacement was not faithful, however,
since `home.sessionVariablesExtra` is sourced also in non-interactive
shells. With this commit, the shells' profile options (where
`home.sessionVariablesExtra` is sourced) are used to set
`$SSH_AUTH_SOCK`.

Fixes #8129.
2025-12-17 08:15:55 -06:00
home-manager-ci[bot]
22202ff0d8 flake.lock: Update
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/2fbfb1d73d239d2402a8fe03963e37aab15abe8b?narHash=sha256-9VvC20PJPsleGMewwcWYKGzDIyjckEz8uWmT0vCDYK0%3D' (2025-12-11)
  → 'github:NixOS/nixpkgs/1306659b587dc277866c7b69eb97e5f07864d8c4?narHash=sha256-KJ2wa/BLSrTqDjbfyNx70ov/HdgNBCBBSQP3BIzKnv4%3D' (2025-12-15)
2025-12-17 07:57:35 -06:00
Anton Mosich
09de9577d4 pimsync: add Install.WantedBy for default.target (#8344) 2025-12-15 22:40:45 -06:00
dependabot[bot]
f575cb24f6 ci: bump korthout/backport-action from 3 to 4
Bumps [korthout/backport-action](https://github.com/korthout/backport-action) from 3 to 4.
- [Release notes](https://github.com/korthout/backport-action/releases)
- [Commits](https://github.com/korthout/backport-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: korthout/backport-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-15 22:38:37 -06:00
DaRacci
3a92ffa192 home-manager: expose all attributes returned by evalModules
This change brings the homeConfigurations output inline with how the
nixosConfiguration output presents its attributes.

The primary purpose is for exposing the graph attribute however there is
no downside to exposing the rest along with it to prevent needing to add
each desired attribute individually in the future if more are added.
2025-12-15 22:36:33 -06:00
home-manager-ci[bot]
6cdf765eed flake.lock: Update
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/addf7cf5f383a3101ecfba091b98d0a1263dc9b8?narHash=sha256-hM20uyap1a0M9d344I692r%2Bik4gTMyj60cQWO%2BhAYP8%3D' (2025-12-08)
  → 'github:NixOS/nixpkgs/2fbfb1d73d239d2402a8fe03963e37aab15abe8b?narHash=sha256-9VvC20PJPsleGMewwcWYKGzDIyjckEz8uWmT0vCDYK0%3D' (2025-12-11)
2025-12-15 22:13:51 -06:00
home-manager-ci[bot]
8315c1544f maintainers: update all-maintainers.nix
Automated update of the master maintainers list combining:
- Home Manager specific maintainers from modules/lib/maintainers.nix
- Nixpkgs maintainers referenced in Home Manager modules

**Added:** 0 maintainers
**Removed:** 0 maintainers
**Total:** 282 → 282 maintainers

Generated by: lib/python/generate-all-maintainers.py
2025-12-15 19:32:11 +01:00
will
58bf3ecb2d modules/services/colima: init 2025-12-13 21:17:23 -06:00
Benedikt Rips
d787ec69c3 less: list options in correct order 2025-12-13 00:08:50 -06:00
Benedikt Rips
07d79726f1 less: enable options to be specified multiple times 2025-12-13 00:08:50 -06:00
Olmo Kramer
4767a9c719 herbstluftwm: Make herbstclient alias optional
The `herbstclient` alias in the generated `autostart` made it impossible
to use bash functions.

This makes the `herbstclient` alias optional by adding an extra
`herbstclientAlias` option on the herbstluftwm configuration. The new
option defaults to `false` as to not confuse newcomers to the
herbstluftwm module, which is not a breaking change because it was only
an optimization.
2025-12-12 23:53:36 -06:00
Austin Horstman
39cb677ed9 news: add defaultEditor entry
Let users know about new variable being set.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-11 13:12:54 -06:00
Jacob Abel
0cf525a5be option defaultEditor: Set {env}VISUAL on true (#8322)
The defaultEditor option sets {env}`EDITOR` however strictly speaking
{env}`EDITOR` is intended for editors that are fully compatible with
teletype terminals (ex: `ed` or `vi`'s `ex` mode).

The {env}`VISUAL variable is intended for modern "visual mode"
terminal editors (ex: `vi` or `emacs`).

Technically speaking editors that are assigned to {env}`EDITOR` should
be configured to operate in teletype compatible mode (see `vi -e` and
`vim -e`).

We don't do this currently because for most users this would be
unintuitive behavior when a script or program mistakenly checks
{env}`EDITOR` instead of first checking {env}`VISUAL`.

In the future it may be worthwhile to introduce an additional option to
these modules to configure {env}`EDITOR` in a strictly conforming manner
(i.e. using the teletype/`ex` mode flags or unsetting {env}`EDITOR`
entirely).

Related Issue: #8314

Signed-off-by: Jacob Abel <jacobabel@nullpo.dev>
2025-12-11 13:04:13 -06:00
Mirko Lenz
9b5ac85d79 npm: add module 2025-12-11 12:58:36 -06:00
Austin Horstman
574f6d3526 hyprpanel: perchun -> PerchunPak
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-11 12:51:49 -06:00
Austin Horstman
e52be4fb78 tldr-update: perchun -> PerchunPak
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-11 12:51:49 -06:00
home-manager-ci[bot]
dd18018d06 flake.lock: Update
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/f61125a668a320878494449750330ca58b78c557?narHash=sha256-BmPWzogsG2GsXZtlT%2BMTcAWeDK5hkbGRZTeZNW42fwA%3D' (2025-12-05)
  → 'github:NixOS/nixpkgs/addf7cf5f383a3101ecfba091b98d0a1263dc9b8?narHash=sha256-hM20uyap1a0M9d344I692r%2Bik4gTMyj60cQWO%2BhAYP8%3D' (2025-12-08)
2025-12-11 12:51:49 -06:00
Nick DeGroot
7b34e428f3 chromium: fix null package 2025-12-11 14:56:50 +01:00
Kyure_A
af7c726e8b sheldon: replace initExtra with initContent 2025-12-11 14:55:22 +01:00
fidgetingbits
13cc1efd78 snixembed: add waybar incompatbility warning
If snixembed is enabled and you try to use the waybar tray the two tools
conflict with eachother and often waybar's tray will not show any icons.
This adds a warning about it, as the problem can be difficult to
diagnose.
2025-12-09 21:27:32 -06:00
June Stepp
e5b1f87841 anki: enable tests on Darwin
Anki is no longer marked as broken in nixpkgs.
2025-12-08 12:16:00 -06:00
home-manager-ci[bot]
caa47b637d maintainers: update all-maintainers.nix
Automated update of the master maintainers list combining:
- Home Manager specific maintainers from modules/lib/maintainers.nix
- Nixpkgs maintainers referenced in Home Manager modules

**Added:** 1 maintainers
**Removed:** 0 maintainers
**Total:** 281 → 282 maintainers

** Added:** xavwe

Generated by: lib/python/generate-all-maintainers.py
2025-12-08 08:04:06 -06:00
Austin Horstman
a788734077 swayidle: fix events default
Changed from list to attrset, but default never updated.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-07 23:45:14 -06:00
Mirko Lenz
6bdf2a68e1 ty: add module 2025-12-07 23:30:36 -06:00
Viktor Titov
f9d45d664e qt: added qt{5,6}ctSettings options (#8271)
Added qtctSettings option to qt module to make it possible to configure qt(5/6)ct declaratively.
2025-12-07 23:17:30 -06:00
home-manager-ci[bot]
082822b8a6 flake.lock: Update
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/2d293cbfa5a793b4c50d17c05ef9e385b90edf6c?narHash=sha256-pp3uT4hHijIC8JUK5MEqeAWmParJrgBVzHLNfJDZxg4%3D' (2025-11-30)
  → 'github:NixOS/nixpkgs/f61125a668a320878494449750330ca58b78c557?narHash=sha256-BmPWzogsG2GsXZtlT%2BMTcAWeDK5hkbGRZTeZNW42fwA%3D' (2025-12-05)
2025-12-07 23:14:56 -06:00
Austin Horstman
27a6182347 tests/diff-highlight: add null assertion test
Verify eval when setting git package to null.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-05 23:18:20 -06:00
Austin Horstman
012cfcc44a diff-highlight: add git package assertion
Git package can be made nullable now, but module is written with
expectation of its availability.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-05 23:18:20 -06:00
Hanwen Guo
36817384a6 programs/git: package nullable
Some platforms (e.g. macOS) provide their customized version of git with
exclusive features, and user might want to use that instead.
2025-12-05 23:03:42 -06:00
Aguirre Matteo
571c5eed1d news: add hyprlauncher entry 2025-12-05 22:35:12 -06:00
Aguirre Matteo
2e02e22e28 hyprlauncher: add module 2025-12-05 22:35:12 -06:00
Aguirre Matteo
ccd22c13b2 restic: change cache directory to $XDG_CACHE_HOME/restic 2025-12-05 20:04:55 -06:00
Austin Horstman
519828bf1c claude-code: refactor wrapper to use append-flags
Alternative approach suggested in
https://github.com/nix-community/home-manager/pull/8290#discussion_r2593114782

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-05 10:42:15 -06:00
David
1a99a515a1 nixos/common: guard nix.package access when nix.enable is false
When nix-darwin has `nix.enable = false` (e.g., for Determinate Nix
users), accessing `config.nix.package` throws an error:

    error: nix.package: accessed when `nix.enable` is off

This regression was introduced in commit a521eab when adding the
`home.uid` option. The code restructuring changed `inherit (config.nix)
package` to be evaluated unconditionally, whereas PR #6383 had
previously ensured this worked correctly.

The fix wraps the package assignment in `mkIf config.nix.enable` to
only access `config.nix.package` when nix management is enabled in the
host OS configuration.

Fixes: #8303
2025-12-05 10:37:47 -06:00
Austin Horstman
6bcb2395ab home-environment: style cleanup
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-04 23:34:56 -06:00
Austin Horstman
f16bfa59e3 home-environment: fix undefined access eval
`uid` isn't guaranteed to be defined, have fallback logic in place to
account for that. Even if we require it eventually, we can't show a
proper assertion/warning without being able to eval.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-04 23:34:56 -06:00
Aguirre Matteo
35545f71dd news: add screen entry 2025-12-04 22:41:15 -06:00
Aguirre Matteo
6bbc48804b screen: add module 2025-12-04 22:41:15 -06:00
Jess
a8b6296a1e tests/restic: fix timedatectl failure
Systemd
[added a check](6a12c90ca3)
which broke this test. So use `date` instead of `timedatectl`.
2025-12-04 22:39:18 -06:00
Aguirre Matteo
68f7b34179 news: add calibre entry 2025-12-04 22:38:55 -06:00
Aguirre Matteo
24cc5c080c calibre: add module 2025-12-04 22:38:55 -06:00
Aguirre Matteo
df7bac2b2b rclone: change cache directory to $XDG_CACHE_HOME/rclone 2025-12-05 00:33:32 +01:00
Austin Horstman
05a56dbf24 claude-code: fix wrapper to inject --mcp-config after subcommands
Manually wrap program to maintain options called from cli.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-04 12:19:32 -06:00
Urocissa Caerulea.Tw
9379fbf4f5 Translate using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (39 of 39 strings)

Translate using Weblate (Chinese (Traditional Han script))

Currently translated at 100.0% (17 of 17 strings)

Co-authored-by: Urocissa Caerulea.Tw <urocissa.tw@proton.me>
Translate-URL: https://hosted.weblate.org/projects/home-manager/cli/zh_Hant/
Translate-URL: https://hosted.weblate.org/projects/home-manager/modules/zh_Hant/
Translation: Home Manager/Home Manager CLI
Translation: Home Manager/Home Manager Modules
2025-12-04 10:33:19 -06:00
Bernardo Meurer
a521eab881 home-environment: add home.uid option
Add a home.uid option similar to home.username. When set, the
activation script verifies the current UID matches the expected
value using the new checkUid function.

When using the NixOS or nix-darwin modules, home.uid is
auto-discovered from users.users.<name>.uid when that value
is set.

This is useful for constructing paths that depend on the user's
UID, such as /run/user/<uid> paths for gpg-agent sockets or
other user-specific runtime directories.
2025-12-04 17:22:25 +01:00
Urocissa Caerulea.Tw
2f93d7333e Translate using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (39 of 39 strings)

Translate using Weblate (Chinese (Traditional Han script))

Currently translated at 100.0% (39 of 39 strings)

Translate using Weblate (Chinese (Traditional Han script))

Currently translated at 100.0% (17 of 17 strings)

Co-authored-by: Urocissa Caerulea.Tw <urocissa.tw@proton.me>
Translate-URL: https://hosted.weblate.org/projects/home-manager/cli/zh_Hant/
Translate-URL: https://hosted.weblate.org/projects/home-manager/modules/zh_Hant/
Translation: Home Manager/Home Manager CLI
Translation: Home Manager/Home Manager Modules
2025-12-04 09:16:41 +00:00
tsrk.
d441981b20 thunderbird: fix aliases SMTP configuration not being listed as usable
Signed-off-by: tsrk. <tsrk@tsrk.me>
2025-12-04 10:16:29 +01:00
Xaver Wenhart
fca4cba863 parallel: package nullable 2025-12-03 12:58:50 -06:00
trash-panda-v91-beta
af324afa72 cargo: fix typo in tests
testing docker-cli instead of cargo in empty-config.nix
2025-12-03 10:43:50 -06:00
Bruno BELANYI
12e7786854 programs/ssh: use 'toList' 2025-12-03 09:48:51 -06:00
Bruno BELANYI
28741978a3 programs/ssh: use 'toKeyValue' for 'extraOptions'
A first step towards refactoring the module.

Unfortunately the config is not consistent in using comma-separated
values or repeated keys for lists, since the user can always add commas
by themselves, we should default to repeated keys in the generator.
2025-12-03 09:44:29 -06:00
Andrew Jeffery
43173abcb4 pimsync: Make storage names unique
This includes the calendar/contacts prefix in the storage name as well
as the pair name to ensure that if the same name is used for contacts
and calendar then it is correctly referenced.
2025-12-03 13:46:21 +01:00
home-manager-ci[bot]
bcc7afa1d8 flake.lock: Update
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/2fad6eac6077f03fe109c4d4eb171cf96791faa4?narHash=sha256-sKoIWfnijJ0%2B9e4wRvIgm/HgE27bzwQxcEmo2J/gNpI%3D' (2025-11-27)
  → 'github:NixOS/nixpkgs/2d293cbfa5a793b4c50d17c05ef9e385b90edf6c?narHash=sha256-pp3uT4hHijIC8JUK5MEqeAWmParJrgBVzHLNfJDZxg4%3D' (2025-11-30)
2025-12-02 22:41:07 -06:00
Patrick Steinhardt
281e9398cc swayidle: improve confusing "events" configuration
With swayidle one can configure two different kinds of hooks:

  - Idle timeouts are executed after the session has been idle for a
    specific amount of time.

  - Events are executed when systemd notifies us that for example the
    user session is locked or that the device is about to suspend.

While not obvious, there is a significant difference between how these
two kinds are configured: there can be several timeouts with separate
commands to be executed, but each event can only be specified once. If
an event is specified multiple times, then the last command wins.

This can be very easy to miss in swayidle's documentation. Furthermore,
because the config is a list of `{ event = "..."; command = "..."; }`
attrset, we double down on this confusion and make it seem like having
multiple handlers for an event was actually supported.

Fix this by converting from a list of "event" submodules to an attrset
where the key is the event name and the value is the command to be
executed. This makes it impossible to specify multiple commands for a
single event by accident.

If a user _does_ want to have multiple commands executed on any event
they can for example use `pkgs.writeShellScript` and manually chain the
commands in that script.
2025-12-02 22:24:56 -06:00
Aguirre Matteo
93d907a205 news: ludusavi's default backup path changed entry 2025-12-02 21:57:23 -06:00
Aguirre Matteo
eca5f967cd ludusavi: use config.xdg.stateHome instead of $XDG_STATE_HOME 2025-12-02 21:57:23 -06:00
Aguirre Matteo
db44f38047 ludusavi: add test 2025-12-02 21:57:23 -06:00
Mirko Lenz
06f81463bb infat: add module 2025-12-02 21:39:05 -06:00
Matt Sturgeon
ab8e4b2b5a home-environment: extend release check to include pkgs
`lib` comes from the Nixpkgs used to instantiate Home Manager itself and
cannot change within the module fixpoint. However, `pkgs` is configurable
(via `nixpkgs.*` or `_module.args`) and may come from a different Nixpkgs
instance from the one providing `lib`.

Mismatches between Home Manager's release and the release of the `pkgs`
instance are more common and also more likely to cause subtle issues.

This change extends the release check to include `pkgs.lib.trivial.release`
so that such mismatches can be detected and reported.
2025-12-02 21:35:34 -06:00
Anton Mosich
c3d1e5c65a pimsync: extend test to contacts
If I had added such a test right away, I would have encountered #8258
myself. I mistakenly believed the contact and calendar modules to be the
same.
2025-12-03 04:10:48 +01:00
Anton Mosich
bf003999ed accounts.contacts: fix eval error
You would encounter an eval error when a module (such as pimsync) would
try to access an attribute of `accounts.contacts.<name>.local`, since it
would default to `null`. The same problem was encountered in the
`accounts.calendar` module, and fixed in
2c157e22dc which has the same solution.

Closes #8258

Reported-by: redbeardymcgee
2025-12-03 04:10:48 +01:00
Xaver Wenhart
ff067cfc61 parallel: init module (#8240) 2025-12-02 01:44:57 +01:00
Austin Horstman
effe4c007d ci: remove unused dependabot ignore
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-01 09:37:35 -06:00
home-manager-ci[bot]
6cedf24ada maintainers: update all-maintainers.nix
Automated update of the master maintainers list combining:
- Home Manager specific maintainers from modules/lib/maintainers.nix
- Nixpkgs maintainers referenced in Home Manager modules

**Added:** 1 maintainers
**Removed:** 0 maintainers
**Total:** 280 → 281 maintainers

** Added:** arunoruto

Generated by: lib/python/generate-all-maintainers.py
2025-12-01 09:34:48 -06:00
novenary
e4e25a8c31 fish: ensure generated completions considered last
home-manager's generated completions shadow built-in completion scripts.
fish actually has logic to deal with this when the path ends with
/generated_completions, so let's take advantage of it.

Link: 47c773300a/src/autoload.rs (L421-L424)
2025-11-30 17:12:04 -06:00
novenary
13b089b586 Revert "fish: avoid shadowing builtin completions"
This reverts commit 23f2ba7ae0.
2025-11-30 17:12:04 -06:00
Victor Engmark
784a83782c nixos: Don't "[a]ttempt to evaluate package pkgs.trash-cli"
Closes #8161.
2025-11-30 14:28:55 -06:00
Brian E
704b6ffa8a Translate using Weblate (Faroese)
Currently translated at 7.6% (3 of 39 strings)

Translate using Weblate (Faroese)

Currently translated at 17.6% (3 of 17 strings)

Co-authored-by: Brian E <brianellingsgaard9@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/home-manager/cli/fo/
Translate-URL: https://hosted.weblate.org/projects/home-manager/modules/fo/
Translation: Home Manager/Home Manager CLI
Translation: Home Manager/Home Manager Modules
2025-11-30 14:18:18 -06:00
Carl
83053e1d33 GPU freedom (#8239)
* gpu: only add intel driver for x86_64-linux

* gpu: allow configuring drivers option

Allow overriding the drivers option if you're an advanced user
2025-11-30 14:48:38 +01:00
Aguirre Matteo
ae400a1dcc shikane: add package to PATH (#8233) 2025-11-30 14:48:16 +01:00
DDoSolitary
edbb012a21 dconf: support configuring specific user databases (#6301)
By default, dconf uses $XDG_CONFIG_HOME/dconf/user as the user database, but this can be changed by specifying user-db:<name> in a profile file and setting the DCONF_PROFILE environment variable to that profile. One may want to use different user databases for different DE/WMs to avoid collision.

Currently the module invokes dconf without touching DCONF_PROFILE, which means that 1) it is unable to configure multiple different user databases, and 2) the behavior of activation script will be affected by the DCONF_PROFILE environment variable when it is invoked, possibly leading to undesired results.

This PR adds a dconf.databases option, so that settings under dconf.databases.<name> will be written to $XDG_CONFIG_HOME/dconf/<name>. The old dconf.settings option is left as-is to avoid breaking compatibility.
2025-11-30 14:37:17 +01:00
Jo²
b1bb534c17 xsession: only require xdg autostart target if explicitely enabled (#8237)
This is a fix for PR #7108 that forcibly enables xdg-desktop-autostart
units, whether or not `config.xdg.autostart` is enabled.
Partially fixes #7708, there is still a risk for conflict if
`xdg.autostart` and `services.picom` are enabled.
2025-11-30 14:35:54 +01:00
Austin Horstman
780be8ef50 tests: disable release check bypass
nixos-unstable bumped

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-11-28 14:27:50 -06:00
home-manager-ci[bot]
40c18076d8 flake.lock: Update
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/5ae3b07d8d6527c42f17c876e404993199144b6a?narHash=sha256-6eeL1YPcY1MV3DDStIDIdy/zZCDKgHdkCmsrLJFiZf0%3D' (2025-11-24)
  → 'github:NixOS/nixpkgs/2fad6eac6077f03fe109c4d4eb171cf96791faa4?narHash=sha256-sKoIWfnijJ0%2B9e4wRvIgm/HgE27bzwQxcEmo2J/gNpI%3D' (2025-11-27)
2025-11-28 14:27:50 -06:00
Austin Horstman
d13041d6f0 tests/gtk4: add test for stateversion change
Ensure default behavior with new state version works properly.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-11-28 14:14:32 -06:00
Fugi
ae9f38e889 gtk4: don't enable theme by default
This is not officially supported and causes issues in some cases.
Also adds a warning to the option.
2025-11-28 14:14:32 -06:00
Friedrich Altheide
86ff0ef506 cargo: add module 2025-11-27 22:29:55 -06:00
damidoug
c220f242cd aerospace: add more tests and fix expected values 2025-11-27 22:27:29 -06:00
damidoug
1ed596c638 aerospace: remove extraConfig, use settings instead 2025-11-27 22:27:29 -06:00
damidoug
9f31ea236b aerospace: add more settings examples 2025-11-27 22:27:29 -06:00
damidoug
b414c94d4e aerospace: fallback default settings 2025-11-27 22:27:29 -06:00
damidoug
5b8d259ee6 aerospace: auto-reload config on file changes; 2025-11-27 22:27:29 -06:00
damidoug
29b672194d aerospace: add assertion to ensure launchd.enable and after-startup-command are used instead of start-at-login and after-login-command 2025-11-27 22:27:29 -06:00
damidoug
f302550865 aerospace: rename userSettings → settings 2025-11-27 22:27:29 -06:00
Matt Sturgeon
23f2ba7ae0 fish: avoid shadowing builtin completions
The fish shell comes with builtin completions. For example, git
completion supports context-aware completion of things like commit
hashes, branch names, sub-commands, etc.

Until fish 4.2, builtin completions were explicitly loaded from
`share/fish/completions`, however that is now deprecated and disabled.
In effect, this means generating manpage-based completion will shadow
and disable builtin completion.

Avoid that, by only generating completion when fish does not have
builtin support for the command.
2025-11-27 22:17:20 -06:00
Mirza Arnaut
470d24d809 vivid: change colorMode type to enum 2025-11-27 22:07:41 -06:00
Mirza Arnaut
740134d4af vivid: replace theme content from yaml with json
This should fix missinterpretation of hex colors (which should be a
string) as numbers in scientific notation. For example: 1e2030.
2025-11-27 22:07:41 -06:00
Mirza Arnaut
c23379a330 vivid: add arunoruto to maintainers list 2025-11-27 22:07:41 -06:00
Austin Horstman
9651819d75 ci: update checkout and update-flake-lock
https://github.com/DeterminateSystems/update-flake-lock/releases/tag/v28
updated with checkout v6 support.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-11-26 16:02:49 -06:00
Austin Horstman
8220473f95 ci: revert actions/checkout to v5 due to update-flake-lock incompatibility
Root cause: DeterminateSystems/update-flake-lock@v27 uses
peter-evans/create-pull-request@v6.0.5 internally, which is incompatible
with actions/checkout@v6's new credential storage mechanism.

The Problem Chain:
- actions/checkout@v6 moved credentials from .git/config to $RUNNER_TEMP
  (security improvement)
- peter-evans/create-pull-request@v6.0.5 cannot access credentials from
  the new $RUNNER_TEMP location
- This causes exit code 128 when update-flake-lock tries to create PRs

The Fix:
- create-pull-request@v7.0.9 fixed v6 compatibility
- However, update-flake-lock@v27 (released July 2025) hasn't upgraded yet
- Reverting to v5 restores working credential access

Next Steps:
- Can upgrade to v6 once update-flake-lock uses create-pull-request@v7.0.9+
  - https://github.com/DeterminateSystems/update-flake-lock/pull/224
- Dependabot configured to ignore v6 upgrades until compatibility is fixed

Fixes: https://github.com/nix-community/home-manager/actions/runs/19712979574
See: https://github.com/peter-evans/create-pull-request/issues/690

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-11-26 12:47:12 -06:00
Austin Horstman
946907fa6a maintaining.md: add note about dependabot release branch update
When creating a new release branch, dependabot.yml needs to be updated
to include the new branch for automated dependency updates.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-11-26 12:38:45 -06:00
Austin Horstman
201c883d0d ci: dependabot update release branch
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-11-26 12:38:45 -06:00
Austin Horstman
cc0425becf ci: disable fail fast on flake update
We don't need to block a channels flake update because of a bug in
another.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-11-26 11:59:27 -06:00
Austin Horstman
ee7f4646da maintaining.md: add note about flake.nix / lock update
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-11-26 11:20:41 -06:00
Austin Horstman
ad0b497533 tests: disable release check temporarily
Remove after nixos-unstable bumped

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-11-26 11:16:38 -06:00
Austin Horstman
089d5bf615 ci: update release in matrix
New stable branch

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-11-26 11:16:38 -06:00
Austin Horstman
4d5fbb182e flake.lock: update
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-11-26 11:16:38 -06:00
Austin Horstman
8433591183 home-manager: prepare 26.05
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-11-26 11:16:38 -06:00
321 changed files with 5922 additions and 2344 deletions

View File

@@ -7,10 +7,9 @@ updates:
interval: "weekly"
commit-message:
prefix: "ci:"
- package-ecosystem: "github-actions"
directory: "/"
target-branch: "release-25.05"
target-branch: "release-25.11"
schedule:
interval: "weekly"
commit-message:

View File

@@ -37,7 +37,7 @@ jobs:
ref: ${{ github.event.pull_request.head.sha }}
- name: Create backport PRs
id: backport
uses: korthout/backport-action@v3
uses: korthout/backport-action@v4
with:
# See https://github.com/korthout/backport-action#inputs
github_token: ${{ steps.app-token.outputs.token || secrets.GITHUB_TOKEN }}

View File

@@ -9,8 +9,9 @@ jobs:
runs-on: ubuntu-latest
if: github.event_name != 'schedule' || github.repository_owner == 'nix-community'
strategy:
fail-fast: false
matrix:
branch: [master, release-25.05]
branch: [master, release-25.11]
steps:
- name: Create GitHub App token
uses: actions/create-github-app-token@v2
@@ -41,7 +42,7 @@ jobs:
- name: Install Nix
uses: cachix/install-nix-action@v31
- name: Update flake.lock
uses: DeterminateSystems/update-flake-lock@v27
uses: DeterminateSystems/update-flake-lock@v28
with:
token: ${{ steps.app-token.outputs.token || secrets.GITHUB_TOKEN }}
git-committer-name: ${{ steps.user-info.outputs.name || 'github-actions[bot]' }}

View File

@@ -121,6 +121,22 @@ Reference commits:
- Change `isReleaseBranch` from `false` to `true`
- Do NOT change the `release` field (it's already correct from Step 1)
2. **flake.nix**
- Update the nixpkgs input to track the corresponding stable branch
- Example: For `release-25.11`, change from:
```nix
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
```
to:
```nix
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
```
- Run `nix flake update` to update flake.lock to the stable branch
- Commit the flake.nix and flake.lock changes
**Note**: The release branch should track the stable NixOS release channel
(e.g., `nixos-25.11`), while master continues to track `nixos-unstable`.
#### Step 3.5: On master - Update CI for the New Release Branch
**When**: After marking the release branch as a release branch (Step 3)
@@ -150,6 +166,37 @@ Reference commits:
- This ensures automated flake.lock updates run on the current stable branch
- Note: We only maintain CI for the latest stable release, not older releases
2. **.github/dependabot.yml** (on master)
- Replace the old stable branch with the new release branch
- Example: When creating `release-25.11`, update the target-branch from:
```yaml
- package-ecosystem: "github-actions"
directory: "/"
target-branch: "release-25.05"
schedule:
interval: "weekly"
commit-message:
prefix: "ci:"
```
to:
```yaml
- package-ecosystem: "github-actions"
directory: "/"
target-branch: "release-25.11"
schedule:
interval: "weekly"
commit-message:
prefix: "ci:"
```
- This ensures automated dependency updates for GitHub Actions on the current
stable branch
- Note: We only maintain dependabot for the latest stable release, not older
releases
**Important**: CI workflows are executed from master, so this change must be
committed to the master branch.

View File

@@ -361,6 +361,11 @@
email = "nixpkgs@perchun.it";
github = "PerchunPak";
githubId = 68118654;
keys = [
{
fingerprint = "BBB5 1142 959D 8549 A3D2 F6C5 313F 67D1 EAB7 70F9";
}
];
name = "Perchun Pak";
source = "nixpkgs";
};
@@ -629,6 +634,13 @@
name = "Arjan Schrijver";
source = "nixpkgs";
};
arunoruto = {
email = "mirza.arnaut45@gmail.com";
github = "arunoruto";
githubId = 21687187;
name = "Mirza Arnaut";
source = "nixpkgs";
};
asymmetric = {
email = "lorenzo@mailbox.org";
github = "asymmetric";
@@ -1085,19 +1097,6 @@
name = "Hoang Nguyen";
source = "home-manager";
};
foo-dogsquared = {
email = "foodogsquared@foodogsquared.one";
github = "foo-dogsquared";
githubId = 34962634;
keys = [
{
fingerprint = "DDD7 D0BD 602E 564B AA04 FC35 1431 0D91 4115 2B92";
}
];
matrix = "@foodogsquared:matrix.org";
name = "Gabriel Arazas";
source = "nixpkgs";
};
fpob = {
email = "fpob@proton.me";
github = "fpob";
@@ -2066,7 +2065,7 @@
source = "nixpkgs";
};
shikanime = {
email = "deva.shikanime@protonmail.com";
email = "william.phetsinorath@shikanime.studio";
github = "shikanime";
githubId = 22115108;
name = "William Phetsinorath";
@@ -2304,6 +2303,13 @@
name = "Florian Peter";
source = "nixpkgs";
};
xavwe = {
email = "git@xavwe.dev";
github = "xavwe";
githubId = 125409009;
name = "Xaver Wenhart";
source = "nixpkgs";
};
xlambein = {
email = "xlambein@gmail.com";
github = "xlambein";

6
docs/flake.lock generated
View File

@@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1743938762,
"narHash": "sha256-UgFYn8sGv9B8PoFpUfCa43CjMZBl1x/ShQhRDHBFQdI=",
"lastModified": 1764081664,
"narHash": "sha256-sUoHmPr/EwXzRMpv1u/kH+dXuvJEyyF2Q7muE+t0EU4=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "74a40410369a1c35ee09b8a1abee6f4acbedc059",
"rev": "dc205f7b4fdb04c8b7877b43edb7b73be7730081",
"type": "github"
},
"original": {

View File

@@ -1,6 +1,6 @@
# Home Manager Manual {#home-manager-manual}
## Version 25.11
## Version 26.05 (unstable)
```{=include=} preface

View File

@@ -4,6 +4,7 @@ This section lists the release notes for stable versions of Home Manager
and the current unstable version.
```{=include=} chapters
rl-2605.md
rl-2511.md
rl-2505.md
rl-2411.md

View File

@@ -57,3 +57,9 @@ changes are only active if the `home.stateVersion` option is set to
now default to `true` which is consistent with the default values
for those options used by `i3` and `sway`.
- The [](#opt-programs.swaylock.enable) option now defaults to `false`
and must be explicitly enabled. Previously, it would be implicitly
enabled when `programs.swaylock.settings` was non-empty. Users with
`home.stateVersion` set to earlier versions will continue to get the
old implicit behavior.

View File

@@ -27,4 +27,8 @@ The state version in this release includes the changes below. These
changes are only active if the `home.stateVersion` option is set to
\"25.05\" or later.
- No changes.
- The [](#opt-programs.git.signing.format) option no longer defaults to
`"openpgp"`. Users who use Git signing with GPG should explicitly set
this option to `"openpgp"` to maintain the previous behavior. Users
with `home.stateVersion` set to earlier versions will continue to get
the `"openpgp"` default for backwards compatibility.

View File

@@ -80,3 +80,10 @@ changes are only active if the `home.stateVersion` option is set to
`{ PASSWORD_STORE_DIR = $XDG_DATA_HOME/password-store; }` anymore by its
default value. This will revert to the default behaviour of the program,
namely `$HOME/.password-store` to be used as the store path.
- On macOS, [](#opt-targets.darwin.copyApps.enable) is now enabled by
default instead of [](#opt-targets.darwin.linkApps.enable). This means
applications from `home.packages` will be copied to
`~/Applications/Home Manager Apps` rather than symlinked, making them
work properly with Spotlight. Users with `home.stateVersion` set to
earlier versions will continue to use `linkApps` by default.

View File

@@ -0,0 +1,25 @@
# Release 26.05 {#sec-release-26.05}
This is the current unstable branch and the information in this
section is therefore not final.
## Highlights {#sec-release-26.05-highlights}
This release has the following notable changes:
- The [](#opt-programs.anki.uiScale) option now expects a value in the
range 1.02.0, previously it erroneously expected values in the
range `0.01.0`.
## State Version Changes {#sec-release-26.05-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.05\" or later.
- The [](#opt-gtk.gtk4.theme) option does not mirror
[](#opt-gtk.theme) by default anymore.
- The [](#opt-programs.zsh.dotDir) option now defaults to the XDG
configuration directory (usually `~/.config/zsh`) when
[](#opt-xdg.enable) is true.

6
flake.lock generated
View File

@@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1763678758,
"narHash": "sha256-+hBiJ+kG5IoffUOdlANKFflTT5nO3FrrR2CA3178Y5s=",
"lastModified": 1767640445,
"narHash": "sha256-UWYqmD7JFBEDBHWYcqE6s6c77pWdcU/i+bwD6XxMb8A=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "117cc7f94e8072499b0a7aa4c52084fa4e11cc9b",
"rev": "9f0c42f8bc7151b8e7e5840fb3bd454ad850d8c5",
"type": "github"
},
"original": {

View File

@@ -1277,7 +1277,7 @@ while [[ $# -gt 0 ]]; do
export VERBOSE=1
;;
--version)
echo 25.11-pre
echo 26.05-pre
exit 0
;;
*)

View File

@@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: Home Manager\n"
"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n"
"POT-Creation-Date: 2025-07-22 10:59+0200\n"
"PO-Revision-Date: 2025-08-23 20:02+0000\n"
"PO-Revision-Date: 2025-11-30 14:00+0000\n"
"Last-Translator: Brian E <brianellingsgaard9@gmail.com>\n"
"Language-Team: Faroese <https://hosted.weblate.org/projects/home-manager/cli/"
"fo/>\n"
@@ -17,12 +17,12 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.13\n"
"X-Generator: Weblate 5.15-dev\n"
#. translators: For example: "home-manager: missing argument for --cores"
#: home-manager/home-manager:16
msgid "%s: missing argument for %s"
msgstr ""
msgstr "%s: manglar eitt ávirki fyri %s"
#. translators: For example: "home-manager: --rollback can only be used after switch"
#: home-manager/home-manager:22
@@ -31,7 +31,7 @@ msgstr "%s: %s kann bert brúkast aftaná %s"
#: home-manager/home-manager:71
msgid "No configuration file found at %s"
msgstr ""
msgstr "Eingin samansetingsfíla funni hjá %s"
#. translators: The first '%s' specifier will be replaced by either
#. 'home.nix' or 'flake.nix'.

View File

@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: Home Manager\n"
"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n"
"POT-Creation-Date: 2025-07-22 10:59+0200\n"
"PO-Revision-Date: 2025-03-07 18:58+0000\n"
"Last-Translator: 807 <s10855168@gmail.com>\n"
"PO-Revision-Date: 2025-12-04 09:16+0000\n"
"Last-Translator: \"Urocissa Caerulea.Tw\" <urocissa.tw@proton.me>\n"
"Language-Team: Chinese (Traditional Han script) <https://hosted.weblate.org/"
"projects/home-manager/cli/zh_Hant/>\n"
"Language: zh_Hant\n"
@@ -17,21 +17,21 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 5.10.3-dev\n"
"X-Generator: Weblate 5.15-dev\n"
#. translators: For example: "home-manager: missing argument for --cores"
#: home-manager/home-manager:16
msgid "%s: missing argument for %s"
msgstr "%s: 缺少參數 %s"
msgstr "%s:缺少 %s 的引數"
#. translators: For example: "home-manager: --rollback can only be used after switch"
#: home-manager/home-manager:22
msgid "%s: %s can only be used after %s"
msgstr ""
msgstr "%s%s 只能在 %s 之後使用"
#: home-manager/home-manager:71
msgid "No configuration file found at %s"
msgstr "在 %s 處找到配置檔案"
msgstr "在 %s 找不到設定檔"
#. translators: The first '%s' specifier will be replaced by either
#. 'home.nix' or 'flake.nix'.
@@ -41,12 +41,12 @@ msgid ""
"Keeping your Home Manager %s in %s is deprecated,\n"
"please move it to %s"
msgstr ""
"保持你的 Home Manager 在 %s 中,%s 已被拋棄\n"
"請將它移動到 %s"
" Home Manager 的 %s 放在 %s 中, 已經被棄用\n"
"請改放到 %s"
#: home-manager/home-manager:99
msgid "No configuration file found. Please create one at %s"
msgstr "未找到配置檔案。請在 %s 建立一份"
msgstr "找不到設定檔。請在 %s 建立新的設定檔"
#: home-manager/home-manager:114
msgid "Home Manager not found at %s."
@@ -57,7 +57,7 @@ msgstr "在 %s 中找不到 Home Manager。"
msgid ""
"The fallback Home Manager path %s has been deprecated and a file/directory "
"was found there."
msgstr "備用的 Home Manager 路徑 %s 已被拋棄,但一個檔案/資料夾在這被找到。"
msgstr "備用的 Home Manager 路徑 %s 已被棄用,且在該處找到了檔案/目錄。"
#. translators: This message will be seen by very few users that likely are familiar with English. So feel free to leave this untranslated.
#: home-manager/home-manager:125
@@ -80,21 +80,21 @@ msgid ""
"\n"
" $ rm -r \"%s\""
msgstr ""
"要消除這個警告,請做以下其中一。\n"
"若要移除此警告,請執行下列其中一。\n"
"\n"
"1. 告訴Home Manager使用路徑,例如加入\n"
"1. 明確告知 Home Manager 使用路徑,例如\n"
"\n"
" { programs.home-manager.path = \"%s\"; }\n"
"\n"
" 到你的配置中。\n"
" 中,加入您的設定。\n"
"\n"
" 如果你想要直接引入Home Manager 請你使用 `path` 參數r\n"
" 如果想直接匯入 Home Manager可以在呼叫時使用 `path` 參數來指定路徑:\n"
"\n"
" pkgs.callPackage /path/to/home-manager-package { path = \"%s\"; }\n"
"\n"
" 當呼叫 Home Manager 模組。\n"
" 這樣就能正確傳遞 Home Manager 的路徑。\n"
"\n"
"2. 刪除無效的路徑\n"
"2. 移除已棄用的路徑\n"
"\n"
" $ rm -r \"%s\""
@@ -104,33 +104,33 @@ msgstr "正在進行 Nix 完整性檢查"
#: home-manager/home-manager:173
msgid "Could not find suitable profile directory, tried %s and %s"
msgstr "找不到合適的 profile 目錄,已嘗試 %s 和 %s"
msgstr "找不到合適的設定檔目錄,已嘗試 %s 和 %s"
#. translators: Here "flake" is a noun that refers to the Nix Flakes feature.
#: home-manager/home-manager:230
msgid "Can't inspect options of a flake configuration"
msgstr "無法檢查 flake 配置中的選項"
msgstr "無法檢查 flake 設定的選項"
#: home-manager/home-manager:305 home-manager/home-manager:328
#: home-manager/home-manager:734 home-manager/home-manager:1237
msgid "%s: unknown option '%s'"
msgstr "%s未知選項 %s"
msgstr "%s未知選項 '%s'"
#: home-manager/home-manager:310 home-manager/home-manager:1238
msgid "Run '%s --help' for usage help"
msgstr "執行 %s --help 獲取用法幫助"
msgstr "執行 '%s --help' 以取得使用說明"
#: home-manager/home-manager:336 home-manager/home-manager:441
msgid "The file %s already exists, leaving it unchanged..."
msgstr "檔案 %s 已存在,不更改它..."
msgstr "檔案 %s 已存在,保持不變..."
#: home-manager/home-manager:338 home-manager/home-manager:443
msgid "Creating %s..."
msgstr "創建 %s..."
msgstr "正在建立 %s..."
#: home-manager/home-manager:487
msgid "Creating initial Home Manager generation..."
msgstr "正在建立初始 Home Manager 世代 ..."
msgstr "正在建立初始 Home Manager 世代..."
#. translators: The "%s" specifier will be replaced by a file path.
#: home-manager/home-manager:492
@@ -142,12 +142,12 @@ msgid ""
"to configure Home Manager. Run 'man home-configuration.nix' to\n"
"see all available options."
msgstr ""
"全部工作完成home-manager 工具現應已安裝,您可以編輯\n"
"全部完成home-manager 工具現在應該已被安裝,您可以編輯\n"
"\n"
" %s\n"
"\n"
"來配置 Home Manager。執行 man home-configuration.nix\n"
"來檢視所有可用選項。"
"來設定 Home Manager。執行 'man home-configuration.nix' 時\n"
"可查看所有可用選項。"
#. translators: The "%s" specifier will be replaced by a URL.
#: home-manager/home-manager:497
@@ -158,16 +158,16 @@ msgid ""
"\n"
"if the error seems to be the fault of Home Manager."
msgstr ""
"啊哦,安裝失敗了!如果感覺是 Home Manager 造成的錯誤,請在下方\n"
"糟糕,安裝失敗了!如果感覺是 Home Manager 造成的錯誤,請在此連結\n"
"\n"
" %s\n"
"\n"
"建立 Issue 告知我們。"
"中,建立 Issue 告知我們。"
#. translators: Here "flake" is a noun that refers to the Nix Flakes feature.
#: home-manager/home-manager:508
msgid "Can't instantiate a flake configuration"
msgstr "無法建立 flake 配置例項"
msgstr "無法實例化 flake 設定"
#: home-manager/home-manager:584
msgid ""
@@ -177,12 +177,12 @@ msgid_plural ""
"There are %d unread and relevant news items.\n"
"Read them by running the command \"%s news\"."
msgstr[0] ""
"有 %d 未讀相關新聞或訊息。\n"
"執行%s news” 命令進行閱讀。"
"有 %d 未讀相關的消息項目。\n"
"執行指令 \"%s news\" 來進行確認。"
#: home-manager/home-manager:598
msgid "Unknown \"news.display\" setting \"%s\"."
msgstr "未知的 news.display 設定項 “%s”。"
msgstr "未知的 \"news.display\" 設定值 \"%s\"。"
#: home-manager/home-manager:606
#, sh-format
@@ -191,11 +191,11 @@ msgstr "請設定 $EDITOR 或 $VISUAL 環境變數"
#: home-manager/home-manager:624
msgid "Cannot run build in read-only directory"
msgstr "無法在唯讀目錄中執行建"
msgstr "無法在唯讀目錄中執行建"
#: home-manager/home-manager:787
msgid "The configuration did not contain the specialisation \"%s\""
msgstr ""
msgstr "設定中不包含特化設定 \"%s\""
#: home-manager/home-manager:841
msgid "No generation with ID %s"
@@ -203,7 +203,7 @@ msgstr "沒有 ID 為 %s 的世代"
#: home-manager/home-manager:843
msgid "Cannot remove the current generation %s"
msgstr "無法移除當前世代 %s"
msgstr "無法移除目前的世代 %s"
#: home-manager/home-manager:845
msgid "Removing generation %s"
@@ -215,7 +215,7 @@ msgstr "沒有即將過期的世代"
#: home-manager/home-manager:877
msgid "No home-manager packages seem to be installed."
msgstr "似乎沒有安裝 home-manager 軟體包。"
msgstr "似乎沒有安裝 home-manager 套件。"
#: home-manager/home-manager:962
msgid "Unknown argument %s"
@@ -223,11 +223,11 @@ msgstr "未知引數 %s"
#: home-manager/home-manager:987
msgid "This will remove Home Manager from your system."
msgstr "這將會從系統中移除 Home Manager。"
msgstr "這將會從您的系統中移除 Home Manager。"
#: home-manager/home-manager:990
msgid "This is a dry run, nothing will actually be uninstalled."
msgstr "這是試執行結果,沒有實際解除安裝任何軟體包。"
msgstr "這是模擬執行,實際上並不會解除安裝任何內容。"
#: home-manager/home-manager:994
msgid "Really uninstall Home Manager?"
@@ -235,27 +235,27 @@ msgstr "確定要解除安裝 Home Manager 嗎?"
#: home-manager/home-manager:1000
msgid "Switching to empty Home Manager configuration..."
msgstr "正在切換至空的 Home Manager 配置 ..."
msgstr "正在切換至空的 Home Manager 設定..."
#: home-manager/home-manager:1015
msgid "Yay!"
msgstr "好耶"
msgstr "太好了"
#: home-manager/home-manager:1020
msgid "Home Manager is uninstalled but your home.nix is left untouched."
msgstr "Home Manager 已解除安裝,但未改動您的 home.nix 配置檔案。"
msgstr "Home Manager 已解除安裝,但您的 home.nix 保持不變。"
#: home-manager/home-manager:1285
msgid "expire-generations expects one argument, got %d."
msgstr "expire-generations 須要一個引數,但獲取到了 %d 個。"
msgstr "expire-generations 預期一個引數,但到了 %d 個。"
#: home-manager/home-manager:1310
msgid "Unknown command: %s"
msgstr "未知令:%s"
msgstr "未知令:%s"
#: home-manager/install.nix:21
msgid "This derivation is not buildable, please run it using nix-shell."
msgstr "此配置檔案/變體不可構建,請在 nix-shell 執行。"
msgstr "此 derivation 無法建置,請使用 nix-shell 執行。"
#, sh-format
#~ msgid "Please set the $EDITOR environment variable"

View File

@@ -102,8 +102,8 @@ let
};
local = mkOption {
type = types.nullOr (localModule name);
default = null;
type = localModule name;
default = { };
description = ''
Local configuration for the contacts.
'';

View File

@@ -57,9 +57,8 @@ let
let
module = moduleChecks rawModule;
in
{
inherit (module) options config;
module
// {
activationPackage = module.config.home.activationPackage;
# For backwards compatibility. Please use activationPackage instead.

View File

@@ -193,6 +193,13 @@ in
description = "The user's username.";
};
home.uid = mkOption {
type = types.nullOr types.ints.unsigned;
default = null;
example = 1000;
description = "The user's uid.";
};
home.homeDirectory = mkOption {
type = types.path;
defaultText = literalExpression ''
@@ -570,14 +577,25 @@ in
warnings =
let
hmRelease = config.home.version.release;
nixpkgsRelease = lib.trivial.release;
releaseMismatch = config.home.enableNixpkgsReleaseCheck && hmRelease != nixpkgsRelease;
libRelease = lib.trivial.release;
pkgsRelease = pkgs.lib.trivial.release;
releaseMismatch = hmRelease != libRelease || hmRelease != pkgsRelease;
versionsSummary =
if libRelease == pkgsRelease then
''
Home Manager version ${hmRelease} and
Nixpkgs version ${libRelease}.''
else
''
Home Manager version: ${hmRelease}
Nixpkgs version used to evaluate Home Manager: ${libRelease}
Nixpkgs version used for packages (`pkgs`): ${pkgsRelease}'';
in
lib.optional releaseMismatch ''
lib.optional (config.home.enableNixpkgsReleaseCheck && releaseMismatch) ''
You are using
Home Manager version ${hmRelease} and
Nixpkgs version ${nixpkgsRelease}.
${lib.replaceString "\n" "\n " versionsSummary}
Using mismatched versions is likely to cause errors and unexpected
behavior. It is therefore highly recommended to use a release of Home
@@ -831,6 +849,9 @@ in
if [[ ! -v SKIP_SANITY_CHECKS ]]; then
checkUsername ${lib.escapeShellArg config.home.username}
checkHomeDirectory ${lib.escapeShellArg config.home.homeDirectory}
${lib.optionalString (config.home.uid != null) ''
checkUid ${toString config.home.uid}
''}
fi
${lib.optionalString config.home.activationGenerateGcRoot ''

View File

@@ -270,9 +270,7 @@ in
setupLaunchAgents
# Restore errexit
if [[ -o errexit ]]; then
set -e
fi
set -e
'';
})
];

View File

@@ -117,6 +117,17 @@ function checkHomeDirectory() {
fi
}
function checkUid() {
local expectedUid="$1"
local actualUid
actualUid="$(id -u)"
if [[ "$actualUid" != "$expectedUid" ]]; then
_iError 'Error: UID is "%s" but we expect "%s"' "$actualUid" "$expectedUid"
exit 1
fi
}
# Note, the VERBOSE_ECHO variable is deprecated and should not be used inside
# the Home Manager project. It is provided here for backwards compatibility.
if [[ -v VERBOSE ]]; then

View File

@@ -21,6 +21,7 @@
isList
mapAttrsToList
replicate
attrNames
;
initialIndent = concatStrings (replicate indentLevel " ");
@@ -28,31 +29,36 @@
toHyprconf' =
indent: attrs:
let
sections = filterAttrs (n: v: isAttrs v || (isList v && all isAttrs v)) attrs;
isImportantField =
n: _: foldl (acc: prev: if hasPrefix prev n then true else acc) false importantPrefixes;
importantFields = filterAttrs isImportantField attrs;
withoutImportantFields = fields: removeAttrs fields (attrNames importantFields);
allSections = filterAttrs (n: v: isAttrs v || isList v) attrs;
sections = withoutImportantFields allSections;
mkSection =
n: attrs:
if lib.isList attrs then
(concatMapStringsSep "\n" (a: mkSection n a) attrs)
else
if isList attrs then
let
separator = if all isAttrs attrs then "\n" else "";
in
(concatMapStringsSep separator (a: mkSection n a) attrs)
else if isAttrs attrs then
''
${indent}${n} {
${toHyprconf' " ${indent}" attrs}${indent}}
'';
''
else
toHyprconf' indent { ${n} = attrs; };
mkFields = generators.toKeyValue {
listsAsDuplicateKeys = true;
inherit indent;
};
allFields = filterAttrs (n: v: !(isAttrs v || (isList v && all isAttrs v))) attrs;
isImportantField =
n: _: foldl (acc: prev: if hasPrefix prev n then true else acc) false importantPrefixes;
importantFields = filterAttrs isImportantField allFields;
fields = builtins.removeAttrs allFields (mapAttrsToList (n: _: n) importantFields);
allFields = filterAttrs (n: v: !(isAttrs v || isList v)) attrs;
fields = withoutImportantFields allFields;
in
mkFields importantFields
+ concatStringsSep "\n" (mapAttrsToList mkSection sections)

View File

@@ -17,15 +17,29 @@ let
# The dconf keys managed by this configuration. We store this as part of the
# generation state to be able to reset keys that become unmanaged during
# switch.
stateDconfKeys = pkgs.writeText "dconf-keys.json" (
builtins.toJSON (
lib.concatLists (
lib.mapAttrsToList (
dir: entries: lib.mapAttrsToList (key: _: "/${dir}/${key}") entries
) cfg.settings
mkStateDconfKeys =
nameSuffix: settings:
pkgs.writeText "dconf-keys${nameSuffix}.json" (
builtins.toJSON (
lib.concatLists (
lib.mapAttrsToList (dir: entries: lib.mapAttrsToList (key: _: "/${dir}/${key}") entries) settings
)
)
)
);
);
databases =
lib.optional (cfg.settings != { }) {
dconfProfile = null;
stateDconfKeys = mkStateDconfKeys "" cfg.settings;
inherit (cfg) settings;
}
++ lib.mapAttrsToList (name: value: {
dconfProfile = pkgs.writeText "dconf-profile-${name}" ''
user-db:${name}
'';
stateDconfKeys = mkStateDconfKeys "-${name}" value;
settings = value;
}) cfg.databases;
in
{
@@ -81,73 +95,87 @@ in
to convert dconf database dumps into compatible Nix expression.
'';
};
databases = lib.mkOption {
type = with types; attrsOf (attrsOf (attrsOf lib.hm.types.gvariant));
default = { };
description = ''
Settings to write to specific dconf user databases.
See [](#opt-dconf.settings) for details.
'';
};
};
};
config = lib.mkIf (cfg.enable && cfg.settings != { }) {
config = lib.mkIf (cfg.enable && databases != [ ]) {
# Make sure the dconf directory exists.
xdg.configFile."dconf/.keep".source = builtins.toFile "keep" "";
home.extraBuilderCommands = ''
mkdir -p $out/state/
ln -s ${stateDconfKeys} $out/state/${stateDconfKeys.name}
'';
''
+ lib.concatMapStrings (db: ''
ln -s ${db.stateDconfKeys} $out/state/${db.stateDconfKeys.name}
'') databases;
home.activation.dconfSettings = lib.hm.dag.entryAfter [ "installPackages" ] (
let
iniFile = pkgs.writeText "hm-dconf.ini" (toDconfIni cfg.settings);
lib.concatMapStrings (
db:
let
iniFile = pkgs.writeText "hm-dconf.ini" (toDconfIni db.settings);
statePath = "state/${stateDconfKeys.name}";
statePath = "state/${db.stateDconfKeys.name}";
cleanup = pkgs.writeShellScript "dconf-cleanup" ''
set -euo pipefail
cleanup = pkgs.writeShellScript "dconf-cleanup" ''
set -euo pipefail
${config.lib.bash.initHomeManagerLib}
${config.lib.bash.initHomeManagerLib}
PATH=${
lib.makeBinPath [
pkgs.dconf
pkgs.jq
]
}''${PATH:+:}$PATH
PATH=${
lib.makeBinPath [
pkgs.dconf
pkgs.jq
]
}''${PATH:+:}$PATH
oldState="$1"
newState="$2"
oldState="$1"
newState="$2"
# Can't do cleanup if we don't know the old state.
if [[ ! -f $oldState ]]; then
exit 0
# Can't do cleanup if we don't know the old state.
if [[ ! -f $oldState ]]; then
exit 0
fi
# Reset all keys that are present in the old generation but not the new
# one.
jq -r -n \
--slurpfile old "$oldState" \
--slurpfile new "$newState" \
'($old[] - $new[])[]' \
| while read -r key; do
verboseEcho "Resetting dconf key \"$key\""
run $DCONF_DBUS_RUN_SESSION dconf reset "$key"
done
'';
envCommand = lib.optionalString (db.dconfProfile != null) "env DCONF_PROFILE=${db.dconfProfile}";
in
''
if [[ -v DBUS_SESSION_BUS_ADDRESS ]]; then
export DCONF_DBUS_RUN_SESSION="${envCommand}"
else
export DCONF_DBUS_RUN_SESSION="${pkgs.dbus}/bin/dbus-run-session --dbus-daemon=${pkgs.dbus}/bin/dbus-daemon ${envCommand}"
fi
# Reset all keys that are present in the old generation but not the new
# one.
jq -r -n \
--slurpfile old "$oldState" \
--slurpfile new "$newState" \
'($old[] - $new[])[]' \
| while read -r key; do
verboseEcho "Resetting dconf key \"$key\""
run $DCONF_DBUS_RUN_SESSION dconf reset "$key"
done
'';
in
''
if [[ -v DBUS_SESSION_BUS_ADDRESS ]]; then
export DCONF_DBUS_RUN_SESSION=""
else
export DCONF_DBUS_RUN_SESSION="${pkgs.dbus}/bin/dbus-run-session --dbus-daemon=${pkgs.dbus}/bin/dbus-daemon"
fi
if [[ -v oldGenPath ]]; then
${cleanup} \
"$oldGenPath/${statePath}" \
"$newGenPath/${statePath}"
fi
if [[ -v oldGenPath ]]; then
${cleanup} \
"$oldGenPath/${statePath}" \
"$newGenPath/${statePath}"
fi
run $DCONF_DBUS_RUN_SESSION ${pkgs.dconf}/bin/dconf load / < ${iniFile}
run $DCONF_DBUS_RUN_SESSION ${pkgs.dconf}/bin/dconf load / < ${iniFile}
unset DCONF_DBUS_RUN_SESSION
''
unset DCONF_DBUS_RUN_SESSION
''
) databases
);
};
}

View File

@@ -59,7 +59,7 @@ in
theme = mkOption {
type = types.nullOr themeType;
default = null;
description = "Default theme for all GTK versions.";
description = "Default theme for GTK 2/3.";
};
iconTheme = mkOption {

View File

@@ -45,9 +45,17 @@ in
packageExample = "pkgs.gnome.gnome-themes-extra";
}
);
default = cfg.theme;
defaultText = literalExpression "config.gtk.theme";
description = "Theme for GTK 4 applications.";
default = if lib.versionOlder config.home.stateVersion "26.05" then cfg.theme else null;
defaultText = literalExpression ''if lib.versionOlder config.home.stateVersion "26.05" then cfg.theme else null'';
description = ''
Theme for GTK 4 applications.
Warning: This is not officially supported and applied using a workaround.
It may cause issues with some apps.
For context, see [Please dont theme our apps](https://stopthemingmy.app/)
and [Restyling apps at scale](https://blogs.gnome.org/tbernard/2018/10/15/restyling-apps-at-scale/).
'';
};
iconTheme = mkOption {

View File

@@ -0,0 +1,9 @@
{
time = "2025-10-14T23:44:58+00:00";
condition = true;
message = ''
A new module is available: `services.colima`
Colima is a tool for orchestrating container runtimes under a linux VM.
'';
}

View File

@@ -0,0 +1,9 @@
{
time = "2025-11-26T05:33:49+00:00";
condition = true;
message = ''
A new module is available: 'programs.cargo'.
cargo is the build system and package manager of Rust.
'';
}

View File

@@ -0,0 +1,11 @@
{
time = "2025-11-26T10:55:28+00:00";
condition = true;
message = ''
The option 'gtk.theme' does not apply to GTK 4 automatically anymore for new
installations (with `home.stateVersion` >= "26.05"). Using a custom theme is
not officially supported by GTK 4, and implemented by home-manager using a
workaround that may cause issues in some cases. If you still want to use a GTK
4 theme, you need to explicitly set 'gtk.gtk4.theme'.
'';
}

View File

@@ -0,0 +1,10 @@
{ pkgs, ... }:
{
time = "2025-11-27T07:22:14+00:00";
condition = pkgs.stdenv.hostPlatform.isDarwin;
message = ''
A new module is available: 'programs.infat'.
Infat is a command line tool to set default openers
for file formats and url schemes on macOS.
'';
}

View File

@@ -0,0 +1,7 @@
{
time = "2025-11-29T23:04:38+00:00";
condition = true;
message = ''
A new module is available: 'programs.parallel'.
'';
}

View File

@@ -0,0 +1,16 @@
{ config, ... }:
{
time = "2025-12-01T12:35:38+00:00";
condition = config.services.ludusavi.enable;
message = ''
BREAKING CHANGE:
The `ludusavi` module has changed its default backup and restore path.
The new module implements a mechanism to automatically migrate the backups
to the new path, but if it doesn't work and you can't find your backups in
`ludusavi`, they should be in the old path: ~/\$XDG_STATE_HOME/backups/ludusavi/
(that means a directory literally called $XDG_STATE_HOME in your home, rather than
the env var expanded). For more info, see pull #8234.
'';
}

View File

@@ -0,0 +1,12 @@
{
time = "2025-12-03T13:14:53+00:00";
condition = true;
message = ''
A new module is available: `programs.calibre`
Calibre is a powerful and easy to use e-book manager. Users say its outstanding
and a must-have. Itll allow you to do nearly everything and it takes things a
step beyond normal e-book software. Its also completely free and open source
and great for both casual users and computer experts.
'';
}

View File

@@ -0,0 +1,12 @@
{
time = "2025-12-04T19:34:38+00:00";
condition = true;
message = ''
A new module is available: `programs.screen`
GNU Screen is a terminal multiplexer, a software application that can
be used to multiplex several virtual consoles, allowing a user to access
multiple separate login sessions inside a single terminal window, or detach
and reattach sessions from a terminal.
'';
}

View File

@@ -0,0 +1,12 @@
{ pkgs, ... }:
{
time = "2025-12-05T01:50:03+00:00";
condition = pkgs.stdenv.hostPlatform.isLinux;
message = ''
A new module is available: `programs.hyprlauncher`
Hyprlauncher is a multipurpose and versatile launcher/picker
for hyprland. Its fast, simple, and provides various modules.
'';
}

View File

@@ -0,0 +1,10 @@
{
time = "2025-12-06T10:03:01+00:00";
condition = true;
message = ''
A new module is available: `programs.npm`
It allows you manage your npm user configuration (`.npmrc`)
and install a specific version of the package.
'';
}

View File

@@ -0,0 +1,10 @@
{
time = "2025-12-06T10:05:43+00:00";
condition = true;
message = ''
A new module is available: `programs.ty`
It allows to manage the configuration and package
of the Python language server `ty` by Astral.
'';
}

View File

@@ -0,0 +1,32 @@
{ config, ... }:
{
time = "2025-12-11T19:04:30+00:00";
condition =
let
helixEnabled = config.programs.helix.enable && config.programs.helix.defaultEditor;
kakouneEnabled = config.programs.kakoune.enable && config.programs.kakoune.defaultEditor;
neovimEnabled = config.programs.neovim.enable && config.programs.neovim.defaultEditor;
vimEnabled = config.programs.vim.enable && config.programs.vim.defaultEditor;
emacsEnabled = config.services.emacs.enable && config.services.emacs.defaultEditor;
in
helixEnabled || kakouneEnabled || neovimEnabled || vimEnabled || emacsEnabled;
message = ''
The 'defaultEditor' option now sets both {env}`EDITOR` and {env}`VISUAL`
environment variables.
Previously, only {env}`EDITOR` was set. The {env}`VISUAL` variable is now
also configured to point to the same editor, which is the expected behavior
for modern terminal editors.
This change affects the following modules:
- programs.helix
- programs.kakoune
- programs.neovim
- programs.vim
- services.emacs
No action is required. This change should improve compatibility with tools
that check {env}`VISUAL` before {env}`EDITOR`.
'';
}

View File

@@ -0,0 +1,12 @@
{ config, ... }:
{
time = "2025-12-12T19:20:28+00:00";
condition = config.xsession.windowManager.herbstluftwm.enable;
message = ''
It is now possible to disable the `herbstclient` alias in the autostart
script by setting `xsession.windowManagers.herbsluftwm.enableAlias = false`.
This makes it possible to use the `herbstclient` command in bash functions,
though may cause flickering while the autostart script runs.
'';
}

View File

@@ -0,0 +1,20 @@
{ config, ... }:
{
time = "2025-12-27T19:00:00+00:00";
condition = config.programs.zsh.enable;
message = ''
The default value of `programs.zsh.dotDir` has changed.
When `home.stateVersion` is set to "26.05" or later, and `xdg.enable` is
`true` (the default), `programs.zsh.dotDir` now defaults to
`''${config.xdg.configHome}/zsh`. Previously, it defaulted to the home
directory.
This means your Zsh configuration files (`.zshrc`, `.zshenv`, etc.) will be
moved to `~/.config/zsh` (or your configured XDG config home).
If you prefer the old behavior, you can explicitly set:
`programs.zsh.dotDir = config.home.homeDirectory;`
'';
}

View File

@@ -0,0 +1,10 @@
{ config, ... }:
{
time = "2026-01-02T00:03:48+00:00";
condition = config.services.mpd.enable;
message = ''
`MPD_HOST` and `MPD_PORT` environment variables are now set automatically.
This can be disabled with `services.mpd.enableSessionVariables = false`.
'';
}

View File

@@ -8,6 +8,10 @@
let
cfg = config.qt;
qtctFormat = pkgs.formats.ini {
listToValue = values: lib.concatStringsSep ", " values;
};
# Map platform names to their packages.
platformPackages = with pkgs; {
gnome = [
@@ -286,7 +290,34 @@ in
'';
};
};
};
}
// (lib.genAttrs' [ "qt5ct" "qt6ct" ] (
name:
lib.nameValuePair "${name}Settings" (
lib.mkOption {
type = lib.types.nullOr qtctFormat.type;
default = null;
example = lib.literalExpression ''
{
Appearance = {
style = "kvantum";
icon_theme = "Papirus-Dark";
standar_dialogs = "xdgdesktopportal";
};
Fonts = {
fixed = "\"DejaVuSansM Nerd Font Mono,12\"";
general = "\"DejaVu Sans,12\"";
};
}
'';
description = ''
Qtct configuration. Writes settings to `${name}/${name}.conf`
file. Lists will be translated to comma-separated strings.
Fonts must be quoted (see example).
'';
}
)
));
};
config =
@@ -397,5 +428,18 @@ in
]
++ lib.optionals (platformTheme.name != null) [ "QT_QPA_PLATFORMTHEME" ]
++ lib.optionals (cfg.style.name != null) [ "QT_STYLE_OVERRIDE" ];
xdg.configFile =
lib.pipe
[ "qt5ct" "qt6ct" ]
[
(lib.filter (qtct: cfg."${qtct}Settings" != null))
(lib.flip lib.genAttrs' (
qtct:
lib.nameValuePair "${qtct}/${qtct}.conf" {
source = qtctFormat.generate "${qtct}-config" cfg."${qtct}Settings";
}
))
];
};
}

View File

@@ -26,6 +26,7 @@ in
"24.11"
"25.05"
"25.11"
"26.05"
];
description = ''
It is occasionally necessary for Home Manager to change

View File

@@ -136,7 +136,7 @@ in
xdg.stateHome = mkOptionDefault defaultStateHome;
home.sessionVariables = variables;
systemd.user.sessionVariables = mkIf pkgs.stdenv.hostPlatform.isLinux variables;
systemd.user.sessionVariables = variables;
}
)

View File

@@ -135,7 +135,7 @@ in
home.activation.xfconfSettings = lib.hm.dag.entryAfter [ "installPackages" ] (
let
mkCommand = channel: property: value: ''
run ${pkgs.xfce.xfconf}/bin/xfconf-query \
run ${pkgs.xfconf}/bin/xfconf-query \
${lib.escapeShellArgs (
[
"-c"

View File

@@ -8,26 +8,28 @@ msgstr ""
"Project-Id-Version: Home Manager Modules\n"
"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n"
"POT-Creation-Date: 2025-07-22 10:59+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
"PO-Revision-Date: 2025-11-30 14:00+0000\n"
"Last-Translator: Brian E <brianellingsgaard9@gmail.com>\n"
"Language-Team: Faroese <https://hosted.weblate.org/projects/home-manager/"
"modules/fo/>\n"
"Language: fo\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.15-dev\n"
#: modules/files.nix:206
msgid "Creating home file links in %s"
msgstr ""
msgstr "Stávni heimafílaleinkir innaní %s"
#: modules/files.nix:219
msgid "Cleaning up orphan links from %s"
msgstr ""
msgstr "Ruddi foreldraleys leinkir frá %s"
#: modules/home-environment.nix:647
msgid "Creating new profile generation"
msgstr ""
msgstr "Stovni nýggjan profil ættarlið"
#: modules/home-environment.nix:650
msgid "No change so reusing latest profile generation"

View File

@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: Home Manager Modules\n"
"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n"
"POT-Creation-Date: 2025-07-22 10:59+0200\n"
"PO-Revision-Date: 2025-03-07 18:58+0000\n"
"Last-Translator: 807 <s10855168@gmail.com>\n"
"PO-Revision-Date: 2025-12-04 04:17+0000\n"
"Last-Translator: \"Urocissa Caerulea.Tw\" <urocissa.tw@proton.me>\n"
"Language-Team: Chinese (Traditional Han script) <https://hosted.weblate.org/"
"projects/home-manager/modules/zh_Hant/>\n"
"Language: zh_Hant\n"
@@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 5.10.3-dev\n"
"X-Generator: Weblate 5.15-dev\n"
#: modules/files.nix:206
msgid "Creating home file links in %s"
@@ -25,15 +25,15 @@ msgstr "正在 %s 中建立家目錄檔案連結"
#: modules/files.nix:219
msgid "Cleaning up orphan links from %s"
msgstr "正在 %s 清理孤立連結"
msgstr "正在清理 %s 中的孤立連結"
#: modules/home-environment.nix:647
msgid "Creating new profile generation"
msgstr "正在建立新一代的配置文件中"
msgstr "正在建立新的世代設定檔"
#: modules/home-environment.nix:650
msgid "No change so reusing latest profile generation"
msgstr "為發生改變,請重新使用新一代的配置文件"
msgstr "沒有變更,將重複使用最新的設定檔世代"
#: modules/home-environment.nix:699
msgid ""
@@ -50,18 +50,18 @@ msgid ""
"\n"
"Then try activating your Home Manager configuration again."
msgstr ""
"糟糕Nix 未能安裝您的新 Home Manager 配置文件\n"
"糟糕Nix 無法安裝您的新 Home Manager 設定檔\n"
"\n"
"也許這裏和使用 \"%s\" 安裝的包有衝突?\n"
"嘗試行\n"
"可能與使用 \"%s\" 安裝的套件衝突?\n"
"嘗試行\n"
"\n"
" %s\n"
"\n"
"如果有衝突的包,你可以用\n"
"如果有衝突的套件,您可以使用以下指令移除\n"
"\n"
" %s\n"
"\n"
"來移除。然後嘗試再次啟用您的 Home Manager 配置。"
"然後再次嘗試啟用您的 Home Manager 設定。"
#: modules/home-environment.nix:735
msgid "Activating %s"
@@ -69,27 +69,27 @@ msgstr "正在啟用 %s"
#: modules/home-environment.nix:807
msgid "%s: unknown option '%s'"
msgstr ""
msgstr "%s未知選項 '%s'"
#: modules/lib-bash/activation-init.sh:22
msgid "Migrating profile from %s to %s"
msgstr "正在從 %S 配置文件轉移到 %s"
msgstr "正在將設定檔從 %s 遷移至 %s"
#: modules/lib-bash/activation-init.sh:54
msgid "Could not find suitable profile directory, tried %s and %s"
msgstr "找不到合適的 profile 目錄,已嘗試 %s 和 %s"
msgstr "找不到合適的設定檔目錄,已嘗試 %s 和 %s"
#: modules/lib-bash/activation-init.sh:106
msgid "Error: USER is set to \"%s\" but we expect \"%s\""
msgstr "錯誤USER 被設定為 「%s」但我們希望是 「%s」"
msgstr "錯誤USER 被設定為「%s」但我們的預期為「%s」"
#: modules/lib-bash/activation-init.sh:115
msgid "Error: HOME is set to \"%s\" but we expect \"%s\""
msgstr "錯誤HOME 被設定為 「%s」但我們預期得到 「%s」"
msgstr "錯誤HOME 被設定為「%s」但我們預期「%s」"
#: modules/lib-bash/activation-init.sh:132
msgid "Starting Home Manager activation"
msgstr "正在啟動 Home Manager 初始化程式"
msgstr "正在進行 Home Manager 啟用程序"
#: modules/lib-bash/activation-init.sh:136
msgid "Sanity checking Nix"
@@ -97,19 +97,19 @@ msgstr "正在進行 Nix 完整性檢查"
#: modules/lib-bash/activation-init.sh:149
msgid "This is a dry run"
msgstr "這是試運行"
msgstr "這是模擬執行"
#: modules/lib-bash/activation-init.sh:153
msgid "This is a live run"
msgstr "這是實際行"
msgstr "這是實際行"
#: modules/lib-bash/activation-init.sh:159
msgid "Using Nix version: %s"
msgstr "正在使用的 Nix 版本: %s"
msgstr "使用的 Nix 版本%s"
#: modules/lib-bash/activation-init.sh:162
msgid "Activation variables:"
msgstr "啟用變數:"
msgstr "啟用變數"
#~ msgid "Creating profile generation %s"
#~ msgstr "正在建立配置檔案世代 %s"

View File

@@ -10,6 +10,12 @@ let
tomlFormat = pkgs.formats.toml { };
configPath =
if config.xdg.enable then
"${lib.removePrefix config.home.homeDirectory config.xdg.configHome}/aerospace/aerospace.toml"
else
".aerospace.toml";
# filterAttrsRecursive supporting lists, as well.
filterListAndAttrsRecursive =
pred: set:
@@ -39,6 +45,19 @@ in
{
meta.maintainers = with lib.maintainers; [ damidoug ];
imports = [
(lib.mkRenamedOptionModule
[ "programs" "aerospace" "userSettings" ]
[ "programs" "aerospace" "settings" ]
)
(lib.mkRemovedOptionModule [
"programs"
"aerospace"
"extraConfig"
] "This option has been removed. Please use 'programs.aerospace.settings' instead.")
];
options.programs.aerospace = {
enable = lib.mkEnableOption "AeroSpace window manager";
@@ -81,24 +100,7 @@ in
};
};
extraConfig = mkOption {
type = types.lines;
default = "";
description = ''
Extra configuration to append to the aerospace.toml file.
This allows you to add raw TOML content, including multiline strings.
'';
example = lib.literalExpression ''
alt-enter = ''''exec-and-forget osascript -e '
tell application "Terminal"
do script
activate
end tell'
''''
'';
};
userSettings = mkOption {
settings = mkOption {
inherit (tomlFormat) type;
default = { };
example = lib.literalExpression ''
@@ -115,6 +117,27 @@ in
alt-k = "focus up";
alt-l = "focus right";
};
on-window-detected = [
{
"if".app-id = "com.apple.finder";
run = "move-node-to-workspace 9";
}
{
"if" = {
app-id = "com.apple.systempreferences";
app-name-regex-substring = "settings";
window-title-regex-substring = "substring";
workspace = "workspace-name";
during-aerospace-startup = true;
};
check-further-callbacks = true;
run = [
"layout floating"
"move-node-to-workspace S"
];
}
];
}
'';
description = ''
@@ -128,32 +151,68 @@ in
config = lib.mkIf cfg.enable {
assertions = [
(lib.hm.assertions.assertPlatform "programs.aerospace" pkgs lib.platforms.darwin)
# 1. Fail if user sets start-at-login = true BUT launchd is disabled.
{
assertion =
!((lib.hasAttr "start-at-login" cfg.settings) && (cfg.settings."start-at-login" == true))
|| (cfg.launchd.enable == true);
message = ''
You have set `programs.aerospace.settings."start-at-login" = true;`
but `programs.aerospace.launchd.enable` is false.
This tells AeroSpace to manage its own startup, which can conflict
with Home Manager.
To manage startup with Home Manager, please set
`programs.aerospace.launchd.enable = true;`
(You can leave `start-at-login = true` in your settings, it will be
correctly overridden).
'';
}
# 2. Fail if user sets after-login-command (in any case).
{
assertion =
!(
(lib.hasAttr "after-login-command" cfg.settings)
&& (lib.isList cfg.settings."after-login-command")
&& (cfg.settings."after-login-command" != [ ])
);
message = ''
You have set `programs.aerospace.settings."after-login-command"`.
This setting is not supported when using this Home Manager module,
as it either conflicts with the launchd service (if enabled)
or bypasses it (if disabled).
The correct way to run commands after AeroSpace starts is to use:
1. `programs.aerospace.launchd.enable = true;`
2. `programs.aerospace.settings."after-startup-command" = [ ... ];`
'';
}
];
home = {
packages = lib.mkIf (cfg.package != null) [ cfg.package ];
file.".config/aerospace/aerospace.toml".source =
let
generatedConfig = tomlFormat.generate "aerospace" (
filterNulls (
cfg.userSettings
// lib.optionalAttrs cfg.launchd.enable {
# Override these to avoid launchd conflicts
start-at-login = false;
after-login-command = [ ];
}
)
);
extraConfig = pkgs.writeText "aerospace-extra-config" cfg.extraConfig;
in
pkgs.runCommandLocal "aerospace.toml"
{
inherit generatedConfig extraConfig;
}
''
cat "$generatedConfig" "$extraConfig" > "$out"
'';
file.${configPath} = lib.mkIf (cfg.settings != { }) {
source = tomlFormat.generate "aerospace" (
filterNulls (
cfg.settings
// {
# Override these to avoid launchd conflicts
start-at-login = false;
after-login-command = [ ];
}
)
);
onChange = lib.mkIf cfg.launchd.enable ''
echo "AeroSpace config changed, reloading..."
${lib.getExe cfg.package} reload-config
'';
};
};
launchd.agents.aerospace = {

View File

@@ -82,7 +82,7 @@ in
};
uiScale = lib.mkOption {
type = with lib.types; nullOr (numbers.between 0.0 1.0);
type = with lib.types; nullOr (numbers.between 1.0 2.0);
default = null;
example = 1.0;
description = "User interface scale.";

View File

@@ -112,7 +112,7 @@ let
answer_keys: tuple[tuple[int, str], ...] = (${
lib.strings.concatMapStringsSep ", " (val: "(${toString val.ease}, '${val.key}')") cfg.answerKeys
})
}${if cfg.answerKeys != [ ] then "," else ""})
for ease, key in answer_keys:
profile_manager.set_answer_key(ease, key)

View File

@@ -185,7 +185,7 @@ in
extraCss = mkOption {
type = nullOr lines;
default = "";
default = null;
description = ''
Extra CSS lines to add to {file}`~/.config/anyrun/style.css`.
'';

View File

@@ -11,7 +11,6 @@ let
tomlFormat = pkgs.formats.toml { };
inherit (lib) mkIf mkOption types;
inherit (pkgs.stdenv) isLinux isDarwin;
in
{
meta.maintainers = with lib.maintainers; [
@@ -221,98 +220,82 @@ in
};
}
(mkIf daemonCfg.enable (
lib.mkMerge [
(mkIf daemonCfg.enable {
assertions = [
{
assertions = [
{
assertion = lib.versionAtLeast cfg.package.version "18.2.0";
message = ''
The Atuin daemon requires at least version 18.2.0 or later.
'';
}
{
assertion = isLinux || isDarwin;
message = "The Atuin daemon can only be configured on either Linux or macOS.";
}
];
programs.atuin.settings = {
daemon = {
enabled = true;
};
};
assertion = lib.versionAtLeast cfg.package.version "18.2.0";
message = ''
The Atuin daemon requires at least version 18.2.0 or later.
'';
}
(mkIf isLinux {
programs.atuin.settings = {
daemon = {
systemd_socket = true;
};
};
{
assertion = config.systemd.user.enable || config.launchd.enable;
message = "The Atuin daemon can only be configured on systems with systemd or launchd.";
}
];
systemd.user.services.atuin-daemon = {
Unit = {
Description = "Atuin daemon";
Requires = [ "atuin-daemon.socket" ];
};
Install = {
Also = [ "atuin-daemon.socket" ];
WantedBy = [ "default.target" ];
};
Service = {
ExecStart = "${lib.getExe cfg.package} daemon";
Environment = lib.optionals (daemonCfg.logLevel != null) [ "ATUIN_LOG=${daemonCfg.logLevel}" ];
Restart = "on-failure";
RestartSteps = 3;
RestartMaxDelaySec = 6;
};
};
programs.atuin.settings.daemon = {
enabled = true;
systemd_socket = config.systemd.user.enable;
socket_path = lib.mkIf (!config.systemd.user.enable) (
lib.mkDefault "${config.xdg.dataHome}/atuin/daemon.sock"
);
};
systemd.user.sockets.atuin-daemon =
let
socket_dir = if lib.versionAtLeast cfg.package.version "18.4.0" then "%t" else "%D/atuin";
in
{
Unit = {
Description = "Atuin daemon socket";
};
Install = {
WantedBy = [ "sockets.target" ];
};
Socket = {
ListenStream = "${socket_dir}/atuin.sock";
SocketMode = "0600";
RemoveOnStop = true;
};
};
})
(mkIf isDarwin {
programs.atuin.settings = {
daemon = {
socket_path = lib.mkDefault "${config.xdg.dataHome}/atuin/daemon.sock";
};
};
systemd.user.services.atuin-daemon = {
Unit = {
Description = "Atuin daemon";
Requires = [ "atuin-daemon.socket" ];
};
Install = {
Also = [ "atuin-daemon.socket" ];
WantedBy = [ "default.target" ];
};
Service = {
ExecStart = "${lib.getExe cfg.package} daemon";
Environment = lib.optionals (daemonCfg.logLevel != null) [ "ATUIN_LOG=${daemonCfg.logLevel}" ];
Restart = "on-failure";
RestartSteps = 3;
RestartMaxDelaySec = 6;
};
};
launchd.agents.atuin-daemon = {
enable = true;
config = {
ProgramArguments = [
"${lib.getExe cfg.package}"
"daemon"
];
EnvironmentVariables = lib.optionalAttrs (daemonCfg.logLevel != null) {
ATUIN_LOG = daemonCfg.logLevel;
};
KeepAlive = {
Crashed = true;
SuccessfulExit = false;
};
ProcessType = "Background";
};
systemd.user.sockets.atuin-daemon =
let
socket_dir = if lib.versionAtLeast cfg.package.version "18.4.0" then "%t" else "%D/atuin";
in
{
Unit = {
Description = "Atuin daemon socket";
};
})
]
))
Install = {
WantedBy = [ "sockets.target" ];
};
Socket = {
ListenStream = "${socket_dir}/atuin.sock";
SocketMode = "0600";
RemoveOnStop = true;
};
};
launchd.agents.atuin-daemon = {
enable = true;
config = {
ProgramArguments = [
"${lib.getExe cfg.package}"
"daemon"
];
EnvironmentVariables = lib.optionalAttrs (daemonCfg.logLevel != null) {
ATUIN_LOG = daemonCfg.logLevel;
};
KeepAlive = {
Crashed = true;
SuccessfulExit = false;
};
ProcessType = "Background";
};
};
})
]
);
}

View File

@@ -8,7 +8,7 @@ let
cfg = config.programs.bashmount;
in
{
meta.maintainers = [ lib.maintainers.AndersonTorres ];
meta.maintainers = [ ];
options.programs.bashmount = {
enable = lib.mkEnableOption "bashmount";

View File

@@ -0,0 +1,44 @@
{
lib,
pkgs,
config,
...
}:
let
inherit (lib)
types
mkIf
mkEnableOption
mkPackageOption
mkOption
;
cfg = config.programs.calibre;
in
{
meta.maintainers = with lib.hm.maintainers; [ aguirre-matteo ];
options.programs.calibre = {
enable = mkEnableOption "calibre";
package = mkPackageOption pkgs "calibre" { nullable = true; };
plugins = mkOption {
type = with types; listOf path;
default = [ ];
description = "List of plugins to install for calibre";
};
};
config = mkIf cfg.enable {
home.packages = mkIf (cfg.package != null) [ cfg.package ];
xdg.configFile = mkIf (cfg.plugins != [ ]) (
let
symlinkedPlugins = pkgs.symlinkJoin {
name = "calibre-plugins";
paths = cfg.plugins;
};
in
lib.mapAttrs' (
k: _: lib.nameValuePair "calibre/plugins/${k}" { source = (symlinkedPlugins + "/${k}"); }
) (builtins.readDir symlinkedPlugins)
);
};
}

View File

@@ -0,0 +1,43 @@
{
lib,
config,
pkgs,
...
}:
let
inherit (lib) mkEnableOption;
tomlFormat = pkgs.formats.toml { };
cfg = config.programs.cargo;
in
{
meta.maintainers = [ lib.maintainers.friedrichaltheide ];
options = {
programs = {
cargo = {
enable = mkEnableOption "management of cargo config";
settings = lib.mkOption {
inherit (tomlFormat) type;
default = { };
description = ''
Available configuration options for the .cargo/config see:
https://doc.rust-lang.org/cargo/reference/config.html
'';
};
};
};
};
config = lib.mkIf cfg.enable {
home = {
file = {
".cargo/config.toml" = {
source = tomlFormat.generate "config.toml" cfg.settings;
};
};
};
};
}

View File

@@ -40,7 +40,7 @@ let
finalPackage = mkOption {
inherit visible;
type = types.package;
type = types.nullOr types.package;
readOnly = true;
description = ''
Resulting customized ${name} package
@@ -220,15 +220,22 @@ let
};
in
lib.mkIf cfg.enable {
programs.${browser}.finalPackage = lib.mkIf (cfg.package != null) (
assertions = [
{
assertion = !(cfg.package == null && cfg.commandLineArgs != [ ]);
message = "Cannot set `commandLineArgs` when `package` is null for ${browser}.";
}
];
programs.${browser}.finalPackage =
if cfg.commandLineArgs != [ ] then
cfg.package.override {
commandLineArgs = lib.concatStringsSep " " cfg.commandLineArgs;
}
else
cfg.package
);
cfg.package;
home.packages = lib.mkIf (cfg.finalPackage != null) [
cfg.finalPackage

View File

@@ -197,6 +197,47 @@ in
};
};
rules = lib.mkOption {
type = lib.types.attrsOf (lib.types.either lib.types.lines lib.types.path);
default = { };
description = ''
Modular rule files for Claude Code.
The attribute name becomes the rule filename, and the value is either:
- Inline content as a string
- A path to a file containing the rule content
Rules are stored in .claude/rules/ directory.
All markdown files in .claude/rules/ are automatically loaded as project memory.
'';
example = lib.literalExpression ''
{
code-style = '''
# Code Style Guidelines
- Use consistent formatting
- Follow language conventions
''';
testing = '''
# Testing Conventions
- Write tests for all new features
- Maintain test coverage above 80%
''';
security = ./rules/security.md;
}
'';
};
rulesDir = lib.mkOption {
type = lib.types.nullOr lib.types.path;
default = null;
description = ''
Path to a directory containing rule files for Claude Code.
Rule files from this directory will be symlinked to .claude/rules/.
All markdown files in this directory are automatically loaded as project memory.
'';
example = lib.literalExpression "./rules";
};
agentsDir = lib.mkOption {
type = lib.types.nullOr lib.types.path;
default = null;
@@ -325,6 +366,10 @@ in
assertion = !(cfg.memory.text != null && cfg.memory.source != null);
message = "Cannot specify both `programs.claude-code.memory.text` and `programs.claude-code.memory.source`";
}
{
assertion = !(cfg.rules != { } && cfg.rulesDir != null);
message = "Cannot specify both `programs.claude-code.rules` and `programs.claude-code.rulesDir`";
}
{
assertion = !(cfg.agents != { } && cfg.agentsDir != null);
message = "Cannot specify both `programs.claude-code.agents` and `programs.claude-code.agentsDir`";
@@ -348,7 +393,7 @@ in
makeWrapperArgs = lib.flatten (
lib.filter (x: x != [ ]) [
(lib.optional (cfg.mcpServers != { }) [
"--add-flags"
"--append-flags"
"--mcp-config ${jsonFormat.generate "claude-code-mcp-config.json" { inherit (cfg) mcpServers; }}"
])
]
@@ -386,6 +431,11 @@ in
if cfg.memory.text != null then { text = cfg.memory.text; } else { source = cfg.memory.source; }
);
".claude/rules" = lib.mkIf (cfg.rulesDir != null) {
source = cfg.rulesDir;
recursive = true;
};
".claude/agents" = lib.mkIf (cfg.agentsDir != null) {
source = cfg.agentsDir;
recursive = true;
@@ -406,6 +456,12 @@ in
recursive = true;
};
}
// lib.mapAttrs' (
name: content:
lib.nameValuePair ".claude/rules/${name}.md" (
if lib.isPath content then { source = content; } else { text = content; }
)
) cfg.rules
// lib.mapAttrs' (
name: content:
lib.nameValuePair ".claude/agents/${name}.md" (

View File

@@ -68,8 +68,15 @@ in
in
lib.mkMerge [
(mkIf cfg.enable {
# Auto-enable git integration if programs.git.diff-highlight.enable was set to true
programs.diff-highlight.enableGitIntegration = lib.mkIf oldOptionEnabled (lib.mkOverride 1490 true);
assertions = [
{
assertion = !cfg.enableGitIntegration || config.programs.git.package != null;
message = ''
programs.diff-highlight.enableGitIntegration requires programs.git.package to be set.
Please set programs.git.package to a valid git package.
'';
}
];
warnings =
lib.optional
@@ -77,9 +84,12 @@ in
cfg.enableGitIntegration && options.programs.diff-highlight.enableGitIntegration.highestPrio == 1490
)
"`programs.diff-highlight.enableGitIntegration` automatic enablement is deprecated. Please explicitly set `programs.diff-highlight.enableGitIntegration = true`.";
# Auto-enable git integration if programs.git.diff-highlight.enable was set to true
programs.diff-highlight.enableGitIntegration = lib.mkIf oldOptionEnabled (lib.mkOverride 1490 true);
})
(mkIf (cfg.enable && cfg.enableGitIntegration) {
(mkIf (cfg.enable && cfg.enableGitIntegration && config.programs.git.package != null) {
programs.git = {
enable = lib.mkDefault true;
iniContent =

View File

@@ -75,25 +75,7 @@ in
enableBashIntegration = lib.hm.shell.mkBashIntegrationOption { inherit config; };
enableFishIntegration =
lib.hm.shell.mkFishIntegrationOption {
inherit config;
extraDescription = ''
Note, enabling the direnv module will always activate its functionality
for Fish since the direnv package automatically gets loaded in Fish.
If this is not the case try adding
```nix
environment.pathsToLink = [ "/share/fish" ];
```
to the system configuration.
'';
}
// {
default = true;
readOnly = true;
};
enableFishIntegration = lib.hm.shell.mkFishIntegrationOption { inherit config; };
enableNushellIntegration = lib.hm.shell.mkNushellIntegrationOption { inherit config; };

View File

@@ -645,7 +645,7 @@ in
# Support completion for `man` by building a cache for `apropos`.
programs.man.generateCaches = lib.mkDefault true;
xdg.dataFile."fish/home-manager_generated_completions".source =
xdg.dataFile."fish/home-manager/generated_completions".source =
let
# Paths later in the list will overwrite those already linked
destructiveSymlinkJoin =
@@ -696,7 +696,7 @@ in
set -l post_joined (string replace $prev_joined "" $joined)
set -l prev (string split " " (string trim $prev_joined))
set -l post (string split " " (string trim $post_joined))
set fish_complete_path $prev "${config.xdg.dataHome}/fish/home-manager_generated_completions" $post
set fish_complete_path $prev "${config.xdg.dataHome}/fish/home-manager/generated_completions" $post
end
'';
}

View File

@@ -21,14 +21,19 @@ in
settings = lib.mkOption {
inherit (jsonFormat) type;
default = { };
example = lib.literalExpression ''
{
"theme": "Default",
"vimMode": true,
"preferredEditor": "nvim",
"autoAccept": true
}
'';
example = {
ui.theme = "Default";
general = {
vimMode = true;
preferredEditor = "nvim";
previewFeatures = true;
};
ide.enabled = true;
privacy.usageStatisticsEnabled = false;
tools.autoAccept = false;
context.loadMemoryFromIncludeDirectories = true;
security.auth.selectedType = "oauth-personal";
};
description = "JSON config for gemini-cli";
};
@@ -81,12 +86,12 @@ in
};
defaultModel = lib.mkOption {
type = lib.types.str;
default = "gemini-2.5-pro";
type = lib.types.nullOr lib.types.str;
default = null;
example = "gemini-2.5-flash";
description = ''
The default model to use for the CLI.
Will be set as $GEMINI_MODEL.
Will be set as $GEMINI_MODEL when configured.
'';
};
@@ -138,7 +143,9 @@ in
file.".gemini/settings.json" = lib.mkIf (cfg.settings != { }) {
source = jsonFormat.generate "gemini-cli-settings.json" cfg.settings;
};
sessionVariables.GEMINI_MODEL = cfg.defaultModel;
sessionVariables = lib.mkIf (cfg.defaultModel != null) {
GEMINI_MODEL = cfg.defaultModel;
};
};
}
{

View File

@@ -224,8 +224,24 @@ in
message = "Ghostty systemd integration cannot be enabled for non-linux platforms";
}
];
xdg.configFile."systemd/user/app-com.mitchellh.ghostty.service".source =
"${cfg.package}/share/systemd/user/app-com.mitchellh.ghostty.service";
xdg.configFile."systemd/user/app-com.mitchellh.ghostty.service.d/overrides.conf".text = ''
[Unit]
X-SwitchMethod=keep-old
X-Reload-Triggers=${
let
storePathOf = name: config.xdg.configFile.${name}.source;
in
toString (
lib.optionals (cfg.settings != { }) [ (storePathOf "ghostty/config") ]
++ lib.mapAttrsToList (name: _: storePathOf "ghostty/themes/${name}") cfg.themes
)
}
'';
dbus.packages = [ cfg.package ];
})

View File

@@ -41,6 +41,7 @@ in
enable = mkEnableOption "Git";
package = lib.mkPackageOption pkgs "git" {
nullable = true;
example = "pkgs.gitFull";
extraDescription = ''
Use {var}`pkgs.gitFull`
@@ -328,7 +329,7 @@ in
config = mkIf cfg.enable (
lib.mkMerge [
{
home.packages = [ cfg.package ];
home.packages = lib.optionals (cfg.package != null) [ cfg.package ];
assertions = [
{
@@ -516,7 +517,7 @@ in
Type = "oneshot";
ExecStart =
let
exe = lib.getExe cfg.package;
exe = if cfg.package != null then lib.getExe cfg.package else "git";
in
''
"${exe}" for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%i
@@ -553,7 +554,7 @@ in
launchd.agents =
let
baseArguments = [
"${lib.getExe cfg.package}"
"${if cfg.package != null then lib.getExe cfg.package else "git"}"
"for-each-repo"
"--keep-going"
"--config=maintenance.repo"

View File

@@ -16,18 +16,13 @@ let
cfg = config.programs.gpg;
mkKeyValue =
key: value: if lib.isString value then "${key} ${value}" else lib.optionalString value key;
cfgText = lib.generators.toKeyValue {
inherit mkKeyValue;
listsAsDuplicateKeys = true;
} cfg.settings;
scdaemonCfgText = lib.generators.toKeyValue {
inherit mkKeyValue;
listsAsDuplicateKeys = true;
} cfg.scdaemonSettings;
toKeyValue =
settings:
lib.generators.toKeyValue {
mkKeyValue =
key: value: if lib.isString value then "${key} ${value}" else lib.optionalString value key;
listsAsDuplicateKeys = true;
} settings;
primitiveType = types.oneOf [
types.str
@@ -193,6 +188,7 @@ in
scdaemonSettings = mkOption {
type = types.attrsOf (types.either primitiveType (types.listOf types.str));
default = { };
example = literalExpression ''
{
disable-ccid = true;
@@ -207,6 +203,41 @@ in
'';
};
dirmngrSettings = mkOption {
type = types.attrsOf (types.either primitiveType (types.listOf types.str));
default = { };
example = literalExpression ''
{
allow-version-check = true;
keyserver = "ldaps://ldap.example.com";
}
'';
description = ''
Dirmngr configuration options. Available options are described
in
[
{manpage}`dirmngr(1)`
](https://www.gnupg.org/documentation/manuals/gnupg/Dirmngr-Options.html)
'';
};
gpgsmSettings = mkOption {
type = types.attrsOf (types.either primitiveType (types.listOf types.str));
default = { };
example = literalExpression ''
{
with-key-data = true;
}
'';
description = ''
GPGSM configuration options. Available options are described
in
[
{manpage}`gpgsm(1)`
](https://www.gnupg.org/documentation/manuals/gnupg/GPGSM-Options.html)
'';
};
homedir = mkOption {
type = types.path;
example = literalExpression ''"''${config.xdg.dataHome}/gnupg"'';
@@ -267,8 +298,7 @@ in
cert-digest-algo = mkDefault "SHA512";
s2k-digest-algo = mkDefault "SHA512";
s2k-cipher-algo = mkDefault "AES256";
charset = mkDefault "utf-8";
fixed-list-mode = mkDefault true;
display-charset = mkDefault "utf-8";
no-comments = mkDefault true;
no-emit-version = mkDefault true;
keyid-format = mkDefault "0xlong";
@@ -277,11 +307,6 @@ in
with-fingerprint = mkDefault true;
require-cross-certification = mkDefault true;
no-symkey-cache = mkDefault true;
use-agent = mkDefault true;
};
programs.gpg.scdaemonSettings = {
# no defaults for scdaemon
};
home.packages = [ cfg.package ];
@@ -289,9 +314,21 @@ in
GNUPGHOME = cfg.homedir;
};
home.file."${cfg.homedir}/gpg.conf".text = cfgText;
home.file."${cfg.homedir}/gpg.conf" = mkIf (cfg.settings != { }) {
text = toKeyValue cfg.settings;
};
home.file."${cfg.homedir}/scdaemon.conf".text = scdaemonCfgText;
home.file."${cfg.homedir}/scdaemon.conf" = mkIf (cfg.scdaemonSettings != { }) {
text = toKeyValue cfg.scdaemonSettings;
};
home.file."${cfg.homedir}/dirmngr.conf" = mkIf (cfg.dirmngrSettings != { }) {
text = toKeyValue cfg.dirmngrSettings;
};
home.file."${cfg.homedir}/gpgsm.conf" = mkIf (cfg.gpgsmSettings != { }) {
text = toKeyValue cfg.gpgsmSettings;
};
# Link keyring if keys are not mutable
home.file."${cfg.homedir}/pubring.kbx" = mkIf (!cfg.mutableKeys && cfg.publicKeys != [ ]) {

View File

@@ -9,7 +9,7 @@ let
iniFormat = pkgs.formats.ini { };
in
{
meta.maintainers = with lib.maintainers; [ AndersonTorres ];
meta.maintainers = with lib.maintainers; [ ];
options.programs.havoc = {
enable = lib.mkEnableOption "Havoc terminal";

View File

@@ -49,7 +49,8 @@ in
default = false;
description = ''
Whether to configure {command}`hx` as the default
editor using the {env}`EDITOR` environment variable.
editor using the {env}`EDITOR` and {env}`VISUAL`
environment variables.
'';
};
@@ -225,7 +226,10 @@ in
else
[ cfg.package ];
home.sessionVariables = mkIf cfg.defaultEditor { EDITOR = "hx"; };
home.sessionVariables = mkIf cfg.defaultEditor {
EDITOR = "hx";
VISUAL = "hx";
};
xdg.configFile =
let

View File

@@ -9,7 +9,7 @@ let
jsonFormat = pkgs.formats.json { };
in
{
meta.maintainers = [ lib.maintainers.perchun ];
meta.maintainers = [ lib.maintainers.PerchunPak ];
imports = [
(lib.mkRemovedOptionModule [ "programs" "hyprpanel" "dontAssertNotificationDaemons " ] ''

View File

@@ -0,0 +1,81 @@
{
lib,
config,
pkgs,
...
}:
let
cfg = config.programs.infat;
tomlFormat = pkgs.formats.toml { };
configDir =
if config.xdg.enable then
config.xdg.configHome
else
"${config.home.homeDirectory}/Library/Application Support";
configFile = "${configDir}/infat/config.toml";
in
{
meta.maintainers = with lib.maintainers; [
mirkolenz
];
options = {
programs.infat = {
enable = lib.mkEnableOption "infat";
package = lib.mkPackageOption pkgs "infat" { nullable = true; };
settings = lib.mkOption {
type = tomlFormat.type;
default = { };
example = lib.literalExpression ''
{
extensions = {
md = "TextEdit";
html = "Safari";
pdf = "Preview";
};
schemes = {
mailto = "Mail";
web = "Safari";
};
types = {
plain-text = "VSCode";
};
}
'';
description = ''
Configuration written to
{file}`$XDG_CONFIG_HOME/infat/config.toml`.
'';
};
autoActivate = lib.mkEnableOption "auto-activate infat" // {
default = true;
example = false;
description = ''
Automatically activate infat on startup.
This is useful if you want to use infat as a
default application handler for certain file types.
If you don't want this, set this to false.
This option is only effective if `settings` is set.
'';
};
};
};
config = lib.mkIf cfg.enable {
assertions = [
(lib.hm.assertions.assertPlatform "programs.infat" pkgs lib.platforms.darwin)
];
home = {
packages = lib.mkIf (cfg.package != null) [ cfg.package ];
file.${configFile} = lib.mkIf (cfg.settings != { }) {
source = tomlFormat.generate "infat-settings.toml" cfg.settings;
};
activation = lib.mkIf (cfg.settings != { } && cfg.package != null && cfg.autoActivate) {
infat = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
run ${lib.getExe cfg.package} --config "${configFile}" $VERBOSE_ARG
'';
};
};
};
}

View File

@@ -705,7 +705,8 @@ in
default = false;
description = ''
Whether to configure {command}`kak` as the default
editor using the {env}`EDITOR` environment variable.
editor using the {env}`EDITOR` and {env}`VISUAL`
environment variables.
'';
};
@@ -755,7 +756,10 @@ in
programs.kakoune.finalPackage = lib.mkIf (cfg.package != null) kakouneWithPlugins;
home.packages = lib.mkIf (cfg.finalPackage != null) [ cfg.finalPackage ];
home.sessionVariables = mkIf cfg.defaultEditor { EDITOR = "kak"; };
home.sessionVariables = mkIf cfg.defaultEditor {
EDITOR = "kak";
VISUAL = "kak";
};
xdg.configFile = lib.mkMerge [
{ "kak/kakrc".source = configFile; }
(mkIf (cfg.colorSchemePackage != null) {

View File

@@ -62,8 +62,15 @@ in
Configuration written to
{file}`$XDG_CONFIG_HOME/keepassxc/keepassxc.ini`.
See <https://github.com/keepassxreboot/keepassxc/blob/647272e9c5542297d3fcf6502e6173c96f12a9a0/src/core/Config.cpp#L49-L223>
See <https://github.com/keepassxreboot/keepassxc/blob/develop/src/core/Config.cpp>
for the full list of options.
::: {.note}
When the settings are non-empty, the configuration file will be linked
into the Nix store and KeePassXC will report an access error for its
configuration file. This is expected and can not be fixed in a way that
aligns with Home Manager's principles. See [#8257](https://github.com/nix-community/home-manager/issues/8257) for more details.
:::
'';
};

View File

@@ -37,13 +37,17 @@ in
options = lib.mkOption {
type =
with lib.types;
attrsOf (oneOf [
bool
int
str
]);
default = { };
description = "GNU-style options to be set via {env}`$LESS`.";
let
scalar = oneOf [
bool
int
str
];
attrs = attrsOf (either scalar (listOf scalar));
in
coercedTo attrs (lib.cli.toGNUCommandLine { }) (listOf str);
default = [ ];
description = "Options to be set via {env}`$LESS`.";
example = {
RAW-CONTROL-CHARS = true;
quiet = true;
@@ -58,10 +62,10 @@ in
xdg.configFile."lesskey" = lib.mkIf (cfg.config != "") { text = cfg.config; };
programs.less.config = lib.mkIf (cfg.options != { }) (
programs.less.config = lib.mkIf (cfg.options != [ ]) (
lib.mkBefore ''
#env
LESS = ${lib.cli.toGNUCommandLineShell { } cfg.options}
LESS = ${lib.concatStringsSep " " cfg.options}
''
);
};

View File

@@ -24,7 +24,8 @@ let
meliAccounts = (lib.attrsets.mapAttrs (name: value: (mkMeliAccounts name value)) enabledAccounts);
mkMeliAccounts = (
name: account: {
name: account:
{
root_mailbox = "${config.accounts.email.maildirBasePath}/${account.maildir.path}";
format = "Maildir";
identity = account.address;
@@ -33,6 +34,14 @@ let
send_mail = mkSmtp account;
mailboxes = account.meli.mailboxAliases;
}
// lib.optionalAttrs (account.flavor == "fastmail.com") {
server_username = account.userName;
server_password_command = lib.concatMapStringsSep " " lib.escapeShellArg account.passwordCommand;
format = "jmap";
server_url = "https://api.fastmail.com/jmap/session";
use_token = true;
}
// account.meli.settings
);
mkSmtp = account: {
@@ -153,6 +162,14 @@ in
};
description = "Folder display name";
};
settings = mkOption {
type = types.submodule {
freeformType = tomlFormat.type;
};
default = { };
description = "Account specific meli configuration";
};
};
}
)
@@ -160,6 +177,15 @@ in
};
};
config = mkIf config.programs.meli.enable {
assertions = [
{
assertion = cfg.settings ? accounts == false;
message = ''
programs.meli.settings.accounts override the accounts.email values.
Use per-email accounts.email.<ACCOUNT>.meli.settings instead'';
}
];
home.packages = [ config.programs.meli.package ];
# Generate meli configuration from email accounts

View File

@@ -7,121 +7,46 @@
let
inherit (lib)
concatMapStringsSep
literalExpression
mkEnableOption
mkIf
mkOption
mkRemovedOptionModule
mkPackageOption
optionals
types
;
cfg = config.programs.neovim;
fileType =
(import ../lib/file-type.nix {
inherit (config.home) homeDirectory;
inherit lib pkgs;
}).fileType;
inherit
(
(import ../lib/file-type.nix {
inherit (config.home) homeDirectory;
inherit lib pkgs;
})
)
fileType
;
jsonFormat = pkgs.formats.json { };
pluginWithConfigType = types.submodule {
options = {
config = mkOption {
type = types.nullOr types.lines;
description = "Script to configure this plugin. The scripting language should match type.";
default = null;
};
type = mkOption {
type = types.either (types.enum [
"lua"
"viml"
"teal"
"fennel"
]) types.str;
description = "Language used in config. Configurations are aggregated per-language.";
default = "viml";
};
optional = mkEnableOption "optional" // {
description = "Don't load by default (load with :packadd)";
};
plugin = lib.mkPackageOption pkgs.vimPlugins "plugin" {
default = null;
example = "pkgs.vimPlugins.nvim-treesitter";
pkgsText = "pkgs.vimPlugins";
};
runtime = mkOption {
default = { };
# passing actual "${xdg.configHome}/nvim" as basePath was a bit tricky
# due to how fileType.target is implemented
type = fileType "programs.neovim.plugins._.runtime" "{var}`xdg.configHome/nvim`" "nvim";
example = literalExpression ''
{ "ftplugin/c.vim".text = "setlocal omnifunc=v:lua.vim.lsp.omnifunc"; }
'';
description = ''
Set of files that have to be linked in nvim config folder.
'';
};
};
};
allPlugins =
cfg.plugins
++ lib.optional cfg.coc.enable {
type = "viml";
plugin = cfg.coc.package;
config = cfg.coc.pluginConfig;
optional = false;
};
luaPackages = cfg.finalPackage.unwrapped.lua.pkgs;
resolvedExtraLuaPackages = cfg.extraLuaPackages luaPackages;
extraMakeWrapperArgs = lib.optionalString (
cfg.extraPackages != [ ]
) ''--suffix PATH : "${lib.makeBinPath cfg.extraPackages}"'';
extraMakeWrapperLuaCArgs =
lib.optionalString (resolvedExtraLuaPackages != [ ])
''--suffix LUA_CPATH ";" "${
lib.concatMapStringsSep ";" luaPackages.getLuaCPath resolvedExtraLuaPackages
}"'';
extraMakeWrapperLuaArgs =
lib.optionalString (resolvedExtraLuaPackages != [ ])
''--suffix LUA_PATH ";" "${
lib.concatMapStringsSep ";" luaPackages.getLuaPath resolvedExtraLuaPackages
}"'';
in
{
meta.maintainers = with lib.maintainers; [ khaneliman ];
imports = [
(mkRemovedOptionModule [
"programs"
"neovim"
"withPython"
] "Python2 support has been removed from neovim.")
(mkRemovedOptionModule [
"programs"
"neovim"
"extraPythonPackages"
] "Python2 support has been removed from neovim.")
(mkRemovedOptionModule [ "programs" "neovim" "configure" ] ''
programs.neovim.configure is deprecated.
Other programs.neovim options can override its settings or ignore them.
Please use the other options at your disposal:
configure.packages.*.opt -> programs.neovim.plugins = [ { plugin = ...; optional = true; }]
configure.packages.*.start -> programs.neovim.plugins = [ { plugin = ...; }]
configure.customRC -> programs.neovim.extraConfig
'')
];
options = {
programs.neovim = {
enable = mkEnableOption "Neovim";
package = mkPackageOption pkgs "neovim" { default = "neovim-unwrapped"; };
finalPackage = mkOption {
type = types.package;
readOnly = true;
description = "Resulting customized neovim package.";
};
# Aliases
viAlias = mkOption {
type = types.bool;
default = false;
@@ -146,6 +71,17 @@ in
'';
};
defaultEditor = mkOption {
type = types.bool;
default = false;
description = ''
Whether to configure {command}`nvim` as the default
editor using the {env}`EDITOR` and {env}`VISUAL`
environment variables.
'';
};
# Providers & Runtimes
withNodeJs = mkOption {
type = types.bool;
default = false;
@@ -155,11 +91,12 @@ in
'';
};
withRuby = mkOption {
type = types.nullOr types.bool;
default = true;
withPerl = mkOption {
type = types.bool;
default = false;
description = ''
Enable ruby provider.
Enable perl provider. Set to `true` to
use Perl plugins.
'';
};
@@ -172,21 +109,16 @@ in
'';
};
withRuby = mkOption {
type = types.nullOr types.bool;
default = true;
description = ''
Enable ruby provider.
'';
};
extraPython3Packages = mkOption {
# In case we get a plain list, we need to turn it into a function,
# as expected by the function in nixpkgs.
# The only way to do so is to call `const`, which will ignore its input.
type =
let
fromType = types.listOf types.package;
in
types.coercedTo fromType (lib.flip lib.warn lib.const ''
Assigning a plain list to extraPython3Packages is deprecated.
Please assign a function taking a package set as argument, so
extraPython3Packages = [ pkgs.python3Packages.xxx ];
should become
extraPython3Packages = ps: [ ps.xxx ];
'') (types.functionTo fromType);
type = types.functionTo (types.listOf types.package);
default = _: [ ];
defaultText = literalExpression "ps: [ ]";
example = literalExpression "pyPkgs: with pyPkgs; [ python-language-server ]";
@@ -198,21 +130,8 @@ in
'';
};
# We get the Lua package from the final package and use its
# Lua packageset to evaluate the function that this option was set to.
# This ensures that we always use the same Lua version as the Neovim package.
extraLuaPackages = mkOption {
type =
let
fromType = types.listOf types.package;
in
types.coercedTo fromType (lib.flip lib.warn lib.const ''
Assigning a plain list to extraLuaPackages is deprecated.
Please assign a function taking a package set as argument, so
extraLuaPackages = [ pkgs.lua51Packages.xxx ];
should become
extraLuaPackages = ps: [ ps.xxx ];
'') (types.functionTo fromType);
type = types.functionTo (types.listOf types.package);
default = _: [ ];
defaultText = literalExpression "ps: [ ]";
example = literalExpression "luaPkgs: with luaPkgs; [ luautf8 ]";
@@ -224,8 +143,34 @@ in
'';
};
# Wrapper Configuration
extraName = mkOption {
type = types.str;
default = "";
description = ''
Extra name appended to the wrapper package name.
'';
};
autowrapRuntimeDeps = mkOption {
type = types.bool;
default = true;
description = ''
Whether to automatically wrap the binary with the runtime dependencies of the plugins.
'';
};
waylandSupport = mkOption {
type = types.bool;
default = pkgs.stdenv.isLinux;
defaultText = literalExpression "pkgs.stdenv.isLinux";
description = ''
Whether to enable Wayland clipboard support.
'';
};
extraWrapperArgs = mkOption {
type = with types; listOf str;
type = types.listOf types.str;
default = [ ];
example = literalExpression ''
[
@@ -246,53 +191,14 @@ in
'';
};
generatedConfigViml = mkOption {
type = types.lines;
visible = true;
readOnly = true;
description = ''
Generated vimscript config.
'';
};
generatedConfigs = mkOption {
type = types.attrsOf types.lines;
visible = true;
readOnly = true;
example = literalExpression ''
{
viml = '''
" Generated by home-manager
map <leader> ,
''';
lua = '''
-- Generated by home-manager
vim.opt.background = "dark"
''';
}'';
description = ''
Generated configurations with as key their language (set via type).
'';
};
package = lib.mkPackageOption pkgs "neovim" { default = "neovim-unwrapped"; };
finalPackage = mkOption {
type = types.package;
readOnly = true;
description = "Resulting customized neovim package.";
};
defaultEditor = mkOption {
type = types.bool;
default = false;
description = ''
Whether to configure {command}`nvim` as the default
editor using the {env}`EDITOR` environment variable.
'';
extraPackages = mkOption {
type = types.listOf types.package;
default = [ ];
example = literalExpression "[ pkgs.shfmt ]";
description = "Extra packages available to nvim.";
};
# Configuration & Plugins
extraConfig = mkOption {
type = types.lines;
default = "";
@@ -307,45 +213,92 @@ in
extraLuaConfig = mkOption {
type = types.lines;
default = "";
example = ''
vim.opt.nobackup = true
example = lib.literalExpression ''
let
nvimEarlyInit = lib.mkOrder 500 "set rtp+=vim.opt.rtp:prepend('/home/user/myplugin')";
nvimLateInit = lib.mkAfter "vim.opt.signcolumn = 'auto:1-3'";
in
lib.mkMerge [ nvimEarlyInit nvimLateInit ];
'';
description = ''
Custom lua lines.
Content to be added to {file}`init.lua`.
To specify the order, use `lib.mkOrder`, `lib.mkBefore`, `lib.mkAfter`.
'';
};
extraPackages = mkOption {
type = with types; listOf package;
default = [ ];
example = literalExpression "[ pkgs.shfmt ]";
description = "Extra packages available to nvim.";
};
plugins =
let
pluginWithConfigType = types.submodule {
options = {
config = mkOption {
type = types.nullOr types.lines;
description = "Script to configure this plugin. The scripting language should match type.";
default = null;
};
plugins = mkOption {
type = with types; listOf (either package pluginWithConfigType);
default = [ ];
example = literalExpression ''
with pkgs.vimPlugins; [
yankring
vim-nix
{ plugin = vim-startify;
config = "let g:startify_change_to_vcs_root = 0";
}
]
'';
description = ''
List of vim plugins to install optionally associated with
configuration to be placed in init.vim.
type = mkOption {
type = types.either (types.enum [
"lua"
"viml"
"teal"
"fennel"
]) types.str;
description = "Language used in config. Configurations are aggregated per-language.";
default = "viml";
};
This option is mutually exclusive with {var}`configure`.
'';
};
optional = mkEnableOption "optional" // {
description = "Don't load by default (load with :packadd)";
};
plugin = mkPackageOption pkgs.vimPlugins "plugin" {
default = null;
example = "pkgs.vimPlugins.nvim-treesitter";
pkgsText = "pkgs.vimPlugins";
};
runtime = mkOption {
default = { };
# passing actual "${xdg.configHome}/nvim" as basePath was a bit tricky
# due to how fileType.target is implemented
type = fileType "programs.neovim.plugins._.runtime" "{var}`xdg.configHome/nvim`" "nvim";
example = literalExpression ''
{ "ftplugin/c.vim".text = "setlocal omnifunc=v:lua.vim.lsp.omnifunc"; }
'';
description = ''
Set of files that have to be linked in nvim config folder.
'';
};
};
};
in
mkOption {
type = types.listOf (types.either types.package pluginWithConfigType);
default = [ ];
example = literalExpression ''
with pkgs.vimPlugins;
[
yankring
vim-nix
{ plugin = vim-startify;
config = "let g:startify_change_to_vcs_root = 0";
}
]
'';
description = ''
List of vim plugins to install optionally associated with
configuration to be placed in init.vim.
This option is mutually exclusive with {var}`configure`.
'';
};
coc = {
enable = mkEnableOption "Coc";
package = lib.mkPackageOption pkgs "coc-nvim" {
package = mkPackageOption pkgs "coc-nvim" {
default = [
"vimPlugins"
"coc-nvim"
@@ -375,7 +328,7 @@ in
filetypes = [ "haskell" "lhaskell" ];
};
};
};
}
'';
description = ''
Extra configuration lines to add to
@@ -392,11 +345,52 @@ in
description = "Script to configure CoC. Must be viml.";
};
};
# Generated / Read-Only
generatedConfigViml = mkOption {
type = types.lines;
visible = true;
readOnly = true;
description = ''
Generated vimscript config.
'';
};
generatedConfigs = mkOption {
type = types.attrsOf types.lines;
visible = true;
readOnly = true;
example = literalExpression ''
{
viml = '''
" Generated by home-manager
map <leader> ,
''';
lua = '''
-- Generated by home-manager
vim.opt.background = "dark"
''';
}
'';
description = ''
Generated configurations with as key their language (set via type).
'';
};
};
};
config =
config = mkIf cfg.enable (
let
allPlugins =
cfg.plugins
++ lib.optional cfg.coc.enable {
type = "viml";
plugin = cfg.coc.package;
config = cfg.coc.pluginConfig;
optional = false;
};
defaultPlugin = {
type = "viml";
plugin = null;
@@ -412,78 +406,100 @@ in
suppressNotVimlConfig = p: if p.type != "viml" then p // { config = null; } else p;
neovimConfig = pkgs.neovimUtils.makeNeovimConfig {
# Lua & Python Package Resolution
luaPackages = cfg.finalPackage.unwrapped.lua.pkgs;
resolvedExtraLuaPackages = cfg.extraLuaPackages luaPackages;
# Wrapper Arguments Construction
extraMakeWrapperArgs = optionals (cfg.extraPackages != [ ]) [
"--suffix"
"PATH"
":"
(lib.makeBinPath cfg.extraPackages)
];
extraMakeWrapperLuaCArgs = optionals (resolvedExtraLuaPackages != [ ]) [
"--suffix"
"LUA_CPATH"
";"
(concatMapStringsSep ";" luaPackages.getLuaCPath resolvedExtraLuaPackages)
];
extraMakeWrapperLuaArgs = optionals (resolvedExtraLuaPackages != [ ]) [
"--suffix"
"LUA_PATH"
";"
(concatMapStringsSep ";" luaPackages.getLuaPath resolvedExtraLuaPackages)
];
wrappedNeovim' = pkgs.wrapNeovimUnstable cfg.package {
withNodeJs = cfg.withNodeJs || cfg.coc.enable;
plugins = map suppressNotVimlConfig pluginsNormalized;
inherit (cfg)
extraPython3Packages
withPython3
withRuby
withPerl
viAlias
vimAlias
extraName
autowrapRuntimeDeps
waylandSupport
;
withNodeJs = cfg.withNodeJs || cfg.coc.enable;
plugins = map suppressNotVimlConfig pluginsNormalized;
customRC = cfg.extraConfig;
neovimRcContent = cfg.extraConfig;
wrapperArgs =
cfg.extraWrapperArgs ++ extraMakeWrapperArgs ++ extraMakeWrapperLuaCArgs ++ extraMakeWrapperLuaArgs;
wrapRc = false;
};
in
{
programs.neovim = {
generatedConfigViml = cfg.extraConfig;
generatedConfigs =
let
grouped = lib.groupBy (x: x.type) pluginsNormalized;
configsOnly = lib.foldl (acc: p: if p.config != null then acc ++ [ p.config ] else acc) [ ];
in
lib.mapAttrs (_name: vals: lib.concatStringsSep "\n" (configsOnly vals)) grouped;
finalPackage = wrappedNeovim';
};
wrappedNeovim' = pkgs.wrapNeovimUnstable cfg.package (
neovimConfig
// {
wrapperArgs =
(lib.escapeShellArgs (neovimConfig.wrapperArgs ++ cfg.extraWrapperArgs))
+ " "
+ extraMakeWrapperArgs
+ " "
+ extraMakeWrapperLuaCArgs
+ " "
+ extraMakeWrapperLuaArgs;
wrapRc = false;
}
home = {
packages = [ cfg.finalPackage ];
sessionVariables = mkIf cfg.defaultEditor {
EDITOR = "nvim";
VISUAL = "nvim";
};
shellAliases = mkIf cfg.vimdiffAlias { vimdiff = "nvim -d"; };
};
programs.neovim.extraLuaConfig = lib.mkMerge [
(lib.mkIf (wrappedNeovim'.initRc != "") (
lib.mkBefore "vim.cmd [[source ${pkgs.writeText "nvim-init-home-manager.vim" wrappedNeovim'.initRc}]]"
))
(lib.mkIf (lib.hasAttr "lua" cfg.generatedConfigs) (lib.mkAfter cfg.generatedConfigs.lua))
];
xdg.configFile = lib.mkMerge (
# writes runtime
(map (x: x.runtime) pluginsNormalized)
++ [
{
"nvim/init.lua" = mkIf (cfg.extraLuaConfig != "") {
text = cfg.extraLuaConfig;
};
"nvim/coc-settings.json" = mkIf cfg.coc.enable {
source = jsonFormat.generate "coc-settings.json" cfg.coc.settings;
};
}
]
);
in
mkIf cfg.enable {
programs.neovim.generatedConfigViml = neovimConfig.neovimRcContent;
programs.neovim.generatedConfigs =
let
grouped = lib.lists.groupBy (x: x.type) pluginsNormalized;
configsOnly = lib.foldl (acc: p: if p.config != null then acc ++ [ p.config ] else acc) [ ];
in
lib.mapAttrs (name: vals: lib.concatStringsSep "\n" (configsOnly vals)) grouped;
home.packages = [ cfg.finalPackage ];
home.sessionVariables = mkIf cfg.defaultEditor { EDITOR = "nvim"; };
home.shellAliases = mkIf cfg.vimdiffAlias { vimdiff = "nvim -d"; };
xdg.configFile =
let
hasLuaConfig = lib.hasAttr "lua" config.programs.neovim.generatedConfigs;
in
lib.mkMerge (
# writes runtime
(map (x: x.runtime) pluginsNormalized)
++ [
{
"nvim/init.lua" =
let
luaRcContent =
lib.optionalString (
wrappedNeovim'.initRc != ""
) "vim.cmd [[source ${pkgs.writeText "nvim-init-home-manager.vim" wrappedNeovim'.initRc}]]\n"
+ config.programs.neovim.extraLuaConfig
+ lib.optionalString hasLuaConfig config.programs.neovim.generatedConfigs.lua;
in
mkIf (luaRcContent != "") { text = luaRcContent; };
"nvim/coc-settings.json" = mkIf cfg.coc.enable {
source = jsonFormat.generate "coc-settings.json" cfg.coc.settings;
};
}
]
);
programs.neovim.finalPackage = wrappedNeovim';
};
}
);
}

View File

@@ -100,7 +100,7 @@ in
lib.optional (cfg.clean.enable && config.nix.gc.automatic)
"programs.nh.clean.enable and nix.gc.automatic (Home-Manager) are both enabled. Please use one or the other to avoid conflict.";
assertions = lib.optionals pkgs.stdenv.isDarwin [
assertions = [
(lib.hm.darwin.assertInterval "programs.nh.clean.dates" cfg.clean.dates pkgs)
];
@@ -131,30 +131,25 @@ in
];
};
systemd.user = lib.mkIf (cfg.clean.enable && pkgs.stdenv.isLinux) {
systemd.user = lib.mkIf cfg.clean.enable {
services.nh-clean = {
Unit.Description = "Nh clean (user)";
Service = {
Type = "oneshot";
ExecStart = "${lib.getExe cfg.package} clean user ${cfg.clean.extraArgs}";
};
};
timers.nh-clean = {
Unit.Description = "Run nh clean";
Timer = {
OnCalendar = cfg.clean.dates;
Persistent = true;
};
Install.WantedBy = [ "timers.target" ];
};
};
launchd.agents.nh-clean = lib.mkIf (cfg.clean.enable && pkgs.stdenv.isDarwin) {
launchd.agents.nh-clean = lib.mkIf cfg.clean.enable {
enable = true;
config = {
ProgramArguments = [
@@ -163,9 +158,7 @@ in
"user"
]
++ lib.optional (cfg.clean.extraArgs != "") cfg.clean.extraArgs;
StartCalendarInterval = lib.hm.darwin.mkCalendarInterval cfg.clean.dates;
};
};
};

View File

@@ -66,10 +66,7 @@ in
config = lib.mkIf cfg.enable {
assertions = [
{
assertion = pkgs.stdenv.hostPlatform.isLinux;
message = "niriswitcher is only available on Linux.";
}
(lib.hm.assertions.assertPlatform "programs.niriswitcher" pkgs lib.platforms.linux)
];
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];

74
modules/programs/npm.nix Normal file
View File

@@ -0,0 +1,74 @@
# https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/programs/npm.nix
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.npm;
xdgConfigHome = lib.removePrefix config.home.homeDirectory config.xdg.configHome;
configFile = if config.home.preferXdgDirectories then "${xdgConfigHome}/npm/npmrc" else ".npmrc";
iniFormat = pkgs.formats.ini {
listsAsDuplicateKeys = true;
};
toNpmrc =
let
mkLine = lib.generators.mkKeyValueDefault { } "=";
mkLines = k: v: if lib.isList v then map (x: mkLine "${k}[]" x) v else [ (mkLine k v) ];
in
attrs: lib.concatLines (lib.concatLists (lib.mapAttrsToList mkLines attrs));
in
{
meta.maintainers = with lib.maintainers; [ mirkolenz ];
options = {
programs.npm = {
enable = lib.mkEnableOption "{command}`npm` user config";
package = lib.mkPackageOption pkgs [ "nodejs" ] {
example = "nodejs_24";
nullable = true;
};
settings = lib.mkOption {
type = lib.types.attrsOf iniFormat.lib.types.atom;
description = ''
The user-specific npm configuration.
See <https://docs.npmjs.com/cli/using-npm/config> and
<https://docs.npmjs.com/cli/configuring-npm/npmrc>
for more information.
'';
default = {
prefix = "\${HOME}/.npm";
};
example = lib.literalExpression ''
{
color = true;
include = [
"dev"
"prod"
];
init-license = "MIT";
prefix = "''${HOME}/.npm";
}
'';
};
};
};
config = lib.mkIf cfg.enable {
home = {
packages = lib.mkIf (cfg.package != null) [ cfg.package ];
file.${configFile} = lib.mkIf (cfg.settings != { }) {
text = toNpmrc cfg.settings;
};
sessionVariables = lib.mkIf (cfg.settings != { }) {
NPM_CONFIG_USERCONFIG = "${config.home.homeDirectory}/${configFile}";
};
};
};
}

View File

@@ -133,7 +133,7 @@ in
The attribute name becomes the command filename, and the value is either:
- Inline content as a string
- A path to a file containing the command content
Commands are stored in {file}`$XDG_CONFIG_HOME/.config/opencode/command/` directory.
Commands are stored in {file}`$XDG_CONFIG_HOME/opencode/command/` directory.
'';
example = lib.literalExpression ''
{
@@ -162,7 +162,7 @@ in
The attribute name becomes the agent filename, and the value is either:
- Inline content as a string
- A path to a file containing the agent content
Agents are stored in {file}`$XDG_CONFIG_HOME/.config/opencode/agent/` directory.
Agents are stored in {file}`$XDG_CONFIG_HOME/opencode/agent/` directory.
'';
example = lib.literalExpression ''
{
@@ -183,6 +183,49 @@ in
'';
};
skills = lib.mkOption {
type = lib.types.either (lib.types.attrsOf (lib.types.either lib.types.lines lib.types.path)) lib.types.path;
default = { };
description = ''
Custom agent skills for opencode.
This option can either be:
- An attribute set defining skills
- A path to a directory containing multiple skill folders
If an attribute set is used, the attribute name becomes the skill directory name,
and the value is either:
- Inline content as a string (creates `opencode/skill/<name>/SKILL.md`)
- A path to a file (creates `opencode/skill/<name>/SKILL.md`)
- A path to a directory (creates `opencode/skill/<name>/` with all files)
If a path is used, it is expected to contain one folder per skill name, each
containing a {file}`SKILL.md`. The directory is symlinked to
{file}`$XDG_CONFIG_HOME/opencode/skill/`.
See <https://opencode.ai/docs/skills/> for the documentation.
'';
example = lib.literalExpression ''
{
git-release = '''
---
name: git-release
description: Create consistent releases and changelogs
---
## What I do
- Draft release notes from merged PRs
- Propose a version bump
- Provide a copy-pasteable `gh release create` command
''';
# A skill can also be a directory containing SKILL.md and other files.
data-analysis = ./skills/data-analysis;
}
'';
};
themes = mkOption {
type = lib.types.attrsOf (lib.types.either jsonFormat.type lib.types.path);
default = { };
@@ -199,6 +242,13 @@ in
};
config = mkIf cfg.enable {
assertions = [
{
assertion = !lib.isPath cfg.skills || lib.pathIsDirectory cfg.skills;
message = "`programs.opencode.skills` must be a directory when set to a path";
}
];
home.packages = mkIf (cfg.package != null) [ cfg.package ];
xdg.configFile = {
@@ -227,6 +277,11 @@ in
text = cfg.rules;
})
);
"opencode/skill" = mkIf (lib.isPath cfg.skills) {
source = cfg.skills;
recursive = true;
};
}
// lib.mapAttrs' (
name: content:
@@ -240,6 +295,18 @@ in
if lib.isPath content then { source = content; } else { text = content; }
)
) cfg.agents
// lib.mapAttrs' (
name: content:
if lib.isPath content && lib.pathIsDirectory content then
lib.nameValuePair "opencode/skill/${name}" {
source = content;
recursive = true;
}
else
lib.nameValuePair "opencode/skill/${name}/SKILL.md" (
if lib.isPath content then { source = content; } else { text = content; }
)
) (if builtins.isAttrs cfg.skills then cfg.skills else { })
// lib.mapAttrs' (
name: content:
lib.nameValuePair "opencode/themes/${name}.json" (

View File

@@ -0,0 +1,42 @@
{
config,
lib,
pkgs,
...
}:
let
inherit (lib)
mkIf
mkEnableOption
mkOption
types
;
cfg = config.programs.parallel;
in
{
meta.maintainers = [ lib.maintainers.xavwe ];
options.programs.parallel = {
enable = mkEnableOption "GNU Parallel";
package = lib.mkPackageOption pkgs "parallel-full" { nullable = true; };
will-cite = mkOption {
type = types.bool;
default = false;
description = ''
Accept GNU Parallels citation policy: <https://www.gnu.org/software/parallel/parallel_design.html#citation-notice>
'';
};
};
config = mkIf cfg.enable {
home = {
packages = lib.mkIf (cfg.package != null) [ cfg.package ];
file.".parallel/will-cite" = mkIf cfg.will-cite {
text = "generated by home manager (programs.parallel.will-cite)";
};
};
};
}

View File

@@ -51,7 +51,7 @@
localStorage = calendar: name: acc: {
name = "storage";
params = [ "${name}-local" ];
params = [ "${if calendar then "calendar" else "contacts"}-${name}-local" ];
children =
(attrsToDirectives {
inherit (acc.local) path;
@@ -63,7 +63,7 @@
remoteStorage = calendar: name: acc: {
name = "storage";
params = [ "${name}-remote" ];
params = [ "${if calendar then "calendar" else "contacts"}-${name}-remote" ];
children =
(attrsToDirectives {
inherit (acc.remote) url;
@@ -91,8 +91,8 @@
params = lib.singleton "${if calendar then "calendar" else "contacts"}-${name}";
children =
(attrsToDirectives {
storage_a = "${name}-local";
storage_b = "${name}-remote";
storage_a = "${if calendar then "calendar" else "contacts"}-${name}-local";
storage_b = "${if calendar then "calendar" else "contacts"}-${name}-remote";
})
++ acc.pimsync.extraPairDirectives;
};

View File

@@ -153,7 +153,7 @@ in
default = { };
apply = lib.mergeAttrs {
vfs-cache-mode = "full";
cache-dir = "%C";
cache-dir = "%C/rclone";
};
description = ''
An attribute set of option values passed to `rclone mount`. To set

View File

@@ -0,0 +1,55 @@
{
lib,
pkgs,
config,
...
}:
let
inherit (lib)
types
mkIf
mkEnableOption
mkPackageOption
mkOption
;
cfg = config.programs.screen;
in
{
meta.maintainers = with lib.hm.maintainers; [ aguirre-matteo ];
options.programs.screen = {
enable = mkEnableOption "screen";
package = mkPackageOption pkgs "screen" { nullable = true; };
screenrc = mkOption {
type = with types; nullOr (either path lines);
default = null;
example = ''
screen -t rtorrent rtorrent
screen -t irssi irssi
screen -t centerim centerim
screen -t ncmpc ncmpc -c
screen -t bash4
screen -t bash5
screen -t bash6
screen -t bash7
screen -t bash8
screen -t bash9
altscreen on
term screen-256color
bind ',' prev
bind '.' next
'';
description = ''
Config file for GNU Screen. All the details can be found here:
<https://www.gnu.org/software/screen/manual/screen.html>.
'';
};
};
config = mkIf cfg.enable {
home.packages = mkIf (cfg.package != null) [ cfg.package ];
home.file.".screenrc" = mkIf (cfg.screenrc != null) {
source = if lib.isPath cfg.screenrc then cfg.screenrc else pkgs.writeText "screenrc" cfg.screenrc;
};
};
}

View File

@@ -52,7 +52,7 @@ in
eval "$(sheldon source)"
'';
programs.zsh.initExtra = mkIf cfg.enableZshIntegration ''
programs.zsh.initContent = mkIf cfg.enableZshIntegration ''
eval "$(sheldon source)"
'';

View File

@@ -30,44 +30,42 @@ let
mapAttrsToList (name: value: ''${name}="${lib.escape [ ''"'' "\\" ] (toString value)}"'') envStr
);
bindOptions = {
address = mkOption {
type = types.str;
default = "localhost";
example = "example.org";
description = "The address where to bind the port.";
};
port = mkOption {
type = types.nullOr types.port;
default = null;
example = 8080;
description = "Specifies port number to bind on bind address.";
};
};
dynamicForwardModule = types.submodule { options = bindOptions; };
forwardModule = types.submodule {
options = {
bind = bindOptions;
host = {
mkAddressPortModule =
{
actionType,
nullableAddress ? actionType == "forward",
}:
types.submodule {
options = {
address = mkOption {
type = types.nullOr types.str;
default = null;
type = if nullableAddress then types.nullOr types.str else types.str;
default = if nullableAddress then null else "localhost";
example = "example.org";
description = "The address where to forward the traffic to.";
description = "The address to ${actionType} to.";
};
port = mkOption {
type = types.nullOr types.port;
default = null;
example = 80;
description = "Specifies port number to forward the traffic to.";
example = 8080;
description = "Specifies port number to ${actionType} to.";
};
};
};
dynamicForwardModule = mkAddressPortModule { actionType = "bind"; };
forwardModule = types.submodule {
options = {
bind = mkOption {
type = mkAddressPortModule { actionType = "bind"; };
description = "Local port binding options";
};
host = mkOption {
type = mkAddressPortModule { actionType = "forward"; };
description = "Host port binding options";
};
};
};
matchBlockModule = types.submodule {
@@ -151,14 +149,7 @@ let
identityFile = mkOption {
type = with types; either (listOf str) (nullOr str);
default = [ ];
apply =
p:
if p == null then
[ ]
else if lib.isString p then
[ p ]
else
p;
apply = p: if p == null then [ ] else lib.toList p;
description = ''
Specifies files from which the user identity is read.
Identities will be tried in the given order.
@@ -168,14 +159,7 @@ let
identityAgent = mkOption {
type = with types; either (listOf str) (nullOr str);
default = [ ];
apply =
p:
if p == null then
[ ]
else if lib.isString p then
[ p ]
else
p;
apply = p: if p == null then [ ] else lib.toList p;
description = ''
Specifies the location of the ssh identity agent.
'';
@@ -265,14 +249,7 @@ let
certificateFile = mkOption {
type = with types; either (listOf str) (nullOr str);
default = [ ];
apply =
p:
if p == null then
[ ]
else if lib.isString p then
[ p ]
else
p;
apply = p: if p == null then [ ] else lib.toList p;
description = ''
Specifies files from which the user certificate is read.
'';
@@ -404,6 +381,18 @@ let
example = "10m";
description = "Whether control socket should remain open in the background.";
};
kexAlgorithms = mkOption {
type = types.nullOr (types.listOf types.str);
default = null;
example = [
"curve25519-sha256@libssh.org"
"diffie-hellman-group-exchange-sha256"
];
description = ''
Specifies the available KEX (Key Exchange) algorithms.
'';
};
};
# config.host = mkDefault dagName;
@@ -451,7 +440,16 @@ let
++ map (f: " LocalForward" + addressPort f.bind + addressPort f.host) cf.localForwards
++ map (f: " RemoteForward" + addressPort f.bind + addressPort f.host) cf.remoteForwards
++ map (f: " DynamicForward" + addressPort f) cf.dynamicForwards
++ mapAttrsToList (n: v: " ${n} ${v}") cf.extraOptions
++ optional (
cf.kexAlgorithms != null
) " KexAlgorithms ${builtins.concatStringsSep "," cf.kexAlgorithms}"
++ [
(lib.generators.toKeyValue {
mkKeyValue = lib.generators.mkKeyValueDefault { } " ";
listsAsDuplicateKeys = true;
indent = " ";
} cf.extraOptions)
]
);
in

View File

@@ -106,13 +106,13 @@ in
];
programs.bash.initExtra = lib.mkIf cfg.enableBashIntegration ''
eval "$(${lib.getExe cfg.package} init bash)"
source ${cfg.package}/share/television/completion.bash
'';
programs.zsh.initContent = lib.mkIf cfg.enableZshIntegration ''
eval "$(${lib.getExe cfg.package} init zsh)"
source ${cfg.package}/share/television/completion.zsh
'';
programs.fish.interactiveShellInit = lib.mkIf cfg.enableFishIntegration ''
${lib.getExe cfg.package} init fish | source
source ${cfg.package}/share/television/completion.fish
'';
};
}

View File

@@ -9,6 +9,7 @@ let
attrValues
concatStringsSep
filter
flatten
length
literalExpression
mapAttrsToList
@@ -918,7 +919,14 @@ in
calendarAccounts = getAccountsForProfile name enabledCalendarAccountsWithId;
contactAccounts = getAccountsForProfile name enabledContactAccountsWithId;
smtp = filter (a: a.smtp != null) emailAccounts;
accountsSmtp = filter (a: a.smtp != null) emailAccounts;
aliasesSmtp =
let
getAliasesWithSmtp = a: filter (al: builtins.isAttrs al && al.smtp != null) a.aliases;
getAliasesWithId = a: map (al: al // { id = getId a al; }) (getAliasesWithSmtp a);
in
flatten (map getAliasesWithId emailAccounts);
smtp = accountsSmtp ++ aliasesSmtp;
feedAccounts = addId (attrValues profile.feedAccounts);

51
modules/programs/ty.nix Normal file
View File

@@ -0,0 +1,51 @@
{
pkgs,
config,
lib,
...
}:
let
inherit (lib)
mkEnableOption
mkPackageOption
mkOption
literalExpression
;
tomlFormat = pkgs.formats.toml { };
cfg = config.programs.ty;
in
{
meta.maintainers = with lib.maintainers; [ mirkolenz ];
options.programs.ty = {
enable = mkEnableOption "ty";
package = mkPackageOption pkgs "ty" { nullable = true; };
settings = mkOption {
type = tomlFormat.type;
default = { };
example = literalExpression ''
{
rules.index-out-of-bounds = "ignore";
}
'';
description = ''
Configuration written to
{file}`$XDG_CONFIG_HOME/ty/ty.toml`.
See <https://docs.astral.sh/ty/configuration/>
and <https://docs.astral.sh/ty/reference/configuration/>
for more information.
'';
};
};
config = lib.mkIf cfg.enable {
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
xdg.configFile."ty/ty.toml" = lib.mkIf (cfg.settings != { }) {
source = tomlFormat.generate "ty-config.toml" cfg.settings;
};
};
}

View File

@@ -12,6 +12,7 @@ let
packageVersion = if cfg.package != null then lib.getVersion cfg.package else null;
themeIsToml = lib.versionAtLeast packageVersion "0.15.0";
versionPost0_17 = lib.versionAtLeast packageVersion "0.17.0";
in
{
meta.maintainers = [ lib.maintainers.leiserfg ];
@@ -43,7 +44,12 @@ in
useLayerShell = lib.mkOption {
type = lib.types.bool;
default = true;
description = "If vicinae should use the layer shell";
description = ''
Whether vicinae should use the layer shell.
If you are using version 0.17 or newer, you should use
{option}.programs.vicinae.settings.launcher_window.layer_shell.enabled = false
instead.
'';
};
extensions = lib.mkOption {
@@ -127,27 +133,22 @@ in
settings = lib.mkOption {
inherit (jsonFormat) type;
default = { };
description = "Settings written as JSON to `~/.config/vicinae/vicinae.json.";
example = lib.literalExpression ''
{
faviconService = "twenty";
font = {
size = 10;
};
popToRootOnClose = false;
rootSearch = {
searchFiles = false;
};
favicon_service = "twenty";
font.normal.size = 10;
pop_to_root_on_close=false;
search_files_in_root= false;
theme = {
name = "vicinae-dark";
};
window = {
csd = true;
opacity = 0.95;
rounding = 10;
dark.name = "vicinae-dark";
light.name = "vicinae-light";
};
}
'';
description = ''
Settings written as JSON to {file}`~/.config/vicinae/settings.json`.
See {command}`vicinae config default`.
'';
};
};
@@ -158,6 +159,10 @@ in
assertion = cfg.systemd.enable -> cfg.package != null;
message = "{option}programs.vicinae.systemd.enable requires non null {option}programs.vicinae.package";
}
{
assertion = !cfg.useLayerShell -> !versionPost0_17;
message = ''After version 0.17, if you want to explicitly disable the use of layer shell, you need to set {option}.programs.vicinae.settings.launcher_window.layer_shell.enabled = false.'';
}
];
lib.vicinae.mkExtension = (
{
@@ -223,10 +228,11 @@ in
source = themeFormat.generate "vicinae-${name}-theme" theme;
}
) cfg.themes;
settingsPath = if versionPost0_17 then "vicinae/settings.json" else "vicinae/vicinae.json";
in
{
configFile = {
"vicinae/vicinae.json" = lib.mkIf (cfg.settings != { }) {
"${settingsPath}" = lib.mkIf (cfg.settings != { }) {
source = jsonFormat.generate "vicinae-settings" cfg.settings;
};
}
@@ -250,14 +256,16 @@ in
PartOf = [ cfg.systemd.target ];
};
Service = {
EnvironmentFile = pkgs.writeText "vicinae-env" ''
USE_LAYER_SHELL=${if cfg.useLayerShell then builtins.toString 1 else builtins.toString 0}
'';
Type = "simple";
ExecStart = "${lib.getExe' cfg.package "vicinae"} server";
Restart = "always";
RestartSec = 5;
KillMode = "process";
EnvironmentFile = lib.mkIf (!versionPost0_17) (
pkgs.writeText "vicinae-env" ''
USE_LAYER_SHELL=${if cfg.useLayerShell then builtins.toString 1 else builtins.toString 0}
''
);
};
Install = lib.mkIf cfg.systemd.autoStart {
WantedBy = [ cfg.systemd.target ];

View File

@@ -162,7 +162,8 @@ in
default = false;
description = ''
Whether to configure {command}`vim` as the default
editor using the {env}`EDITOR` environment variable.
editor using the {env}`EDITOR` and {env}`VISUAL`
environment variables.
'';
};
};
@@ -213,7 +214,10 @@ in
home.packages = [ cfg.package ];
home.sessionVariables = lib.mkIf cfg.defaultEditor { EDITOR = "vim"; };
home.sessionVariables = lib.mkIf cfg.defaultEditor {
EDITOR = "vim";
VISUAL = "vim";
};
programs.vim = {
package = vim;

View File

@@ -23,7 +23,10 @@ let
yamlFormat = pkgs.formats.yaml { };
in
{
meta.maintainers = with lib.hm.maintainers; [ aguirre-matteo ];
meta.maintainers = [
lib.hm.maintainers.aguirre-matteo
lib.maintainers.arunoruto
];
options.programs.vivid = {
enable = mkEnableOption "vivid";
@@ -34,7 +37,14 @@ in
enableFishIntegration = mkFishIntegrationOption { inherit config; };
colorMode = mkOption {
type = with types; nullOr str;
type =
with types;
nullOr (
either str (enum [
"8-bit"
"24-bit"
])
);
default = null;
example = "8-bit";
description = ''
@@ -135,7 +145,7 @@ in
// (lib.mapAttrs' (
name: value:
lib.nameValuePair "vivid/themes/${name}.yml" {
source = if lib.isAttrs value then yamlFormat.generate "${name}.yml" value else value;
source = if lib.isAttrs value then pkgs.writeText "${name}.json" (builtins.toJSON value) else value;
}
) cfg.themes);

View File

@@ -9,12 +9,27 @@ let
cfg = config.programs.yt-dlp;
renderSettings = lib.mapAttrsToList (
configAtom =
with types;
oneOf [
bool
int
str
];
renderSingleOption =
name: value:
if lib.isBool value then
if value then "--${name}" else "--no-${name}"
else
"--${name} ${toString value}"
"--${name} ${toString value}";
renderSettings = lib.mapAttrsToList (
name: value:
if lib.isList value then
lib.concatStringsSep "\n" (map (renderSingleOption name) value)
else
renderSingleOption name value
);
in
@@ -27,13 +42,7 @@ in
package = lib.mkPackageOption pkgs "yt-dlp" { };
settings = mkOption {
type =
with types;
attrsOf (oneOf [
bool
int
str
]);
type = with types; attrsOf (either configAtom (listOf configAtom));
default = { };
example = lib.literalExpression ''
{
@@ -42,6 +51,10 @@ in
sub-langs = "all";
downloader = "aria2c";
downloader-args = "aria2c:'-c -x8 -s8 -k1M'";
color = [
"stdout:no_color"
"stderr:always"
];
}
'';
description = ''

View File

@@ -2,6 +2,7 @@
config,
lib,
pkgs,
options,
...
}:
let
@@ -100,9 +101,18 @@ in
};
dotDir = mkOption {
default = homeDir;
defaultText = "`config.home.homeDirectory`";
example = "`\${config.xdg.configHome}/zsh`";
default =
if config.xdg.enable && lib.versionAtLeast config.home.stateVersion "26.05" then
"${config.xdg.configHome}/zsh"
else
homeDir;
defaultText = lib.literalExpression ''
if config.xdg.enable && lib.versionAtLeast config.home.stateVersion "26.05" then
"''${config.xdg.configHome}/zsh"
else
config.home.homeDirectory
'';
example = literalExpression ''"''${config.xdg.configHome}/zsh"'';
description = ''
Directory where the zsh configuration and more should be located,
relative to the users home directory. The default is the home
@@ -391,7 +401,24 @@ in
- config.xdg.dataHome (XDG data directory)
- config.xdg.cacheHome (XDG cache directory)
''
];
]
++
lib.optionals
(
config.xdg.enable
&& !lib.versionAtLeast config.home.stateVersion "26.05"
&& options.programs.zsh.dotDir.highestPrio >= 1500
)
[
''
The default value of `programs.zsh.dotDir` will change in future versions.
You are currently using the legacy default (home directory) because `home.stateVersion` is less than "26.05".
To silence this warning and lock in the current behavior, set:
programs.zsh.dotDir = config.home.homeDirectory;
To adopt the new behavior (XDG config directory), set:
programs.zsh.dotDir = "''${config.xdg.configHome}/zsh";
''
];
}
(mkIf (cfg.envExtra != "") {
@@ -412,7 +439,7 @@ in
(mkIf (dotDirAbs != homeDir) {
home.file."${dotDirRel}/.zshenv".text = ''
export ZDOTDIR=${dotDirAbs}
${config.lib.zsh.export "ZDOTDIR" dotDirAbs}
'';
# When dotDir is set, only use ~/.zshenv to source ZDOTDIR/.zshenv,
@@ -420,7 +447,7 @@ in
# already set correctly (by e.g. spawning a zsh inside a zsh), all env
# vars still get exported
home.file.".zshenv".text = ''
source ${dotDirAbs}/.zshenv
source ${lib.escapeShellArg "${dotDirAbs}/.zshenv"}
'';
})

View File

@@ -1,9 +1,12 @@
{ config, lib, ... }:
let
cfg = config.programs.zsh;
stripSlash = lib.removeSuffix "/";
in
rec {
homeDir = config.home.homeDirectory;
# Raw home directory, no trailing slash.
homeDir = stripSlash config.home.homeDirectory;
/*
Escape a path string for shell usage and remove trailing slashes.
@@ -18,10 +21,11 @@ rec {
cleanPathStr "/path/to/dir/" => "'/path/to/dir'"
cleanPathStr "path with spaces" => "'path with spaces'"
*/
cleanPathStr = pathStr: lib.escapeShellArg (lib.removeSuffix "/" pathStr);
cleanPathStr = pathStr: lib.escapeShellArg (stripSlash pathStr);
/*
Convert an absolute path to a relative path by stripping the home directory prefix.
Returns the raw path (unescaped) for use in home.file keys.
This function converts absolute paths within the home directory to relative paths
by removing the home directory prefix. Paths already relative are returned as-is.
@@ -30,19 +34,22 @@ rec {
Type: String -> String
Example:
mkRelPathStr "/home/user/config" => "'config'"
mkRelPathStr "config" => "'config'"
mkRelPathStr "/home/user/config" => "config"
mkRelPathStr "config" => "config"
mkRelPathStr "/home/user" => "."
mkRelPathStr "/etc/config" => <error>
*/
mkRelPathStr =
pathStr:
# is already a relative path
if (!lib.hasPrefix "/" pathStr) then
cleanPathStr pathStr
# is an absolute path within home dir
else if (lib.hasPrefix homeDir pathStr) then
cleanPathStr (lib.removePrefix "${homeDir}/" pathStr)
# is an absolute path not in home dir
let
normPath = stripSlash pathStr;
in
if (!lib.hasPrefix "/" normPath) then
normPath
else if normPath == homeDir then
"."
else if (lib.hasPrefix "${homeDir}/" normPath) then
lib.removePrefix "${homeDir}/" normPath
else
throw ''
Attempted to convert an absolute path not within home directory to a
@@ -54,47 +61,47 @@ rec {
'';
/*
Convert a relative path to an absolute path by prepending the home directory.
Convert a relative path to an absolute path.
Returns RAW path (unescaped).
This function ensures paths are absolute by prepending the home directory
to relative paths. Already absolute paths are returned unchanged (after cleaning).
This function does NOT support shell variables.
Type: String -> String
Example:
mkAbsPathStr "config" => "'/home/user/config'"
mkAbsPathStr "/absolute/path" => "'/absolute/path'"
mkAbsPathStr "config" => "/home/user/config"
mkAbsPathStr "/absolute/path" => "/absolute/path"
*/
mkAbsPathStr =
pathStr: cleanPathStr ((lib.optionalString (!lib.hasPrefix "/" pathStr) "${homeDir}/") + pathStr);
pathStr:
let
normPath = stripSlash pathStr;
in
if lib.hasPrefix "/" normPath then normPath else "${homeDir}/${normPath}";
/*
Convert a path to absolute form while preserving shell variables for runtime expansion.
Convert a path to absolute form while preserving shell variables.
Returns RAW path (unescaped) unless vars are present (then preserves vars).
This function handles both literal paths and shell variable expressions.
Shell variables (containing '$') are preserved unescaped to allow runtime expansion.
Literal paths are made absolute and properly escaped for shell usage.
Literal paths are made absolute.
Type: String -> String
Example:
mkShellVarPathStr "config" => "'/home/user/config'"
mkShellVarPathStr "config" => "/home/user/config"
mkShellVarPathStr "$HOME/config" => "$HOME/config"
mkShellVarPathStr "\${XDG_CONFIG_HOME:-$HOME/.config}/app" => "\${XDG_CONFIG_HOME:-$HOME/.config}/app"
*/
mkShellVarPathStr =
pathStr:
let
cleanPath = lib.removeSuffix "/" pathStr;
hasShellVars = lib.hasInfix "$" cleanPath;
normPath = stripSlash pathStr;
hasShellVars = lib.hasInfix "$" normPath;
in
if hasShellVars then
# Does not escape shell variables, allowing them to be expanded at runtime
cleanPath
else
# For literal paths, make them absolute if needed and escape them
cleanPathStr ((lib.optionalString (!lib.hasPrefix "/" cleanPath) "${homeDir}/") + cleanPath);
if hasShellVars then normPath else mkAbsPathStr normPath;
dotDirAbs = mkAbsPathStr cfg.dotDir;
dotDirRel = mkRelPathStr cfg.dotDir;
@@ -107,5 +114,5 @@ rec {
Type: String
*/
pluginsDir = dotDirAbs + (lib.optionalString (homeDir == dotDirAbs) "/.zsh") + "/plugins";
pluginsDir = dotDirAbs + (lib.optionalString (mkRelPathStr cfg.dotDir == ".") "/.zsh") + "/plugins";
}

View File

@@ -136,7 +136,7 @@ let
);
in
{
meta.maintainers = with lib.maintainers; [ foo-dogsquared ];
meta.maintainers = [ ];
options.services.activitywatch = {
enable = lib.mkEnableOption "ActivityWatch, an automated time tracker";

View File

@@ -32,78 +32,72 @@ in
};
};
config = lib.mkIf serviceConfig.enable (
lib.mkMerge [
(lib.mkIf pkgs.stdenv.isLinux {
systemd.user = {
services.borgmatic = {
Unit = {
Description = "borgmatic backup";
# Prevent borgmatic from running unless the machine is
# plugged into power:
ConditionACPower = true;
};
Service = {
Type = "oneshot";
# Lower CPU and I/O priority:
Nice = 19;
IOSchedulingClass = "best-effort";
IOSchedulingPriority = 7;
IOWeight = 100;
Restart = "no";
LogRateLimitIntervalSec = 0;
# Delay start to prevent backups running during boot:
ExecStartPre = "${pkgs.coreutils}/bin/sleep 3m";
ExecStart = ''
${pkgs.systemd}/bin/systemd-inhibit \
--who="borgmatic" \
--what="sleep:shutdown" \
--why="Prevent interrupting scheduled backup" \
${programConfig.package}/bin/borgmatic \
--stats \
--verbosity -1 \
--list \
--syslog-verbosity 1
'';
};
};
timers.borgmatic = {
Unit.Description = "Run borgmatic backup";
Timer = {
OnCalendar = serviceConfig.frequency;
Persistent = true;
RandomizedDelaySec = "10m";
};
Install.WantedBy = [ "timers.target" ];
};
config = lib.mkIf serviceConfig.enable {
systemd.user = {
services.borgmatic = {
Unit = {
Description = "borgmatic backup";
# Prevent borgmatic from running unless the machine is
# plugged into power:
ConditionACPower = true;
};
})
Service = {
Type = "oneshot";
(lib.mkIf pkgs.stdenv.isDarwin {
assertions = [
(lib.hm.darwin.assertInterval "services.borgmatic.frequency" serviceConfig.frequency pkgs)
# Lower CPU and I/O priority:
Nice = 19;
IOSchedulingClass = "best-effort";
IOSchedulingPriority = 7;
IOWeight = 100;
Restart = "no";
LogRateLimitIntervalSec = 0;
# Delay start to prevent backups running during boot:
ExecStartPre = "${pkgs.coreutils}/bin/sleep 3m";
ExecStart = ''
${pkgs.systemd}/bin/systemd-inhibit \
--who="borgmatic" \
--what="sleep:shutdown" \
--why="Prevent interrupting scheduled backup" \
${programConfig.package}/bin/borgmatic \
--stats \
--verbosity -1 \
--list \
--syslog-verbosity 1
'';
};
};
timers.borgmatic = {
Unit.Description = "Run borgmatic backup";
Timer = {
OnCalendar = serviceConfig.frequency;
Persistent = true;
RandomizedDelaySec = "10m";
};
Install.WantedBy = [ "timers.target" ];
};
};
assertions = [
(lib.hm.darwin.assertInterval "services.borgmatic.frequency" serviceConfig.frequency pkgs)
];
launchd.agents.borgmatic = {
enable = true;
config = {
ProgramArguments = [
(lib.getExe programConfig.package)
"--stats"
"--list"
];
launchd.agents.borgmatic = {
enable = true;
config = {
ProgramArguments = [
(lib.getExe programConfig.package)
"--stats"
"--list"
];
ProcessType = "Background";
StartCalendarInterval = lib.hm.darwin.mkCalendarInterval serviceConfig.frequency;
StandardOutPath = "${config.home.homeDirectory}/Library/Logs/borgmatic/launchd-stdout.log";
StandardErrorPath = "${config.home.homeDirectory}/Library/Logs/borgmatic/launchd-stderr.log";
};
};
})
]
);
ProcessType = "Background";
StartCalendarInterval = lib.hm.darwin.mkCalendarInterval serviceConfig.frequency;
StandardOutPath = "${config.home.homeDirectory}/Library/Logs/borgmatic/launchd-stdout.log";
StandardErrorPath = "${config.home.homeDirectory}/Library/Logs/borgmatic/launchd-stderr.log";
};
};
};
}

View File

@@ -156,7 +156,7 @@ in
xdg.configFile."clipse/custom_theme.json".source = jsonFormat.generate "theme" cfg.theme;
systemd.user.services.clipse = lib.mkIf (pkgs.stdenv.isLinux && (cfg.package != null)) {
systemd.user.services.clipse = lib.mkIf (cfg.package != null) {
Unit = {
Description = "Clipse listener";
PartOf = [ "graphical-session.target" ];

262
modules/services/colima.nix Normal file
View File

@@ -0,0 +1,262 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.colima;
yamlFormat = pkgs.formats.yaml { };
in
{
meta.maintainers = [
lib.hm.maintainers.will-lol
];
options.services.colima = {
enable = lib.mkEnableOption "Colima, a container runtime";
package = lib.mkPackageOption pkgs "colima" { };
dockerPackage = lib.mkPackageOption pkgs "docker" {
extraDescription = "Used by colima to activate profiles. Not needed if no profile is set to isActive.";
};
perlPackage = lib.mkPackageOption pkgs "perl" {
extraDescription = "Used by colima during image download for the shasum command.";
};
sshPackage = lib.mkPackageOption pkgs "openssh" {
extraDescription = "Used by colima to manage the vm.";
};
coreutilsPackage = lib.mkPackageOption pkgs "coreutils" {
extraDescription = "Used in various ways by colima.";
};
curlPackage = lib.mkPackageOption pkgs "curl" {
extraDescription = "Used by colima to donwload images.";
};
bashPackage = lib.mkPackageOption pkgs "bashNonInteractive" {
extraDescription = "Used by colima's internal scripts.";
};
profiles = lib.mkOption {
default = {
default = {
isActive = true;
isService = true;
};
};
description = ''
Profiles allow multiple colima configurations. The default profile is active by default.
If you have used colima before, you may need to delete existing configuration using `colima delete` or use a different profile.
Note that removing a configured profile will not delete the corresponding Colima instance.
You will need to manually run `colima delete <profile-name>` to remove the instance and release resources.
'';
example = ''
{
default = {
isActive = true;
isService = true;
};
rosetta = {
isService = true;
settings.rosetta = true;
};
powerful = {
settings.cpu = 8;
};
};
'';
type = lib.types.attrsOf (
lib.types.submodule (
{ name, ... }:
{
options = {
name = lib.mkOption {
type = lib.types.str;
default = name;
readOnly = true;
description = "The profile's name.";
};
isService = lib.mkOption {
type = lib.types.bool;
default = false;
example = true;
description = ''
Whether this profile will run as a service.
'';
};
isActive = lib.mkOption {
type = lib.types.bool;
default = false;
example = true;
description = ''
Whether to set this profile as:
- active docker context
- active kubernetes context
- active incus remote
Exactly one or zero profiles should have this option set.
'';
};
logFile = lib.mkOption {
type = lib.types.path;
default = "${config.home.homeDirectory}/.local/state/colima-${name}.log";
defaultText = lib.literalExpression "\${config.home.homeDirectory}/.local/state/colima-\${name}.log";
description = "Combined stdout and stderr log file for the Colima service.";
};
settings = lib.mkOption {
inherit (yamlFormat) type;
default = { };
description = "Colima configuration settings, see <https://github.com/abiosoft/colima/blob/main/embedded/defaults/colima.yaml> or run `colima template`.";
example = ''
{
cpu = 2;
disk = 100;
memory = 2;
arch = "host";
runtime = "docker";
hostname = null;
kubernetes = {
enabled = false;
version = "v1.33.3+k3s1";
k3sArgs = [ "--disable=traefik" ];
port = 0;
};
autoActivate = true;
network = {
address = false;
mode = "shared";
interface = "en0";
preferredRoute = false;
dns = [ ];
dnsHosts = {
"host.docker.internal" = "host.lima.internal";
};
hostAddresses = false;
};
forwardAgent = false;
docker = { };
vmType = "qemu";
portForwarder = "ssh";
rosetta = false;
binfmt = true;
nestedVirtualization = false;
mountType = "sshfs";
mountInotify = false;
cpuType = "host";
provision = [ ];
sshConfig = true;
sshPort = 0;
mounts = [ ];
diskImage = "";
rootDisk = 20;
env = { };
}
'';
};
};
}
)
);
};
};
config = lib.mkIf cfg.enable {
assertions = [
{
assertion = (lib.count (p: p.isActive) (lib.attrValues cfg.profiles)) <= 1;
message = "Only one Colima profile can be active at a time.";
}
];
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
home.file = lib.mkMerge (
lib.mapAttrsToList (profileName: profile: {
".colima/${profileName}/colima.yaml" = {
source = yamlFormat.generate "colima.yaml" profile.settings;
};
}) (lib.filterAttrs (name: profile: profile.settings != { }) cfg.profiles)
);
programs.docker-cli.settings.currentContext =
let
activeProfile = lib.findFirst (p: p.isActive) null (lib.attrValues cfg.profiles);
in
lib.mkIf (activeProfile != null) (
if activeProfile.name != "default" then "colima-${activeProfile.name}" else "colima"
);
launchd.agents = lib.mapAttrs' (
name: profile:
lib.nameValuePair "colima-${name}" {
enable = true;
config = {
ProgramArguments = [
"${lib.getExe cfg.package}"
"start"
name
"-f"
"--activate=${if profile.isActive then "true" else "false"}"
"--save-config=false"
];
KeepAlive = true;
RunAtLoad = true;
EnvironmentVariables.PATH = lib.makeBinPath [
cfg.package
cfg.perlPackage
cfg.dockerPackage
cfg.sshPackage
cfg.coreutilsPackage
cfg.curlPackage
cfg.bashPackage
pkgs.darwin.DarwinTools
];
StandardOutPath = profile.logFile;
StandardErrorPath = profile.logFile;
};
}
) (lib.filterAttrs (_: p: p.isService) cfg.profiles);
systemd.user.services = lib.mapAttrs' (
name: profile:
lib.nameValuePair "colima-${name}" {
Unit = {
Description = "Colima container runtime (${name} profile)";
After = [ "network-online.target" ];
Wants = [ "network-online.target" ];
};
Service = {
ExecStart = ''
${lib.getExe cfg.package} start ${name} \
-f \
--activate=${if profile.isActive then "true" else "false"} \
--save-config=false
'';
Restart = "always";
RestartSec = 2;
Environment = [
"PATH=${
lib.makeBinPath [
cfg.package
cfg.perlPackage
cfg.dockerPackage
cfg.sshPackage
cfg.coreutilsPackage
cfg.curlPackage
cfg.bashPackage
]
}"
];
StandardOutput = "append:${profile.logFile}";
StandardError = "append:${profile.logFile}";
};
Install = {
WantedBy = [ "default.target" ];
};
}
) (lib.filterAttrs (_: p: p.isService) cfg.profiles);
};
}

View File

@@ -117,6 +117,8 @@ in
systemd.user.services.easyeffects = {
Unit = {
Description = "Easyeffects daemon";
After = [ "graphical-session.target" ];
PartOf = [ "graphical-session.target" ];
};
Install.WantedBy = [ "graphical-session.target" ];

View File

@@ -107,133 +107,129 @@ in
'';
};
defaultEditor = mkOption rec {
defaultEditor = mkOption {
type = types.bool;
default = false;
example = !default;
example = true;
description = ''
Whether to configure {command}`emacsclient` as the default
editor using the {env}`EDITOR` environment variable.
editor using the {env}`EDITOR` and {env}`VISUAL`
environment variables.
'';
};
};
config = mkIf cfg.enable (
lib.mkMerge [
{
home.sessionVariables = mkIf cfg.defaultEditor {
EDITOR = lib.getBin (
pkgs.writeShellScript "editor" ''exec ${lib.getBin cfg.package}/bin/emacsclient "''${@:---create-frame}"''
);
};
config = mkIf cfg.enable {
home.sessionVariables =
let
editorBin = lib.getBin (
pkgs.writeShellScript "editor" ''exec ${lib.getBin cfg.package}/bin/emacsclient "''${@:---create-frame}"''
);
in
mkIf cfg.defaultEditor {
EDITOR = editorBin;
VISUAL = editorBin;
};
home.packages = optional (cfg.client.enable && pkgs.stdenv.isLinux) (lib.hiPrio clientDesktopItem);
systemd.user.services.emacs = {
Unit = {
Description = "Emacs text editor";
Documentation = "info:emacs man:emacs(1) https://gnu.org/software/emacs/";
After = optional (cfg.startWithUserSession == "graphical") "graphical-session.target";
PartOf = optional (cfg.startWithUserSession == "graphical") "graphical-session.target";
# Avoid killing the Emacs session, which may be full of
# unsaved buffers.
X-RestartIfChanged = false;
}
// optionalAttrs needsSocketWorkaround {
# Emacs deletes its socket when shutting down, which systemd doesn't
# handle, resulting in a server without a socket.
# See https://github.com/nix-community/home-manager/issues/2018
RefuseManualStart = true;
};
(mkIf pkgs.stdenv.isLinux {
systemd.user.services.emacs = {
Unit = {
Description = "Emacs text editor";
Documentation = "info:emacs man:emacs(1) https://gnu.org/software/emacs/";
Service = {
Type = "notify";
After = optional (cfg.startWithUserSession == "graphical") "graphical-session.target";
PartOf = optional (cfg.startWithUserSession == "graphical") "graphical-session.target";
# We wrap ExecStart in a login shell so Emacs starts with the user's
# environment, most importantly $PATH and $NIX_PROFILES. It may be
# worth investigating a more targeted approach for user services to
# import the user environment.
ExecStart = ''${pkgs.runtimeShell} -l -c "${emacsBinPath}/emacs --fg-daemon${
# In case the user sets 'server-directory' or 'server-name' in
# their Emacs config, we want to specify the socket path explicitly
# so launching 'emacs.service' manually doesn't break emacsclient
# when using socket activation.
lib.optionalString cfg.socketActivation.enable "=${lib.escapeShellArg socketPath}"
} ${lib.escapeShellArgs cfg.extraOptions}"'';
# Avoid killing the Emacs session, which may be full of
# unsaved buffers.
X-RestartIfChanged = false;
}
// optionalAttrs needsSocketWorkaround {
# Emacs deletes its socket when shutting down, which systemd doesn't
# handle, resulting in a server without a socket.
# See https://github.com/nix-community/home-manager/issues/2018
RefuseManualStart = true;
};
# Emacs will exit with status 15 after having received SIGTERM, which
# is the default "KillSignal" value systemd uses to stop services.
SuccessExitStatus = 15;
Service = {
Type = "notify";
Restart = "on-failure";
}
// optionalAttrs needsSocketWorkaround {
# Use read-only directory permissions to prevent emacs from
# deleting systemd's socket file before exiting.
ExecStartPost = "${pkgs.coreutils}/bin/chmod --changes -w ${socketDir}";
ExecStopPost = "${pkgs.coreutils}/bin/chmod --changes +w ${socketDir}";
};
}
// optionalAttrs (cfg.startWithUserSession != false) {
Install = {
WantedBy = [
(if cfg.startWithUserSession == true then "default.target" else "graphical-session.target")
];
};
};
# We wrap ExecStart in a login shell so Emacs starts with the user's
# environment, most importantly $PATH and $NIX_PROFILES. It may be
# worth investigating a more targeted approach for user services to
# import the user environment.
ExecStart = ''${pkgs.runtimeShell} -l -c "${emacsBinPath}/emacs --fg-daemon${
# In case the user sets 'server-directory' or 'server-name' in
# their Emacs config, we want to specify the socket path explicitly
# so launching 'emacs.service' manually doesn't break emacsclient
# when using socket activation.
lib.optionalString cfg.socketActivation.enable "=${lib.escapeShellArg socketPath}"
} ${lib.escapeShellArgs cfg.extraOptions}"'';
systemd.user.sockets.emacs = mkIf cfg.socketActivation.enable {
Unit = {
Description = "Emacs text editor";
Documentation = "info:emacs man:emacs(1) https://gnu.org/software/emacs/";
};
# Emacs will exit with status 15 after having received SIGTERM, which
# is the default "KillSignal" value systemd uses to stop services.
SuccessExitStatus = 15;
Socket = {
ListenStream = socketPath;
FileDescriptorName = "server";
SocketMode = "0600";
DirectoryMode = "0700";
# This prevents the service from immediately starting again
# after being stopped, due to the function
# `server-force-stop' present in `kill-emacs-hook', which
# calls `server-running-p', which opens the socket file.
FlushPending = true;
};
Restart = "on-failure";
}
// optionalAttrs needsSocketWorkaround {
# Use read-only directory permissions to prevent emacs from
# deleting systemd's socket file before exiting.
ExecStartPost = "${pkgs.coreutils}/bin/chmod --changes -w ${socketDir}";
ExecStopPost = "${pkgs.coreutils}/bin/chmod --changes +w ${socketDir}";
};
}
// optionalAttrs (cfg.startWithUserSession != false) {
Install = {
WantedBy = [
(if cfg.startWithUserSession == true then "default.target" else "graphical-session.target")
];
};
Install = {
WantedBy = [ "sockets.target" ];
# Adding this Requires= dependency ensures that systemd
# manages the socket file, in the case where the service is
# started when the socket is stopped.
# The socket unit is implicitly ordered before the service.
RequiredBy = [ "emacs.service" ];
};
};
launchd.agents.emacs = {
enable = true;
config = {
ProgramArguments = [
"${cfg.package}/bin/emacs"
"--fg-daemon"
]
++ cfg.extraOptions;
RunAtLoad = true;
KeepAlive = {
Crashed = true;
SuccessfulExit = false;
};
home.packages = optional cfg.client.enable (lib.hiPrio clientDesktopItem);
})
(mkIf (cfg.socketActivation.enable && pkgs.stdenv.isLinux) {
systemd.user.sockets.emacs = {
Unit = {
Description = "Emacs text editor";
Documentation = "info:emacs man:emacs(1) https://gnu.org/software/emacs/";
};
Socket = {
ListenStream = socketPath;
FileDescriptorName = "server";
SocketMode = "0600";
DirectoryMode = "0700";
# This prevents the service from immediately starting again
# after being stopped, due to the function
# `server-force-stop' present in `kill-emacs-hook', which
# calls `server-running-p', which opens the socket file.
FlushPending = true;
};
Install = {
WantedBy = [ "sockets.target" ];
# Adding this Requires= dependency ensures that systemd
# manages the socket file, in the case where the service is
# started when the socket is stopped.
# The socket unit is implicitly ordered before the service.
RequiredBy = [ "emacs.service" ];
};
};
})
(mkIf pkgs.stdenv.isDarwin {
launchd.agents.emacs = {
enable = true;
config = {
ProgramArguments = [
"${cfg.package}/bin/emacs"
"--fg-daemon"
]
++ cfg.extraOptions;
RunAtLoad = true;
KeepAlive = {
Crashed = true;
SuccessfulExit = false;
};
};
};
})
]
);
};
};
};
}

View File

@@ -15,49 +15,12 @@ let
cfg = config.services.git-sync;
mkUnit = name: repo: {
Unit.Description = "Git Sync ${name}";
Install.WantedBy = [ "default.target" ];
Service = {
Environment = [
"PATH=${
lib.makeBinPath (
with pkgs;
[
openssh
git
]
++ repo.extraPackages
)
}"
"GIT_SYNC_DIRECTORY=${lib.strings.escapeShellArg repo.path}"
"GIT_SYNC_COMMAND=${cfg.package}/bin/git-sync"
"GIT_SYNC_REPOSITORY=${lib.strings.escapeShellArg repo.uri}"
"GIT_SYNC_INTERVAL=${toString repo.interval}"
];
ExecStart = "${cfg.package}/bin/git-sync-on-inotify";
Restart = "on-abort";
};
};
mkAgent = name: repo: {
enable = true;
config = {
StartInterval = repo.interval;
ProcessType = "Background";
WorkingDirectory = "${repo.path}";
WatchPaths = [ "${repo.path}" ];
ProgramArguments = [ "${cfg.package}/bin/git-sync" ];
};
};
mkService = if pkgs.stdenv.isLinux then mkUnit else mkAgent;
services = lib.mapAttrs' (name: repo: {
name = "git-sync-${name}";
value = mkService name repo;
}) cfg.repositories;
services =
mkService:
lib.mapAttrs' (name: repo: {
name = "git-sync-${name}";
value = mkService name repo;
}) cfg.repositories;
repositoryType = types.submodule (
{ name, ... }:
@@ -141,11 +104,48 @@ in
};
};
config = mkIf cfg.enable (
lib.mkMerge [
(mkIf pkgs.stdenv.isLinux { systemd.user.services = services; })
(mkIf pkgs.stdenv.isDarwin { launchd.agents = services; })
]
);
config = mkIf cfg.enable {
launchd.agents = services (
name: repo: {
enable = true;
config = {
StartInterval = repo.interval;
ProcessType = "Background";
WorkingDirectory = "${repo.path}";
WatchPaths = [ "${repo.path}" ];
ProgramArguments = [ "${cfg.package}/bin/git-sync" ];
};
}
);
systemd.user.services = services (
name: repo: {
Unit.Description = "Git Sync ${name}";
Install.WantedBy = [ "default.target" ];
Service = {
Environment = [
"PATH=${
lib.makeBinPath (
with pkgs;
[
openssh
git
]
++ repo.extraPackages
)
}"
"GIT_SYNC_DIRECTORY=${lib.strings.escapeShellArg repo.path}"
"GIT_SYNC_COMMAND=${cfg.package}/bin/git-sync"
"GIT_SYNC_REPOSITORY=${lib.strings.escapeShellArg repo.uri}"
"GIT_SYNC_INTERVAL=${toString repo.interval}"
];
ExecStart = "${cfg.package}/bin/git-sync-on-inotify";
Restart = "on-abort";
};
}
);
};
}

View File

@@ -344,125 +344,115 @@ in
};
};
config = mkIf cfg.enable (
lib.mkMerge [
{
# Grab the default binary name and fallback to expected value if `meta.mainProgram` not set
services.gpg-agent.pinentry.program = lib.mkOptionDefault (
cfg.pinentry.package.meta.mainProgram or "pinentry"
);
config = mkIf cfg.enable {
# Grab the default binary name and fallback to expected value if `meta.mainProgram` not set
services.gpg-agent.pinentry.program = lib.mkOptionDefault (
cfg.pinentry.package.meta.mainProgram or "pinentry"
);
home.file."${homedir}/gpg-agent.conf".text = lib.concatStringsSep "\n" (
optional cfg.enableSshSupport "enable-ssh-support"
++ optional cfg.grabKeyboardAndMouse "grab"
++ optional (!cfg.enableScDaemon) "disable-scdaemon"
++ optional cfg.noAllowExternalCache "no-allow-external-cache"
++ optional (cfg.defaultCacheTtl != null) "default-cache-ttl ${toString cfg.defaultCacheTtl}"
++ optional (
cfg.defaultCacheTtlSsh != null
) "default-cache-ttl-ssh ${toString cfg.defaultCacheTtlSsh}"
++ optional (cfg.maxCacheTtl != null) "max-cache-ttl ${toString cfg.maxCacheTtl}"
++ optional (cfg.maxCacheTtlSsh != null) "max-cache-ttl-ssh ${toString cfg.maxCacheTtlSsh}"
++ optional (
cfg.pinentry.package != null
) "pinentry-program ${lib.getExe' cfg.pinentry.package cfg.pinentry.program}"
++ [ cfg.extraConfig ]
);
home.file."${homedir}/gpg-agent.conf".text = lib.concatStringsSep "\n" (
optional cfg.enableSshSupport "enable-ssh-support"
++ optional cfg.grabKeyboardAndMouse "grab"
++ optional (!cfg.enableScDaemon) "disable-scdaemon"
++ optional cfg.noAllowExternalCache "no-allow-external-cache"
++ optional (cfg.defaultCacheTtl != null) "default-cache-ttl ${toString cfg.defaultCacheTtl}"
++ optional (
cfg.defaultCacheTtlSsh != null
) "default-cache-ttl-ssh ${toString cfg.defaultCacheTtlSsh}"
++ optional (cfg.maxCacheTtl != null) "max-cache-ttl ${toString cfg.maxCacheTtl}"
++ optional (cfg.maxCacheTtlSsh != null) "max-cache-ttl-ssh ${toString cfg.maxCacheTtlSsh}"
++ optional (
cfg.pinentry.package != null
) "pinentry-program ${lib.getExe' cfg.pinentry.package cfg.pinentry.program}"
++ [ cfg.extraConfig ]
);
home.sessionVariablesExtra = optionalString cfg.enableSshSupport ''
unset SSH_AGENT_PID
if [ -z "$SSH_CONNECTION" -o -z "$SSH_AUTH_SOCK" ] && [ "''${gnupg_SSH_AUTH_SOCK_by:-0}" -ne $$ ]; then
export SSH_AUTH_SOCK="$(${gpgPkg}/bin/gpgconf --list-dirs agent-ssh-socket)"
fi
'';
home.sessionVariablesExtra = optionalString cfg.enableSshSupport ''
unset SSH_AGENT_PID
if [ -z "$SSH_CONNECTION" -o -z "$SSH_AUTH_SOCK" ] && [ "''${gnupg_SSH_AUTH_SOCK_by:-0}" -ne $$ ]; then
export SSH_AUTH_SOCK="$(${gpgPkg}/bin/gpgconf --list-dirs agent-ssh-socket)"
fi
'';
programs = {
bash.initExtra = mkIf cfg.enableBashIntegration gpgBashInitStr;
zsh.initContent = mkIf cfg.enableZshIntegration gpgZshInitStr;
fish.interactiveShellInit = mkIf cfg.enableFishIntegration gpgFishInitStr;
nushell.extraConfig = mkIf cfg.enableNushellIntegration gpgNushellInitStr;
programs = {
bash.initExtra = mkIf cfg.enableBashIntegration gpgBashInitStr;
zsh.initContent = mkIf cfg.enableZshIntegration gpgZshInitStr;
fish.interactiveShellInit = mkIf cfg.enableFishIntegration gpgFishInitStr;
nushell.extraConfig = mkIf cfg.enableNushellIntegration gpgNushellInitStr;
};
# Trailing newlines are important
home.file."${homedir}/sshcontrol" = mkIf (cfg.sshKeys != null) {
text = lib.concatMapStrings (s: ''
${s}
'') cfg.sshKeys;
};
systemd.user = {
services.gpg-agent = {
Unit = {
Description = "GnuPG cryptographic agent and passphrase cache";
Documentation = "man:gpg-agent(1)";
Requires = "gpg-agent.socket";
After = "gpg-agent.socket";
# This is a socket-activated service:
RefuseManualStart = true;
};
}
(mkIf (cfg.sshKeys != null) {
# Trailing newlines are important
home.file."${homedir}/sshcontrol".text = lib.concatMapStrings (s: ''
${s}
'') cfg.sshKeys;
})
Service = {
ExecStart = "${gpgPkg}/bin/gpg-agent --supervised" + optionalString cfg.verbose " --verbose";
ExecReload = "${gpgPkg}/bin/gpgconf --reload gpg-agent";
Environment = [ "GNUPGHOME=${homedir}" ];
};
};
(lib.mkMerge [
(mkIf pkgs.stdenv.isLinux {
systemd.user = {
services.gpg-agent = {
Unit = {
Description = "GnuPG cryptographic agent and passphrase cache";
Documentation = "man:gpg-agent(1)";
Requires = "gpg-agent.socket";
After = "gpg-agent.socket";
# This is a socket-activated service:
RefuseManualStart = true;
};
sockets = {
gpg-agent = mkSocket {
desc = "GnuPG cryptographic agent and passphrase cache";
docs = "man:gpg-agent(1)";
stream = "S.gpg-agent";
fdName = "std";
};
Service = {
ExecStart = "${gpgPkg}/bin/gpg-agent --supervised" + optionalString cfg.verbose " --verbose";
ExecReload = "${gpgPkg}/bin/gpgconf --reload gpg-agent";
Environment = [ "GNUPGHOME=${homedir}" ];
};
};
gpg-agent-ssh = mkIf cfg.enableSshSupport (mkSocket {
desc = "GnuPG cryptographic agent (ssh-agent emulation)";
docs = "man:gpg-agent(1) man:ssh-add(1) man:ssh-agent(1) man:ssh(1)";
stream = "S.gpg-agent.ssh";
fdName = "ssh";
});
sockets = {
gpg-agent = mkSocket {
desc = "GnuPG cryptographic agent and passphrase cache";
docs = "man:gpg-agent(1)";
stream = "S.gpg-agent";
fdName = "std";
};
gpg-agent-extra = mkIf cfg.enableExtraSocket (mkSocket {
desc = "GnuPG cryptographic agent and passphrase cache (restricted)";
docs = "man:gpg-agent(1) man:ssh(1)";
stream = "S.gpg-agent.extra";
fdName = "extra";
});
};
};
gpg-agent-ssh = mkIf cfg.enableSshSupport (mkSocket {
desc = "GnuPG cryptographic agent (ssh-agent emulation)";
docs = "man:gpg-agent(1) man:ssh-add(1) man:ssh-agent(1) man:ssh(1)";
stream = "S.gpg-agent.ssh";
fdName = "ssh";
});
gpg-agent-extra = mkIf cfg.enableExtraSocket (mkSocket {
desc = "GnuPG cryptographic agent and passphrase cache (restricted)";
docs = "man:gpg-agent(1) man:ssh(1)";
stream = "S.gpg-agent.extra";
fdName = "extra";
});
};
};
})
(mkIf pkgs.stdenv.isDarwin {
launchd.agents.gpg-agent = {
enable = true;
config = {
ProgramArguments = [
"${gpgPkg}/bin/gpg-agent"
"--supervised"
]
++ optional cfg.verbose "--verbose";
EnvironmentVariables = {
GNUPGHOME = homedir;
};
KeepAlive = {
Crashed = true;
SuccessfulExit = false;
};
ProcessType = "Background";
RunAtLoad = cfg.enableSshSupport;
Sockets = {
Agent = mkAgentSock "S.gpg-agent";
Ssh = mkIf cfg.enableSshSupport (mkAgentSock "S.gpg-agent.ssh");
Extra = mkIf cfg.enableExtraSocket (mkAgentSock "S.gpg-agent.extra");
};
};
};
})
])
]
);
launchd.agents.gpg-agent = {
enable = true;
config = {
ProgramArguments = [
"${gpgPkg}/bin/gpg-agent"
"--supervised"
]
++ optional cfg.verbose "--verbose";
EnvironmentVariables = {
GNUPGHOME = homedir;
};
KeepAlive = {
Crashed = true;
SuccessfulExit = false;
};
ProcessType = "Background";
RunAtLoad = cfg.enableSshSupport;
Sockets = {
Agent = mkAgentSock "S.gpg-agent";
Ssh = mkIf cfg.enableSshSupport (mkAgentSock "S.gpg-agent.ssh");
Extra = mkIf cfg.enableExtraSocket (mkAgentSock "S.gpg-agent.extra");
};
};
};
};
}

View File

@@ -81,46 +81,38 @@ in
};
};
config = lib.mkIf cfg.enable (
lib.mkMerge [
(lib.mkIf pkgs.stdenv.isLinux {
systemd.user = {
timers.home-manager-auto-expire = {
Unit.Description = "Home Manager expire generations timer";
config = lib.mkIf cfg.enable {
Install.WantedBy = [ "timers.target" ];
Timer = {
OnCalendar = cfg.frequency;
Unit = "home-manager-auto-expire.service";
Persistent = true;
};
};
services.home-manager-auto-expire = {
Unit.Description = "Home Manager expire generations";
Service.ExecStart = toString script;
};
systemd.user = {
timers.home-manager-auto-expire = {
Unit.Description = "Home Manager expire generations timer";
Install.WantedBy = [ "timers.target" ];
Timer = {
OnCalendar = cfg.frequency;
Unit = "home-manager-auto-expire.service";
Persistent = true;
};
})
};
services.home-manager-auto-expire = {
Unit.Description = "Home Manager expire generations";
Service.ExecStart = toString script;
};
};
(lib.mkIf pkgs.stdenv.isDarwin {
assertions = [
(lib.hm.darwin.assertInterval "services.home-manager.autoExpire.frequency" cfg.frequency pkgs)
];
assertions = [
(lib.hm.darwin.assertInterval "services.home-manager.autoExpire.frequency" cfg.frequency pkgs)
];
launchd.agents.home-manager-auto-expire = {
enable = true;
config = {
ProgramArguments = [ (toString script) ];
ProcessType = "Background";
StartCalendarInterval = lib.hm.darwin.mkCalendarInterval cfg.frequency;
StandardOutPath = "${config.home.homeDirectory}/Library/Logs/home-manager-auto-expire/launchd-stdout.log";
StandardErrorPath = "${config.home.homeDirectory}/Library/Logs/home-manager-auto-expire/launchd-stderr.log";
};
};
})
]
);
launchd.agents.home-manager-auto-expire = {
enable = true;
config = {
ProgramArguments = [ (toString script) ];
ProcessType = "Background";
StartCalendarInterval = lib.hm.darwin.mkCalendarInterval cfg.frequency;
StandardOutPath = "${config.home.homeDirectory}/Library/Logs/home-manager-auto-expire/launchd-stdout.log";
StandardErrorPath = "${config.home.homeDirectory}/Library/Logs/home-manager-auto-expire/launchd-stderr.log";
};
};
};
}

Some files were not shown because too many files have changed in this diff Show More