Compare commits

...

94 Commits

Author SHA1 Message Date
teto
8bc5473b6b maintainers: remove duplicated aionescu
already exists in nixpkgs
2026-01-10 19:06:42 +01:00
home-manager-ci[bot]
3ca9701774 flake.lock: Update
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/5912c1772a44e31bf1c63c0390b90501e5026886?narHash=sha256-Mj3d3PfwltLmukFal5i3fFt27L6NiKXdBezC1EBuZs4%3D' (2026-01-07)
  → 'github:NixOS/nixpkgs/3497aa5c9457a9d88d71fa93a4a8368816fbeeba?narHash=sha256-dhhvQY67aboBk8b0/u0XB6vwHdgbROZT3fJAjyNh5Ww%3D' (2026-01-08)
2026-01-10 19:06:42 +01:00
Robert Helgesson
d0aefc169f home-manager: update copyright year in man page 2026-01-10 18:16:55 +01:00
Austin Horstman
312c4fe0bb rclone: migrate to lib.cli.toCommandLineShellGNU
Replace deprecated lib.cli.toGNUCommandLineShell with
lib.cli.toCommandLineShellGNU. This changes the behavior but `rclone`
supports the `=` separator for its flags.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-10 11:29:16 -05:00
Benedikt Rips
7c5d9345ad news: add 'services.ssh-agent.pkcs11Whitelist' entry 2026-01-09 23:20:10 -05:00
Michael Farber Brodsky
0e4217b2c4 news: add workstyle entry 2026-01-09 10:17:21 -05:00
Michael Farber Brodsky
90e53291cb workstyle: add module 2026-01-09 10:17:21 -05:00
Michael Farber Brodsky
480b0b2b81 maintainers: add farberbrodsky 2026-01-09 10:17:21 -05:00
Thierry Delafontaine
b52d47d670 news: add podman darwin support entry 2026-01-09 09:15:55 -05:00
Thierry Delafontaine
f4bcc1ae1c podman: add darwin support with machine management
- restructure module from `podman-linux` to platform-agnostic `podman`
- move linux-specific implementation to `modules/services/podman/linux/`
- add darwin module with declarative machine management
- implement launchd-based watchdog for auto-starting machines
- maintains backward compatibility with existing linux functionality
2026-01-09 09:15:55 -05:00
Benjamin Saunders
297a085108 PULL_REQUEST_TEMPLATE: update treefmt shell
Previously, following these instructions lead to a failure with:

Error: failed to create composite formatter: failed to initialise formatter nixf-diagnose: formatter command not found in PATH: error looking up 'nixf-diagnose'
2026-01-08 22:40:51 -05:00
Lena Fuhrimann
cd6e96d56e hyprland: import XDG_SESSION_TYPE for systemd 2026-01-08 16:53:03 -05:00
Thierry Delafontaine
b1b1c68033 opencode: add custom tools support
Adds support for custom tools - user-defined functions that the LLM can
call during conversations. Custom tools work alongside opencode's built-in
tools and are configured through the new `tools` option.

The configuration follows the same pattern as other opencode settings like
`agents` and `commands`, supporting:
- Inline TypeScript content
- Individual file paths
- Bulk directory imports
2026-01-08 16:32:29 -05:00
Thierry Delafontaine
081234b704 opencode: support directory-based configuration for commands, agents, and themes
The `commands`, `agents`, and `themes` options now accept either an
attribute set (existing behavior) or a path to a directory containing
multiple files. When a directory path is provided, it is symlinked to
the appropriate `$XDG_CONFIG_HOME/opencode/` subdirectory.

This change aligns with the existing `skills` option implementation and
provides a more convenient way to manage multiple configuration files
without needing to define each one individually in Nix.
2026-01-08 16:32:29 -05:00
Austin Horstman
2be878259a makefile: add nixf-diagnose
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 16:30:04 -05:00
Austin Horstman
fa6de26b4d treewide: nixf-diagnose cleanup
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 16:30:04 -05:00
Austin Horstman
9fff37e6ff flake: add nixf-diagnose to treefmt
Start off conservative ignoring more things. Handle the simple auto-fix
things initially.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 16:30:04 -05:00
Austin Horstman
a2cc7b0bab less: migrate to lib.cli.toCommandLineGNU
Migrates from the deprecated toCommandLine to toCommandLineGNU.

This changes the output format to use GNU-style options with equals
(--wheel-lines=3). Both formats were verified to work correctly with less.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 14:56:14 -05:00
Benedikt Rips
37158e5267 vesktop: deduplicate platform-dependent files 2026-01-08 14:49:34 -05:00
Benedikt Rips
cd74467526 streamlink: deduplicate platform-dependent files 2026-01-08 14:49:34 -05:00
Benedikt Rips
72476602b9 sapling: deduplicate platform-dependent files 2026-01-08 14:49:34 -05:00
Benedikt Rips
e926e27968 rbw: deduplicate platform-dependent files 2026-01-08 14:49:34 -05:00
Benedikt Rips
db116ceb76 qutebrowser: deduplicate platform-dependent files 2026-01-08 14:49:34 -05:00
Benedikt Rips
f7b2bdf042 pueue: deduplicate platform-dependent files 2026-01-08 14:49:34 -05:00
Benedikt Rips
a1a11393d9 pistol: deduplicate platform-dependent files 2026-01-08 14:49:34 -05:00
Benedikt Rips
802ce0a7b1 mullvad-vpn: deduplicate platform-dependent files 2026-01-08 14:49:34 -05:00
Benedikt Rips
e69fbc243a lazygit: deduplicate platform-dependent files 2026-01-08 14:49:34 -05:00
Benedikt Rips
ebab435f3e lazydocker: deduplicate platform-dependent files 2026-01-08 14:49:34 -05:00
Benedikt Rips
bacad23b8c kubecolor: deduplicate platform-dependent files 2026-01-08 14:49:34 -05:00
Benedikt Rips
6067be4770 kitty: deduplicate platform-dependent files 2026-01-08 14:49:34 -05:00
Benedikt Rips
12a723df97 gurk-rs: deduplicate platform-dependent files 2026-01-08 14:49:34 -05:00
Austin Horstman
40deed4ffe ci: validate-maintainers all-maintainers update
Might as well, can't hurt.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 13:57:12 -05:00
Austin Horstman
9500721e96 maintainers: update all-maintainers
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 13:57:12 -05:00
Austin Horstman
db105fadc4 maintainers: rrvsh moved to nixpkgs
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 13:57:12 -05:00
Austin Horstman
609846bfd2 maintainers: nickthegroot moved to nixpkgs
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 13:57:12 -05:00
Austin Horstman
2db6bcc7ca ci: validate-maintainers on flake.lock update
Keep missing conflicts from nixpkgs updates.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 13:57:12 -05:00
Jure Varlec
a3ac4bb1f8 generic-linux-gpu: put systemd unit in lib/systemd
This is where unit files are expected to be, making GPU setup compatible
with things like selinux. Fixes #8438. The `resources/` directory was
kept because it is expected to be used in the future.
2026-01-08 13:15:31 -05:00
Xinyang Li
47db0fde35 ssh-agent: add allowedPKCS11Providers option 2026-01-08 13:10:56 -05:00
Michael Strobel
3351348827 sftpman: add missing options
- `authType` is missing the `authentication-agent` enum value
- `mountDestPath` is missing completely
2026-01-08 12:31:15 -05:00
NAHO
7688293f06 home-manager: update copyright year 2026-01-08 12:29:25 -05:00
Austin Horstman
92394f9dea difftastic: migrate to lib.cli.toCommandLineShellGNU
Migrates from the deprecated toCommandLineShell to toCommandLineShellGNU.

This changes the output format to use GNU-style concatenated options
(--color=always) with shell escaping for git config values. Both formats
were verified to work correctly with difftastic.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 11:44:04 -05:00
Austin Horstman
fb6a8404ee redshift-gammastep: migrate to lib.cli.toCommandLineShellGNU
Migrates from the deprecated toCommandLineShell to toCommandLineShellGNU.

This changes the output format from space-separated short options
(-c /path) to concatenated GNU-style options (-c/path). Both formats
were verified to work correctly with redshift and gammastep.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 11:21:16 -05:00
Austin Horstman
9afe77a70b wlsunset: migrate to lib.cli.toCommandLineShellGNU
Migrates from the deprecated toGNUCommandLineShell to toCommandLineShellGNU.

This changes the output format from space-separated short options
(-t 3500) to concatenated GNU-style options (-t3500). Both formats
were verified to work correctly with wlsunset.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 11:18:42 -05:00
Austin Horstman
246b8eaffb linux-wallpaperengine: migrate to lib.cli.toCommandLineGNU
Replace deprecated lib.cli.toGNUCommandLine with lib.cli.toCommandLineGNU. 
Should support the GNU style of convention.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 10:17:17 -06:00
Austin Horstman
f9ce7c5234 bemenu: migrate to lib.cli.toCommandLineShellGNU
Migrates from the deprecated toCommandLineShell to toCommandLineShellGNU.

