me like nix
1{ inputs, ... }:
2
3{
4 flake.modules.homeManager.apps =
5 { pkgs, ... }:
6 {
7 home.packages = with pkgs; [
8 # Browsers
9 chromium
10
11 # Communication
12 (element-desktop.override {
13 commandLineArgs = "--password-store=gnome-libsecret";
14 })
15 signal-desktop
16 discord
17
18 # Media
19 youtube-tui
20 yt-dlp
21 immich-cli
22 darktable
23 loupe
24 glycin-loaders
25
26 # Dev tools
27 git
28 jujutsu
29 htop
30 iotop
31 ncdu
32 atac
33 trippy
34 just
35 docker-compose
36 flyctl
37 rainfrog
38 sqlitebrowser
39 cachix
40
41 # System tools
42 nautilus
43 gnome-characters
44 sendme
45 desktop-file-utils
46 gnome-network-displays
47 fastfetch
48 mangohud
49 prismlauncher
50 libnotify
51 sox
52
53 # Claude Code
54 pi-coding-agent
55 claude-code
56 (pkgs.writeShellScriptBin "claude-notify" ''
57 PANE_ID="$ZELLIJ_PANE_ID"
58 SESSION="$ZELLIJ_SESSION_NAME"
59 ID_FILE="/tmp/claude-notify-''${PANE_ID}"
60 (
61 {
62 read -r NOTIFY_ID
63 echo "$NOTIFY_ID" > "$ID_FILE"
64 while read -r line; do
65 if [ "$line" = "default" ]; then
66 WIN_ID=$(niri msg windows | ${pkgs.gnugrep}/bin/grep -B1 "$SESSION" | ${pkgs.gnugrep}/bin/grep -oP '(?<=Window ID )\d+')
67 if [ -n "$WIN_ID" ]; then
68 niri msg action focus-window --id "$WIN_ID"
69 fi
70 zjctl pane focus --pane "id:terminal:$PANE_ID"
71 fi
72 done
73 } < <(${pkgs.libnotify}/bin/notify-send "Claude Code" "Waiting for your approval" \
74 --app-name=claude-code \
75 --action=default=Open \
76 --print-id \
77 --wait)
78 rm -f "$ID_FILE"
79 ) &
80 '')
81 (pkgs.writeShellScriptBin "claude-notify-clear" ''
82 PANE_ID="$ZELLIJ_PANE_ID"
83 ID_FILE="/tmp/claude-notify-''${PANE_ID}"
84 if [ -f "$ID_FILE" ]; then
85 NOTIFY_ID=$(cat "$ID_FILE")
86 ${pkgs.dbus}/bin/dbus-send --session \
87 --print-reply \
88 --dest=org.freedesktop.Notifications \
89 --type=method_call \
90 /org/freedesktop/Notifications \
91 org.freedesktop.Notifications.CloseNotification \
92 "uint32:$NOTIFY_ID" >/dev/null 2>&1
93 rm -f "$ID_FILE"
94 fi
95 '')
96 ];
97
98 # Pi coding agent config
99 home.file.".pi/agent/AGENTS.md".source = ./_config/pi/AGENTS.md;
100 home.file.".pi/agent/skills/caveman".source = ./_config/pi/skills/caveman;
101 home.file.".pi/agent/extensions/permission-pi".source = ./_config/pi/extensions/permission-pi;
102
103 # Claude Code config
104 home.file.".claude/settings.json".text = builtins.toJSON {
105 preferences = {
106 thinking = "high";
107 };
108 enabledPlugins = {
109 "caveman@caveman" = true;
110 };
111 hooks = {
112 Notification = [
113 {
114 matcher = "permission_prompt";
115 hooks = [
116 {
117 type = "command";
118 command = "claude-notify";
119 }
120 ];
121 }
122 ];
123 Stop = [
124 {
125 hooks = [
126 {
127 type = "command";
128 command = "claude-notify-clear";
129 }
130 ];
131 }
132 ];
133 };
134 };
135
136 programs.zen-browser.enable = true;
137
138 programs.obs-studio = {
139 enable = true;
140 plugins = with pkgs.obs-studio-plugins; [
141 obs-backgroundremoval
142 ];
143 };
144
145 programs.mpv = {
146 enable = true;
147 scripts = [ pkgs.mpvScripts.mpris ];
148 config.af = "loudnorm=I=-16:TP=-1.5:LRA=11";
149 };
150
151 xdg.configFile."youtube-tui/commands.yml".source = ./_config/youtube-tui/commands.yml;
152 };
153}