This changes the output format to use GNU-style concatenated options
(--line-height=28) and adds shell escaping for values with special
characters (e.g., '#1e1e2e' becomes '--ab=#1e1e2e'). The format
was verified to work correctly with bemenu.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 11:11:43 -05:00
Benedikt Rips
d1da1de5c2 lib.darwin: simplify assertInterval 2026-01-08 14:29:57 +01:00
Ian Chamberlain
af7f14ddf7 fish: expose session variables package
This allows fish users to source the `hm-session-vars.fish` if they are
not using the generated `config.fish` (which now sources the same file).
2026-01-08 10:25:35 +01:00
Austin Horstman
46c9af8a92 fish: migrate to lib.cli.toCommandLineShell
Replace deprecated lib.cli.toGNUCommandLineShell with the new
lib.cli.toCommandLineShell API, migrating from the old mkOption
parameter format to the new optionFormat function.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 10:14:18 +01:00
Amneesh
a630bbdedd mpd: fix incorrect use of mkIf (#8504)
Currently, if cfg.network.listenAddress is set to "any", MPD_HOST causes
partial evaluation which fails the sanity check while trying to build a
home-manager generation. Hence make a separate attrset for MPD_HOST
which will be evaluated conditionally and then concatenated.

Signed-off-by: Amneesh Singh <natto@weirdnatto.in>
2026-01-07 23:51:16 -06:00
home-manager-ci[bot]
86e0f6f227 flake.lock: Update
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/9f0c42f8bc7151b8e7e5840fb3bd454ad850d8c5?narHash=sha256-UWYqmD7JFBEDBHWYcqE6s6c77pWdcU/i%2BbwD6XxMb8A%3D' (2026-01-05)
  → 'github:NixOS/nixpkgs/5912c1772a44e31bf1c63c0390b90501e5026886?narHash=sha256-Mj3d3PfwltLmukFal5i3fFt27L6NiKXdBezC1EBuZs4%3D' (2026-01-07)
2026-01-08 00:37:14 -05:00
Brian E
d4c406cfa8 Translate using Weblate (Faroese)
Currently translated at 23.5% (4 of 17 strings)

Translate using Weblate (Faroese)

Currently translated at 12.8% (5 of 39 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
2026-01-08 00:01:18 -05:00
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
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
265 changed files with 3723 additions and 2250 deletions

View File

@@ -22,7 +22,7 @@ Also make sure to read the guidelines found at
- [ ] Change is backwards compatible.
- [ ] Code formatted with `nix fmt` or
`nix-shell -p treefmt nixfmt deadnix keep-sorted --run treefmt`.
`nix-shell -p treefmt nixfmt deadnix keep-sorted nixf-diagnose --run treefmt`.
- [ ] Code tested through `nix run .#tests -- test-all` or
`nix-shell --pure tests -A run.all`.

2
.github/labeler.yml vendored
View File

@@ -165,7 +165,7 @@
"containers":
- changed-files:
- any-glob-to-any-file:
- modules/services/podman-linux/**/*
- modules/services/podman/linux/**/*
- modules/programs/distrobox.nix
- modules/programs/docker-cli.nix
"desktop-ui":

View File

@@ -1,7 +1,10 @@
name: Validate maintainers.nix
on:
pull_request:
paths: ["modules/lib/maintainers.nix"]
paths:
- "modules/lib/maintainers.nix"
- "flake.lock"
- "all-maintainers.nix"
workflow_dispatch:
inputs:
run_tests:

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2017-2025 Home Manager contributors
Copyright (c) 2017-2026 Home Manager contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -17,4 +17,4 @@ test-install:
HOME=$(shell mktemp -d) NIX_PATH=${NIX_PATH} nix-shell . -A install
format:
nix-shell -p treefmt nixfmt deadnix keep-sorted --run "treefmt --config-file ./treefmt.toml"
nix-shell -p treefmt nixfmt deadnix keep-sorted nixf-diagnose --run "treefmt --config-file ./treefmt.toml"

View File

@@ -19,6 +19,11 @@
email = "da157@voidq.com";
github = "0xda157";
githubId = 153149335;
keys = [
{
fingerprint = "5A66 FF95 36DE B501 DDD2 1647 B7AC 1B10 365D 45FF";
}
];
matrix = "@da157:catgirl.cloud";
name = "0xda157";
source = "nixpkgs";
@@ -65,14 +70,6 @@
name = "Alex";
source = "home-manager";
};
AndersonTorres = {
email = "torres.anderson.85@protonmail.com";
github = "AndersonTorres";
githubId = 5954806;
matrix = "@anderson_torres:matrix.org";
name = "Anderson Torres";
source = "nixpkgs";
};
AndreasMager = {
email = "andreas@mager.eu";
github = "AndreasMager";
@@ -1760,7 +1757,7 @@
github = "nickthegroot";
githubId = 1966472;
name = "Nick DeGroot";
source = "home-manager";
source = "nixpkgs";
};
nikp123 = {
email = "nikp123@users.noreply.github.com";
@@ -2012,7 +2009,7 @@
github = "rrvsh";
githubId = 20300874;
name = "Mohammad Rafiq";
source = "home-manager";
source = "nixpkgs";
};
rszamszur = {
email = "radoslawszamszur@gmail.com";

View File

@@ -110,8 +110,7 @@ let
in
pkgs.buildPackages.nixosOptionsDoc (
{
options =
if includeModuleSystemOptions then options else builtins.removeAttrs options [ "_module" ];
options = if includeModuleSystemOptions then options else removeAttrs options [ "_module" ];
transformOptions =
opt:
opt
@@ -133,7 +132,7 @@ let
) opt.declarations;
};
}
// builtins.removeAttrs args [
// removeAttrs args [
"modules"
"includeModuleSystemOptions"
]

View File

@@ -420,5 +420,5 @@ Author.
.Sh COPYRIGHT
.br
Copyright \(co 2017\(en2025 Home Manager contributors
Copyright \(co 2017\(en2026 Home Manager contributors
.br

View File

@@ -17,8 +17,11 @@ way. In Bash and Z shell this can be done by adding
to your `.profile` and `.zshrc` files, respectively. The
`hm-session-vars.sh` file should work in most Bourne-like shells. For
fish shell, it is possible to source it using [the foreign-env
plugin](https://github.com/oh-my-fish/plugin-foreign-env)
plugin](https://github.com/oh-my-fish/plugin-foreign-env) or using the builtin
[babelfish](https://github.com/bouk/babelfish)-translated variables:
``` bash
fenv source "$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh" > /dev/null
# or
source "$HOME/.nix-profile/etc/profile.d/hm-session-vars.fish"
```

6
flake.lock generated
View File

@@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1766902085,
"narHash": "sha256-coBu0ONtFzlwwVBzmjacUQwj3G+lybcZ1oeNSQkgC0M=",
"lastModified": 1767892417,
"narHash": "sha256-dhhvQY67aboBk8b0/u0XB6vwHdgbROZT3fJAjyNh5Ww=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "c0b0e0fddf73fd517c3471e546c0df87a42d53f4",
"rev": "3497aa5c9457a9d88d71fa93a4a8368816fbeeba",
"type": "github"
},
"original": {

View File

@@ -57,6 +57,7 @@
nixfmt
deadnix
keep-sorted
nixf-diagnose
];
settings = pkgs.lib.importTOML ./treefmt.toml;
}

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-11-30 14:00+0000\n"
"PO-Revision-Date: 2026-01-07 17:01+0000\n"
"Last-Translator: Brian E <brianellingsgaard9@gmail.com>\n"
"Language-Team: Faroese <https://hosted.weblate.org/projects/home-manager/cli/"
"fo/>\n"
@@ -17,7 +17,7 @@ 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.15-dev\n"
"X-Generator: Weblate 5.15.1\n"
#. translators: For example: "home-manager: missing argument for --cores"
#: home-manager/home-manager:16
@@ -41,10 +41,12 @@ msgid ""
"Keeping your Home Manager %s in %s is deprecated,\n"
"please move it to %s"
msgstr ""
"At hava Heimvørðurin %s í %s er fyrnast,\n"
"vinarliga flyt hann til %s"
#: home-manager/home-manager:99
msgid "No configuration file found. Please create one at %s"
msgstr ""
msgstr "Eingin samansetingsfíla funni. Vinarliga stovna ein hjá %s"
#: home-manager/home-manager:114
msgid "Home Manager not found at %s."

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-12-04 04:17+0000\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"
@@ -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

@@ -31,7 +31,7 @@ let
modules = [ configuration ] ++ hmModules;
class = "homeManager";
specialArgs = {
modulesPath = builtins.toString ./.;
modulesPath = toString ./.;
}
// extraSpecialArgs;
};

View File

@@ -192,7 +192,7 @@ in
++ lib.optionals (cfg.quickPhraseFiles != { }) [
(pkgs.linkFarm "quickPhraseFiles" (
lib.mapAttrs' (
name: value: lib.nameValuePair ("share/fcitx5/data/quickphrase.d/${name}.mb") value
name: value: lib.nameValuePair "share/fcitx5/data/quickphrase.d/${name}.mb" value
) cfg.quickPhraseFiles
))
];

View File

@@ -13,12 +13,9 @@ let
mergeDefinitions
;
inherit (builtins)
map
filter
length
deepSeq
throw
toString
concatLists
;
inherit (lib.options) showDefs;

View File

@@ -63,12 +63,12 @@ let
intervalsString = lib.concatStringsSep ", " intervals;
assertInterval = option: interval: pkgs: {
assertion = (!pkgs.stdenv.isDarwin) || (lib.elem interval intervals);
message = "On Darwin ${option} must be one of: ${intervalsString}.";
assertion = pkgs.stdenv.isDarwin -> lib.elem interval intervals;
message = "On Darwin, ${option} must be one of: ${intervalsString}.";
};
intervalDocumentation = ''
On Darwin it must be one of: ${intervalsString}, which are implemented as defined in {manpage}`systemd.time(7)`.
On Darwin, it must be one of: ${intervalsString}, which are implemented as defined in {manpage}`systemd.time(7)`.
'';
in
{

View File

@@ -67,12 +67,6 @@
github = "aheaume";
githubId = 13830042;
};
aionescu = {
name = "Alex Ionescu";
email = "github@ionescu.sh";
github = "aionescu";
githubId = 48064242;
};
austreelis = {
email = "github@accounts.austreelis.net";
github = "Austreelis";
@@ -175,6 +169,12 @@
github = "exzombie";
githubId = 11456290;
};
farberbrodsky = {
name = "Michael Farber Brodsky";
email = "misha@farberbrodsky.com";
github = "farberbrodsky";
githubId = 36243759;
};
fendse = {
email = "46252070+Fendse@users.noreply.github.com";
github = "Fendse";
@@ -423,12 +423,6 @@
github = "natecox";
githubId = 2782695;
};
nickthegroot = {
name = "Nick DeGroot";
email = "nick@nickthegroot.com";
github = "nickthegroot";
githubId = 1966472;
};
nikp123 = {
name = "nikp123";
email = "nikp123@users.noreply.github.com";
@@ -507,12 +501,6 @@
github = "Rosuavio";
githubId = 7164552;
};
rrvsh = {
name = "Mohammad Rafiq";
email = "rafiq@rrv.sh";
github = "rrvsh";
githubId = 20300874;
};
rszamszur = {
name = "Radosław Szamszur";
email = "radoslawszamszur@gmail.com";

View File

@@ -278,7 +278,7 @@ in
else if builtins.isString value then
"<const>${value}</const>"
else
throw ("expected bool or string but got ${builtins.typeOf value}: ${toString value}");
throw "expected bool or string but got ${builtins.typeOf value}: ${toString value}";
in
''
<match target="font">
@@ -338,7 +338,7 @@ in
xdg.configFile = lib.mapAttrs' (
name: config:
lib.nameValuePair "fontconfig/conf.d/${builtins.toString config.priority}-hm-${config.label}.conf" {
lib.nameValuePair "fontconfig/conf.d/${toString config.priority}-hm-${config.label}.conf" {
inherit (config) enable text;
source = lib.mkIf (config.source != null) config.source;
}

View File

@@ -72,7 +72,7 @@ let
fileList ++ subdirFiles;
newsFiles = collectNixFiles ./news;
newsEntries = builtins.map (
newsEntries = map (
newsFile:
let
imported = import newsFile;

View File

@@ -0,0 +1,34 @@
{
config,
lib,
pkgs,
...
}:
{
time = "2025-11-04T15:44:03+00:00";
condition = true;
message = ''
The 'services.podman' module now supports Darwin (macOS) with declarative
machine management.
On Darwin, podman requires running containers inside a virtual machine.
The new configuration options allow you to declaratively manage podman
machines with automatic creation, configuration, and startup.
By default, a machine named 'podman-machine-default' will be created
automatically. You can customize machines or disable the default with:
services.podman.useDefaultMachine = false;
services.podman.machines = {
"my-machine" = {
cpus = 4;
memory = 8192;
diskSize = 100;
autoStart = true;
};
};
The module includes a launchd-based watchdog service that automatically
starts configured machines on login and keeps them running.
'';
}

View File

@@ -0,0 +1,12 @@
{ pkgs, ... }:
{
time = "2026-01-05T11:57:57+00:00";
condition = pkgs.stdenv.hostPlatform.isLinux;
message = ''
A new module is available: 'programs.workstyle'.
Workstyle dynamically renames Sway/i3/Hyprland workspaces to indicate
which programs are running in each one. For example, with a font icon.
'';
}

View File

@@ -0,0 +1,9 @@
{ config, ... }:
{
time = "2026-01-09T23:16:48+00:00";
condition = config.services.ssh-agent.enable;
message = ''
There is a new 'services.ssh-agent.pkcs11Whitelist' option to whitelist
PKCS#11 and FIDO authenticators.
'';
}

View File

@@ -47,9 +47,9 @@ in
desktop: terminals:
# Map desktop name such as GNOME to `.config/gnome-xdg-terminals.list`,
# default to `.config/xdg-terminals.list`.
lib.nameValuePair (
"${if desktop == "default" then "" else "${lib.toLower desktop}-"}xdg-terminals.list"
) { text = lib.concatLines terminals; }
lib.nameValuePair "${
if desktop == "default" then "" else "${lib.toLower desktop}-"
}xdg-terminals.list" { text = lib.concatLines terminals; }
) cfg.settings;
};
}

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

@@ -8,7 +8,7 @@ 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-11-30 14:00+0000\n"
"PO-Revision-Date: 2026-01-07 17:01+0000\n"
"Last-Translator: Brian E <brianellingsgaard9@gmail.com>\n"
"Language-Team: Faroese <https://hosted.weblate.org/projects/home-manager/"
"modules/fo/>\n"
@@ -17,7 +17,7 @@ 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.15-dev\n"
"X-Generator: Weblate 5.15.1\n"
#: modules/files.nix:206
msgid "Creating home file links in %s"
@@ -33,7 +33,7 @@ msgstr "Stovni nýggjan profil ættarlið"
#: modules/home-environment.nix:650
msgid "No change so reusing latest profile generation"
msgstr ""
msgstr "Eingin broyting. Seinastið umhvarv ættarlið er enn í brúk"
#: modules/home-environment.nix:699
msgid ""

View File

@@ -104,7 +104,7 @@ in
};
stylesets = mkOption {
type = with types; attrsOf (sectionsOrLines);
type = with types; attrsOf sectionsOrLines;
default = { };
example = literalExpression ''
{ default = { ui = { "tab.selected.reverse" = "toggle"; }; }; };

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

@@ -6,9 +6,7 @@
}:
let
inherit (builtins)
map
toJSON
toString
substring
stringLength
;

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

@@ -54,7 +54,7 @@ in
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
home.sessionVariables = lib.mkIf (cfg.settings != { }) {
BEMENU_OPTS = lib.cli.toGNUCommandLineShell { } cfg.settings;
BEMENU_OPTS = lib.cli.toCommandLineShellGNU { } cfg.settings;
};
};
}

View File

@@ -281,7 +281,7 @@ in
) supportedBrowsers;
config = lib.mkMerge (
builtins.map (browser: browserConfig browser config.programs.${browser}) (
map (browser: browserConfig browser config.programs.${browser}) (
builtins.attrNames supportedBrowsers
)
);

View File

@@ -129,7 +129,7 @@ in
enable = lib.mkDefault true;
iniContent =
let
difftCommand = "${lib.getExe cfg.package} ${lib.cli.toGNUCommandLineShell { } cfg.options}";
difftCommand = "${lib.getExe cfg.package} ${lib.cli.toCommandLineShellGNU { } cfg.options}";
in
mkMerge [
{

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

@@ -16,8 +16,7 @@ let
generateConfig = lib.generators.toKeyValue {
mkKeyValue =
name: value:
if lib.isString value then ''${name}="${value}"'' else "${name}=${builtins.toString value}";
name: value: if lib.isString value then ''${name}="${value}"'' else "${name}=${toString value}";
};
iniFormat = pkgs.formats.ini { listsAsDuplicateKeys = true; };

View File

@@ -103,7 +103,7 @@ in
{
name = path;
value = {
source = jsonFormat.generate "config.json" (ctx);
source = jsonFormat.generate "config.json" ctx;
};
}
) cfg.contexts;

View File

@@ -471,7 +471,7 @@ in
order = mkOption {
type = with types; uniq (listOf str);
apply = builtins.map migrateEngineNameToIdV7;
apply = map migrateEngineNameToIdV7;
default = [ ];
example = [
"ddg"

View File

@@ -301,20 +301,13 @@ let
let
name = if isAttrs def && def.name != null then def.name else attrName;
mods =
lib.cli.toGNUCommandLineShell
{
mkOption =
k: v:
if v == null then
[ ]
else if k == "set-cursor" then
[ "--${k}=${lib.generators.mkValueStringDefault { } v}" ]
else
[
"--${k}"
(lib.generators.mkValueStringDefault { } v)
];
}
lib.cli.toCommandLineShell
(optionName: {
option = "--${optionName}";
sep = if optionName == "set-cursor" then "=" else null;
explicitBool = false;
formatArg = lib.generators.mkValueStringDefault { };
})
{
inherit (def)
position
@@ -395,12 +388,14 @@ let
passAsFile = [ "text" ];
} "env HOME=$(mktemp -d) fish_indent < $textPath > $out";
translatedSessionVariables = pkgs.runCommandLocal "hm-session-vars.fish" { } ''
sessionVarsFile = "etc/profile.d/hm-session-vars.fish";
sessionVarsPkg = pkgs.runCommandLocal "hm-session-vars.fish" { } ''
mkdir -p "$(dirname $out/${sessionVarsFile})"
(echo "function setup_hm_session_vars;"
${pkgs.buildPackages.babelfish}/bin/babelfish \
<${config.home.sessionVariablesPackage}/etc/profile.d/hm-session-vars.sh
<${config.home.sessionVariablesPackage}/etc/profile.d/hm-session-vars.sh
echo "end"
echo "setup_hm_session_vars") > $out
echo "setup_hm_session_vars") > $out/${sessionVarsFile}
'';
in
@@ -598,11 +593,25 @@ in
<https://fishshell.com/docs/current/completions.html>.
'';
};
programs.fish.sessionVariablesPackage = mkOption {
type = types.package;
internal = true;
description = ''
The package containing the translated {file}`hm-session-vars.fish` file.
'';
};
};
config = mkIf cfg.enable (
lib.mkMerge [
{ home.packages = [ cfg.package ]; }
{
home.packages = [
cfg.package
cfg.sessionVariablesPackage
];
programs.fish.sessionVariablesPackage = sessionVarsPkg;
}
(mkIf cfg.generateCompletions (
let
@@ -618,7 +627,7 @@ in
package
]
++ lib.filter (p: p != null) (
builtins.map (outName: package.${outName} or null) config.home.extraOutputsToInstall
map (outName: package.${outName} or null) config.home.extraOutputsToInstall
);
nativeBuildInputs = [ pkgs.python3 ];
buildInputs = [ cfg.package ];
@@ -715,7 +724,7 @@ in
set -q __fish_home_manager_config_sourced; and exit
set -g __fish_home_manager_config_sourced 1
source ${translatedSessionVariables}
source ${cfg.sessionVariablesPackage}/${sessionVarsFile}
${cfg.shellInit}

View File

@@ -11,7 +11,7 @@ let
tomlFormat = pkgs.formats.toml { };
in
{
meta.maintainers = [ lib.hm.maintainers.rrvsh ];
meta.maintainers = [ lib.maintainers.rrvsh ];
options.programs.gemini-cli = {
enable = lib.mkEnableOption "gemini-cli";

View File

@@ -204,7 +204,7 @@ in
xdg.dataFile."gh/extensions" = mkIf (cfg.extensions != [ ]) {
source = pkgs.linkFarm "gh-extensions" (
builtins.map (p: {
map (p: {
name = p.pname;
path = "${p}/bin";
}) cfg.extensions

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

@@ -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

@@ -7,6 +7,8 @@
let
tomlFormat = pkgs.formats.toml { };
cfg = config.programs.gurk-rs;
configDir =
if pkgs.stdenv.hostPlatform.isDarwin then "Library/Application Support" else config.xdg.configHome;
in
{
meta.maintainers = [ lib.maintainers.da157 ];
@@ -46,9 +48,8 @@ in
config = lib.mkIf cfg.enable {
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
home.file."${
if pkgs.stdenv.hostPlatform.isDarwin then "Library/Application Support" else config.xdg.configHome
}/gurk/gurk.toml".source =
lib.mkIf (cfg.settings != { }) (tomlFormat.generate "gurk-config" cfg.settings);
home.file."${configDir}/gurk/gurk.toml" = lib.mkIf (cfg.settings != { }) {
source = tomlFormat.generate "gurk-config" cfg.settings;
};
};
}

View File

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

View File

@@ -70,7 +70,7 @@ in
"mako"
];
in
builtins.map (name: {
map (name: {
assertion = !config.services.${name}.enable;
message = ''
Only one notification daemon can be enabled at once. You have enabled

View File

@@ -139,7 +139,7 @@ in
in
lib.hm.dag.entryAfter [ "linkGeneration" ] ''
# Ensure that settings.json exists.
mkdir -p ${builtins.dirOf configPath}
mkdir -p ${dirOf configPath}
touch ${configPath}
# Config has to be written to temporary variable because jq cannot edit files in place.
config="$(jq -s '.[0] + .[1]' ${configPath} ${newConfig})"

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

@@ -14,7 +14,7 @@ let
renderSettings =
with lib.generators;
toINI {
mkKeyValue = mkKeyValueDefault rec {
mkKeyValue = mkKeyValueDefault {
mkValueString =
v:
if lib.isList v then
@@ -139,7 +139,7 @@ in
let
makePath =
baseDir: subDir:
builtins.toString (
toString (
/.
+ lib.concatStringsSep "/" [
baseDir

View File

@@ -341,16 +341,13 @@ in
# See https://sw.kovidgoyal.net/kitty/conf.html
${cfg.extraConfig}
'';
}
// lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux {
onChange = ''
${pkgs.procps}/bin/pkill -USR1 -u $USER kitty || true
'';
}
// lib.optionalAttrs pkgs.stdenv.hostPlatform.isDarwin {
onChange = ''
/usr/bin/pkill -USR1 -u $USER kitty || true
'';
onChange =
let
prefix = if pkgs.stdenv.hostPlatform.isDarwin then "/usr" else pkgs.procps;
in
''
${prefix}/bin/pkill -USR1 -u $USER kitty || true
'';
};
xdg.configFile."kitty/quick-access-terminal.conf" = mkIf (cfg.quickAccessTerminalConfig != { }) {

View File

@@ -9,7 +9,6 @@ let
cfg = config.programs.kubecolor;
yamlFormat = pkgs.formats.yaml { };
inherit (pkgs.stdenv.hostPlatform) isDarwin;
in
{
@@ -50,18 +49,20 @@ in
config =
let
preferXdgDirectories = config.home.preferXdgDirectories && (!isDarwin || config.xdg.enable);
preferXdgDirectories =
config.home.preferXdgDirectories && (!pkgs.stdenv.hostPlatform.isDarwin || config.xdg.enable);
configDir =
if preferXdgDirectories then
"${config.xdg.configHome}/kube"
else if pkgs.stdenv.hostPlatform.isDarwin then
"Library/Application Support/kube"
else
".kube";
# https://github.com/kubecolor/kubecolor/pull/145
configPathSuffix =
if
cfg.package.pname == "kubecolor"
&& lib.strings.toInt (lib.versions.major cfg.package.version) == 0
&& lib.strings.toInt (lib.versions.minor cfg.package.version) < 4
then
"kube/"
else
"kube/color.yaml";
configPathSuffix = lib.optionalString (
cfg.package.pname == "kubecolor" && lib.versionOlder (lib.getVersion cfg.package) "0.4"
) "color.yaml";
in
mkIf cfg.enable {
@@ -73,31 +74,10 @@ in
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
home.sessionVariables =
if preferXdgDirectories then
{
KUBECOLOR_CONFIG = "${config.xdg.configHome}/${configPathSuffix}";
}
else if isDarwin then
{
KUBECOLOR_CONFIG = "${config.home.homeDirectory}/Library/Application Support/${configPathSuffix}";
}
else
{ };
home.sessionVariables.KUBECOLOR_CONFIG = "${configDir}/${configPathSuffix}";
xdg.configFile = mkIf preferXdgDirectories {
"kube/color.yaml" = mkIf (cfg.settings != { }) {
source = yamlFormat.generate "kubecolor-settings" cfg.settings;
};
};
home.file = mkIf (!preferXdgDirectories) {
"Library/Application Support/kube/color.yaml" = mkIf (isDarwin && cfg.settings != { }) {
source = yamlFormat.generate "kubecolor-settings" cfg.settings;
};
".kube/color.yaml" = mkIf (!isDarwin && cfg.settings != { }) {
source = yamlFormat.generate "kubecolor-settings" cfg.settings;
};
home.file."${configDir}/color.yaml" = mkIf (cfg.settings != { }) {
source = yamlFormat.generate "kubecolor-settings" cfg.settings;
};
home.shellAliases = lib.mkIf (cfg.enableAlias && (cfg.package != null)) {

View File

@@ -201,7 +201,7 @@ let
plugins:
pkgs.linkFarm "lapce-plugins" (
builtins.listToAttrs (
builtins.map (
map (
{
author,
name,

View File

@@ -11,7 +11,11 @@ let
yamlFormat = pkgs.formats.yaml { };
inherit (pkgs.stdenv.hostPlatform) isDarwin;
configDir =
if pkgs.stdenv.hostPlatform.isDarwin && !config.xdg.enable then
"Library/Application Support/jesseduffield"
else
config.xdg.configHome;
in
{
@@ -51,16 +55,8 @@ in
config = lib.mkIf cfg.enable {
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
home.file."Library/Application Support/jesseduffield/lazydocker/config.yml" =
lib.mkIf (cfg.settings != { } && (isDarwin && !config.xdg.enable))
{
source = yamlFormat.generate "lazydocker-config" cfg.settings;
};
xdg.configFile."lazydocker/config.yml" =
lib.mkIf (cfg.settings != { } && !(isDarwin && !config.xdg.enable))
{
source = yamlFormat.generate "lazydocker-config" cfg.settings;
};
home.file."${configDir}/lazydocker/config.yml" = lib.mkIf (cfg.settings != { }) {
source = yamlFormat.generate "lazydocker-config" cfg.settings;
};
};
}

View File

@@ -11,8 +11,11 @@ let
yamlFormat = pkgs.formats.yaml { };
inherit (pkgs.stdenv.hostPlatform) isDarwin;
configDir =
if pkgs.stdenv.hostPlatform.isDarwin && !config.xdg.enable then
"Library/Application Support"
else
config.xdg.configHome;
in
{
meta.maintainers = [
@@ -71,17 +74,10 @@ in
config = mkIf cfg.enable {
home.packages = mkIf (cfg.package != null) [ cfg.package ];
home.file."Library/Application Support/lazygit/config.yml" =
mkIf (cfg.settings != { } && (isDarwin && !config.xdg.enable))
{
source = yamlFormat.generate "lazygit-config" cfg.settings;
};
xdg.configFile."lazygit/config.yml" =
mkIf (cfg.settings != { } && !(isDarwin && !config.xdg.enable))
{
source = yamlFormat.generate "lazygit-config" cfg.settings;
};
home.file."${configDir}/lazygit/config.yml" = {
enable = cfg.settings != { };
source = yamlFormat.generate "lazygit-config" cfg.settings;
};
programs =
let

View File

@@ -45,7 +45,7 @@ in
];
attrs = attrsOf (either scalar (listOf scalar));
in
coercedTo attrs (lib.cli.toGNUCommandLine { }) (listOf str);
coercedTo attrs (lib.cli.toCommandLineGNU { }) (listOf str);
default = [ ];
description = "Options to be set via {env}`$LESS`.";
example = {

View File

@@ -82,7 +82,7 @@ in
package = lib.mkPackageOption pkgs "meli" { };
includes = mkOption {
type = with types; listOf (str);
type = with types; listOf str;
description = "Paths of the various meli configuration files to include.";
default = [ ];
};

View File

@@ -7,6 +7,8 @@
let
cfg = config.programs.mullvad-vpn;
jsonFormat = pkgs.formats.json { };
configDir =
if pkgs.stdenv.hostPlatform.isDarwin then "Library/Application Support" else config.xdg.configHome;
in
{
meta.maintainers = [ lib.maintainers.da157 ];
@@ -42,11 +44,8 @@ in
config = lib.mkIf cfg.enable {
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
home.file."${
if pkgs.stdenv.hostPlatform.isDarwin then "Library/Application Support" else config.xdg.configHome
}/Mullvad VPN/gui_settings.json" =
lib.mkIf (cfg.settings != { }) {
source = jsonFormat.generate "mullvad-gui-settings" cfg.settings;
};
home.file."${configDir}/Mullvad VPN/gui_settings.json" = lib.mkIf (cfg.settings != { }) {
source = jsonFormat.generate "mullvad-gui-settings" cfg.settings;
};
};
}

View File

@@ -459,7 +459,7 @@ in
generatedConfigs =
let
grouped = builtins.groupBy (x: x.type) pluginsNormalized;
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;

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

@@ -13,7 +13,7 @@ let
renderSettings = settings: lib.concatStringsSep ";" (lib.mapAttrsToList renderSetting settings);
pluginModule = types.submodule ({
pluginModule = types.submodule {
options = {
src = mkOption {
type = with types; nullOr path;
@@ -46,7 +46,7 @@ let
'';
};
};
});
};
in
{
meta.maintainers = with lib.maintainers; [ thiagokokada ];

View File

@@ -254,7 +254,7 @@ in
cssSnippets =
let
checkCssPath = path: lib.filesystem.pathIsRegularFile path && lib.strings.hasSuffix ".css" path;
toCssName = path: lib.strings.removeSuffix ".css" (builtins.baseNameOf path);
toCssName = path: lib.strings.removeSuffix ".css" (baseNameOf path);
cssSnippetsOptions =
{ config, ... }:
{
@@ -423,7 +423,7 @@ in
source = (pkgs.formats.json { }).generate "appearance.json" (
vault.settings.appearance
// {
enabledCssSnippets = builtins.map (snippet: snippet.name) enabledCssSnippets;
enabledCssSnippets = map (snippet: snippet.name) enabledCssSnippets;
}
// lib.attrsets.optionalAttrs (activeTheme != null) {
cssTheme = getManifest activeTheme;
@@ -438,14 +438,14 @@ in
{
name = "${vault.target}/.obsidian/core-plugins.json";
value.source = (pkgs.formats.json { }).generate "core-plugins.json" (
builtins.map (plugin: plugin.name) vault.settings.corePlugins
map (plugin: plugin.name) vault.settings.corePlugins
);
}
{
name = "${vault.target}/.obsidian/core-plugins-migration.json";
value.source = (pkgs.formats.json { }).generate "core-plugins-migration.json" (
builtins.listToAttrs (
builtins.map (name: {
map (name: {
inherit name;
value = builtins.any (plugin: name == plugin.name && plugin.enable) vault.settings.corePlugins;
}) corePlugins
@@ -453,7 +453,7 @@ in
);
}
]
++ builtins.map (plugin: {
++ map (plugin: {
name = "${vault.target}/.obsidian/${plugin.name}.json";
value.source = (pkgs.formats.json { }).generate "${plugin.name}.json" plugin.settings;
}) (builtins.filter (plugin: plugin.settings != { }) vault.settings.corePlugins);
@@ -464,25 +464,25 @@ in
{
name = "${vault.target}/.obsidian/community-plugins.json";
value.source = (pkgs.formats.json { }).generate "community-plugins.json" (
builtins.map getManifest (builtins.filter (plugin: plugin.enable) vault.settings.communityPlugins)
map getManifest (builtins.filter (plugin: plugin.enable) vault.settings.communityPlugins)
);
}
]
++ builtins.map (plugin: {
++ map (plugin: {
name = "${vault.target}/.obsidian/plugins/${getManifest plugin}";
value = {
source = plugin.pkg;
recursive = true;
};
}) vault.settings.communityPlugins
++ builtins.map (plugin: {
++ map (plugin: {
name = "${vault.target}/.obsidian/plugins/${getManifest plugin}/data.json";
value.source = (pkgs.formats.json { }).generate "data.json" plugin.settings;
}) (builtins.filter (plugin: plugin.settings != { }) vault.settings.communityPlugins);
mkCssSnippets =
vault:
builtins.map (snippet: {
map (snippet: {
name = "${vault.target}/.obsidian/snippets/${snippet.name}.css";
value =
if snippet.source != null then
@@ -497,7 +497,7 @@ in
mkThemes =
vault:
builtins.map (theme: {
map (theme: {
name = "${vault.target}/.obsidian/themes/${getManifest theme}";
value.source = theme.pkg;
}) vault.settings.themes;
@@ -509,7 +509,7 @@ in
mkExtraFiles =
vault:
builtins.map (file: {
map (file: {
name = "${vault.target}/.obsidian/${file.target}";
value =
if file.source != null then
@@ -524,7 +524,7 @@ in
in
builtins.listToAttrs (
lib.lists.flatten (
builtins.map (vault: [
map (vault: [
(mkApp vault)
(mkAppearance vault)
(mkCorePlugins vault)
@@ -540,7 +540,7 @@ in
xdg.configFile."obsidian/obsidian.json".source = (pkgs.formats.json { }).generate "obsidian.json" {
vaults = builtins.listToAttrs (
builtins.map (vault: {
map (vault: {
name = builtins.hashString "md5" vault.target;
value = {
path = "${config.home.homeDirectory}/${vault.target}";

View File

@@ -126,14 +126,22 @@ in
};
commands = lib.mkOption {
type = lib.types.attrsOf (lib.types.either lib.types.lines lib.types.path);
type = lib.types.either (lib.types.attrsOf (lib.types.either lib.types.lines lib.types.path)) lib.types.path;
default = { };
description = ''
Custom commands for opencode.
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/opencode/command/` directory.
This option can either be:
- An attribute set defining commands
- A path to a directory containing multiple command files
If an attribute set is used, the attribute name becomes the command filename,
and the value is either:
- Inline content as a string (creates `opencode/command/<name>.md`)
- A path to a file (creates `opencode/command/<name>.md`)
If a path is used, it is expected to contain command files.
The directory is symlinked to {file}`$XDG_CONFIG_HOME/opencode/command/`.
'';
example = lib.literalExpression ''
{
@@ -155,14 +163,22 @@ in
};
agents = lib.mkOption {
type = lib.types.attrsOf (lib.types.either lib.types.lines lib.types.path);
type = lib.types.either (lib.types.attrsOf (lib.types.either lib.types.lines lib.types.path)) lib.types.path;
default = { };
description = ''
Custom agents for opencode.
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/opencode/agent/` directory.
This option can either be:
- An attribute set defining agents
- A path to a directory containing multiple agent files
If an attribute set is used, the attribute name becomes the agent filename,
and the value is either:
- Inline content as a string (creates `opencode/agent/<name>.md`)
- A path to a file (creates `opencode/agent/<name>.md`)
If a path is used, it is expected to contain agent files.
The directory is symlinked to {file}`$XDG_CONFIG_HOME/opencode/agent/`.
'';
example = lib.literalExpression ''
{
@@ -227,26 +243,94 @@ in
};
themes = mkOption {
type = lib.types.attrsOf (lib.types.either jsonFormat.type lib.types.path);
type = lib.types.either (lib.types.attrsOf (lib.types.either jsonFormat.type lib.types.path)) lib.types.path;
default = { };
description = ''
Custom themes for opencode. The attribute name becomes the theme
filename, and the value is either:
- An attribute set, that is converted to a json
- A path to a file containing the content
Themes are stored in {file}`$XDG_CONFIG_HOME/opencode/themes/` directory.
Custom themes for opencode.
This option can either be:
- An attribute set defining themes
- A path to a directory containing multiple theme files
If an attribute set is used, the attribute name becomes the theme filename,
and the value is either:
- An attribute set that is converted to a JSON file (creates `opencode/themes/<name>.json`)
- A path to a file (creates `opencode/themes/<name>.json`)
If a path is used, it is expected to contain theme files.
The directory is symlinked to {file}`$XDG_CONFIG_HOME/opencode/themes/`.
Set `programs.opencode.settings.theme` to enable the custom theme.
See <https://opencode.ai/docs/themes/> for the documentation.
'';
};
tools = lib.mkOption {
type = lib.types.either (lib.types.attrsOf (lib.types.either lib.types.lines lib.types.path)) lib.types.path;
default = { };
description = ''
Custom tools for opencode.
This option can either be:
- An attribute set defining tools
- A path to a directory containing multiple tool files
If an attribute set is used, the attribute name becomes the tool filename,
and the value is either:
- Inline content as a string (creates `opencode/tool/<name>.ts`)
- A path to a file (creates `opencode/tool/<name>.ts` or `opencode/tool/<name>.js`)
If a path is used, it is expected to contain tool files.
The directory is symlinked to {file}`$XDG_CONFIG_HOME/opencode/tool/`.
See <https://opencode.ai/docs/tools/> for the documentation.
'';
example = lib.literalExpression ''
{
database-query = '''
import { tool } from "@opencode-ai/plugin"
export default tool({
description: "Query the project database",
args: {
query: tool.schema.string().describe("SQL query to execute"),
},
async execute(args) {
// Your database logic here
return `Executed query: ''${args.query}`
},
})
''';
# Or reference an existing file
api-client = ./tools/api-client.ts;
}
'';
};
};
config = mkIf cfg.enable {
assertions = [
{
assertion = !lib.isPath cfg.commands || lib.pathIsDirectory cfg.commands;
message = "`programs.opencode.commands` must be a directory when set to a path";
}
{
assertion = !lib.isPath cfg.agents || lib.pathIsDirectory cfg.agents;
message = "`programs.opencode.agents` must be a directory when set to a path";
}
{
assertion = !lib.isPath cfg.tools || lib.pathIsDirectory cfg.tools;
message = "`programs.opencode.tools` must be a directory when set to a path";
}
{
assertion = !lib.isPath cfg.skills || lib.pathIsDirectory cfg.skills;
message = "`programs.opencode.skills` must be a directory when set to a path";
}
{
assertion = !lib.isPath cfg.themes || lib.pathIsDirectory cfg.themes;
message = "`programs.opencode.themes` must be a directory when set to a path";
}
];
home.packages = mkIf (cfg.package != null) [ cfg.package ];
@@ -278,23 +362,55 @@ in
})
);
"opencode/command" = mkIf (lib.isPath cfg.commands) {
source = cfg.commands;
recursive = true;
};
"opencode/agent" = mkIf (lib.isPath cfg.agents) {
source = cfg.agents;
recursive = true;
};
"opencode/tool" = mkIf (lib.isPath cfg.tools) {
source = cfg.tools;
recursive = true;
};
"opencode/skill" = mkIf (lib.isPath cfg.skills) {
source = cfg.skills;
recursive = true;
};
"opencode/themes" = mkIf (lib.isPath cfg.themes) {
source = cfg.themes;
recursive = true;
};
}
// lib.mapAttrs' (
name: content:
lib.nameValuePair "opencode/command/${name}.md" (
if lib.isPath content then { source = content; } else { text = content; }
)
) cfg.commands
// lib.mapAttrs' (
name: content:
lib.nameValuePair "opencode/agent/${name}.md" (
if lib.isPath content then { source = content; } else { text = content; }
)
) cfg.agents
// lib.optionalAttrs (builtins.isAttrs cfg.commands) (
lib.mapAttrs' (
name: content:
lib.nameValuePair "opencode/command/${name}.md" (
if lib.isPath content then { source = content; } else { text = content; }
)
) cfg.commands
)
// lib.optionalAttrs (builtins.isAttrs cfg.agents) (
lib.mapAttrs' (
name: content:
lib.nameValuePair "opencode/agent/${name}.md" (
if lib.isPath content then { source = content; } else { text = content; }
)
) cfg.agents
)
// lib.optionalAttrs (builtins.isAttrs cfg.tools) (
lib.mapAttrs' (
name: content:
lib.nameValuePair "opencode/tool/${name}.ts" (
if lib.isPath content then { source = content; } else { text = content; }
)
) cfg.tools
)
// lib.mapAttrs' (
name: content:
if lib.isPath content && lib.pathIsDirectory content then
@@ -307,23 +423,25 @@ in
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" (
if lib.isPath content then
{
source = content;
}
else
{
source = jsonFormat.generate "opencode-${name}.json" (
{
"$schema" = "https://opencode.ai/theme.json";
}
// content
);
}
)
) cfg.themes;
// lib.optionalAttrs (builtins.isAttrs cfg.themes) (
lib.mapAttrs' (
name: content:
lib.nameValuePair "opencode/themes/${name}.json" (
if lib.isPath content then
{
source = content;
}
else
{
source = jsonFormat.generate "opencode-${name}.json" (
{
"$schema" = "https://opencode.ai/theme.json";
}
// content
);
}
)
) cfg.themes
);
};
}

View File

@@ -19,7 +19,7 @@ let
in
{
meta.maintainers = [ lib.hm.maintainers.nickthegroot ];
meta.maintainers = [ lib.maintainers.nickthegroot ];
options.programs.pgcli = {
enable = mkEnableOption "pgcli";

View File

@@ -9,6 +9,9 @@ let
cfg = config.programs.pistol;
configDir =
if pkgs.stdenv.hostPlatform.isDarwin then "Library/Preferences" else config.xdg.configHome;
configFile = lib.concatStringsSep "\n" (
map (
{
@@ -74,31 +77,23 @@ in
};
config = mkIf cfg.enable (
lib.mkMerge [
config = mkIf cfg.enable {
assertions = [
{
assertions = [
{
assertion = lib.all (
{ fpath, mime, ... }: (fpath != "" && mime == "") || (fpath == "" && mime != "")
) cfg.associations;
message = ''
Each entry in programs.pistol.associations must contain exactly one
of fpath or mime.
'';
}
];
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
assertion = lib.all (
{ fpath, mime, ... }: (fpath != "" && mime == "") || (fpath == "" && mime != "")
) cfg.associations;
message = ''
Each entry in programs.pistol.associations must contain exactly one
of fpath or mime.
'';
}
];
(mkIf (cfg.associations != [ ] && pkgs.stdenv.hostPlatform.isDarwin) {
home.file."Library/Preferences/pistol/pistol.conf".text = configFile;
})
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
(mkIf (cfg.associations != [ ] && !pkgs.stdenv.hostPlatform.isDarwin) {
xdg.configFile."pistol/pistol.conf".text = configFile;
})
]
);
home.file."${configDir}/pistol/pistol.conf" = mkIf (cfg.associations != [ ]) {
text = configFile;
};
};
}

View File

@@ -19,11 +19,11 @@ let
valueToString =
value:
if builtins.isList value then
builtins.concatStringsSep "," (builtins.map valueToString value)
builtins.concatStringsSep "," (map valueToString value)
else if builtins.isAttrs value then
valueToString (lib.mapAttrsToList (key: val: "${valueToString key}=${valueToString val}") value)
else
builtins.toString value;
toString value;
modulesArgument = optionalString (cfg.modules != null) " -modules ${valueToString cfg.modules}";

View File

@@ -27,7 +27,7 @@ let
else if builtins.isList v then
"[${concatStringsSep ", " (map pythonize v)}]"
else
builtins.toString v;
toString v;
formatDictLine =
o: n: v:
@@ -336,22 +336,20 @@ in
greasemonkeyDir = lib.optionals (
cfg.greasemonkey != [ ]
) pkgs.linkFarmFromDrvs "greasemonkey-userscripts" cfg.greasemonkey;
configDir =
if pkgs.stdenv.hostPlatform.isDarwin then
".qutebrowser"
else
"${config.xdg.configHome}/qutebrowser";
in
mkIf cfg.enable {
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
home.file.".qutebrowser/config.py" = mkIf pkgs.stdenv.hostPlatform.isDarwin {
text = qutebrowserConfig;
};
home.file.".qutebrowser/quickmarks" =
mkIf (cfg.quickmarks != { } && pkgs.stdenv.hostPlatform.isDarwin)
{
text = quickmarksFile;
};
xdg.configFile."qutebrowser/config.py" = mkIf pkgs.stdenv.hostPlatform.isLinux {
home.file."${configDir}/config.py" = {
text = qutebrowserConfig;
}
// lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux {
onChange = ''
hash="$(echo -n "$USER" | md5sum | cut -d' ' -f1)"
socket="''${XDG_RUNTIME_DIR:-/run/user/$UID}/qutebrowser/ipc-$hash"
@@ -371,22 +369,12 @@ in
'';
};
xdg.configFile."qutebrowser/quickmarks" =
mkIf (cfg.quickmarks != { } && pkgs.stdenv.hostPlatform.isLinux)
{
text = quickmarksFile;
};
home.file."${configDir}/quickmarks" = mkIf (cfg.quickmarks != { }) {
text = quickmarksFile;
};
home.file.".qutebrowser/greasemonkey" =
mkIf (cfg.greasemonkey != [ ] && pkgs.stdenv.hostPlatform.isDarwin)
{
source = greasemonkeyDir;
};
xdg.configFile."qutebrowser/greasemonkey" =
mkIf (cfg.greasemonkey != [ ] && pkgs.stdenv.hostPlatform.isLinux)
{
source = greasemonkeyDir;
};
home.file."${configDir}/greasemonkey" = mkIf (cfg.greasemonkey != [ ]) {
source = greasemonkeyDir;
};
};
}

View File

@@ -168,7 +168,7 @@ in
}
{
assertion = cfg.uri.web-rad.enable -> cfg.uri.web-rad.browser != null;
message = "Could not detect preferred browser. Please set `${builtins.toString opt.uri.web-rad.browser}`.";
message = "Could not detect preferred browser. Please set `${toString opt.uri.web-rad.browser}`.";
}
{
assertion =

View File

@@ -71,7 +71,7 @@ in
home.file.".rbenv/plugins" = mkIf (cfg.plugins != [ ]) {
source = pkgs.linkFarm "rbenv-plugins" (
builtins.map (p: {
map (p: {
name = p.name;
path = p.src;
}) cfg.plugins

View File

@@ -10,7 +10,6 @@ let
jsonFormat = pkgs.formats.json { };
inherit (lib) mkOption types;
inherit (pkgs.stdenv.hostPlatform) isDarwin;
settingsModule = types.submodule {
freeformType = jsonFormat.type;
@@ -62,6 +61,9 @@ let
};
};
};
configDir =
if pkgs.stdenv.hostPlatform.isDarwin then "Library/Application Support" else config.xdg.configHome;
in
{
meta.maintainers = with lib.maintainers; [ ambroisie ];
@@ -93,21 +95,11 @@ in
};
};
config = lib.mkIf cfg.enable (
lib.mkMerge [
{
home.packages = [ cfg.package ];
}
config = lib.mkIf cfg.enable {
home.packages = [ cfg.package ];
# Only manage configuration if not empty
(lib.mkIf (cfg.settings != null && !isDarwin) {
xdg.configFile."rbw/config.json".source = jsonFormat.generate "rbw-config.json" cfg.settings;
})
(lib.mkIf (cfg.settings != null && isDarwin) {
home.file."Library/Application Support/rbw/config.json".source =
jsonFormat.generate "rbw-config.json" cfg.settings;
})
]
);
home.file."${configDir}/rbw/config.json" = lib.mkIf (cfg.settings != null) {
source = jsonFormat.generate "rbw-config.json" cfg.settings;
};
};
}

View File

@@ -158,7 +158,7 @@ in
description = ''
An attribute set of option values passed to `rclone mount`. To set
a boolean option, assign it `true` or `false`. See
<https://nixos.org/manual/nixpkgs/stable/#function-library-lib.cli.toGNUCommandLineShell>
<https://nixos.org/manual/nixpkgs/stable/#function-library-lib.cli.toCommandLineShellGNU>
for more details on the format.
Some caching options are set by default, namely `vfs-cache-mode = "full"`
@@ -374,7 +374,7 @@ in
ExecStart = lib.concatStringsSep " " [
(lib.getExe cfg.package)
"mount"
(lib.cli.toGNUCommandLineShell { } mount.options)
(lib.cli.toCommandLineShellGNU { } mount.options)
"${remote-name}:${mount-path}"
"${mount.mountPoint}"
];

View File

@@ -135,7 +135,7 @@ let
modes = map (mode: if isString mode then mode else "${mode.name}:${mode.path}") cfg.modes;
in
{
meta.maintainers = with lib.maintainers; [ ];
meta.maintainers = [ ];
options.programs.rofi = {
enable = lib.mkEnableOption "Rofi: A window switcher, application launcher and dmenu replacement";

View File

@@ -11,6 +11,9 @@ let
iniFormat = pkgs.formats.ini { };
configDir =
if pkgs.stdenv.hostPlatform.isDarwin then "Library/Preferences" else config.xdg.configHome;
in
{
meta.maintainers = [ lib.maintainers.pbar ];
@@ -55,32 +58,22 @@ in
{
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
programs.sapling.iniContent.ui = {
username = cfg.userName + " <" + cfg.userEmail + ">";
programs.sapling.iniContent = {
alias = mkIf (cfg.aliases != { }) cfg.aliases;
ui.username = cfg.userName + " <" + cfg.userEmail + ">";
};
home.file."${configDir}/sapling/sapling.conf" = mkIf (cfg.iniContent != { }) {
source = iniFormat.generate "sapling.conf" cfg.iniContent;
};
}
(mkIf (!pkgs.stdenv.isDarwin) {
xdg.configFile."sapling/sapling.conf".source = iniFormat.generate "sapling.conf" cfg.iniContent;
})
(mkIf (pkgs.stdenv.isDarwin) {
home.file."Library/Preferences/sapling/sapling.conf".source =
iniFormat.generate "sapling.conf" cfg.iniContent;
})
(mkIf (cfg.aliases != { }) {
programs.sapling.iniContent.alias = cfg.aliases;
})
(mkIf (lib.isAttrs cfg.extraConfig) {
programs.sapling.iniContent = cfg.extraConfig;
})
(mkIf (lib.isString cfg.extraConfig && !pkgs.stdenv.isDarwin) {
xdg.configFile."sapling/sapling.conf".text = cfg.extraConfig;
})
(mkIf (lib.isString cfg.extraConfig && pkgs.stdenv.isDarwin) {
home.file."Library/Preferences/sapling/sapling.conf".text = cfg.extraConfig;
(mkIf (lib.isString cfg.extraConfig) {
home.file."${configDir}/sapling/sapling.conf".text = cfg.extraConfig;
})
]
);

View File

@@ -40,6 +40,12 @@ let
description = "The remote path to mount.";
};
mountDestPath = mkOption {
type = types.nullOr types.str;
default = null;
description = "The path on the current machine where the remote path would be mounted.";
};
authType = mkOption {
type = types.enum [
"password"
@@ -47,6 +53,7 @@ let
"hostbased"
"keyboard-interactive"
"gssapi-with-mic"
"authentication-agent"
];
default = "publickey";
description = "The authentication method to use.";

View File

@@ -158,7 +158,7 @@ in
prjConf =
lib.attrsets.mapAttrs' (
name: value:
(lib.attrsets.nameValuePair (if name == "beforeStart" then "before_start" else name) (value))
(lib.attrsets.nameValuePair (if name == "beforeStart" then "before_start" else name) value)
) v
// {
session = k;

View File

@@ -9,6 +9,11 @@ let
cfg = config.programs.streamlink;
configDir =
if pkgs.stdenv.hostPlatform.isDarwin then "Library/Application Support" else config.xdg.configHome;
dataDir =
if pkgs.stdenv.hostPlatform.isDarwin then "Library/Application Support" else config.xdg.dataHome;
renderSettings =
settings:
lib.concatLines (
@@ -18,9 +23,9 @@ let
if (builtins.isBool value) then
if value then name else ""
else if (builtins.isList value) then
lib.concatStringsSep "\n" (builtins.map (item: "${name}=${builtins.toString item}") value)
lib.concatStringsSep "\n" (map (item: "${name}=${toString item}") value)
else
"${name}=${builtins.toString value}"
"${name}=${toString value}"
) settings
)
);
@@ -130,72 +135,36 @@ in
};
};
config = lib.mkIf cfg.enable (
lib.mkMerge [
{ home.packages = lib.mkIf (cfg.package != null) [ cfg.package ]; }
config = lib.mkIf cfg.enable {
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
(lib.mkIf pkgs.stdenv.hostPlatform.isLinux {
xdg.configFile = {
"streamlink/config" = lib.mkIf (cfg.settings != { }) {
text = renderSettings cfg.settings;
};
home.file = {
"${configDir}/streamlink/config" = lib.mkIf (cfg.settings != { }) {
text = renderSettings cfg.settings;
};
}
// (lib.mapAttrs' (
name: value:
lib.nameValuePair "${configDir}/streamlink/config.${name}" (
lib.mkIf (value.settings != { }) {
text = renderSettings value.settings;
}
// (lib.mapAttrs' (
name: value:
lib.nameValuePair "streamlink/config.${name}" (
lib.mkIf (value.settings != { }) {
text = renderSettings value.settings;
)
) cfg.plugins)
// (lib.mapAttrs' (
name: value:
lib.nameValuePair "${dataDir}/streamlink/plugins/${name}.py" (
lib.mkIf (value.src != null) (
if (builtins.isPath value.src) then
{
source = value.src;
}
)
) cfg.plugins);
xdg.dataFile = lib.mapAttrs' (
name: value:
lib.nameValuePair "streamlink/plugins/${name}.py" (
lib.mkIf (value.src != null) (
if (builtins.isPath value.src) then
{
source = value.src;
}
else
{
text = value.src;
}
)
)
) cfg.plugins;
})
(lib.mkIf pkgs.stdenv.hostPlatform.isDarwin {
home.file = {
"Library/Application Support/streamlink/config" = lib.mkIf (cfg.settings != { }) {
text = renderSettings cfg.settings;
};
}
// (lib.mapAttrs' (
name: value:
lib.nameValuePair "Library/Application Support/streamlink/config.${name}" (
lib.mkIf (value.settings != { }) {
text = renderSettings value.settings;
else
{
text = value.src;
}
)
) cfg.plugins)
// (lib.mapAttrs' (
name: value:
lib.nameValuePair "Library/Application Support/streamlink/plugins/${name}.py" (
lib.mkIf (value.src != null) (
if (builtins.isPath value.src) then
{
source = value.src;
}
else
{
text = value.src;
}
)
)
) cfg.plugins);
})
]
);
)
)
) cfg.plugins);
};
}

View File

@@ -85,8 +85,7 @@ in
if v == false then
""
else
(if v == true then n else n + "=" + (if builtins.isPath v then "${v}" else builtins.toString v))
+ "\n"
(if v == true then n else n + "=" + (if builtins.isPath v then "${v}" else toString v)) + "\n"
) cfg.settings
);
};

View File

@@ -183,14 +183,12 @@ let
3;
"mail.smtpserver.smtp_${id}.username" = account.userName;
}
// builtins.foldl' (a: b: a // b) { } (
builtins.map (address: toThunderbirdSMTP account address) addresses
)
// builtins.foldl' (a: b: a // b) { } (map (address: toThunderbirdSMTP account address) addresses)
// optionalAttrs (account.smtp != null && account.primary) {
"mail.smtp.defaultserver" = "smtp_${id}";
}
// builtins.foldl' (a: b: a // b) { } (
builtins.map (address: toThunderbirdIdentity account address) addresses
map (address: toThunderbirdIdentity account address) addresses
)
// account.thunderbird.settings id;

View File

@@ -69,7 +69,7 @@ in
let
conf =
optional (cfg.host != null) ''set -g tmate-server-host "${cfg.host}"''
++ optional (cfg.port != null) "set -g tmate-server-port ${builtins.toString cfg.port}"
++ optional (cfg.port != null) "set -g tmate-server-port ${toString cfg.port}"
++ optional (
cfg.dsaFingerprint != null
) ''set -g tmate-server-ed25519-fingerprint "${cfg.dsaFingerprint}"''

View File

@@ -92,9 +92,12 @@ in
};
};
config = lib.mkIf cfg.enable (
config =
let
config =
configDir =
if pkgs.stdenv.hostPlatform.isDarwin then "Library/Application Support" else config.xdg.configHome;
configFiles =
lib.attrsets.unionOfDisjoint
{
"vesktop/settings.json" = lib.mkIf (cfg.settings != { }) {
@@ -117,16 +120,11 @@ in
) cfg.vencord.themes
);
in
lib.mkMerge [
{
home.packages = [
(cfg.package.override { withSystemVencord = cfg.vencord.useSystem; })
];
}
(lib.mkIf (!pkgs.stdenv.hostPlatform.isDarwin) { xdg.configFile = config; })
(lib.mkIf pkgs.stdenv.hostPlatform.isDarwin {
home.file = lib.mapAttrs' (n: v: lib.nameValuePair "Library/Application Support/${n}" v) config;
})
]
);
lib.mkIf cfg.enable {
home.packages = [
(cfg.package.override { withSystemVencord = cfg.vencord.useSystem; })
];
home.file = lib.mapAttrs' (n: lib.nameValuePair "${configDir}/${n}") configFiles;
};
}

View File

@@ -240,7 +240,7 @@ in
dataFile =
builtins.listToAttrs (
builtins.map (item: {
map (item: {
name = "vicinae/extensions/${item.name}";
value.source = item;
}) cfg.extensions
@@ -263,7 +263,7 @@ in
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}
USE_LAYER_SHELL=${if cfg.useLayerShell then toString 1 else toString 0}
''
);
};

View File

@@ -517,7 +517,7 @@ in
else
{ };
# Merge MCP servers: transformed servers + user servers, with user servers taking precedence
mergedServers = transformedMcpServers // ((v.userMcp.servers or { }));
mergedServers = transformedMcpServers // (v.userMcp.servers or { });
# Merge all MCP config
mergedMcpConfig =
v.userMcp // (lib.optionalAttrs (mergedServers != { }) { servers = mergedServers; });

View File

@@ -301,7 +301,7 @@ in
{
assertions = [
(lib.hm.assertions.assertPlatform "programs.waybar" pkgs lib.platforms.linux)
({
{
assertion =
if lib.versionAtLeast config.home.stateVersion "22.05" then
all (x: !hasAttr "modules" x || x.modules == null) settings
@@ -311,7 +311,7 @@ in
The `programs.waybar.settings.[].modules` option has been removed.
It is now possible to declare modules in the configuration without nesting them under the `modules` option.
'';
})
}
];
home.packages = [ cfg.package ];

View File

@@ -58,7 +58,7 @@ in
xdg.configFile."waylogout/config" = lib.mkIf (cfg.settings != { }) {
text = lib.concatStrings (
lib.mapAttrsToList (
n: v: if v == false then "" else (if v == true then n else n + "=" + builtins.toString v) + "\n"
n: v: if v == false then "" else (if v == true then n else n + "=" + toString v) + "\n"
) cfg.settings
);
};

View File

@@ -0,0 +1,94 @@
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) literalExpression mkOption mkEnableOption;
inherit (lib.modules) mkIf;
cfg = config.programs.workstyle;
tomlFormat = pkgs.formats.toml { };
configFile = tomlFormat.generate "config.toml" cfg.settings;
in
{
meta.maintainers = with lib.hm.maintainers; [ farberbrodsky ];
options.programs.workstyle = {
enable = mkEnableOption "Workstyle";
package = lib.mkPackageOption pkgs "workstyle" { };
systemd = {
enable = mkEnableOption "Workstyle systemd integration";
debug = mkEnableOption "Workstyle debug logs";
target = mkOption {
type = lib.types.str;
default = config.wayland.systemd.target;
defaultText = literalExpression "config.wayland.systemd.target";
example = "sway-session.target";
description = ''
The systemd target that will automatically start the Workstyle service.
When setting this value to `"sway-session.target"`,
make sure to also enable {option}`wayland.windowManager.sway.systemd.enable`,
otherwise the service may never be started.
'';
};
};
settings = lib.mkOption {
inherit (tomlFormat) type;
default = { };
description = "Configuration for workstyle";
example = literalExpression ''
{
# Config for workstyle
# Format: "pattern" = "icon";
# The pattern will be used to match against the application name, class_id or WM_CLASS.
# The icon will be used to represent that application.
# Note if multiple patterns are present in the same application name,
# precedence is given in order of apparition in this file.
kitty = "T";
firefox = "B";
other = {
fallback_icon = "F";
deduplicate_icons = false;
separator = ": ";
};
}
'';
};
};
config = lib.mkIf cfg.enable {
assertions = [
(lib.hm.assertions.assertPlatform "programs.workstyle" pkgs lib.platforms.linux)
];
home.packages = [ cfg.package ];
xdg.configFile."workstyle/config.toml" = mkIf (cfg.settings != { }) { source = configFile; };
systemd.user.services.workstyle = mkIf cfg.systemd.enable {
Unit = {
Description = "workstyle autostart";
BindsTo = [ cfg.systemd.target ];
# This is not necessary: workstyle reloads the config file after every window event.
# It might become necessary in the future.
# X-Restart-Triggers = mkIf (cfg.settings != { }) [ "${configFile}" ];
};
Service = {
ExecStart = "${cfg.package}/bin/workstyle";
Restart = "always";
RestartSec = 3;
Environment = mkIf (cfg.systemd.debug) "RUST_LOG=debug";
};
Install.WantedBy = [ cfg.systemd.target ];
};
};
}

View File

@@ -35,7 +35,7 @@ let
'';
}
else
builtins.dirOf value;
dirOf value;
makePluginSearchPath = p: "${p}/?/init.lua;${p}/?.lua";
@@ -46,9 +46,9 @@ let
searchPaths = map makePluginSearchPath wrappedPlugins;
pluginSearchPath = lib.concatStringsSep ";" searchPaths;
in
(''
''
package.path = "${pluginSearchPath};" .. package.path
'')
''
else
"\n";

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" ];

View File

@@ -163,7 +163,7 @@ in
};
};
config = lib.mkIf cfg.enable ({
config = lib.mkIf cfg.enable {
assertions = [
{
assertion = (lib.count (p: p.isActive) (lib.attrValues cfg.profiles)) <= 1;
@@ -189,78 +189,74 @@ in
if activeProfile.name != "default" then "colima-${activeProfile.name}" else "colima"
);
launchd.agents = lib.mkIf pkgs.stdenv.isDarwin (
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)
);
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.mkIf pkgs.stdenv.isLinux (
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)
);
});
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

@@ -119,127 +119,117 @@ in
};
};
config = mkIf cfg.enable (
lib.mkMerge [
{
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;
};
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

@@ -127,7 +127,7 @@ in
};
Service = {
Environment = with pkgs; "PATH=${makeBinPath cfg.extraPackages}";
Environment = "PATH=${makeBinPath cfg.extraPackages}";
ExecStart = "${cfg.package}/bin/fusuma";
};

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";
};
};
};
}

View File

@@ -45,16 +45,18 @@ in
'';
example = lib.literalExpression ''
{
ipc = "on";
splash = false;
splash_offset = 2.0;
preload =
[ "/share/wallpapers/buttons.png" "/share/wallpapers/cat_pacman.png" ];
wallpaper = [
"DP-3,/share/wallpapers/buttons.png"
"DP-1,/share/wallpapers/cat_pacman.png"
{
monitor = "DP-3";
path = "/share/wallpapers/buttons.png";
fit_mode = "tile";
}
{
monitor = "DP-1";
path = "/share/wallpapers/cat_pacman.png";
}
];
}
'';
@@ -62,7 +64,10 @@ in
importantPrefixes = lib.mkOption {
type = with lib.types; listOf str;
default = [ "$" ];
default = [
"$"
"monitor"
];
example = [ "$" ];
description = ''
List of prefix of attributes to source at the top of the config.

View File

@@ -117,7 +117,7 @@ in
args = lib.lists.forEach cfg.wallpapers (
each:
lib.concatStringsSep " " (
lib.cli.toGNUCommandLine { } {
lib.cli.toCommandLineGNU { } {
screen-root = each.monitor;
inherit (each) scaling fps;
inherit (each.audio) silent;
@@ -125,9 +125,11 @@ in
no-audio-processing = !each.audio.processing;
}
++ each.extraOptions
++ [
"--bg"
each.wallpaperId
]
)
# This has to be the last argument in each group
+ " --bg ${each.wallpaperId}"
);
in
{

View File

@@ -166,10 +166,14 @@ in
mkIf cfg.enable {
home = {
packages = [ cfg.package ];
sessionVariables = mkIf cfg.enableSessionVariables {
MPD_HOST = mkIf (cfg.network.listenAddress != "any") cfg.network.listenAddress;
MPD_PORT = builtins.toString cfg.network.port;
};
sessionVariables = mkIf cfg.enableSessionVariables (
{
MPD_PORT = toString cfg.network.port;
}
// lib.optionalAttrs (cfg.network.listenAddress != "any") {
MPD_HOST = cfg.network.listenAddress;
}
);
};
services.mpd = lib.mkMerge [
@@ -182,7 +186,7 @@ in
})
];
systemd.user = lib.mkIf pkgs.stdenv.hostPlatform.isLinux {
systemd.user = {
services.mpd = {
Unit = lib.mkMerge [
{
@@ -236,7 +240,7 @@ in
};
};
launchd.agents.mpd = lib.mkIf pkgs.stdenv.hostPlatform.isDarwin {
launchd.agents.mpd = {
enable = true;
config = {
ProgramArguments = [

View File

@@ -83,56 +83,51 @@ in
};
};
config = lib.mkIf cfg.automatic (
lib.mkMerge [
(lib.mkIf pkgs.stdenv.isLinux {
systemd.user.services.nix-gc = {
Unit = {
Description = "Nix Garbage Collector";
};
Service = {
Type = "oneshot";
ExecStart = pkgs.writeShellScript "nix-gc" "exec ${nixPackage}/bin/nix-collect-garbage ${
lib.optionalString (cfg.options != null) cfg.options
}";
};
};
systemd.user.timers.nix-gc = {
Unit = {
Description = "Nix Garbage Collector";
};
Timer = {
OnCalendar = cfg.dates;
RandomizedDelaySec = cfg.randomizedDelaySec;
Persistent = cfg.persistent;
Unit = "nix-gc.service";
};
Install = {
WantedBy = [ "timers.target" ];
};
};
})
config = lib.mkIf cfg.automatic {
systemd.user.services.nix-gc = {
Unit = {
Description = "Nix Garbage Collector";
};
Service = {
Type = "oneshot";
ExecStart = pkgs.writeShellScript "nix-gc" "exec ${nixPackage}/bin/nix-collect-garbage ${
lib.optionalString (cfg.options != null) cfg.options
}";
};
};
(lib.mkIf pkgs.stdenv.isDarwin {
assertions = [
{
assertion = (lib.length cfg.dates) == 1;
message = "On Darwin, `nix.gc.dates` must contain a single element.";
}
(lib.hm.darwin.assertInterval "nix.gc.dates.*" (lib.elemAt cfg.dates 0) pkgs)
];
systemd.user.timers.nix-gc = {
Unit = {
Description = "Nix Garbage Collector";
};
Timer = {
OnCalendar = cfg.dates;
RandomizedDelaySec = cfg.randomizedDelaySec;
Persistent = cfg.persistent;
Unit = "nix-gc.service";
};
Install = {
WantedBy = [ "timers.target" ];
};
};
launchd.agents.nix-gc = {
enable = true;
config = {
ProgramArguments = [
"${nixPackage}/bin/nix-collect-garbage"
]
++ lib.optional (cfg.options != null) cfg.options;
StartCalendarInterval = lib.hm.darwin.mkCalendarInterval (lib.elemAt cfg.dates 0);
};
};
})
]
);
assertions = [
{
assertion = pkgs.stdenv.isDarwin -> (lib.length cfg.dates == 1);
message = "On Darwin, `nix.gc.dates` must contain a single element.";
}
(lib.hm.darwin.assertInterval "nix.gc.dates.*" (lib.elemAt cfg.dates 0) pkgs)
];
launchd.agents.nix-gc = {
enable = true;
config = {
ProgramArguments = [
"${nixPackage}/bin/nix-collect-garbage"
]
++ lib.optional (cfg.options != null) cfg.options;
StartCalendarInterval = lib.hm.darwin.mkCalendarInterval (lib.elemAt cfg.dates 0);
};
};
};
}

View File

@@ -87,7 +87,7 @@ in
};
config = mkIf cfg.enable {
systemd.user.services.ollama = mkIf pkgs.stdenv.isLinux {
systemd.user.services.ollama = {
Unit = {
Description = "Server for local large language models";
After = [ "network.target" ];
@@ -105,7 +105,7 @@ in
};
};
launchd.agents.ollama = mkIf pkgs.stdenv.isDarwin {
launchd.agents.ollama = {
enable = true;
config = {
ProgramArguments = [

View File

@@ -0,0 +1,23 @@
{ lib }:
{
assertPlatform =
module: config: pkgs: platforms:
let
modulePath = lib.splitString "." module;
isEmpty = x: x == false || x == null || x == { } || x == [ ] || x == "";
in
{
assertion =
(isEmpty (lib.attrByPath modulePath null config))
|| (lib.elem pkgs.stdenv.hostPlatform.system platforms);
message =
let
platformsStr = lib.concatStringsSep "\n" (map (p: " - ${p}") (lib.sort (a: b: a < b) platforms));
in
''
The module ${module} does not support your platform. It only supports
${platformsStr}'';
};
}

View File

@@ -0,0 +1,301 @@
{
config,
lib,
pkgs,
...
}:
let
inherit (lib)
attrNames
concatStringsSep
filterAttrs
mapAttrs'
mkIf
mkOption
mkMerge
nameValuePair
optionalString
types
;
assertions = import ./assertions.nix { inherit lib; };
cfg = config.services.podman;
machineDefinitionType = types.submodule {
options = {
cpus = mkOption {
type = types.nullOr types.ints.positive;
default = null;
example = 2;
description = "Number of CPUs to allocate to the machine. If null, uses podman's default.";
};
diskSize = mkOption {
type = types.nullOr types.ints.positive;
default = null;
example = 200;
description = "Disk size in GB for the machine. If null, uses podman's default.";
};
image = mkOption {
type = types.nullOr types.str;
default = null;
description = "Bootable image to use for the machine. If null, uses podman's default.";
};
memory = mkOption {
type = types.nullOr types.ints.positive;
default = null;
example = 8192;
description = "Memory in MB to allocate to the machine. If null, uses podman's default.";
};
rootful = mkOption {
type = types.nullOr types.bool;
default = null;
example = true;
description = ''
Whether to run the machine in rootful mode. If null, uses podman's default.
Rootful mode runs containers as root inside the VM.
'';
};
swap = mkOption {
type = types.nullOr types.ints.positive;
default = null;
example = 2048;
description = "Swap size in MB for the machine. If null, uses podman's default.";
};
timezone = mkOption {
type = types.nullOr types.str;
default = null;
example = "UTC";
description = "Timezone to set in the machine. If null, uses podman's default.";
};
username = mkOption {
type = types.nullOr types.str;
default = null;
example = "user";
description = "Username used in the machine image. If null, uses podman's default.";
};
volumes = mkOption {
type = types.listOf types.str;
default = [ ];
example = [
"/Users:/Users"
"/private:/private"
"/var/folders:/var/folders"
];
description = ''
Volumes to mount in the machine, specified as source:target pairs.
If empty, podman will use its default volume mounts.
'';
};
autoStart = mkOption {
type = types.bool;
default = true;
example = false;
description = "Whether to automatically start this machine on login.";
};
watchdogInterval = mkOption {
type = types.ints.positive;
default = 30;
example = 60;
description = "Interval in seconds to check if the machine is running";
};
};
};
mkWatchdogScript =
name: machine:
pkgs.writeShellScript "podman-machine-watchdog-${name}" ''
set -euo pipefail
MACHINE_NAME="${name}"
INTERVAL=${toString machine.watchdogInterval}
PODMAN="${lib.getExe cfg.package}"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >&2
}
check_and_start() {
local state
state=$($PODMAN machine inspect "$MACHINE_NAME" --format '{{.State}}' 2>/dev/null || echo "unknown")
case "$state" in
running)
return 0
;;
stopped|unknown)
log "Machine '$MACHINE_NAME' is starting..."
if $PODMAN machine start "$MACHINE_NAME" 2>&1 | while IFS= read -r line; do log "$line"; done; then
log "Machine '$MACHINE_NAME' started successfully"
return 0
else
log "Failed to start machine '$MACHINE_NAME'"
return 1
fi
;;
*)
log "Machine '$MACHINE_NAME' is $state"
return 1
;;
esac
}
log "Starting watchdog for machine '$MACHINE_NAME' (check interval: ''${INTERVAL}s)"
while true; do
check_and_start || true
sleep "$INTERVAL"
done
'';
in
{
options.services.podman = {
useDefaultMachine = mkOption {
type = types.bool;
default = pkgs.stdenv.hostPlatform.isDarwin;
description = ''
Whether to create and use the default podman machine.
The default machine will be named `podman-machine-default` and configured with podmans default values.
'';
readOnly = pkgs.stdenv.hostPlatform.isLinux;
};
machines = mkOption {
type = types.attrsOf machineDefinitionType;
default = { };
description = "Declarative podman machine configurations.";
example = lib.literalExpression ''
{
"dev-machine" = {
cpus = 4;
diskSize = 100;
memory = 8192;
swap = 2048;
timezone = "UTC";
volumes = [
"/Users:/Users"
"/private:/private"
];
autoStart = true;
watchdogInterval = 30;
};
"testing" = {
cpus = 2;
diskSize = 50;
image = "ghcr.io/your-org/custom-image:latest";
memory = 4096;
username = "podman";
autoStart = false;
};
}
'';
};
};
config =
let
podmanCmd = lib.getExe cfg.package;
allMachines =
cfg.machines
// (
if cfg.useDefaultMachine then
{
"podman-machine-default" = {
cpus = null;
diskSize = null;
image = null;
memory = null;
rootful = null;
swap = null;
timezone = null;
username = null;
volumes = [ ];
autoStart = true;
watchdogInterval = 30;
};
}
else
{ }
);
autoStartMachines = filterAttrs (_name: machine: machine.autoStart) allMachines;
in
mkIf cfg.enable (mkMerge [
{
assertions = [
(assertions.assertPlatform "services.podman.useDefaultMachine" config pkgs lib.platforms.darwin)
(assertions.assertPlatform "services.podman.machines" config pkgs lib.platforms.darwin)
];
}
(mkIf pkgs.stdenv.isDarwin {
home.activation.podmanMachines =
let
mkMachineInitScript =
name: machine:
let
# Automatically mount host's container config into the VM
username = if isNull machine.username then "core" else machine.username;
configVolume = "$HOME/.config/containers:/home/${username}/.config/containers";
allVolumes = [ configVolume ] ++ machine.volumes;
in
''
if ! ${podmanCmd} machine list --format '{{.Name}}' 2>/dev/null | sed 's/\*$//' | grep -q '^${name}$'; then
echo "Creating podman machine: ${name}"
${podmanCmd} machine init ${name} \
${optionalString (machine.cpus != null) "--cpus ${toString machine.cpus}"} \
${optionalString (machine.diskSize != null) "--disk-size ${toString machine.diskSize}"} \
${optionalString (machine.image != null) "--image ${machine.image}"} \
${optionalString (machine.memory != null) "--memory ${toString machine.memory}"} \
${optionalString ((machine.rootful != null) && machine.rootful) "--rootful"} \
${optionalString (machine.swap != null) "--swap ${toString machine.swap}"} \
${optionalString (machine.timezone != null) "--timezone \"${machine.timezone}\""} \
${optionalString (machine.username != null) "--username \"${machine.username}\""} \
${concatStringsSep " " (map (v: "--volume \"${v}\"") allVolumes)}
fi
'';
in
lib.hm.dag.entryAfter [ "writeBoundary" ] ''
PATH="${cfg.package}/bin:$PATH"
${concatStringsSep "\n" (lib.mapAttrsToList mkMachineInitScript allMachines)}
MANAGED_MACHINES="${concatStringsSep " " (attrNames allMachines)}"
EXISTING_MACHINES=$(${podmanCmd} machine list --format '{{.Name}}' 2>/dev/null | sed 's/\*$//' || echo "")
for machine in $EXISTING_MACHINES; do
if [[ ! " $MANAGED_MACHINES " =~ " $machine " ]]; then
echo "Removing unmanaged podman machine: $machine"
${podmanCmd} machine stop "$machine" 2>/dev/null || true
${podmanCmd} machine rm -f "$machine"
fi
done
'';
launchd.agents = mapAttrs' (
name: machine:
nameValuePair "podman-machine-${name}" {
enable = true;
config = {
ProgramArguments = [ "${mkWatchdogScript name machine}" ];
KeepAlive = {
Crashed = true;
SuccessfulExit = false;
};
ProcessType = "Background";
RunAtLoad = true;
};
}
) autoStartMachines;
})
]);
}

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