Compare commits
171 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a210e7e69e | |||
| 035962c9cf | |||
| 711e9d07fa | |||
| 2eb03ebcc8 | |||
| 56e7da9008 | |||
| 1b7bbb3d2e | |||
| 9794578554 | |||
| f53b7dca42 | |||
| 4f0fcc41df | |||
| c22ddec79a | |||
| d872582f28 | |||
| d78f542e42 | |||
| 2dd60b29e1 | |||
| 1a32635d77 | |||
| c3deb1debc | |||
| f15d64018f | |||
| 0322a8d9de | |||
| 21b4f9e30e | |||
| 12105a75d6 | |||
| 108814238a | |||
| b163785d2a | |||
| dd263b3e9f | |||
| 4c16212e0a | |||
| 5ce2aefc67 | |||
| d80b481e1a | |||
| b2f5625a63 | |||
| 2431722fe7 | |||
| d4ee1c66a8 | |||
| 826c4b4058 | |||
| 6ede2df401 | |||
| 0556b58c79 | |||
| 47c0732624 | |||
| e14bdcf3d1 | |||
| c56ef62cf4 | |||
| 914753fb55 | |||
| 2df744b244 | |||
| c4db021783 | |||
| 0a26367881 | |||
| 01de255a7a | |||
| a5661de579 | |||
| 1079822f67 | |||
| eb3eb0fe40 | |||
| 9bd137c31f | |||
| 4088e0f72c | |||
| 79a8cae2e7 | |||
| 0e6109df93 | |||
| 954d23cce6 | |||
| 6f3e4fb462 | |||
| 35f0145e22 | |||
| b21b25fe7b | |||
| a50eaa4707 | |||
| d74f1ac39e | |||
| ccc5d0d88c | |||
| ca1cba782e | |||
| 434ed3729f | |||
| df9fb4c495 | |||
| 4b12fd94db | |||
| aa7a9b179d | |||
| 08db70518b | |||
| 09bd517439 | |||
| 2cfdc7e68e | |||
| 5bafa07427 | |||
| f8c95e3b8d | |||
| 00810b4104 | |||
| ede94f9251 | |||
| ca0ad8f662 | |||
| 0519030103 | |||
| 4cb6e63e55 | |||
| 6581bab9ca | |||
| 7c59ed8af6 | |||
| 2b5c0eabea | |||
| f3acdf7781 | |||
| 16bf875f5b | |||
| 75f216165c | |||
| 89fb6c8b14 | |||
| 13eb534ab3 | |||
| 803f63d92b | |||
| 0d43a0178a | |||
| 5f3f502b8d | |||
| 92b51ddffc | |||
| cf74a9e49b | |||
| f1cbd1d540 | |||
| 448c5df0ed | |||
| 88d0be4098 | |||
| 755de4fb71 | |||
| 7d0018903d | |||
| 799158d90e | |||
| 5da1b61309 | |||
| 7a5c9981a7 | |||
| 0d364dcbbb | |||
| 8d39467f6b | |||
| e56962960b | |||
| 25bb46b706 | |||
| 7381a6b764 | |||
| 8befa14be1 | |||
| bf85f679f8 | |||
| 6d2754318c | |||
| 49579d92dd | |||
| 7495d84f1e | |||
| 9e03f255e4 | |||
| 3922a93586 | |||
| 4a90cd1dfc | |||
| 0039ab20ee | |||
| 5d53b7bf35 | |||
| 51a6696efb | |||
| 05bae722f7 | |||
| 5ee27b6df1 | |||
| d2c03ed846 | |||
| e08e845b38 | |||
| 91e6b195cf | |||
| 4d93e94c12 | |||
| c99627b3f6 | |||
| 2a3ccd2442 | |||
| 2c692550db | |||
| a23488dc52 | |||
| 2e464d2fe8 | |||
| 58e953a857 | |||
| 014dbde21d | |||
| 48c33fdbb5 | |||
| c11acc8b88 | |||
| 3d372cd155 | |||
| 0d2a4cb86f | |||
| fc88ed82fd | |||
| fb01826479 | |||
| d932409986 | |||
| 7c7aa0a7d9 | |||
| f99e0d4a8f | |||
| d41572a51c | |||
| 0f059c02c8 | |||
| 11f6ad5a3d | |||
| 1ce7046994 | |||
| 42fa03ec0e | |||
| 1b52576097 | |||
| 522eda7644 | |||
| 25ca90f134 | |||
| ccf0b2c35d | |||
| 2532100b26 | |||
| 9b4a2b44dc | |||
| 503b3baeb4 | |||
| 7bdff2ff98 | |||
| 9794335ad6 | |||
| 4a1e9aeaa8 | |||
| cd3b271e10 | |||
| 3eb0a098a2 | |||
| 77d8803a8f | |||
| ba5b618e49 | |||
| 7580edb82c | |||
| 88abb49340 | |||
| 9c536f87f6 | |||
| 88915d9cfd | |||
| 94e24f9277 | |||
| 51c852b5ef | |||
| 54fc3e317b | |||
| 81b9cbde44 | |||
| 60f93e604f | |||
| fc7ac103f5 | |||
| ced70ee3e3 | |||
| 5ba12d3684 | |||
| 231b6bdb28 | |||
| a0a69cf58c | |||
| d61700d173 | |||
| b07120973a | |||
| 074cb5faa1 | |||
| 46bb060208 | |||
| 189196fb88 | |||
| 849cd3a5ef | |||
| 013d41aa72 | |||
| 0a4dd8a192 | |||
| 8efd0a1139 | |||
| de527df7c4 | |||
| c7eb5796ea |
Generated
+243
-144
@@ -7,27 +7,26 @@
|
|||||||
"nixpkgs": "nixpkgs"
|
"nixpkgs": "nixpkgs"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1786554876,
|
"lastModified": 1787387938,
|
||||||
"narHash": "sha256-akMknOIdX0QsBsM4lgreXSNNym7TNu9iOrDBqrQuTuQ=",
|
"narHash": "sha256-113jGEYKSeTwYgLdlVuRyqPBHYHJcU1kbRKiAUhj04Q=",
|
||||||
"owner": "agent-of-empires",
|
"ref": "refs/heads/main",
|
||||||
"repo": "agent-of-empires",
|
"rev": "96472052106cb5c448e9fa39244b0d0ccae9be72",
|
||||||
"rev": "9b0d691a6cdaa6d2451f6eda05e83628c54eb95a",
|
"revCount": 2192,
|
||||||
"type": "github"
|
"type": "git",
|
||||||
|
"url": "https://git.naps.pt/yolo/agent-of-empires.git"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "agent-of-empires",
|
"type": "git",
|
||||||
"ref": "v1.14.1",
|
"url": "https://git.naps.pt/yolo/agent-of-empires.git"
|
||||||
"repo": "agent-of-empires",
|
|
||||||
"type": "github"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"agent-skills": {
|
"agent-skills": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1786957004,
|
"lastModified": 1788356316,
|
||||||
"narHash": "sha256-lUyQGAN6Kd5onhPa+ptOiwtIaY6Y02q+nyRt9NWkdDg=",
|
"narHash": "sha256-y5dQioiefegmuPLulFSEL4DrRJMaEHt1UcMGyOM6fRk=",
|
||||||
"ref": "refs/heads/main",
|
"ref": "refs/heads/main",
|
||||||
"rev": "7cb03f879600e87281356fdc411b2690f09a9175",
|
"rev": "abd21928bf993962f98364d48a2877155beaa6d0",
|
||||||
"revCount": 47,
|
"revCount": 111,
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://git.naps.pt/yolo/agent-skills.git"
|
"url": "https://git.naps.pt/yolo/agent-skills.git"
|
||||||
},
|
},
|
||||||
@@ -56,11 +55,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1784368054,
|
"lastModified": 1786464219,
|
||||||
"narHash": "sha256-zF1iJkBQSDWmRO4/LEeHR1SpKY0lqZaxkoQJpPS9K9U=",
|
"narHash": "sha256-WKqWL8r7CyTDYueTr2ffJ9ya50dellv6IR1JX5PghDY=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "aquamarine",
|
"repo": "aquamarine",
|
||||||
"rev": "9b5f14d9483445e766294eb8fbe0b8f370269ed0",
|
"rev": "f3d1804205e8158c15595cdda1b566f93349ffae",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -71,15 +70,15 @@
|
|||||||
},
|
},
|
||||||
"claude-code": {
|
"claude-code": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-utils": "flake-utils",
|
"nixpkgs": "nixpkgs_2",
|
||||||
"nixpkgs": "nixpkgs_2"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1785285785,
|
"lastModified": 1788303707,
|
||||||
"narHash": "sha256-r1cMlvXjRVKe+uQ/GKwy4TpionpmbNgksFP2758D/MM=",
|
"narHash": "sha256-ICEHLJAM480kNrsOQ+DPWWV3XFJUDc6/n/PPcjAuRR8=",
|
||||||
"owner": "sadjow",
|
"owner": "sadjow",
|
||||||
"repo": "claude-code-nix",
|
"repo": "claude-code-nix",
|
||||||
"rev": "da78262708d858861afbe1f68ea65fedda4054c4",
|
"rev": "7f0aeb2f0c6cf1ca2bf3b0b76b823b24b04b5b21",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -90,17 +89,17 @@
|
|||||||
},
|
},
|
||||||
"codex-cli": {
|
"codex-cli": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-utils": "flake-utils_2",
|
"flake-utils": "flake-utils",
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1785294467,
|
"lastModified": 1787094470,
|
||||||
"narHash": "sha256-mylUWHK2wIw8S07K5hbkrLELnflJkDwsSWz2YFbJzLI=",
|
"narHash": "sha256-UiHfeA8umiWByi/ijDnfnlGcVSEAhwNv1Gue3h6ey/U=",
|
||||||
"owner": "sadjow",
|
"owner": "sadjow",
|
||||||
"repo": "codex-cli-nix",
|
"repo": "codex-cli-nix",
|
||||||
"rev": "e4e3b0672bbb8fba7f32fe53cd9c604990970374",
|
"rev": "cfbeeca2f4dfbbfcc3c1a5b21e61a051ff43533d",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -112,17 +111,17 @@
|
|||||||
},
|
},
|
||||||
"codex-desktop-linux": {
|
"codex-desktop-linux": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-utils": "flake-utils_3",
|
"flake-utils": "flake-utils_2",
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1786822283,
|
"lastModified": 1787079200,
|
||||||
"narHash": "sha256-RdoFKwNQ2m2zbHnq/QbgLf2lUI9cohsnlMwLfJuaTh0=",
|
"narHash": "sha256-BYo8mVEqRj6y8PzpFd3rX6TQTknB3Ynp/3ykMTm56D8=",
|
||||||
"owner": "ilysenko",
|
"owner": "ilysenko",
|
||||||
"repo": "codex-desktop-linux",
|
"repo": "codex-desktop-linux",
|
||||||
"rev": "e6b51d96ac2b9b5d9adafa852241bd0982972557",
|
"rev": "1875dc2eaab6f9448617d18d0eda58902edf0f1a",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -146,6 +145,21 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"crane_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1787326676,
|
||||||
|
"narHash": "sha256-lWhBbBvC05/xwivKBBiM2YNizpmgqCgyOIzomvRuwxs=",
|
||||||
|
"owner": "ipetkov",
|
||||||
|
"repo": "crane",
|
||||||
|
"rev": "692f7e9ef2ece8125b466f66f2af532b3edaed0d",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "ipetkov",
|
||||||
|
"repo": "crane",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"ethui": {
|
"ethui": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": "nixpkgs_3",
|
"nixpkgs": "nixpkgs_3",
|
||||||
@@ -205,6 +219,24 @@
|
|||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs-lib": "nixpkgs-lib_2"
|
"nixpkgs-lib": "nixpkgs-lib_2"
|
||||||
},
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1785627969,
|
||||||
|
"narHash": "sha256-4dtXQk/NMePegK/nWp5NSeuZKLATItOq61lpEvmXqGw=",
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"rev": "427bf4bd9435fdf21321c8cc628c24efc14c0f7a",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-parts_3": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs-lib": "nixpkgs-lib_3"
|
||||||
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1775087534,
|
"lastModified": 1775087534,
|
||||||
"narHash": "sha256-91qqW8lhL7TLwgQWijoGBbiD4t7/q75KTi8NxjVmSmA=",
|
"narHash": "sha256-91qqW8lhL7TLwgQWijoGBbiD4t7/q75KTi8NxjVmSmA=",
|
||||||
@@ -220,24 +252,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-utils": {
|
"flake-utils": {
|
||||||
"inputs": {
|
|
||||||
"systems": "systems"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1731533236,
|
|
||||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-utils_2": {
|
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"systems": "systems_2"
|
"systems": "systems_2"
|
||||||
},
|
},
|
||||||
@@ -255,7 +269,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-utils_3": {
|
"flake-utils_2": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"systems": "systems_3"
|
"systems": "systems_3"
|
||||||
},
|
},
|
||||||
@@ -273,7 +287,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-utils_4": {
|
"flake-utils_3": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1644229661,
|
"lastModified": 1644229661,
|
||||||
"narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=",
|
"narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=",
|
||||||
@@ -288,7 +302,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-utils_5": {
|
"flake-utils_4": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"systems": "systems_8"
|
"systems": "systems_8"
|
||||||
},
|
},
|
||||||
@@ -308,17 +322,17 @@
|
|||||||
},
|
},
|
||||||
"foundry": {
|
"foundry": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-utils": "flake-utils_4",
|
"flake-utils": "flake-utils_3",
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1785311662,
|
"lastModified": 1787123762,
|
||||||
"narHash": "sha256-lC5ZlyNMf8wcQnrAzUhYb1p6ndzwEovnXKiMqSTLgUo=",
|
"narHash": "sha256-gKUrkWZRS2BxEcJDyVSBZJ3fi1rN51PPe8U5hCjFNIY=",
|
||||||
"owner": "shazow",
|
"owner": "shazow",
|
||||||
"repo": "foundry.nix",
|
"repo": "foundry.nix",
|
||||||
"rev": "0eb3d1233237eb4e6f4f45f31c087ee1a16245f1",
|
"rev": "a194d90ec9f6a4d70d79220e644c531da8324266",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -334,11 +348,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1785232496,
|
"lastModified": 1787144466,
|
||||||
"narHash": "sha256-65EQYIRRpTdpH8lUiB6Mvo5uBkG60aBIzAJuALfx+O0=",
|
"narHash": "sha256-HHfv2/HkNSKbbSyU9iD/g8lbP6r4tl33sSw1W4rXCk0=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixos-hardware",
|
"repo": "nixos-hardware",
|
||||||
"rev": "2e790b0a6be8ec2b76174ac0931b8ff11919ec98",
|
"rev": "0471accf8d0a8210b31d947497d179ecc99e0021",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -355,11 +369,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1785306346,
|
"lastModified": 1787176219,
|
||||||
"narHash": "sha256-DScBkW0fOgpGPK2trNoX3ryLTlaC14+gglFo/BhGJ4g=",
|
"narHash": "sha256-djoRr6jBpe35q/0JwAvXpFXg1Ktf+X54NU2RLR7wnHw=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "home-manager",
|
"repo": "home-manager",
|
||||||
"rev": "e705714e918c3b11affcdd15db2cbe3a070420a0",
|
"rev": "c53d643b3737e2fcd04e6cb3b3580ef50b2087a0",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -376,11 +390,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1783963347,
|
"lastModified": 1786719456,
|
||||||
"narHash": "sha256-r376E2XpakiXwModDHIxlvB6qLq4iFVEq730vxOO4JY=",
|
"narHash": "sha256-B74DLQs/VjlqyhnnX3tguWwghqJHWSJX30TKZuAljIg=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "home-manager",
|
"repo": "home-manager",
|
||||||
"rev": "a45a7c451455a51ae740ec3bce4024b312809c29",
|
"rev": "83b7606dcf44abe3a94b86e8bb2b3355d22e8797",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -405,11 +419,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1776511930,
|
"lastModified": 1786464181,
|
||||||
"narHash": "sha256-fCpwFiTW0rT7oKJqr3cqHMnkwypSwQKpbtUEtxdkgrM=",
|
"narHash": "sha256-2alOMkLjXANh7unkZnYnCF2K2rApZaOLMoQ3o+VX2CY=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "hyprcursor",
|
"repo": "hyprcursor",
|
||||||
"rev": "39435900785d0c560c6ae8777d29f28617d031ef",
|
"rev": "e4ed7c08123df5af460a0a70961380cbfb872f76",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -434,11 +448,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1782566056,
|
"lastModified": 1786464367,
|
||||||
"narHash": "sha256-haEZcHzYrePnjFOYSWTbxm/Nrla0aPslJfmvdCvqtVc=",
|
"narHash": "sha256-k58p4wbzIXWyRWrW84pP8tD+iaZSSYiiM+fr0Auk4oU=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "hyprgraphics",
|
"repo": "hyprgraphics",
|
||||||
"rev": "c6e7b9f673f4360bc813d3dc75028f75ee88d3f8",
|
"rev": "7c895c44e3ca6d28ed68ddd80ec02b02b925e7fc",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -464,11 +478,11 @@
|
|||||||
"xdph": "xdph"
|
"xdph": "xdph"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1785334807,
|
"lastModified": 1787138659,
|
||||||
"narHash": "sha256-bN0KRhDfwSPqbpgUgWVcQMkuDje+8ghWlm7uUQZzaxc=",
|
"narHash": "sha256-/3fIl+/xZoZqliAfwYB8ahCZK04Qr/zwdOQgiR41dy8=",
|
||||||
"ref": "refs/heads/main",
|
"ref": "refs/heads/main",
|
||||||
"rev": "7803e68638c1bebce57cf9ea8da51fd9a1e19edd",
|
"rev": "52b368f1d7fdee1b0e96ef3dc655b5a577df4fdb",
|
||||||
"revCount": 7669,
|
"revCount": 7745,
|
||||||
"submodules": true,
|
"submodules": true,
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/hyprwm/Hyprland"
|
"url": "https://github.com/hyprwm/Hyprland"
|
||||||
@@ -512,11 +526,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1784196523,
|
"lastModified": 1786464504,
|
||||||
"narHash": "sha256-ahtKMGXFJdlQNhatQm1+BBU/pGfGYnAqQt3vWvq4p8s=",
|
"narHash": "sha256-7sHwM86KILQyHDHDuE2SDBlQ2jvZ0EW3hY7sW009/cg=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "hyprland-guiutils",
|
"repo": "hyprland-guiutils",
|
||||||
"rev": "a6ccb6cb112ed5a244c0191fb972347ecfa893e0",
|
"rev": "4c30cf3097ea963c0e250749ee0c59f8b08816d6",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -566,11 +580,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1777320127,
|
"lastModified": 1786464129,
|
||||||
"narHash": "sha256-Qu+Wf2Bp5qUjyn2YpZNq8a7JyzTGowhT1knrwE38a9U=",
|
"narHash": "sha256-339AkTlpMYSIvFuG0rnR+8Yg4/AZKeJalshJavlnKfg=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "hyprlang",
|
"repo": "hyprlang",
|
||||||
"rev": "090117506ddc3d7f26e650ff344d378c2ec329cc",
|
"rev": "9508458be316a0d70d37ebed1ab725ccd10411ff",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -640,11 +654,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1782554491,
|
"lastModified": 1785930473,
|
||||||
"narHash": "sha256-+p3MlyN/nqRefcf2IckPlGRUn9+hielqpS9XClbLleM=",
|
"narHash": "sha256-DitTu625BhEYpZjtjxtGpjrEJwPwW+X/+jJvhSZNSJM=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "hyprtoolkit",
|
"repo": "hyprtoolkit",
|
||||||
"rev": "bdba25ced39ea39ab004a8f31593ba0b0ff1ca35",
|
"rev": "af515b69dfbe366dc7873aa1475cb2f4db3ebad7",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -665,11 +679,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1784323413,
|
"lastModified": 1786464080,
|
||||||
"narHash": "sha256-XnAVV+H4f8Xdv0yZcSwJ5kCjLyE8fHxPeLX6a3HSrAU=",
|
"narHash": "sha256-W1hxvumEM57yV+QwsZ4QdAHEqOkr7e4S8VAkLX60qDE=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "hyprutils",
|
"repo": "hyprutils",
|
||||||
"rev": "5f03477ab3a005ff27c527486f551883535aea2f",
|
"rev": "c157fe1e3092b980cc69315a6631f89aff09dcce",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -690,11 +704,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1777159683,
|
"lastModified": 1786464033,
|
||||||
"narHash": "sha256-Jxixw6wZphUp+nHYxOKUYSckL17QMBx2d5Zp0rJHr1g=",
|
"narHash": "sha256-QM8Qe4/L8lpdVN4bgwahmi+jyyc4fisseDMe4afcDxA=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "hyprwayland-scanner",
|
"repo": "hyprwayland-scanner",
|
||||||
"rev": "b8632713a6beaf28b56f2a7b0ab2fb7088dbb404",
|
"rev": "62e62c1ca23da17612c6890d4ad2064f575643db",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -719,11 +733,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1778410714,
|
"lastModified": 1786464294,
|
||||||
"narHash": "sha256-o6RzFj4nJXaPRY7EM01siuCQeT41RfwwmcmFQqwFJJg=",
|
"narHash": "sha256-ZQsZ2WvBdkboCIyh8LStDPdAIARmxzn0XMNxxoOhjPE=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "hyprwire",
|
"repo": "hyprwire",
|
||||||
"rev": "85148a8e612808cf5ddb25d0b3c5840f3498a7dc",
|
"rev": "4ce7cd6b6128c1ac41caf23c58a30a26b327f9dd",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -732,6 +746,43 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"maestro": {
|
||||||
|
"inputs": {
|
||||||
|
"crane": "crane_2",
|
||||||
|
"flake-parts": "flake-parts_2",
|
||||||
|
"nixpkgs": "nixpkgs_6",
|
||||||
|
"process-compose-flake": "process-compose-flake"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1788576575,
|
||||||
|
"narHash": "sha256-HA9vVWK9P5+75lY3NMmTrRTGvbTGUkW0KqyrUQRotrQ=",
|
||||||
|
"ref": "refs/heads/main",
|
||||||
|
"rev": "3529947497ab13f844903509042113c0328c62f8",
|
||||||
|
"revCount": 634,
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.naps.pt/naps62/maestro.git"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.naps.pt/naps62/maestro.git"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nix-flatpak": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1767983141,
|
||||||
|
"narHash": "sha256-7ZCulYUD9RmJIDULTRkGLSW1faMpDlPKcbWJLYHoXcs=",
|
||||||
|
"owner": "gmodena",
|
||||||
|
"repo": "nix-flatpak",
|
||||||
|
"rev": "440818969ac2cbd77bfe025e884d0aa528991374",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "gmodena",
|
||||||
|
"ref": "latest",
|
||||||
|
"repo": "nix-flatpak",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nix-index-database": {
|
"nix-index-database": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
@@ -739,11 +790,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1785046085,
|
"lastModified": 1786852476,
|
||||||
"narHash": "sha256-UiK+mmZJuLWQVhJ5b2wDzogIYWAesyRm6LA3h3Ulh3Y=",
|
"narHash": "sha256-IM5CYtf86W4w8eUPpKcY/LpdHElmVBtJhaKnoTKxZEA=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "nix-index-database",
|
"repo": "nix-index-database",
|
||||||
"rev": "11665045df8b9938ef811a3bfdc65cffb02b4b70",
|
"rev": "c7962dc97b45129df8d751bedaf37beb5a17706e",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -784,6 +835,21 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs-lib_2": {
|
"nixpkgs-lib_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1785031560,
|
||||||
|
"narHash": "sha256-OmshNvn2vupOFpYinLUu+1Dnpu4n7Q5N3ggGVNHpkUI=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "nixpkgs.lib",
|
||||||
|
"rev": "0e79af5e3d4dcfcd676ab5ba3f95d2e3352e078c",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "nixpkgs.lib",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs-lib_3": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1774748309,
|
"lastModified": 1774748309,
|
||||||
"narHash": "sha256-+U7gF3qxzwD5TZuANzZPeJTZRHS29OFQgkQ2kiTJBIQ=",
|
"narHash": "sha256-+U7gF3qxzwD5TZuANzZPeJTZRHS29OFQgkQ2kiTJBIQ=",
|
||||||
@@ -800,11 +866,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1784783405,
|
"lastModified": 1787964612,
|
||||||
"narHash": "sha256-4IHyyLgLBdKefkljdKod4IMn023pQiDXAWJA187cmdY=",
|
"narHash": "sha256-0N9nghg3nwzX6b6qc77EzjR9cu/Z+UR66FlfsCqiURs=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "7525d999cd850b9a488817abc89c75dc733acf17",
|
"rev": "e8be7818e19ada32105a8af937a6a473b38167ca",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -848,11 +914,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs_5": {
|
"nixpkgs_5": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1784356753,
|
"lastModified": 1786247143,
|
||||||
"narHash": "sha256-12KrbMiWLcf8m7pCvAtZh1ZrgF85ZXDXvfR/fWTKy84=",
|
"narHash": "sha256-8S3Kcxs7D4UtxJxSJZz0m14CGhuW0MxfrIwJxeGWGnQ=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "61b7c44c4073f0b827768aff0049561b5110ea5a",
|
"rev": "279b4a8275f032c566576b3f181fa0f27197f588",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -864,11 +930,27 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs_6": {
|
"nixpkgs_6": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1785090369,
|
"lastModified": 1787135253,
|
||||||
"narHash": "sha256-m0pDuRJG7EDo9ri+4Ksu83VsI+PlxNC9lNBfydejce4=",
|
"narHash": "sha256-RD2kNWCG+Bjo6h+JVjWVNntZs2GtRoeY2xHjts/FNkA=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "ffb3c9b700e759be2ef13237c9d8f953b32a1e46",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_7": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1787070829,
|
||||||
|
"narHash": "sha256-vXNVDVtvfiQuXthP0NHPFdNvvMTkGpx0UP8oddIWbNk=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "624af665418d3c65d544145b4d34ad696439570e",
|
"rev": "0ae2bc1419c3f345984c2629e72e7a631820fa4d",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -878,7 +960,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_7": {
|
"nixpkgs_8": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1775036866,
|
"lastModified": 1775036866,
|
||||||
"narHash": "sha256-ZojAnPuCdy657PbTq5V0Y+AHKhZAIwSIT2cb8UgAz/U=",
|
"narHash": "sha256-ZojAnPuCdy657PbTq5V0Y+AHKhZAIwSIT2cb8UgAz/U=",
|
||||||
@@ -894,7 +976,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_8": {
|
"nixpkgs_9": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1744536153,
|
"lastModified": 1744536153,
|
||||||
"narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=",
|
"narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=",
|
||||||
@@ -910,26 +992,6 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"noctalia": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1785335804,
|
|
||||||
"narHash": "sha256-oN3I6Kr71lOCE3/ou4GgY2cQYh4B6xQxZXzomFgYn0s=",
|
|
||||||
"owner": "noctalia-dev",
|
|
||||||
"repo": "noctalia-shell",
|
|
||||||
"rev": "aded31799eb0dffdbcf436243083f1ebce26f95d",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "noctalia-dev",
|
|
||||||
"repo": "noctalia-shell",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nvchad-starter": {
|
"nvchad-starter": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
@@ -956,11 +1018,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1785121894,
|
"lastModified": 1786797655,
|
||||||
"narHash": "sha256-AWbstkwe4twd+5iWx8QBVzTgwGAUvn4vVdobGKW5BRc=",
|
"narHash": "sha256-qAWI5Vf0xaRmb8/l9XWYrvEgrIaqKBv8Dg81JO7wkrY=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "nix4nvchad",
|
"repo": "nix4nvchad",
|
||||||
"rev": "8135d402aa554b5f8e5dd2ec341c5a440fd18496",
|
"rev": "b878640ae13c8f70f41aa1159234206051a4378c",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -991,6 +1053,41 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"process-compose-flake": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1782060835,
|
||||||
|
"narHash": "sha256-Q8HH2t1l3MITtWCWY4ytcH5F/Q7aAHo3Iq/QTMAKTe0=",
|
||||||
|
"owner": "Platonic-Systems",
|
||||||
|
"repo": "process-compose-flake",
|
||||||
|
"rev": "464ff6880737f063c3f0d3d2c7781fda9190868f",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "Platonic-Systems",
|
||||||
|
"repo": "process-compose-flake",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rev": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1788517029,
|
||||||
|
"narHash": "sha256-WIX0qEGDAUk9DMtx8Ntw/oQ4MaMd311OdaDR9aXATiM=",
|
||||||
|
"ref": "refs/heads/main",
|
||||||
|
"rev": "7e78a5f04c01204ee3fcba7858c01b43f98c4c9a",
|
||||||
|
"revCount": 238,
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.naps.pt/yolo/rev.git"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.naps.pt/yolo/rev.git"
|
||||||
|
}
|
||||||
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"agent-of-empires": "agent-of-empires",
|
"agent-of-empires": "agent-of-empires",
|
||||||
@@ -1003,11 +1100,13 @@
|
|||||||
"hardware": "hardware",
|
"hardware": "hardware",
|
||||||
"home-manager": "home-manager",
|
"home-manager": "home-manager",
|
||||||
"hyprland": "hyprland",
|
"hyprland": "hyprland",
|
||||||
|
"maestro": "maestro",
|
||||||
|
"nix-flatpak": "nix-flatpak",
|
||||||
"nix-index-database": "nix-index-database",
|
"nix-index-database": "nix-index-database",
|
||||||
"nixpkgs": "nixpkgs_6",
|
"nixpkgs": "nixpkgs_7",
|
||||||
"noctalia": "noctalia",
|
|
||||||
"nvchad-starter": "nvchad-starter",
|
"nvchad-starter": "nvchad-starter",
|
||||||
"nvchad4nix": "nvchad4nix",
|
"nvchad4nix": "nvchad4nix",
|
||||||
|
"rev": "rev",
|
||||||
"rose-pine-hyprcursor": "rose-pine-hyprcursor",
|
"rose-pine-hyprcursor": "rose-pine-hyprcursor",
|
||||||
"sem": "sem",
|
"sem": "sem",
|
||||||
"spicetify-nix": "spicetify-nix",
|
"spicetify-nix": "spicetify-nix",
|
||||||
@@ -1057,7 +1156,7 @@
|
|||||||
},
|
},
|
||||||
"rust-overlay": {
|
"rust-overlay": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": "nixpkgs_8"
|
"nixpkgs": "nixpkgs_9"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1775445266,
|
"lastModified": 1775445266,
|
||||||
@@ -1075,9 +1174,9 @@
|
|||||||
},
|
},
|
||||||
"sem": {
|
"sem": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-parts": "flake-parts_2",
|
"flake-parts": "flake-parts_3",
|
||||||
"flake-utils": "flake-utils_5",
|
"flake-utils": "flake-utils_4",
|
||||||
"nixpkgs": "nixpkgs_7",
|
"nixpkgs": "nixpkgs_8",
|
||||||
"rust-overlay": "rust-overlay"
|
"rust-overlay": "rust-overlay"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
@@ -1102,11 +1201,11 @@
|
|||||||
"systems": "systems_9"
|
"systems": "systems_9"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1785048222,
|
"lastModified": 1786855359,
|
||||||
"narHash": "sha256-LjFVfwxensz76SjnvofF1Jsw+xTLd8Qp31W0J6nh2XI=",
|
"narHash": "sha256-yeKMWFCPeoIKmPBLLvP1/15ulOJO8i9ZIlSSXGuW6aw=",
|
||||||
"owner": "Gerg-L",
|
"owner": "Gerg-L",
|
||||||
"repo": "spicetify-nix",
|
"repo": "spicetify-nix",
|
||||||
"rev": "17e524f330c282d31c32dfe076222d4a12277886",
|
"rev": "0f478ff79b82abb785160cd4531293f61d21be86",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -1329,11 +1428,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1784371182,
|
"lastModified": 1786464334,
|
||||||
"narHash": "sha256-S8A1lezEalltWcCp3gAic5lssS0xTSISK6fKODefhOk=",
|
"narHash": "sha256-/TBQT5rhBB2Dm4HoZzhGDaCwYmRTs3W3DPhMXFWc/BU=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "xdg-desktop-portal-hyprland",
|
"repo": "xdg-desktop-portal-hyprland",
|
||||||
"rev": "08d99f727944dd15e4740090305e31c5fb92a50a",
|
"rev": "9f0e9ff02739cd538d39bd706422dc50e9ca60dd",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -1350,11 +1449,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1785224333,
|
"lastModified": 1787160391,
|
||||||
"narHash": "sha256-8DNJUVM10ktK02V9ZIV064CH+fuPF272VCAZBn6arig=",
|
"narHash": "sha256-5dRTU55IlWABqnWiXDgtzrc3wT54nPoZwDQ91VOY4mE=",
|
||||||
"owner": "0xc000022070",
|
"owner": "0xc000022070",
|
||||||
"repo": "zen-browser-flake",
|
"repo": "zen-browser-flake",
|
||||||
"rev": "5f1a4be4d280e1ae06d61a75775a234b1714da3f",
|
"rev": "228a12a50971a115caa1c87b7de3d87b08e35275",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
@@ -49,10 +49,6 @@
|
|||||||
url = "https://github.com/hyprwm/Hyprland";
|
url = "https://github.com/hyprwm/Hyprland";
|
||||||
submodules = true;
|
submodules = true;
|
||||||
};
|
};
|
||||||
noctalia = {
|
|
||||||
url = "github:noctalia-dev/noctalia-shell";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
};
|
|
||||||
spicetify-nix = {
|
spicetify-nix = {
|
||||||
url = "github:Gerg-L/spicetify-nix";
|
url = "github:Gerg-L/spicetify-nix";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
@@ -68,12 +64,25 @@
|
|||||||
};
|
};
|
||||||
# Pinned to the tag, and pins its own nixpkgs for the same reason ethui does
|
# Pinned to the tag, and pins its own nixpkgs for the same reason ethui does
|
||||||
# — it is a verified Rust build. Bump deliberately, not via `flake update`.
|
# — it is a verified Rust build. Bump deliberately, not via `flake update`.
|
||||||
agent-of-empires.url = "github:agent-of-empires/agent-of-empires/v1.14.1";
|
agent-of-empires.url = "git+https://git.naps.pt/yolo/agent-of-empires.git";
|
||||||
# Semantic-diff tool rev calls via REV_SEM_BIN. NOT nixpkgs' `sem`, which is
|
# Semantic-diff tool rev calls via REV_SEM_BIN. NOT nixpkgs' `sem`, which is
|
||||||
# the unrelated Semaphore CI cli.
|
# the unrelated Semaphore CI cli.
|
||||||
sem.url = "github:Ataraxy-Labs/sem";
|
sem.url = "github:Ataraxy-Labs/sem";
|
||||||
# Claude Code + Codex skills, commands, hooks and CLAUDE.md fragments.
|
# Claude Code + Codex skills, commands, hooks and CLAUDE.md fragments.
|
||||||
agent-skills.url = "git+https://git.naps.pt/yolo/agent-skills.git";
|
agent-skills.url = "git+https://git.naps.pt/yolo/agent-skills.git";
|
||||||
|
# Terminal-session orchestrator. Pins its own nixpkgs for the same reason
|
||||||
|
# ethui and agent-of-empires do — it is a verified Rust build.
|
||||||
|
maestro.url = "git+https://git.naps.pt/naps62/maestro.git";
|
||||||
|
# Always-on local code review server. Follows nixpkgs, unlike the Rust
|
||||||
|
# inputs above: it is a plain node bundle, and a second nixpkgs would put a
|
||||||
|
# second node 26 in the closure for nothing.
|
||||||
|
rev = {
|
||||||
|
url = "git+https://git.naps.pt/yolo/rev.git";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
# Declarative flatpak remotes and packages; nixpkgs' services.flatpak only
|
||||||
|
# exposes `enable`. Has no nixpkgs input to follow.
|
||||||
|
nix-flatpak.url = "github:gmodena/nix-flatpak/?ref=latest";
|
||||||
nix-index-database = {
|
nix-index-database = {
|
||||||
url = "github:nix-community/nix-index-database";
|
url = "github:nix-community/nix-index-database";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
|||||||
@@ -5,6 +5,10 @@
|
|||||||
imports = [
|
imports = [
|
||||||
../common/programs/default.nix
|
../common/programs/default.nix
|
||||||
../common/programs/desktop
|
../common/programs/desktop
|
||||||
|
../common/programs/workstation-apps.nix
|
||||||
|
../common/programs/editors.nix
|
||||||
|
../common/programs/dev-workstation.nix
|
||||||
|
../common/programs/ai-gui.nix
|
||||||
../common/programs/zen-browser.nix
|
../common/programs/zen-browser.nix
|
||||||
../common/programs/hyprland
|
../common/programs/hyprland
|
||||||
../common/programs/kitty
|
../common/programs/kitty
|
||||||
|
|||||||
@@ -1,105 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
self,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
cfg = config.home.mutableFiles;
|
|
||||||
repoPath = config.home.mutableFilesRepoPath;
|
|
||||||
flakePrefix = self.outPath;
|
|
||||||
|
|
||||||
fileEntries = lib.attrsToList cfg;
|
|
||||||
|
|
||||||
toRepoPath = storePath: repoPath + lib.removePrefix flakePrefix (toString storePath);
|
|
||||||
|
|
||||||
checkScript = lib.concatMapStringsSep "\n" (
|
|
||||||
{ name, value }:
|
|
||||||
let
|
|
||||||
target = "${config.home.homeDirectory}/${name}";
|
|
||||||
storePath = value.source;
|
|
||||||
# toRepoPath only works for sources that live in the flake tree. A
|
|
||||||
# generated source is not under flakePrefix, so removePrefix is a no-op
|
|
||||||
# and the hint would print a /nix/store path to copy back onto.
|
|
||||||
originalPath =
|
|
||||||
if value.upstreamPath != null then "${repoPath}/${value.upstreamPath}" else toRepoPath value.source;
|
|
||||||
in
|
|
||||||
''
|
|
||||||
if [ -f "${target}" ] && ! ${lib.getExe' pkgs.diffutils "diff"} -q "${storePath}" "${target}" > /dev/null 2>&1; then
|
|
||||||
echo ""
|
|
||||||
echo "!! mutable file changed: ${name}"
|
|
||||||
echo " To bring changes upstream:"
|
|
||||||
echo " cp ${target} ${originalPath}"
|
|
||||||
echo ""
|
|
||||||
${lib.getExe' pkgs.diffutils "diff"} -u "${storePath}" "${target}" || true
|
|
||||||
_mutable_changed=1
|
|
||||||
fi
|
|
||||||
''
|
|
||||||
) fileEntries;
|
|
||||||
|
|
||||||
copyScript = lib.concatMapStringsSep "\n" (
|
|
||||||
{ name, value }:
|
|
||||||
let
|
|
||||||
target = "${config.home.homeDirectory}/${name}";
|
|
||||||
inherit (value) source;
|
|
||||||
dirName = builtins.dirOf target;
|
|
||||||
in
|
|
||||||
''
|
|
||||||
mkdir -p "${dirName}"
|
|
||||||
cp -f "${source}" "${target}"
|
|
||||||
chmod ${if value.executable then "755" else "644"} "${target}"
|
|
||||||
''
|
|
||||||
) fileEntries;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.home.mutableFilesRepoPath = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
description = "Absolute path to the nixos-config repo on disk.";
|
|
||||||
};
|
|
||||||
|
|
||||||
options.home.mutableFiles = lib.mkOption {
|
|
||||||
type = lib.types.attrsOf (
|
|
||||||
lib.types.submodule {
|
|
||||||
options = {
|
|
||||||
source = lib.mkOption {
|
|
||||||
type = lib.types.path;
|
|
||||||
description = "Path to the source file.";
|
|
||||||
};
|
|
||||||
executable = lib.mkOption {
|
|
||||||
type = lib.types.bool;
|
|
||||||
default = false;
|
|
||||||
description = "Whether the file should be executable.";
|
|
||||||
};
|
|
||||||
|
|
||||||
upstreamPath = lib.mkOption {
|
|
||||||
type = lib.types.nullOr lib.types.str;
|
|
||||||
default = null;
|
|
||||||
example = "home/yolo/claude-settings.json";
|
|
||||||
description = ''
|
|
||||||
Repo-relative file to name in the "bring changes upstream" hint.
|
|
||||||
Required when `source` is generated rather than a file in the
|
|
||||||
flake tree, since the store path cannot be mapped back.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
default = { };
|
|
||||||
description = "Files to copy (not symlink) into the home directory, with change detection.";
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf (cfg != { }) {
|
|
||||||
home.activation.mutableFiles = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
|
|
||||||
_mutable_changed=0
|
|
||||||
${checkScript}
|
|
||||||
if [ "$_mutable_changed" -eq 1 ]; then
|
|
||||||
echo ""
|
|
||||||
echo "!! Aborting: mutable files have been modified outside of nix."
|
|
||||||
echo " Bring the changes upstream first, then re-run."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
${copyScript}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
||||||
+34
-11
@@ -1,20 +1,43 @@
|
|||||||
{
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
pkgs,
|
pkgs,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
|
let
|
||||||
|
cfg = config.custom.blender;
|
||||||
|
in
|
||||||
{
|
{
|
||||||
home.packages = with pkgs; [
|
options.custom.blender = {
|
||||||
blender
|
cuda = lib.mkOption {
|
||||||
prusa-slicer
|
type = lib.types.bool;
|
||||||
];
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Build Blender with CUDA/OptiX so Cycles renders on the GPU instead of
|
||||||
|
the CPU. Only useful on an NVIDIA host; enabling it on arrakis (Intel)
|
||||||
|
would mean a long build for nothing.
|
||||||
|
|
||||||
fonts.fontconfig.enable = true;
|
No binary cache serves this — cuda-maintainers was measured to make no
|
||||||
|
difference — so flipping this on rebuilds Blender, OpenUSD, OpenSubdiv
|
||||||
|
and OpenImageDenoise from source.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
xdg.desktopEntries.prusaslicer-url-handler = {
|
config = {
|
||||||
name = "PrusaSlicer Protocol Handler";
|
home.packages = [
|
||||||
exec = "prusa-slicer %u";
|
(if cfg.cuda then pkgs.blender.override { cudaSupport = true; } else pkgs.blender)
|
||||||
type = "Application";
|
pkgs.prusa-slicer
|
||||||
noDisplay = true;
|
];
|
||||||
mimeType = [ "x-scheme-handler/prusaslicer" ];
|
|
||||||
|
fonts.fontconfig.enable = true;
|
||||||
|
|
||||||
|
xdg.desktopEntries.prusaslicer-url-handler = {
|
||||||
|
name = "PrusaSlicer Protocol Handler";
|
||||||
|
exec = "prusa-slicer %u";
|
||||||
|
type = "Application";
|
||||||
|
noDisplay = true;
|
||||||
|
mimeType = [ "x-scheme-handler/prusaslicer" ];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
inputs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
claude-desktop = pkgs.callPackage ../../../pkgs/claude-desktop/package.nix {
|
||||||
|
inherit (config.custom.aiApps) deviceScaleFactor;
|
||||||
|
};
|
||||||
|
codex-cli = inputs.codex-cli.packages.${pkgs.stdenv.hostPlatform.system}.default;
|
||||||
|
t3-code = pkgs.callPackage ../../../pkgs/t3-code/package.nix {
|
||||||
|
inherit (config.custom.aiApps) deviceScaleFactor;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
imports = [ inputs.codex-desktop-linux.homeManagerModules.default ];
|
||||||
|
|
||||||
|
home.packages = lib.optionals pkgs.stdenv.hostPlatform.isx86_64 [
|
||||||
|
claude-desktop
|
||||||
|
t3-code
|
||||||
|
];
|
||||||
|
|
||||||
|
programs.codexDesktopLinux = {
|
||||||
|
enable = true;
|
||||||
|
cliPackage = codex-cli;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,18 +1,14 @@
|
|||||||
{
|
{
|
||||||
config,
|
|
||||||
pkgs,
|
pkgs,
|
||||||
inputs,
|
inputs,
|
||||||
lib,
|
lib,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
|
||||||
# Official Anthropic Claude desktop app (Linux build, x86_64 only).
|
|
||||||
claude-desktop = pkgs.callPackage ../../../../pkgs/claude-desktop/package.nix {
|
|
||||||
inherit (config.custom.aiApps) deviceScaleFactor;
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
imports = [ inputs.agent-skills.homeModules.default ];
|
imports = [
|
||||||
|
inputs.agent-skills.homeModules.default
|
||||||
|
./synthetic.nix
|
||||||
|
];
|
||||||
|
|
||||||
# Shared UI-scale knob for the Electron AI desktop apps (Claude Desktop, T3 Code).
|
# Shared UI-scale knob for the Electron AI desktop apps (Claude Desktop, T3 Code).
|
||||||
# Set per-host (e.g. konishi's 4K@1x monitors want ~"1.5"); null = native scale.
|
# Set per-host (e.g. konishi's 4K@1x monitors want ~"1.5"); null = native scale.
|
||||||
@@ -23,24 +19,24 @@ in
|
|||||||
description = "--force-device-scale-factor value for Claude Desktop and T3 Code.";
|
description = "--force-device-scale-factor value for Claude Desktop and T3 Code.";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# ~/.claude/settings.json stays unmanaged: Claude Code rewrites it itself
|
||||||
|
# (model pins, permission grants, plugin state), so any nix copy drifts within
|
||||||
|
# a session and every `nh home switch` then aborts on the diff.
|
||||||
config.home = {
|
config.home = {
|
||||||
packages =
|
packages = with pkgs; [
|
||||||
with pkgs;
|
inputs.claude-code.packages.${pkgs.stdenv.hostPlatform.system}.default
|
||||||
[
|
|
||||||
inputs.claude-code.packages.${pkgs.stdenv.hostPlatform.system}.default
|
|
||||||
|
|
||||||
# sandbox
|
# sandbox
|
||||||
bubblewrap
|
bubblewrap
|
||||||
socat
|
socat
|
||||||
libseccomp
|
libseccomp
|
||||||
|
|
||||||
# voice
|
# voice
|
||||||
sox
|
sox
|
||||||
|
|
||||||
# beads
|
# beads
|
||||||
dolt
|
dolt
|
||||||
]
|
];
|
||||||
++ lib.optional pkgs.stdenv.hostPlatform.isx86_64 claude-desktop;
|
|
||||||
|
|
||||||
file = {
|
file = {
|
||||||
".default-npm-packages".text = ''
|
".default-npm-packages".text = ''
|
||||||
@@ -48,17 +44,11 @@ in
|
|||||||
@beads/bd
|
@beads/bd
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
".claude/statusline.sh" = {
|
".claude/statusline.sh" = {
|
||||||
source = ./statusline.sh;
|
source = ./statusline.sh;
|
||||||
executable = true;
|
executable = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
mutableFiles.".claude/settings.json".source = ./settings.json;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,86 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://json.schemastore.org/claude-code-settings.json",
|
|
||||||
"permissions": {
|
|
||||||
"allow": [
|
|
||||||
"Edit",
|
|
||||||
"Write",
|
|
||||||
"Bash(ls:*)",
|
|
||||||
"Bash(tree:*)",
|
|
||||||
"Bash(cat:*)",
|
|
||||||
"Bash(head:*)",
|
|
||||||
"Bash(tail:*)",
|
|
||||||
"Bash(find:*)",
|
|
||||||
"Bash(fd:*)",
|
|
||||||
"Bash(grep:*)",
|
|
||||||
"Bash(rg:*)",
|
|
||||||
"Bash(wc:*)",
|
|
||||||
"Bash(sort:*)",
|
|
||||||
"Bash(uniq:*)",
|
|
||||||
"Bash(diff:*)",
|
|
||||||
"Bash(pwd:*)",
|
|
||||||
"Bash(which:*)",
|
|
||||||
"Bash(jq:*)",
|
|
||||||
"Bash(git:*)",
|
|
||||||
"Bash(gh:*)",
|
|
||||||
"Bash(sed:*)",
|
|
||||||
"Bash(cp:*)",
|
|
||||||
"Bash(chmod:*)",
|
|
||||||
"Bash(mkdir:*)",
|
|
||||||
"Bash(kitty @ set-tab-title:*)"
|
|
||||||
],
|
|
||||||
"additionalDirectories": [
|
|
||||||
"/home/naps62/projects",
|
|
||||||
"/home/naps62/ethui",
|
|
||||||
"/home/naps62/labs",
|
|
||||||
"/home/naps62/subvisual"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"model": "opus[1m]",
|
|
||||||
"statusLine": {
|
|
||||||
"type": "command",
|
|
||||||
"command": "~/.claude/statusline.sh"
|
|
||||||
},
|
|
||||||
"enabledPlugins": {
|
|
||||||
"typescript-lsp@claude-plugins-official": true
|
|
||||||
},
|
|
||||||
"extraKnownMarketplaces": {
|
|
||||||
"impeccable": {
|
|
||||||
"source": {
|
|
||||||
"source": "github",
|
|
||||||
"repo": "pbakaus/impeccable"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sandbox": {
|
|
||||||
"enabled": true,
|
|
||||||
"autoAllowBashIfSandboxed": false,
|
|
||||||
"allowedNetworkHosts": [
|
|
||||||
"github.com",
|
|
||||||
"api.github.com",
|
|
||||||
"raw.githubusercontent.com",
|
|
||||||
"gist.github.com",
|
|
||||||
"release-assets.githubusercontent.com"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"tui": "fullscreen",
|
|
||||||
"voiceEnabled": true,
|
|
||||||
"defaultMode": "acceptEdits",
|
|
||||||
"feedbackSurveyState": {
|
|
||||||
"lastShownTime": 1754052643456
|
|
||||||
},
|
|
||||||
"mcpServers": {
|
|
||||||
"herd-mcp": {
|
|
||||||
"type": "http",
|
|
||||||
"url": "https://mcp.herd.eco/v1"
|
|
||||||
},
|
|
||||||
"linear": {
|
|
||||||
"type": "http",
|
|
||||||
"url": "https://mcp.linear.app/mcp"
|
|
||||||
},
|
|
||||||
"home-assistant": {
|
|
||||||
"type": "http",
|
|
||||||
"url": "https://ha-mcp.n62.casa/mcp"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"agentPushNotifEnabled": true
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
inputs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
# Claude Code pointed at synthetic.new. The three model aliases below are bound
|
||||||
|
# to three Synthetic models, so `/model opus|sonnet|haiku` swaps between them
|
||||||
|
# live; anything else there is reachable by full id (`/model hf:...`).
|
||||||
|
let
|
||||||
|
claude = inputs.claude-code.packages.${pkgs.stdenv.hostPlatform.system}.default;
|
||||||
|
|
||||||
|
# `hf:` ids pin one exact model. The `syn:large:*` aliases in Synthetic's own
|
||||||
|
# docs move under you whenever they rotate what "large" means.
|
||||||
|
kimi = "hf:moonshotai/Kimi-K3";
|
||||||
|
glm = "hf:zai-org/GLM-5.2";
|
||||||
|
|
||||||
|
# Not Qwen3.6-27B for the haiku slot: its chat template rejects Claude Code's
|
||||||
|
# multi-block system prompt with "System message must be at the beginning."
|
||||||
|
glmFlash = "hf:zai-org/GLM-4.7-Flash";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
home.packages = [
|
||||||
|
(pkgs.writeShellScriptBin "synclaude" ''
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [ -z "''${SYNTHETIC_API_KEY:-}" ] && [ -r "$HOME/.env.claude" ]; then
|
||||||
|
set +u
|
||||||
|
# Silenced: the file greets missing tooling on stderr, which would
|
||||||
|
# otherwise print before every session.
|
||||||
|
. "$HOME/.env.claude" >/dev/null 2>&1
|
||||||
|
set -u
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "''${SYNTHETIC_API_KEY:-}" ]; then
|
||||||
|
echo "synclaude: SYNTHETIC_API_KEY is not set" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
export ANTHROPIC_BASE_URL="https://api.synthetic.new/anthropic"
|
||||||
|
export ANTHROPIC_AUTH_TOKEN="$SYNTHETIC_API_KEY"
|
||||||
|
export ANTHROPIC_DEFAULT_OPUS_MODEL="${kimi}"
|
||||||
|
export ANTHROPIC_DEFAULT_SONNET_MODEL="${glm}"
|
||||||
|
export ANTHROPIC_DEFAULT_HAIKU_MODEL="${glmFlash}"
|
||||||
|
export CLAUDE_CODE_SUBAGENT_MODEL="${glm}"
|
||||||
|
export CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1
|
||||||
|
export CLAUDE_CODE_ATTRIBUTION_HEADER=0
|
||||||
|
|
||||||
|
# ~/.env.claude exports both. ANTHROPIC_MODEL outranks the DEFAULT_* trio
|
||||||
|
# above, and ANTHROPIC_API_KEY would send Anthropic's credential to
|
||||||
|
# Synthetic.
|
||||||
|
unset ANTHROPIC_MODEL ANTHROPIC_API_KEY
|
||||||
|
|
||||||
|
# These two dokploy tools spell ttl's bound `"exclusiveMinimum": true`,
|
||||||
|
# which is draft-04. Synthetic validates against draft-2020, where the key
|
||||||
|
# must be a number, and rejects the whole request — a bare 500 with no body
|
||||||
|
# when streaming. Every session fails, not just ones that call these.
|
||||||
|
broken_tools=(
|
||||||
|
mcp__dokploy__dnsProvider-createRecord
|
||||||
|
mcp__dokploy__dnsProvider-updateRecord
|
||||||
|
)
|
||||||
|
|
||||||
|
# ~/.claude/settings.json pins model "opus[1m]". The [1m] context-window
|
||||||
|
# suffix survives alias resolution and reaches Synthetic as part of the id,
|
||||||
|
# which 404s there — so pick the alias explicitly unless the caller did.
|
||||||
|
for arg in "$@"; do
|
||||||
|
case "$arg" in
|
||||||
|
--model | --model=*)
|
||||||
|
exec ${claude}/bin/claude --disallowedTools "''${broken_tools[@]}" "$@"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
exec ${claude}/bin/claude --model sonnet --disallowedTools "''${broken_tools[@]}" "$@"
|
||||||
|
'')
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -7,14 +7,5 @@ let
|
|||||||
codex-cli = inputs.codex-cli.packages.${pkgs.stdenv.hostPlatform.system}.default;
|
codex-cli = inputs.codex-cli.packages.${pkgs.stdenv.hostPlatform.system}.default;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
imports = [ inputs.codex-desktop-linux.homeManagerModules.default ];
|
|
||||||
|
|
||||||
# cliPackage only tells the desktop app where to find codex; it does not put
|
|
||||||
# it on PATH, so the cli needs installing separately.
|
|
||||||
home.packages = [ codex-cli ];
|
home.packages = [ codex-cli ];
|
||||||
|
|
||||||
programs.codexDesktopLinux = {
|
|
||||||
enable = true;
|
|
||||||
cliPackage = codex-cli;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
{
|
{
|
||||||
lib,
|
lib,
|
||||||
pkgs,
|
|
||||||
config,
|
config,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
../features/mutable-file.nix
|
|
||||||
./zsh.nix
|
./zsh.nix
|
||||||
./nix.nix
|
./nix.nix
|
||||||
./neovim
|
./neovim
|
||||||
./editors.nix
|
|
||||||
./rust.nix
|
./rust.nix
|
||||||
./elixir.nix
|
./elixir.nix
|
||||||
./nodejs.nix
|
./nodejs.nix
|
||||||
@@ -30,14 +27,6 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
home = {
|
home = {
|
||||||
# mkDefault: hosts whose clone lives elsewhere (yolo, under ~/tea) override
|
|
||||||
# this with a plain assignment.
|
|
||||||
mutableFilesRepoPath = lib.mkDefault "${config.home.homeDirectory}/projects/nixos-config";
|
|
||||||
|
|
||||||
packages = with pkgs; [
|
|
||||||
impala
|
|
||||||
];
|
|
||||||
|
|
||||||
username = lib.mkDefault "naps62";
|
username = lib.mkDefault "naps62";
|
||||||
homeDirectory = lib.mkDefault "/home/${config.home.username}";
|
homeDirectory = lib.mkDefault "/home/${config.home.username}";
|
||||||
stateVersion = lib.mkDefault "24.05";
|
stateVersion = lib.mkDefault "24.05";
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
{ pkgs, ... }:
|
{ pkgs, config, ... }:
|
||||||
|
let
|
||||||
|
inherit (config.custom.hyprland) cursorTheme cursorSize;
|
||||||
|
in
|
||||||
{
|
{
|
||||||
home.packages = with pkgs; [
|
home.packages = with pkgs; [
|
||||||
dconf
|
dconf
|
||||||
@@ -15,17 +18,14 @@
|
|||||||
'';
|
'';
|
||||||
cursor-theme = ''
|
cursor-theme = ''
|
||||||
${pkgs.dconf}/bin/dconf write \
|
${pkgs.dconf}/bin/dconf write \
|
||||||
/org/gnome/desktop/interface/cursor-theme "'Nordzy-cursors'"
|
/org/gnome/desktop/interface/cursor-theme "'${cursorTheme.dark}'"
|
||||||
|
|
||||||
# Set environment variables for current session
|
# Set environment variables for current session
|
||||||
export HYPRCURSOR_THEME="Nordzy-cursors"
|
export HYPRCURSOR_THEME="${cursorTheme.dark}"
|
||||||
export XCURSOR_THEME="Nordzy-cursors"
|
export XCURSOR_THEME="${cursorTheme.dark}"
|
||||||
|
|
||||||
# Update Hyprland cursor theme
|
# Update Hyprland cursor theme
|
||||||
${pkgs.hyprland}/bin/hyprctl setcursor Nordzy-cursors 24
|
${pkgs.hyprland}/bin/hyprctl setcursor ${cursorTheme.dark} ${toString cursorSize}
|
||||||
'';
|
|
||||||
noctalia-theme = ''
|
|
||||||
noctalia msg theme-mode-set dark
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
lightModeScripts = {
|
lightModeScripts = {
|
||||||
@@ -37,17 +37,14 @@
|
|||||||
'';
|
'';
|
||||||
cursor-theme = ''
|
cursor-theme = ''
|
||||||
${pkgs.dconf}/bin/dconf write \
|
${pkgs.dconf}/bin/dconf write \
|
||||||
/org/gnome/desktop/interface/cursor-theme "'Nordzy-white'"
|
/org/gnome/desktop/interface/cursor-theme "'${cursorTheme.light}'"
|
||||||
|
|
||||||
# Set environment variables for current session
|
# Set environment variables for current session
|
||||||
export HYPRCURSOR_THEME="Nordzy-white"
|
export HYPRCURSOR_THEME="${cursorTheme.light}"
|
||||||
export XCURSOR_THEME="Nordzy-white"
|
export XCURSOR_THEME="${cursorTheme.light}"
|
||||||
|
|
||||||
# Update Hyprland cursor theme
|
# Update Hyprland cursor theme
|
||||||
${pkgs.hyprland}/bin/hyprctl setcursor Nordzy-white 24
|
${pkgs.hyprland}/bin/hyprctl setcursor ${cursorTheme.light} ${toString cursorSize}
|
||||||
'';
|
|
||||||
noctalia-theme = ''
|
|
||||||
noctalia msg theme-mode-set light
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
config,
|
config,
|
||||||
lib,
|
|
||||||
pkgs,
|
pkgs,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./darkman.nix
|
./darkman.nix
|
||||||
./spicetify.nix
|
# mpv is installed by programs.mpv there, not as a bare package here.
|
||||||
|
../mpv.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
home = {
|
home = {
|
||||||
@@ -15,43 +15,21 @@
|
|||||||
# various
|
# various
|
||||||
google-chrome
|
google-chrome
|
||||||
thunar
|
thunar
|
||||||
obsidian
|
|
||||||
mpv
|
|
||||||
# screen recording — evaluating these
|
|
||||||
obs-studio
|
|
||||||
kooha # simple Wayland-native screen+audio recorder
|
|
||||||
vokoscreen-ng # GUI recorder with webcam overlay
|
|
||||||
gimp
|
|
||||||
font-manager
|
|
||||||
imv
|
imv
|
||||||
pavucontrol
|
pavucontrol
|
||||||
zathura
|
zathura
|
||||||
libsForQt5.qt5ct
|
libsForQt5.qt5ct
|
||||||
kdePackages.qt6ct
|
kdePackages.qt6ct
|
||||||
nwg-look
|
nwg-look
|
||||||
xournalpp
|
|
||||||
jq
|
jq
|
||||||
ffmpeg
|
ffmpeg
|
||||||
unzip
|
unzip
|
||||||
|
|
||||||
# remote desktop
|
|
||||||
remmina
|
|
||||||
|
|
||||||
# networking
|
# networking
|
||||||
networkmanagerapplet
|
networkmanagerapplet
|
||||||
mtr
|
mtr
|
||||||
dnsutils
|
dnsutils
|
||||||
|
|
||||||
# communication
|
|
||||||
slack
|
|
||||||
ferdium
|
|
||||||
signal-desktop
|
|
||||||
zoom-us
|
|
||||||
|
|
||||||
# dev tools
|
|
||||||
yaak
|
|
||||||
bun
|
|
||||||
|
|
||||||
# themes
|
# themes
|
||||||
tela-icon-theme
|
tela-icon-theme
|
||||||
];
|
];
|
||||||
@@ -83,36 +61,36 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
xdg.configFile = {
|
xdg.configFile = {
|
||||||
# zathura: include noctalia-generated theme
|
|
||||||
"zathura/zathurarc".text = ''
|
"zathura/zathurarc".text = ''
|
||||||
include noctaliarc
|
set default-bg "#2e3440"
|
||||||
|
set default-fg "#eceff4"
|
||||||
|
set statusbar-bg "#3b4252"
|
||||||
|
set statusbar-fg "#eceff4"
|
||||||
|
set inputbar-bg "#3b4252"
|
||||||
|
set inputbar-fg "#eceff4"
|
||||||
|
set highlight-color "#ebcb8b"
|
||||||
|
set highlight-active-color "#88c0d0"
|
||||||
|
set recolor-lightcolor "#2e3440"
|
||||||
|
set recolor-darkcolor "#eceff4"
|
||||||
'';
|
'';
|
||||||
|
|
||||||
# gtk: include noctalia-generated css (mkForce to override gtk module)
|
# qt: dark color scheme shipped by qt5ct/qt6ct themselves. Applied via
|
||||||
"gtk-3.0/gtk.css".text = lib.mkForce ''
|
# QT_QPA_PLATFORMTHEME=qt6ct, set in the Hyprland env block (and imported
|
||||||
@import url("noctalia.css");
|
# into the dbus activation environment so the xdph screen-share picker
|
||||||
'';
|
# inherits it too). custom_palette=true is required for qt5ct/qt6ct to
|
||||||
"gtk-4.0/gtk.css".text = lib.mkForce ''
|
# actually apply the color scheme; Fusion is used because it fully honors a
|
||||||
@import url("noctalia.css");
|
# custom palette (Breeze/native styles partly ignore it).
|
||||||
'';
|
|
||||||
|
|
||||||
# qt: use noctalia color scheme. Applied via QT_QPA_PLATFORMTHEME=qt6ct,
|
|
||||||
# set in the Hyprland env block (and imported into the dbus activation
|
|
||||||
# environment so the xdph screen-share picker inherits it too).
|
|
||||||
# custom_palette=true is required for qt5ct/qt6ct to actually apply the
|
|
||||||
# color scheme; Fusion is used because it fully honors a custom palette
|
|
||||||
# (Breeze/native styles partly ignore it).
|
|
||||||
"qt5ct/qt5ct.conf".text = ''
|
"qt5ct/qt5ct.conf".text = ''
|
||||||
[Appearance]
|
[Appearance]
|
||||||
style=Fusion
|
style=Fusion
|
||||||
custom_palette=true
|
custom_palette=true
|
||||||
color_scheme_path=${config.home.homeDirectory}/.config/qt5ct/colors/noctalia.conf
|
color_scheme_path=${pkgs.libsForQt5.qt5ct}/share/qt5ct/colors/darker.conf
|
||||||
'';
|
'';
|
||||||
"qt6ct/qt6ct.conf".text = ''
|
"qt6ct/qt6ct.conf".text = ''
|
||||||
[Appearance]
|
[Appearance]
|
||||||
style=Fusion
|
style=Fusion
|
||||||
custom_palette=true
|
custom_palette=true
|
||||||
color_scheme_path=${config.home.homeDirectory}/.config/qt6ct/colors/noctalia.conf
|
color_scheme_path=${pkgs.kdePackages.qt6ct}/share/qt6ct/colors/darker.conf
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
home.packages = with pkgs; [
|
||||||
|
doctl
|
||||||
|
awscli2
|
||||||
|
terraform
|
||||||
|
bruno
|
||||||
|
coturn
|
||||||
|
usbutils
|
||||||
|
ktlint
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -5,8 +5,8 @@
|
|||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./codex.nix
|
./codex.nix
|
||||||
|
./pi.nix
|
||||||
./ralph-claude-code.nix
|
./ralph-claude-code.nix
|
||||||
./t3-code.nix
|
|
||||||
];
|
];
|
||||||
|
|
||||||
programs = {
|
programs = {
|
||||||
@@ -25,19 +25,12 @@
|
|||||||
|
|
||||||
home.packages = with pkgs; [
|
home.packages = with pkgs; [
|
||||||
imagemagick
|
imagemagick
|
||||||
doctl
|
|
||||||
awscli2
|
|
||||||
terraform
|
|
||||||
inotify-tools
|
inotify-tools
|
||||||
devenv
|
devenv
|
||||||
bruno
|
|
||||||
sshfs
|
sshfs
|
||||||
coturn
|
|
||||||
file
|
file
|
||||||
usbutils
|
|
||||||
nmap
|
nmap
|
||||||
lsof
|
lsof
|
||||||
ktlint
|
|
||||||
croc
|
croc
|
||||||
opencode
|
opencode
|
||||||
process-compose
|
process-compose
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ tmp/**/*
|
|||||||
*.log
|
*.log
|
||||||
*.tmp
|
*.tmp
|
||||||
|
|
||||||
|
# Local git worktree checkouts
|
||||||
|
worktrees/
|
||||||
|
|
||||||
# Latex
|
# Latex
|
||||||
_inputs.tex
|
_inputs.tex
|
||||||
_sections.tex
|
_sections.tex
|
||||||
|
|||||||
@@ -1,17 +1,19 @@
|
|||||||
{ pkgs, config, ... }:
|
{ pkgs, config, ... }:
|
||||||
let
|
let
|
||||||
|
cfg = config.custom.hyprland;
|
||||||
nordzy-cursors = pkgs.callPackage ../../../../pkgs/nordzy-cursors/package.nix { };
|
nordzy-cursors = pkgs.callPackage ../../../../pkgs/nordzy-cursors/package.nix { };
|
||||||
cursorSize = config.custom.hyprland.cursorSize;
|
cursorPackage = if cfg.cursorPackage != null then cfg.cursorPackage else nordzy-cursors;
|
||||||
|
cursorSize = cfg.cursorSize;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
home.packages = [
|
home.packages = [
|
||||||
nordzy-cursors
|
cursorPackage
|
||||||
];
|
];
|
||||||
|
|
||||||
home.sessionVariables = {
|
home.sessionVariables = {
|
||||||
HYPRCURSOR_THEME = "Nordzy-cursors"; # Dark variant (default)
|
HYPRCURSOR_THEME = cfg.cursorTheme.dark;
|
||||||
HYPRCURSOR_SIZE = cursorSize;
|
HYPRCURSOR_SIZE = cursorSize;
|
||||||
XCURSOR_THEME = "Nordzy-cursors";
|
XCURSOR_THEME = cfg.cursorTheme.dark;
|
||||||
XCURSOR_SIZE = cursorSize;
|
XCURSOR_SIZE = cursorSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ let
|
|||||||
|
|
||||||
hyprPkgs = inputs.hyprland.packages.${pkgs.stdenv.hostPlatform.system};
|
hyprPkgs = inputs.hyprland.packages.${pkgs.stdenv.hostPlatform.system};
|
||||||
|
|
||||||
|
osd = "${pkgs.swayosd}/bin/swayosd-client";
|
||||||
|
|
||||||
# xdph runs this instead of hyprland-share-picker (screencopy:custom_picker_binary).
|
# xdph runs this instead of hyprland-share-picker (screencopy:custom_picker_binary).
|
||||||
# The contract is just "print [SELECTION] to stdout"; a leading "r" grants a
|
# The contract is just "print [SELECTION] to stdout"; a leading "r" grants a
|
||||||
# restore token. Printing it immediately means the dialog never renders.
|
# restore token. Printing it immediately means the dialog never renders.
|
||||||
@@ -70,6 +72,41 @@ in
|
|||||||
default = 24;
|
default = 24;
|
||||||
description = "Cursor size for XCURSOR_SIZE and HYPRCURSOR_SIZE";
|
description = "Cursor size for XCURSOR_SIZE and HYPRCURSOR_SIZE";
|
||||||
};
|
};
|
||||||
|
cursorPackage = lib.mkOption {
|
||||||
|
type = lib.types.nullOr lib.types.package;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
Package providing cursorTheme.dark/light under share/icons. null uses
|
||||||
|
the nordzy-cursors package built in ./cursor.nix.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
cursorTheme = {
|
||||||
|
dark = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "Nordzy-cursors";
|
||||||
|
description = "Cursor theme darkman selects in dark mode.";
|
||||||
|
};
|
||||||
|
light = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "Nordzy-white";
|
||||||
|
description = "Cursor theme darkman selects in light mode.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
panelScale = lib.mkOption {
|
||||||
|
type = lib.types.float;
|
||||||
|
default = 1.0;
|
||||||
|
example = 1.5;
|
||||||
|
description = "Multiplier for every length in the eww dashboard stylesheet.";
|
||||||
|
};
|
||||||
|
verticalOutputs = lib.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.str;
|
||||||
|
default = [ ];
|
||||||
|
example = [ "DP-2" ];
|
||||||
|
description = ''
|
||||||
|
Outputs that get the portrait wallpaper set. Everything else gets the
|
||||||
|
landscape one.
|
||||||
|
'';
|
||||||
|
};
|
||||||
shareOutput = lib.mkOption {
|
shareOutput = lib.mkOption {
|
||||||
type = lib.types.nullOr lib.types.str;
|
type = lib.types.nullOr lib.types.str;
|
||||||
default = null;
|
default = null;
|
||||||
@@ -84,8 +121,9 @@ in
|
|||||||
|
|
||||||
imports = [
|
imports = [
|
||||||
./cursor.nix
|
./cursor.nix
|
||||||
|
./eww
|
||||||
./kbptr.nix
|
./kbptr.nix
|
||||||
./noctalia
|
./shell.nix
|
||||||
./wallpapers.nix
|
./wallpapers.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -204,11 +242,11 @@ in
|
|||||||
-- environment
|
-- environment
|
||||||
hl.env("GDK_SCALE", "2.0")
|
hl.env("GDK_SCALE", "2.0")
|
||||||
hl.env("XCURSOR_SIZE", "${toString cfg.cursorSize}")
|
hl.env("XCURSOR_SIZE", "${toString cfg.cursorSize}")
|
||||||
hl.env("HYPRCURSOR_THEME", "rose-pine-hyprcursor")
|
hl.env("HYPRCURSOR_THEME", "${cfg.cursorTheme.dark}")
|
||||||
hl.env("HYPRCURSOR_SIZE", "${toString cfg.cursorSize}")
|
hl.env("HYPRCURSOR_SIZE", "${toString cfg.cursorSize}")
|
||||||
-- Route Qt6 apps (incl. the xdph screen-share picker) through qt6ct so
|
-- Route Qt6 apps (incl. the xdph screen-share picker) through qt6ct so
|
||||||
-- the noctalia-generated color scheme actually applies. Without this
|
-- the dark color scheme actually applies. Without this var the
|
||||||
-- var the qt6ct.conf is never read.
|
-- qt6ct.conf is never read.
|
||||||
hl.env("QT_QPA_PLATFORMTHEME", "qt6ct")
|
hl.env("QT_QPA_PLATFORMTHEME", "qt6ct")
|
||||||
|
|
||||||
-- autostart
|
-- autostart
|
||||||
@@ -216,16 +254,17 @@ in
|
|||||||
-- Import the Qt theme var too, so the dbus/systemd-activated
|
-- Import the Qt theme var too, so the dbus/systemd-activated
|
||||||
-- xdg-desktop-portal-hyprland (and its share-picker) inherit it.
|
-- xdg-desktop-portal-hyprland (and its share-picker) inherit it.
|
||||||
hl.exec_cmd("dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME")
|
hl.exec_cmd("dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME")
|
||||||
hl.exec_cmd("hyprctl setcursor Nordzy-cursors ${toString cfg.cursorSize}")
|
hl.exec_cmd("hyprctl setcursor ${cfg.cursorTheme.dark} ${toString cfg.cursorSize}")
|
||||||
hl.exec_cmd("hyprsunset")
|
hl.exec_cmd("hyprsunset")
|
||||||
hl.exec_cmd("noctalia")
|
-- eww, wpaperd, mako and the polkit agent are systemd user services
|
||||||
|
-- bound to graphical-session.target; nothing to start here.
|
||||||
-- kdeconnectd is only DBus-activated; nothing starts it at login,
|
-- kdeconnectd is only DBus-activated; nothing starts it at login,
|
||||||
-- so clipboard sync stays dead until the indicator runs.
|
-- so clipboard sync stays dead until the indicator runs.
|
||||||
hl.exec_cmd("kdeconnect-indicator")
|
hl.exec_cmd("kdeconnect-indicator")
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- layer rules
|
-- layer rules
|
||||||
hl.layer_rule({ match = { namespace = "noctalia-wallpaper" }, blur = true, ignore_alpha = 0.5 })
|
hl.layer_rule({ match = { namespace = "eww-panel" }, blur = true, ignore_alpha = 0.5 })
|
||||||
|
|
||||||
-- workspace rules
|
-- workspace rules
|
||||||
hl.workspace_rule({ workspace = "w[t1]", gaps_out = 0, gaps_in = 0 }) -- no gaps when only window
|
hl.workspace_rule({ workspace = "w[t1]", gaps_out = 0, gaps_in = 0 }) -- no gaps when only window
|
||||||
@@ -253,7 +292,11 @@ in
|
|||||||
})
|
})
|
||||||
|
|
||||||
hl.window_rule({ match = { class = "thunar" }, float = true, size = "1800 1200", move = "(cursor_x-(window_w*0.5)) (cursor_y-(window_h*0.5))" })
|
hl.window_rule({ match = { class = "thunar" }, float = true, size = "1800 1200", move = "(cursor_x-(window_w*0.5)) (cursor_y-(window_h*0.5))" })
|
||||||
hl.window_rule({ match = { class = [[\.blueman-manager-wrapped]] }, float = true, size = "1200 800", move = "(cursor_x-(window_w*0.5)) (cursor_y-(window_h*0.5))" })
|
-- nixpkgs wraps blueman with --inherit-argv0, so the class is
|
||||||
|
-- blueman-manager, not the .blueman-manager-wrapped the old rule expected.
|
||||||
|
hl.window_rule({ match = { class = [[.*[Bb]lueman.*]] }, float = true, size = "1200 800", move = "(cursor_x-(window_w*0.5)) (cursor_y-(window_h*0.5))" })
|
||||||
|
hl.window_rule({ match = { class = "nm-connection-editor" }, float = true, size = "1200 800", move = "(cursor_x-(window_w*0.5)) (cursor_y-(window_h*0.5))" })
|
||||||
|
hl.window_rule({ match = { class = "waypaper" }, float = true, size = "1600 1000", move = "(cursor_x-(window_w*0.5)) (cursor_y-(window_h*0.5))" })
|
||||||
hl.window_rule({ match = { class = [[org\.pulseaudio\.pavucontrol]] }, float = true, size = "1200 1200", move = "(cursor_x-(window_w*0.5)) (cursor_y-(window_h*0.5))" })
|
hl.window_rule({ match = { class = [[org\.pulseaudio\.pavucontrol]] }, float = true, size = "1200 1200", move = "(cursor_x-(window_w*0.5)) (cursor_y-(window_h*0.5))" })
|
||||||
|
|
||||||
-- wine / game installers (Inno Setup temp windows, e.g. Heroic/GOG).
|
-- wine / game installers (Inno Setup temp windows, e.g. Heroic/GOG).
|
||||||
@@ -276,7 +319,7 @@ in
|
|||||||
hl.window_rule({ match = { workspace = "special:yazi" }, center = true })
|
hl.window_rule({ match = { workspace = "special:yazi" }, center = true })
|
||||||
|
|
||||||
-- keybinds
|
-- keybinds
|
||||||
hl.bind(mod .. " + N", hl.dsp.exec_cmd("noctalia msg panel-toggle control-center"))
|
hl.bind(mod .. " + N", hl.dsp.exec_cmd("eww-panel"))
|
||||||
hl.bind(mod .. " + T", hl.dsp.exec_cmd("kitty"))
|
hl.bind(mod .. " + T", hl.dsp.exec_cmd("kitty"))
|
||||||
hl.bind(mod .. " + V", hl.dsp.window.float({ action = "toggle" }))
|
hl.bind(mod .. " + V", hl.dsp.window.float({ action = "toggle" }))
|
||||||
hl.bind(mod .. " + Q", hl.dsp.window.close())
|
hl.bind(mod .. " + Q", hl.dsp.window.close())
|
||||||
@@ -286,7 +329,7 @@ in
|
|||||||
-- lock (routes through logind -> hypridle lock_cmd -> hyprlock)
|
-- lock (routes through logind -> hypridle lock_cmd -> hyprlock)
|
||||||
hl.bind(mod .. " + CTRL + L", hl.dsp.exec_cmd("loginctl lock-session"))
|
hl.bind(mod .. " + CTRL + L", hl.dsp.exec_cmd("loginctl lock-session"))
|
||||||
|
|
||||||
hl.bind(mod .. " + space", hl.dsp.exec_cmd("noctalia msg panel-toggle launcher"))
|
hl.bind(mod .. " + space", hl.dsp.exec_cmd("fuzzel"))
|
||||||
|
|
||||||
-- printscreen
|
-- printscreen
|
||||||
hl.bind("Print", hl.dsp.exec_cmd("hyprshot -m region --raw | satty --filename - --output-filename ~/downloads/screenshots/$(date +%Y-%m-%d_%H-%M-%S).png"))
|
hl.bind("Print", hl.dsp.exec_cmd("hyprshot -m region --raw | satty --filename - --output-filename ~/downloads/screenshots/$(date +%Y-%m-%d_%H-%M-%S).png"))
|
||||||
@@ -324,18 +367,21 @@ in
|
|||||||
hl.dispatch(hl.dsp.window.center())
|
hl.dispatch(hl.dsp.window.center())
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- volume / brightness (locked so they work on the lock screen; repeat on hold)
|
-- volume / brightness / media (locked so they work on the lock screen;
|
||||||
hl.bind("XF86AudioRaiseVolume", hl.dsp.exec_cmd("wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+"), { locked = true, repeating = true })
|
-- volume and brightness repeat on hold). Everything goes through
|
||||||
hl.bind("XF86AudioLowerVolume", hl.dsp.exec_cmd("wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"), { locked = true, repeating = true })
|
-- swayosd-client, which applies the change and draws the OSD popup;
|
||||||
hl.bind("XF86MonBrightnessUp", hl.dsp.exec_cmd("brightnessctl set 5%+"), { locked = true, repeating = true })
|
-- store paths because Hyprland execs these with the login PATH, which
|
||||||
hl.bind("XF86MonBrightnessDown", hl.dsp.exec_cmd("brightnessctl set 5%-"), { locked = true, repeating = true })
|
-- doesn't pick up profile changes made after the session started.
|
||||||
|
hl.bind("XF86AudioRaiseVolume", hl.dsp.exec_cmd("${osd} --output-volume raise"), { locked = true, repeating = true })
|
||||||
|
hl.bind("XF86AudioLowerVolume", hl.dsp.exec_cmd("${osd} --output-volume lower"), { locked = true, repeating = true })
|
||||||
|
hl.bind("XF86MonBrightnessUp", hl.dsp.exec_cmd("${osd} --brightness raise"), { locked = true, repeating = true })
|
||||||
|
hl.bind("XF86MonBrightnessDown", hl.dsp.exec_cmd("${osd} --brightness lower"), { locked = true, repeating = true })
|
||||||
|
|
||||||
-- media keys (locked)
|
hl.bind("XF86AudioMute", hl.dsp.exec_cmd("${osd} --output-volume mute-toggle"), { locked = true })
|
||||||
hl.bind("XF86AudioMute", hl.dsp.exec_cmd("pactl set-sink-mute @DEFAULT_SINK@ toggle"), { locked = true })
|
hl.bind("XF86AudioMicMute", hl.dsp.exec_cmd("${osd} --input-volume mute-toggle"), { locked = true })
|
||||||
hl.bind("XF86AudioMicMute", hl.dsp.exec_cmd("volumectl -m toggle-mute"), { locked = true })
|
hl.bind("XF86AudioNext", hl.dsp.exec_cmd("${osd} --playerctl next"), { locked = true })
|
||||||
hl.bind("XF86AudioNext", hl.dsp.exec_cmd("playerctl next"), { locked = true })
|
hl.bind("XF86AudioPrev", hl.dsp.exec_cmd("${osd} --playerctl prev"), { locked = true })
|
||||||
hl.bind("XF86AudioPrev", hl.dsp.exec_cmd("playerctl previous"), { locked = true })
|
hl.bind("XF86AudioPlay", hl.dsp.exec_cmd("${osd} --playerctl play-pause"), { locked = true })
|
||||||
hl.bind("XF86AudioPlay", hl.dsp.exec_cmd("playerctl play-pause"), { locked = true })
|
|
||||||
|
|
||||||
-- move/resize windows with mod + LMB/RMB drag
|
-- move/resize windows with mod + LMB/RMB drag
|
||||||
hl.bind(mod .. " + mouse:272", hl.dsp.window.drag(), { mouse = true })
|
hl.bind(mod .. " + mouse:272", hl.dsp.window.drag(), { mouse = true })
|
||||||
@@ -345,10 +391,9 @@ in
|
|||||||
|
|
||||||
services.hyprpaper.enable = false;
|
services.hyprpaper.enable = false;
|
||||||
|
|
||||||
# hyprlock: the lock screen, replacing noctalia's built-in locker (which is
|
# hyprlock: the lock screen. Clean minimal dark look; tweak colours/clock/
|
||||||
# ugly and — unlike hyprlock — opaque to scripts/lock-state detection).
|
# font to taste. hypridle below drives it (idle + before-sleep), and
|
||||||
# Clean minimal dark look; tweak colours/clock/font to taste. hypridle below
|
# $mod CTRL+L locks manually.
|
||||||
# drives it (idle + before-sleep), and $mod CTRL+L locks manually.
|
|
||||||
programs.hyprlock = {
|
programs.hyprlock = {
|
||||||
enable = true;
|
enable = true;
|
||||||
settings = {
|
settings = {
|
||||||
|
|||||||
@@ -0,0 +1,292 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
inputs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
cfg = config.custom.hyprland;
|
||||||
|
|
||||||
|
# Every length in the stylesheet goes through this, so one option resizes the
|
||||||
|
# whole dashboard for 4K hosts.
|
||||||
|
px = n: "${toString (builtins.ceil (n * cfg.panelScale))}px";
|
||||||
|
|
||||||
|
mkScript =
|
||||||
|
name: runtimeInputs:
|
||||||
|
pkgs.writeShellApplication {
|
||||||
|
inherit name runtimeInputs;
|
||||||
|
text = builtins.readFile (./scripts + "/${name}.sh");
|
||||||
|
};
|
||||||
|
|
||||||
|
battery = mkScript "battery" [
|
||||||
|
pkgs.coreutils
|
||||||
|
pkgs.findutils
|
||||||
|
pkgs.jq
|
||||||
|
];
|
||||||
|
network = mkScript "network" [
|
||||||
|
pkgs.networkmanager
|
||||||
|
pkgs.gawk
|
||||||
|
pkgs.gnused
|
||||||
|
pkgs.jq
|
||||||
|
];
|
||||||
|
bluetooth = mkScript "bluetooth" [
|
||||||
|
pkgs.bluez
|
||||||
|
pkgs.coreutils
|
||||||
|
pkgs.findutils
|
||||||
|
pkgs.gawk
|
||||||
|
pkgs.jq
|
||||||
|
];
|
||||||
|
audio = mkScript "audio" [
|
||||||
|
pkgs.gawk
|
||||||
|
pkgs.jq
|
||||||
|
pkgs.wireplumber
|
||||||
|
];
|
||||||
|
panelToggle = mkScript "eww-panel" [
|
||||||
|
config.programs.eww.package
|
||||||
|
pkgs.jq
|
||||||
|
inputs.hyprland.packages.${pkgs.stdenv.hostPlatform.system}.hyprland
|
||||||
|
];
|
||||||
|
|
||||||
|
eww = lib.getExe config.programs.eww.package;
|
||||||
|
bluetoothctl = "${pkgs.bluez}/bin/bluetoothctl";
|
||||||
|
wpctl = "${pkgs.wireplumber}/bin/wpctl";
|
||||||
|
wpaperctl = "${pkgs.wpaperd}/bin/wpaperctl";
|
||||||
|
|
||||||
|
# setsid, and before the close rather than after it: eww kills the onclick
|
||||||
|
# handler's process group when the window it came from goes away, so a bare
|
||||||
|
# `close panel; cmd` never reaches cmd.
|
||||||
|
act = cmd: "${pkgs.util-linux}/bin/setsid --fork ${cmd}; ${eww} close panel";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
home.packages = [
|
||||||
|
panelToggle
|
||||||
|
pkgs.waypaper
|
||||||
|
];
|
||||||
|
|
||||||
|
programs.eww = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
systemd.enable = true;
|
||||||
|
|
||||||
|
yuckConfig = ''
|
||||||
|
;; Each script prints one JSON object; widgets read .icon / .label / .sub
|
||||||
|
;; off it.
|
||||||
|
(defpoll clock-time :interval "10s" :initial "--:--" `date +%H:%M`)
|
||||||
|
(defpoll clock-date :interval "1h" :initial "" `date "+%A, %d %B"`)
|
||||||
|
|
||||||
|
(defpoll battery
|
||||||
|
:interval "30s"
|
||||||
|
:initial '{"present":false,"icon":"","label":"","sub":""}'
|
||||||
|
`${lib.getExe battery}`)
|
||||||
|
|
||||||
|
(defpoll network
|
||||||
|
:interval "10s"
|
||||||
|
:initial '{"icon":"","label":"...","sub":""}'
|
||||||
|
`${lib.getExe network}`)
|
||||||
|
|
||||||
|
(defpoll bluetooth
|
||||||
|
:interval "10s"
|
||||||
|
:initial '{"powered":false,"icon":"","label":"...","sub":""}'
|
||||||
|
`${lib.getExe bluetooth}`)
|
||||||
|
|
||||||
|
(defpoll speaker
|
||||||
|
:interval "2s"
|
||||||
|
:initial '{"present":false,"volume":0,"muted":true,"icon":""}'
|
||||||
|
`${lib.getExe audio} sink`)
|
||||||
|
|
||||||
|
(defpoll mic
|
||||||
|
:interval "2s"
|
||||||
|
:initial '{"present":false,"volume":0,"muted":true,"icon":""}'
|
||||||
|
`${lib.getExe audio} source`)
|
||||||
|
|
||||||
|
(defwidget card [title]
|
||||||
|
(box :class "card" :orientation "v" :space-evenly false
|
||||||
|
(label :class "card-title" :halign "start" :text title :visible {title != ""})
|
||||||
|
(box :orientation "v" :space-evenly false
|
||||||
|
(children))))
|
||||||
|
|
||||||
|
(defwidget row [icon label sub onclick]
|
||||||
|
(eventbox :class "row" :cursor "pointer" :onclick onclick
|
||||||
|
(box :space-evenly false
|
||||||
|
(label :class "row-icon" :text icon)
|
||||||
|
(box :orientation "v" :space-evenly false :hexpand true
|
||||||
|
(label :class "row-label" :halign "start" :text label)
|
||||||
|
(label :class "row-sub" :halign "start" :text sub :visible {sub != ""})))))
|
||||||
|
|
||||||
|
;; Mute button, slider, readout. `state` is the speaker/mic json object.
|
||||||
|
(defwidget volume [state node]
|
||||||
|
(box :space-evenly false :visible {state.present}
|
||||||
|
(button :class {state.muted ? "mute muted" : "mute"}
|
||||||
|
:onclick "${wpctl} set-mute ''${node} toggle"
|
||||||
|
{state.icon})
|
||||||
|
(scale :class "slider" :hexpand true
|
||||||
|
:value {state.volume} :min 0 :max 101
|
||||||
|
:onchange "${wpctl} set-volume ''${node} {}%")
|
||||||
|
(label :class "row-sub" :text {"''${state.volume}%"})))
|
||||||
|
|
||||||
|
(defwidget action [icon tooltip onclick]
|
||||||
|
(button :class "action" :tooltip tooltip :onclick onclick icon))
|
||||||
|
|
||||||
|
(defwidget dashboard []
|
||||||
|
(box :class "dash" :orientation "v" :space-evenly false
|
||||||
|
|
||||||
|
(box :space-evenly false
|
||||||
|
|
||||||
|
(card :title ""
|
||||||
|
(label :class "clock-time" :halign "start" :text clock-time)
|
||||||
|
(label :class "clock-date" :halign "start" :text clock-date))
|
||||||
|
|
||||||
|
(card :title "System"
|
||||||
|
(box :visible {battery.present} :space-evenly false
|
||||||
|
(row :icon {battery.icon} :label {battery.label}
|
||||||
|
:sub {battery.sub} :onclick ""))
|
||||||
|
(row :icon {network.icon} :label {network.label} :sub {network.sub}
|
||||||
|
:onclick "${act "${pkgs.networkmanagerapplet}/bin/nm-connection-editor"}")
|
||||||
|
(row :icon {bluetooth.icon} :label {bluetooth.label} :sub {bluetooth.sub}
|
||||||
|
:onclick "${act "${pkgs.blueman}/bin/blueman-manager"}")))
|
||||||
|
|
||||||
|
(box :space-evenly false
|
||||||
|
|
||||||
|
(card :title "Audio"
|
||||||
|
(volume :state speaker :node "@DEFAULT_AUDIO_SINK@")
|
||||||
|
(volume :state mic :node "@DEFAULT_AUDIO_SOURCE@"))
|
||||||
|
|
||||||
|
(card :title "Actions"
|
||||||
|
(box :space-evenly false :halign "start"
|
||||||
|
(action :icon "" :tooltip "Next wallpaper"
|
||||||
|
:onclick "${wpaperctl} next")
|
||||||
|
(action :icon "" :tooltip "Pick wallpaper"
|
||||||
|
:onclick "${act "${lib.getExe pkgs.waypaper}"}")
|
||||||
|
(action :icon "" :tooltip "Toggle bluetooth"
|
||||||
|
:onclick {bluetooth.powered
|
||||||
|
? "${bluetoothctl} power off"
|
||||||
|
: "${bluetoothctl} power on"})
|
||||||
|
(action :icon "" :tooltip "Lock"
|
||||||
|
:onclick "${act "${pkgs.systemd}/bin/loginctl lock-session"}"))))))
|
||||||
|
|
||||||
|
;; Sized to its content. A full-screen backdrop would give click-outside-
|
||||||
|
;; to-close, but its handler also fires for clicks on the sliders.
|
||||||
|
(defwindow panel
|
||||||
|
:namespace "eww-panel"
|
||||||
|
:geometry (geometry :anchor "center")
|
||||||
|
:stacking "overlay"
|
||||||
|
(dashboard))
|
||||||
|
'';
|
||||||
|
|
||||||
|
scssConfig = ''
|
||||||
|
$bg: rgba(46, 52, 64, 0.96);
|
||||||
|
$card: rgba(59, 66, 82, 0.72);
|
||||||
|
$border: #4c566a;
|
||||||
|
$fg: #eceff4;
|
||||||
|
$muted: #81a1c1;
|
||||||
|
$accent: #88c0d0;
|
||||||
|
$red: #bf616a;
|
||||||
|
|
||||||
|
* {
|
||||||
|
all: unset;
|
||||||
|
font-family: "FiraCode Nerd Font", monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
window {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dash {
|
||||||
|
background-color: $bg;
|
||||||
|
border: ${px 1} solid $border;
|
||||||
|
border-radius: ${px 20};
|
||||||
|
padding: ${px 14};
|
||||||
|
color: $fg;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
background-color: $card;
|
||||||
|
border-radius: ${px 14};
|
||||||
|
padding: ${px 16};
|
||||||
|
margin: ${px 6};
|
||||||
|
min-width: ${px 300};
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-title {
|
||||||
|
font-size: ${px 11};
|
||||||
|
color: $muted;
|
||||||
|
margin-bottom: ${px 8};
|
||||||
|
}
|
||||||
|
|
||||||
|
.clock-time {
|
||||||
|
font-size: ${px 56};
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clock-date {
|
||||||
|
font-size: ${px 14};
|
||||||
|
color: $muted;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
border-radius: ${px 10};
|
||||||
|
padding: ${px 10} ${px 12};
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(136, 192, 208, 0.14);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.row-icon {
|
||||||
|
font-size: ${px 22};
|
||||||
|
color: $accent;
|
||||||
|
min-width: ${px 34};
|
||||||
|
}
|
||||||
|
|
||||||
|
.row-label {
|
||||||
|
font-size: ${px 14};
|
||||||
|
}
|
||||||
|
|
||||||
|
.row-sub {
|
||||||
|
font-size: ${px 11};
|
||||||
|
color: $muted;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mute {
|
||||||
|
font-size: ${px 20};
|
||||||
|
color: $accent;
|
||||||
|
min-width: ${px 34};
|
||||||
|
|
||||||
|
&.muted {
|
||||||
|
color: $red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider {
|
||||||
|
margin: 0 ${px 12};
|
||||||
|
min-width: ${px 180};
|
||||||
|
|
||||||
|
trough {
|
||||||
|
background-color: rgba(76, 86, 106, 0.6);
|
||||||
|
border-radius: ${px 8};
|
||||||
|
min-height: ${px 8};
|
||||||
|
|
||||||
|
highlight {
|
||||||
|
background-color: $accent;
|
||||||
|
border-radius: ${px 8};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.action {
|
||||||
|
background-color: rgba(76, 86, 106, 0.45);
|
||||||
|
border-radius: ${px 12};
|
||||||
|
padding: ${px 12} ${px 18};
|
||||||
|
margin-right: ${px 8};
|
||||||
|
font-size: ${px 20};
|
||||||
|
color: $fg;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: $accent;
|
||||||
|
color: #2e3440;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
# One JSON object per audio node. $1 is "sink" or "source". wpctl prints
|
||||||
|
# "Volume: 0.45", with " [MUTED]" appended, and errors when there is no node.
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
sink) node="@DEFAULT_AUDIO_SINK@" ;;
|
||||||
|
source) node="@DEFAULT_AUDIO_SOURCE@" ;;
|
||||||
|
*) echo "usage: audio sink|source" >&2; exit 2 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
raw=$(wpctl get-volume "$node" 2>/dev/null || true)
|
||||||
|
|
||||||
|
case "$raw" in
|
||||||
|
*Volume:*) ;;
|
||||||
|
*)
|
||||||
|
jq -nc '{ present: false, volume: 0, muted: true, icon: "" }'
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
volume=$(printf '%s' "$raw" | awk '{ printf "%d", $2 * 100 }')
|
||||||
|
|
||||||
|
muted=false
|
||||||
|
case "$raw" in *MUTED*) muted=true ;; esac
|
||||||
|
|
||||||
|
if [ "$1" = "source" ]; then
|
||||||
|
if [ "$muted" = true ]; then icon=""; else icon=""; fi
|
||||||
|
elif [ "$muted" = true ]; then icon=""
|
||||||
|
elif [ "$volume" -ge 66 ]; then icon=""
|
||||||
|
elif [ "$volume" -ge 33 ]; then icon=""
|
||||||
|
else icon=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
jq -nc \
|
||||||
|
--argjson volume "$volume" \
|
||||||
|
--argjson muted "$muted" \
|
||||||
|
--arg icon "$icon" \
|
||||||
|
'{ present: true, volume: $volume, muted: $muted, icon: $icon }'
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
# One JSON object for the panel's battery row. `present: false` on the desktops,
|
||||||
|
# which have no BAT* at all — the row hides itself on that.
|
||||||
|
|
||||||
|
bat=$(find /sys/class/power_supply -maxdepth 1 -name 'BAT*' 2>/dev/null | sort | head -1)
|
||||||
|
|
||||||
|
if [ -z "$bat" ]; then
|
||||||
|
jq -nc '{ present: false, icon: "", label: "", sub: "" }'
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
capacity=$(cat "$bat/capacity")
|
||||||
|
status=$(cat "$bat/status")
|
||||||
|
|
||||||
|
if [ "$status" = "Charging" ] || [ "$status" = "Full" ]; then
|
||||||
|
icon=""
|
||||||
|
elif [ "$capacity" -ge 90 ]; then icon=""
|
||||||
|
elif [ "$capacity" -ge 80 ]; then icon=""
|
||||||
|
elif [ "$capacity" -ge 70 ]; then icon=""
|
||||||
|
elif [ "$capacity" -ge 60 ]; then icon=""
|
||||||
|
elif [ "$capacity" -ge 50 ]; then icon=""
|
||||||
|
elif [ "$capacity" -ge 40 ]; then icon=""
|
||||||
|
elif [ "$capacity" -ge 30 ]; then icon=""
|
||||||
|
elif [ "$capacity" -ge 20 ]; then icon=""
|
||||||
|
elif [ "$capacity" -ge 10 ]; then icon=""
|
||||||
|
else icon=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
jq -nc \
|
||||||
|
--arg icon "$icon" \
|
||||||
|
--arg label "$capacity%" \
|
||||||
|
--arg sub "$status" \
|
||||||
|
'{ present: true, icon: $icon, label: $label, sub: $sub }'
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# One JSON object for the panel's bluetooth row. bluetoothctl blocks forever
|
||||||
|
# instead of erroring when there is no adapter, hence the /sys check + timeouts.
|
||||||
|
|
||||||
|
if [ -z "$(find /sys/class/bluetooth -mindepth 1 -maxdepth 1 2>/dev/null)" ]; then
|
||||||
|
jq -nc '{ powered: false, icon: "", label: "No adapter", sub: "" }'
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
powered=$(timeout 2 bluetoothctl show 2>/dev/null | awk '/Powered:/ { print $2; exit }' || true)
|
||||||
|
|
||||||
|
if [ "$powered" != "yes" ]; then
|
||||||
|
jq -nc '{ powered: false, icon: "", label: "Off", sub: "" }'
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
connected=$(timeout 2 bluetoothctl devices Connected 2>/dev/null | cut -d' ' -f3- | paste -sd', ' - || true)
|
||||||
|
|
||||||
|
if [ -n "$connected" ]; then
|
||||||
|
jq -nc --arg sub "$connected" '{ powered: true, icon: "", label: "On", sub: $sub }'
|
||||||
|
else
|
||||||
|
jq -nc '{ powered: true, icon: "", label: "On", sub: "Nothing connected" }'
|
||||||
|
fi
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# Toggle the panel on whichever monitor has focus. `eww open --toggle` can't do
|
||||||
|
# this: it ignores --screen when the window is already open elsewhere, so the
|
||||||
|
# panel would stay stuck on the monitor it first appeared on.
|
||||||
|
|
||||||
|
if eww active-windows | grep -q '^panel'; then
|
||||||
|
exec eww close panel
|
||||||
|
fi
|
||||||
|
|
||||||
|
screen=$(hyprctl -j monitors | jq -r 'map(select(.focused))[0].id // 0')
|
||||||
|
|
||||||
|
exec eww open panel --screen "$screen"
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
# One JSON object for the panel's network row. State must match "connected"
|
||||||
|
# exactly: NetworkManager reports docker0 and br-* as "connected (externally)".
|
||||||
|
|
||||||
|
status=$(nmcli -t -f TYPE,STATE,CONNECTION device status 2>/dev/null || true)
|
||||||
|
|
||||||
|
# nmcli's terse output backslash-escapes colons inside connection names, so
|
||||||
|
# rejoin fields 3..NF and unescape rather than taking $3.
|
||||||
|
pick() {
|
||||||
|
printf '%s\n' "$status" | awk -F: -v want="$1" '
|
||||||
|
$1 == want && $2 == "connected" {
|
||||||
|
name = $3
|
||||||
|
for (i = 4; i <= NF; i++) name = name ":" $i
|
||||||
|
print name
|
||||||
|
exit
|
||||||
|
}' | sed 's/\\:/:/g'
|
||||||
|
}
|
||||||
|
|
||||||
|
wifi=$(pick wifi)
|
||||||
|
ethernet=$(pick ethernet)
|
||||||
|
|
||||||
|
if [ -n "$wifi" ]; then
|
||||||
|
signal=$(nmcli -t -f IN-USE,SIGNAL dev wifi 2>/dev/null | awk -F: '$1 == "*" { print $2; exit }' || true)
|
||||||
|
|
||||||
|
if [ -z "$signal" ]; then icon=""
|
||||||
|
elif [ "$signal" -ge 75 ]; then icon=""
|
||||||
|
elif [ "$signal" -ge 50 ]; then icon=""
|
||||||
|
elif [ "$signal" -ge 25 ]; then icon=""
|
||||||
|
else icon=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$signal" ]; then
|
||||||
|
sub="Wi-Fi · $signal%"
|
||||||
|
else
|
||||||
|
sub="Wi-Fi"
|
||||||
|
fi
|
||||||
|
|
||||||
|
jq -nc --arg icon "$icon" --arg label "$wifi" --arg sub "$sub" \
|
||||||
|
'{ icon: $icon, label: $label, sub: $sub }'
|
||||||
|
elif [ -n "$ethernet" ]; then
|
||||||
|
jq -nc --arg label "$ethernet" '{ icon: "", label: $label, sub: "Ethernet" }'
|
||||||
|
else
|
||||||
|
jq -nc '{ icon: "", label: "Offline", sub: "" }'
|
||||||
|
fi
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
inputs,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
avatar = pkgs.fetchurl {
|
|
||||||
url = "https://github.com/naps62.png";
|
|
||||||
sha256 = "1ck11xg4rwcvn8dcc06ax7i9yfzy21v1n6h5mcjrkrici5sznlsv";
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
imports = [ inputs.noctalia.homeModules.default ];
|
|
||||||
|
|
||||||
# Noctalia v5 rewrote the config schema (TOML, snake_case, flat sections).
|
|
||||||
# The v4 settings (appLauncher.*, bar.widgets.*, controlCenter.shortcuts.*, etc.)
|
|
||||||
# have no v5 equivalents — most must now be tweaked through the in-shell
|
|
||||||
# Settings UI. See docs.noctalia.dev/v5 and example.toml in the upstream repo.
|
|
||||||
programs.noctalia = {
|
|
||||||
enable = true;
|
|
||||||
settings = {
|
|
||||||
shell = {
|
|
||||||
font_family = "Sans Serif";
|
|
||||||
avatar_path = "${config.home.homeDirectory}/.face";
|
|
||||||
telemetry_enabled = false;
|
|
||||||
polkit_agent = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
wallpaper = {
|
|
||||||
enabled = true;
|
|
||||||
fill_mode = "crop";
|
|
||||||
directory = "${config.home.homeDirectory}/.cache/wallpapers/3840x2160";
|
|
||||||
transition = [ "fade" ];
|
|
||||||
transition_duration = 1500;
|
|
||||||
automation = {
|
|
||||||
enabled = true;
|
|
||||||
interval_minutes = 360;
|
|
||||||
order = "random";
|
|
||||||
recursive = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
theme = {
|
|
||||||
mode = "dark";
|
|
||||||
source = "builtin";
|
|
||||||
builtin = "Nord";
|
|
||||||
templates = {
|
|
||||||
enable_builtin_templates = true;
|
|
||||||
builtin_ids = [
|
|
||||||
"btop"
|
|
||||||
"gtk3"
|
|
||||||
"gtk4"
|
|
||||||
"hyprland"
|
|
||||||
"qt"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
notification.enable_daemon = true;
|
|
||||||
|
|
||||||
weather = {
|
|
||||||
enabled = true;
|
|
||||||
unit = "celsius";
|
|
||||||
};
|
|
||||||
|
|
||||||
location = {
|
|
||||||
auto_locate = false;
|
|
||||||
address = "Braga, Portugal";
|
|
||||||
};
|
|
||||||
|
|
||||||
nightlight = {
|
|
||||||
enabled = true;
|
|
||||||
temperature_day = 6500;
|
|
||||||
temperature_night = 4000;
|
|
||||||
};
|
|
||||||
|
|
||||||
bar.main = {
|
|
||||||
position = "top";
|
|
||||||
background_opacity = 0.93;
|
|
||||||
radius = 12;
|
|
||||||
start = [ "launcher" "wallpaper" "workspaces" ];
|
|
||||||
center = [ "media" "clock" ];
|
|
||||||
end = [ "tray" "notifications" "network" "bluetooth" "volume" "brightness" "battery" "control-center" "session" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
home.file.".face".source = avatar;
|
|
||||||
|
|
||||||
# force overwrite files that noctalia may have turned into regular files
|
|
||||||
# (Hyprland 0.55+ is Lua-only, so the managed file is now hyprland.lua)
|
|
||||||
xdg.configFile."hypr/hyprland.lua".force = true;
|
|
||||||
xdg.configFile."gtk-3.0/gtk.css".force = true;
|
|
||||||
|
|
||||||
# NOTE: noctalia still writes its color theme to ~/.config/hypr/noctalia.conf
|
|
||||||
# in *hyprlang* syntax ($primary = rgb(...), general { col.active_border = ... }).
|
|
||||||
# Hyprland 0.55+ dropped the hyprlang parser entirely, so that file can no
|
|
||||||
# longer be `source`d — there is no hl.source, and the lua config can't parse
|
|
||||||
# hyprlang. Hyprland therefore uses the static border colors from
|
|
||||||
# ../default.nix instead of noctalia's themed ones. To restore live theming,
|
|
||||||
# noctalia would need to emit a Lua snippet we can require() here.
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
programs.fuzzel = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
main = {
|
||||||
|
terminal = "${pkgs.kitty}/bin/kitty";
|
||||||
|
layer = "overlay";
|
||||||
|
font = "FiraCode Nerd Font:size=12";
|
||||||
|
icon-theme = "Tela black";
|
||||||
|
lines = 12;
|
||||||
|
width = 40;
|
||||||
|
inner-pad = 8;
|
||||||
|
};
|
||||||
|
border = {
|
||||||
|
radius = 12;
|
||||||
|
width = 1;
|
||||||
|
};
|
||||||
|
colors = {
|
||||||
|
background = "2e3440f0";
|
||||||
|
text = "eceff4ff";
|
||||||
|
match = "88c0d0ff";
|
||||||
|
selection = "434c5eff";
|
||||||
|
selection-text = "eceff4ff";
|
||||||
|
border = "4c566aff";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.mako = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
font = "FiraCode Nerd Font 11";
|
||||||
|
background-color = "#2e3440f0";
|
||||||
|
text-color = "#eceff4";
|
||||||
|
border-color = "#4c566a";
|
||||||
|
border-radius = 12;
|
||||||
|
border-size = 1;
|
||||||
|
padding = "14";
|
||||||
|
margin = "12";
|
||||||
|
default-timeout = 6000;
|
||||||
|
anchor = "top-right";
|
||||||
|
layer = "overlay";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# swayosd: the on-screen volume/brightness/caps-lock popup. Noctalia drew this
|
||||||
|
# before; without it the XF86 keys still work but give no feedback, which reads
|
||||||
|
# as "the keys are dead". swayosd-client does the change *and* the popup, so the
|
||||||
|
# binds in default.nix call it instead of wpctl/brightnessctl directly.
|
||||||
|
services.swayosd = {
|
||||||
|
enable = true;
|
||||||
|
topMargin = 0.85;
|
||||||
|
stylePath = pkgs.writeText "swayosd-style.css" ''
|
||||||
|
window#osd {
|
||||||
|
padding: 12px 20px;
|
||||||
|
border-radius: 12px;
|
||||||
|
border: 1px solid #4c566a;
|
||||||
|
background: alpha(#2e3440, 0.94);
|
||||||
|
}
|
||||||
|
|
||||||
|
window#osd #container { margin: 12px; }
|
||||||
|
|
||||||
|
window#osd image,
|
||||||
|
window#osd label { color: #eceff4; }
|
||||||
|
|
||||||
|
window#osd progressbar:disabled { opacity: 0.5; }
|
||||||
|
|
||||||
|
window#osd trough {
|
||||||
|
min-height: 6px;
|
||||||
|
border-radius: 6px;
|
||||||
|
background: #434c5e;
|
||||||
|
}
|
||||||
|
|
||||||
|
window#osd progress {
|
||||||
|
min-height: 6px;
|
||||||
|
border-radius: 6px;
|
||||||
|
background: #88c0d0;
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
services.hyprpolkitagent.enable = true;
|
||||||
|
}
|
||||||
@@ -1,5 +1,10 @@
|
|||||||
{ pkgs, ... }:
|
{ config, pkgs, ... }:
|
||||||
let
|
let
|
||||||
|
cfg = config.custom.hyprland;
|
||||||
|
|
||||||
|
horizontalDir = "${config.home.homeDirectory}/.cache/wallpapers/3840x2160";
|
||||||
|
verticalDir = "${config.home.homeDirectory}/.cache/wallpapers/2160x3840";
|
||||||
|
|
||||||
# Horizontal wallpapers (3840x2160) for HDMI-A-1 and DP-1
|
# Horizontal wallpapers (3840x2160) for HDMI-A-1 and DP-1
|
||||||
# Just add any image URL you want here
|
# Just add any image URL you want here
|
||||||
horizontal = [
|
horizontal = [
|
||||||
@@ -107,4 +112,25 @@ let
|
|||||||
in
|
in
|
||||||
{
|
{
|
||||||
home.file.".local/bin/wallpaper-fetch".source = fetchScript;
|
home.file.".local/bin/wallpaper-fetch".source = fetchScript;
|
||||||
|
|
||||||
|
# `any` covers every output not named in custom.hyprland.verticalOutputs,
|
||||||
|
# which get the portrait set instead.
|
||||||
|
services.wpaperd = {
|
||||||
|
enable = true;
|
||||||
|
settings =
|
||||||
|
{
|
||||||
|
default = {
|
||||||
|
duration = "6h";
|
||||||
|
sorting = "random";
|
||||||
|
mode = "center";
|
||||||
|
};
|
||||||
|
any.path = horizontalDir;
|
||||||
|
}
|
||||||
|
// builtins.listToAttrs (
|
||||||
|
map (output: {
|
||||||
|
name = output;
|
||||||
|
value.path = verticalDir;
|
||||||
|
}) cfg.verticalOutputs
|
||||||
|
);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ in
|
|||||||
{
|
{
|
||||||
programs.kitty = {
|
programs.kitty = {
|
||||||
enable = true;
|
enable = true;
|
||||||
# Fixed theme — noctalia no longer toggles kitty with dark/light mode.
|
# Fixed theme — nothing toggles kitty with dark/light mode.
|
||||||
themeFile = "Catppuccin-Mocha";
|
themeFile = "Catppuccin-Mocha";
|
||||||
settings = {
|
settings = {
|
||||||
confirm_os_window_close = 0;
|
confirm_os_window_close = 0;
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{ inputs, ... }:
|
||||||
|
# Maestro: the terminal-session orchestrator. Module only — no `enable` here,
|
||||||
|
# because the daemon owns every interactive shell on the host it runs on, and
|
||||||
|
# only one box should be doing that. Hosts opt in from their own services.nix.
|
||||||
|
{
|
||||||
|
imports = [ inputs.maestro.homeManagerModules.default ];
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
cfg = config.custom.mpv;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.custom.mpv = {
|
||||||
|
hwdec = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "auto-safe";
|
||||||
|
example = "nvdec-copy";
|
||||||
|
description = ''
|
||||||
|
Value for mpv's `hwdec`. `auto-safe` only picks a decoder mpv considers
|
||||||
|
reliable for the running driver and falls back to software otherwise,
|
||||||
|
so it is correct on Intel (arrakis) and on hosts with no usable GPU
|
||||||
|
decoder (yolo). NVIDIA hosts override it.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = {
|
||||||
|
programs.mpv = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
config = {
|
||||||
|
hwdec = cfg.hwdec;
|
||||||
|
vo = lib.mkDefault "gpu-next";
|
||||||
|
save-position-on-quit = true;
|
||||||
|
keep-open = "yes";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,198 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
# nix-autodeploy: one webhook endpoint that turns "a repo I own pushed to main"
|
||||||
|
# into "that flake input is bumped, committed, and (optionally) applied".
|
||||||
|
#
|
||||||
|
# Replaces per-app deploy webhooks that rebuilt from a checkout on the box. The
|
||||||
|
# apps are flake inputs now, so deploying one is a lock bump plus a generation
|
||||||
|
# switch — the same operation for every app, hence one service instead of N.
|
||||||
|
let
|
||||||
|
cfg = config.services.nixAutodeploy;
|
||||||
|
|
||||||
|
# A user unit inherits almost no PATH, and the deploy shells out to git (with
|
||||||
|
# the gitea credential helper), nix and nh.
|
||||||
|
profilePath = lib.concatStringsSep ":" [
|
||||||
|
"%h/.local/bin"
|
||||||
|
"%h/.nix-profile/bin"
|
||||||
|
"/etc/profiles/per-user/%u/bin"
|
||||||
|
"/run/current-system/sw/bin"
|
||||||
|
];
|
||||||
|
|
||||||
|
deploy = pkgs.writeShellApplication {
|
||||||
|
name = "nix-autodeploy-deploy";
|
||||||
|
runtimeInputs = [
|
||||||
|
pkgs.git
|
||||||
|
pkgs.nix
|
||||||
|
pkgs.nh
|
||||||
|
pkgs.curl
|
||||||
|
pkgs.jq
|
||||||
|
pkgs.util-linux
|
||||||
|
];
|
||||||
|
text = ''
|
||||||
|
# usage: nix-autodeploy-deploy <flake-input> <apply|notify>
|
||||||
|
input=$1
|
||||||
|
mode=$2
|
||||||
|
flake=${lib.escapeShellArg cfg.flake}
|
||||||
|
topic=${lib.escapeShellArg cfg.ntfy.topic}
|
||||||
|
ntfy_url=${lib.escapeShellArg cfg.ntfy.url}
|
||||||
|
|
||||||
|
notify() {
|
||||||
|
[ -n "''${NTFY_TOKEN:-}" ] || return 0
|
||||||
|
curl -fsS -X POST "$ntfy_url/$topic" \
|
||||||
|
-H "Authorization: Bearer $NTFY_TOKEN" \
|
||||||
|
-H "Title: $1" -d "$2" > /dev/null || true
|
||||||
|
}
|
||||||
|
|
||||||
|
# Serialize: two pushes landing together would otherwise race on the same
|
||||||
|
# working tree and the same flake.lock.
|
||||||
|
exec 9> "''${XDG_RUNTIME_DIR:-/tmp}/nix-autodeploy.lock"
|
||||||
|
flock 9
|
||||||
|
|
||||||
|
cd "$flake"
|
||||||
|
|
||||||
|
branch=$(git rev-parse --abbrev-ref HEAD)
|
||||||
|
if [ "$branch" != main ]; then
|
||||||
|
notify "autodeploy skipped ($input)" "checkout is on $branch, not main"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
if ! git diff --quiet || ! git diff --cached --quiet; then
|
||||||
|
notify "autodeploy skipped ($input)" "working tree is dirty"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
git fetch --quiet origin main
|
||||||
|
git merge --ff-only --quiet origin/main
|
||||||
|
|
||||||
|
nix flake update "$input"
|
||||||
|
if git diff --quiet -- flake.lock; then
|
||||||
|
echo "autodeploy: $input already at the pushed revision"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
rev=$(nix flake metadata --json |
|
||||||
|
jq -r --arg i "$input" '.locks.nodes[$i].locked.rev[0:7]')
|
||||||
|
git commit --quiet -m "chore(flake): bump $input to $rev" -- flake.lock
|
||||||
|
git push --quiet origin main
|
||||||
|
|
||||||
|
if [ "$mode" != apply ]; then
|
||||||
|
notify "$input bumped to $rev" "Not applied — run 'nh home switch' when convenient."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if nh home switch "$flake"; then
|
||||||
|
notify "$input deployed" "Bumped to $rev and switched."
|
||||||
|
else
|
||||||
|
notify "$input FAILED to apply" "Lock is at $rev on main; the switch failed. See journalctl --user -u run-*."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
listener = pkgs.writers.writePython3Bin "nix-autodeploy" {
|
||||||
|
# Only line length: http.server's do_GET/do_POST spelling is already
|
||||||
|
# excused inline.
|
||||||
|
flakeIgnore = [ "E501" ];
|
||||||
|
} (builtins.readFile ./listener.py);
|
||||||
|
|
||||||
|
repoFile = (pkgs.formats.json { }).generate "nix-autodeploy-repos.json" (
|
||||||
|
lib.mapAttrs (_: r: { inherit (r) input apply; }) cfg.repos
|
||||||
|
);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.services.nixAutodeploy = {
|
||||||
|
enable = lib.mkEnableOption "the forge-webhook listener that bumps and applies flake inputs";
|
||||||
|
|
||||||
|
port = lib.mkOption {
|
||||||
|
type = lib.types.port;
|
||||||
|
default = 7375;
|
||||||
|
description = "Port the listener binds on 0.0.0.0. There is no auth beyond the webhook HMAC, so only expose it through the reverse proxy.";
|
||||||
|
};
|
||||||
|
|
||||||
|
flake = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
example = "/home/naps62/tea/nixos-config";
|
||||||
|
description = "Absolute path to the nixos-config checkout whose flake.lock gets bumped. Must be on main and clean, or the deploy skips.";
|
||||||
|
};
|
||||||
|
|
||||||
|
environmentFile = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
example = "%h/.config/nix-autodeploy/env";
|
||||||
|
description = ''
|
||||||
|
File holding `NIX_AUTODEPLOY_SECRET` (the webhook HMAC secret, shared
|
||||||
|
with every repo below) and `NTFY_TOKEN`. Not in the store — these are
|
||||||
|
secrets.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
ntfy = {
|
||||||
|
url = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "https://ntfy.home.naps.pt";
|
||||||
|
description = "Base URL of the ntfy server deploy results are posted to.";
|
||||||
|
};
|
||||||
|
topic = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "nix-autodeploy";
|
||||||
|
description = "ntfy topic for deploy results.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
repos = lib.mkOption {
|
||||||
|
default = { };
|
||||||
|
description = "Forge repositories to listen for, keyed by `<owner>/<repo>` exactly as the webhook payload spells it.";
|
||||||
|
example = lib.literalExpression ''
|
||||||
|
{ "yolo/rev" = { input = "rev"; }; }
|
||||||
|
'';
|
||||||
|
type = lib.types.attrsOf (
|
||||||
|
lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
input = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "Name of the flake input in this repo's flake.nix that tracks that repository.";
|
||||||
|
};
|
||||||
|
apply = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
description = ''
|
||||||
|
Whether to run `nh home switch` after the bump. Set false for an
|
||||||
|
app whose restart disrupts a live session — the lock is still
|
||||||
|
bumped and pushed, and the ntfy message says it is waiting.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
systemd.user.services.nix-autodeploy = {
|
||||||
|
Unit = {
|
||||||
|
Description = "nix-autodeploy — forge webhooks bump and apply flake inputs";
|
||||||
|
After = [ "network.target" ];
|
||||||
|
# Same restart-budget trap every other always-on unit here avoids: at
|
||||||
|
# RestartSec=2 a fast-crashing listener would park in `failed`.
|
||||||
|
StartLimitIntervalSec = 0;
|
||||||
|
};
|
||||||
|
Service = {
|
||||||
|
Type = "simple";
|
||||||
|
ExecStart = lib.getExe listener;
|
||||||
|
EnvironmentFile = cfg.environmentFile;
|
||||||
|
Environment = [
|
||||||
|
"PATH=${profilePath}"
|
||||||
|
"NIX_AUTODEPLOY_PORT=${toString cfg.port}"
|
||||||
|
"NIX_AUTODEPLOY_DEPLOY_BIN=${lib.getExe deploy}"
|
||||||
|
"NIX_AUTODEPLOY_ENV_FILE=${cfg.environmentFile}"
|
||||||
|
"NIX_AUTODEPLOY_REPOS_FILE=${repoFile}"
|
||||||
|
];
|
||||||
|
Restart = "always";
|
||||||
|
RestartSec = 2;
|
||||||
|
};
|
||||||
|
Install.WantedBy = [ "default.target" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
"""Forge webhook listener that turns a push into a flake-input bump.
|
||||||
|
|
||||||
|
Verifies the HMAC a Gitea (or GitHub) webhook signs the body with, then hands
|
||||||
|
the actual work to a transient systemd unit. Nothing is done in-process: the
|
||||||
|
deploy runs `nh home switch`, which restarts every unit home-manager owns —
|
||||||
|
including this listener — so the job has to outlive it.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
import hmac
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
||||||
|
|
||||||
|
SECRET = os.environ.get("NIX_AUTODEPLOY_SECRET", "").encode()
|
||||||
|
PORT = int(os.environ.get("NIX_AUTODEPLOY_PORT", "7375"))
|
||||||
|
DEPLOY = os.environ["NIX_AUTODEPLOY_DEPLOY_BIN"]
|
||||||
|
# {"<owner>/<repo>": {"input": "rev", "apply": true}, ...}. Passed as a file,
|
||||||
|
# not a variable: systemd's Environment= strips the quotes out of inline JSON.
|
||||||
|
with open(os.environ["NIX_AUTODEPLOY_REPOS_FILE"]) as fh:
|
||||||
|
REPOS = json.load(fh)
|
||||||
|
ENV_FILE = os.environ.get("NIX_AUTODEPLOY_ENV_FILE", "")
|
||||||
|
MAX_BODY = 1 << 20
|
||||||
|
|
||||||
|
if not SECRET:
|
||||||
|
sys.exit("NIX_AUTODEPLOY_SECRET is not set")
|
||||||
|
|
||||||
|
|
||||||
|
def signature_ok(body: bytes, headers) -> bool:
|
||||||
|
expected = hmac.new(SECRET, body, hashlib.sha256).hexdigest()
|
||||||
|
# Gitea sends the bare hex digest; GitHub prefixes it with "sha256=".
|
||||||
|
for name in ("X-Gitea-Signature", "X-Hub-Signature-256"):
|
||||||
|
got = headers.get(name)
|
||||||
|
if got and hmac.compare_digest(got.removeprefix("sha256="), expected):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def spawn(repo: str, entry: dict) -> None:
|
||||||
|
cmd = [
|
||||||
|
"systemd-run",
|
||||||
|
"--user",
|
||||||
|
"--collect",
|
||||||
|
f"--description=nix-autodeploy: {repo}",
|
||||||
|
# PATH is not inherited by a transient unit, and the deploy shells out
|
||||||
|
# to git, nix and the gitea credential helper.
|
||||||
|
f"--setenv=PATH={os.environ['PATH']}",
|
||||||
|
]
|
||||||
|
if ENV_FILE:
|
||||||
|
cmd.append(f"--property=EnvironmentFile={ENV_FILE}")
|
||||||
|
cmd += [DEPLOY, entry["input"], "apply" if entry.get("apply", True) else "notify"]
|
||||||
|
subprocess.run(cmd, check=True)
|
||||||
|
|
||||||
|
|
||||||
|
class Handler(BaseHTTPRequestHandler):
|
||||||
|
def reply(self, code: int, text: str) -> None:
|
||||||
|
payload = text.encode()
|
||||||
|
self.send_response(code)
|
||||||
|
self.send_header("Content-Type", "text/plain")
|
||||||
|
self.send_header("Content-Length", str(len(payload)))
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(payload)
|
||||||
|
|
||||||
|
def do_GET(self) -> None: # noqa: N802 - BaseHTTPRequestHandler's spelling
|
||||||
|
if self.path == "/health":
|
||||||
|
self.reply(200, "ok\n")
|
||||||
|
else:
|
||||||
|
self.reply(404, "no\n")
|
||||||
|
|
||||||
|
def do_POST(self) -> None: # noqa: N802
|
||||||
|
length = int(self.headers.get("Content-Length", "0"))
|
||||||
|
if length > MAX_BODY:
|
||||||
|
return self.reply(413, "body too large\n")
|
||||||
|
body = self.rfile.read(length)
|
||||||
|
|
||||||
|
if not signature_ok(body, self.headers):
|
||||||
|
return self.reply(401, "bad signature\n")
|
||||||
|
|
||||||
|
try:
|
||||||
|
event = json.loads(body)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
return self.reply(400, "bad json\n")
|
||||||
|
|
||||||
|
ref = event.get("ref")
|
||||||
|
repo = (event.get("repository") or {}).get("full_name")
|
||||||
|
if ref != "refs/heads/main":
|
||||||
|
return self.reply(200, f"ignored ref {ref}\n")
|
||||||
|
|
||||||
|
entry = REPOS.get(repo)
|
||||||
|
if entry is None:
|
||||||
|
return self.reply(200, f"ignored repo {repo}\n")
|
||||||
|
|
||||||
|
spawn(repo, entry)
|
||||||
|
self.reply(202, f"deploying {entry['input']}\n")
|
||||||
|
|
||||||
|
def log_message(self, fmt: str, *args) -> None:
|
||||||
|
# Journal already timestamps; the default format prepends its own.
|
||||||
|
sys.stderr.write(f"{self.address_string()} {fmt % args}\n")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
ThreadingHTTPServer(("0.0.0.0", PORT), Handler).serve_forever()
|
||||||
@@ -1 +0,0 @@
|
|||||||
Screenshots: stored in ~/downloads/screenshots, with date time in the filename
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
---
|
|
||||||
description: Merge worktree changes and clean up safely
|
|
||||||
---
|
|
||||||
|
|
||||||
# Merge Worktree and Cleanup
|
|
||||||
|
|
||||||
Merge changes from the current worktree into a target branch and clean up the worktree.
|
|
||||||
|
|
||||||
**Usage:** `/merge [target-branch]`
|
|
||||||
|
|
||||||
**Arguments:**
|
|
||||||
- `$1`: Target branch to merge into (default: auto-detect main/master)
|
|
||||||
|
|
||||||
## Process
|
|
||||||
|
|
||||||
### 1. Pre-flight Checks
|
|
||||||
|
|
||||||
```bash
|
|
||||||
CURRENT_BRANCH=$(git branch --show-current)
|
|
||||||
WORKTREE_DIR=$(git rev-parse --git-common-dir)
|
|
||||||
|
|
||||||
if [[ ! "$WORKTREE_DIR" == *".git/worktrees"* ]]; then
|
|
||||||
echo "❌ Error: You're not in a worktree"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! git diff-index --quiet HEAD --; then
|
|
||||||
echo "❌ Error: You have uncommitted changes"
|
|
||||||
git status --short
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Determine Target Branch
|
|
||||||
|
|
||||||
```bash
|
|
||||||
TARGET_BRANCH="${1:-}"
|
|
||||||
if [ -z "$TARGET_BRANCH" ]; then
|
|
||||||
if git show-ref --verify --quiet refs/heads/main; then
|
|
||||||
TARGET_BRANCH="main"
|
|
||||||
elif git show-ref --verify --quiet refs/heads/master; then
|
|
||||||
TARGET_BRANCH="master"
|
|
||||||
else
|
|
||||||
echo "❌ Error: Cannot auto-detect main branch"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Update Target Branch
|
|
||||||
|
|
||||||
```bash
|
|
||||||
WORKTREE_PATH=$(pwd)
|
|
||||||
COMMON_DIR=$(git rev-parse --git-common-dir)
|
|
||||||
REPO_ROOT=$(echo "$COMMON_DIR" | sed 's/\.git.*//' | sed 's/\/$//')
|
|
||||||
if [ "$COMMON_DIR" = ".git" ]; then
|
|
||||||
REPO_ROOT=$(git rev-parse --show-toplevel)
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd "$REPO_ROOT"
|
|
||||||
git checkout "$TARGET_BRANCH"
|
|
||||||
git pull origin "$TARGET_BRANCH"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Merge
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git merge --no-ff "$CURRENT_BRANCH" -m "Merge branch '$CURRENT_BRANCH'"
|
|
||||||
```
|
|
||||||
|
|
||||||
If you prefer a squash merge, do this instead:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git merge --squash "$CURRENT_BRANCH"
|
|
||||||
git commit -m "feat: <summary>"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. Push and Clean Up
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git push origin "$TARGET_BRANCH"
|
|
||||||
|
|
||||||
git worktree remove "$WORKTREE_PATH" --force || rm -rf "$WORKTREE_PATH"
|
|
||||||
git branch -d "$CURRENT_BRANCH" || git branch -D "$CURRENT_BRANCH"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6. Optional: Delete Remote Branch
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git push origin --delete "$CURRENT_BRANCH"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Language-specific checks
|
|
||||||
|
|
||||||
### Rust
|
|
||||||
- `cargo check`
|
|
||||||
- `cargo clippy` (clean up new warnings)
|
|
||||||
|
|
||||||
### TypeScript
|
|
||||||
- `tsc`
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
---
|
|
||||||
description: Rebase/merge upstream changes into the current branch
|
|
||||||
---
|
|
||||||
This command should only work while in a secondary branch (not main or master).
|
|
||||||
|
|
||||||
Commit any unstaged changes
|
|
||||||
Fetch updates from the origin repo
|
|
||||||
If there are new commits on the parent branch (typically origin/main), then merge them back into the current branch
|
|
||||||
Solve any conflicts, and analyze the incoming changes to see if additional changes are required to the branch's code (e.g.: if something was renamed in the meantime in main, our new code may need to be adjusted)
|
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
_:
|
_:
|
||||||
{
|
{
|
||||||
|
# Global rules (opencode/AGENTS.md) and the shared commands (merge, update)
|
||||||
|
# come from the agent-skills home-manager module — opencode has no @file
|
||||||
|
# imports, so the module concatenates the shared fragments into one file.
|
||||||
|
# opencode also auto-loads skills from ~/.claude/skills and ~/.agents/skills.
|
||||||
xdg.configFile = {
|
xdg.configFile = {
|
||||||
# Global config file
|
# Global config file
|
||||||
"opencode/opencode.json".source = ./opencode.json;
|
"opencode/opencode.json".source = ./opencode.json;
|
||||||
|
|
||||||
# Global rules (equivalent to ~/.claude/CLAUDE.md)
|
|
||||||
"opencode/AGENTS.md".source = ./AGENTS.md;
|
|
||||||
|
|
||||||
# Custom agents
|
# Custom agents
|
||||||
"opencode/agents/oracle.md".source = ./agents/oracle.md;
|
"opencode/agents/oracle.md".source = ./agents/oracle.md;
|
||||||
"opencode/agents/explorer.md".source = ./agents/explorer.md;
|
"opencode/agents/explorer.md".source = ./agents/explorer.md;
|
||||||
@@ -16,10 +17,8 @@ _:
|
|||||||
"opencode/agents/designer-bold.md".source = ./agents/designer-bold.md;
|
"opencode/agents/designer-bold.md".source = ./agents/designer-bold.md;
|
||||||
"opencode/agents/analyze-branch.md".source = ./agents/analyze-branch.md;
|
"opencode/agents/analyze-branch.md".source = ./agents/analyze-branch.md;
|
||||||
|
|
||||||
# Global commands
|
# Global commands (opencode-specific ones only)
|
||||||
"opencode/commands/work.md".source = ./commands/work.md;
|
"opencode/commands/work.md".source = ./commands/work.md;
|
||||||
"opencode/commands/merge.md".source = ./commands/merge.md;
|
|
||||||
"opencode/commands/update.md".source = ./commands/update.md;
|
|
||||||
"opencode/commands/smart-debug.md".source = ./commands/smart-debug.md;
|
"opencode/commands/smart-debug.md".source = ./commands/smart-debug.md;
|
||||||
"opencode/commands/tdd-cycle.md".source = ./commands/tdd-cycle.md;
|
"opencode/commands/tdd-cycle.md".source = ./commands/tdd-cycle.md;
|
||||||
"opencode/commands/security-scan.md".source = ./commands/security-scan.md;
|
"opencode/commands/security-scan.md".source = ./commands/security-scan.md;
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
let
|
||||||
|
pi = pkgs.callPackage ../../../pkgs/pi/package.nix { };
|
||||||
|
in
|
||||||
|
{
|
||||||
|
# ~/.pi/agent/AGENTS.md comes from the agent-skills home-manager module
|
||||||
|
# (pi has no @file imports, so the module concatenates the shared fragments).
|
||||||
|
# Pi reads skills straight from ~/.agents/skills, which the module links.
|
||||||
|
# Settings stay unmanaged: pi writes ~/.pi/agent/settings.json itself from
|
||||||
|
# /settings, /trust and `pi config`.
|
||||||
|
home.packages = [ pi ];
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{ inputs, ... }:
|
||||||
|
# rev: the always-on code review server. Module only — no `enable` here. It
|
||||||
|
# discovers every repo under its roots and serves them without auth, so only a
|
||||||
|
# box that is already a trusted single-user machine should run it.
|
||||||
|
{
|
||||||
|
imports = [ inputs.rev.homeManagerModules.default ];
|
||||||
|
}
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
# T3 Code: open-source desktop control plane for coding agents (x86_64 only).
|
|
||||||
# Shares the custom.aiApps.deviceScaleFactor knob (defined in ../claude).
|
|
||||||
t3-code = pkgs.callPackage ../../../pkgs/t3-code/package.nix {
|
|
||||||
inherit (config.custom.aiApps) deviceScaleFactor;
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
home.packages = lib.optional pkgs.stdenv.hostPlatform.isx86_64 t3-code;
|
|
||||||
}
|
|
||||||
@@ -30,6 +30,7 @@ set -ag terminal-overrides ",xterm*:Tc:smcup@:rmcup@"
|
|||||||
|
|
||||||
# Forward Shift+Enter and other modified keys through to applications
|
# Forward Shift+Enter and other modified keys through to applications
|
||||||
set -s extended-keys on
|
set -s extended-keys on
|
||||||
|
set -s extended-keys-format csi-u
|
||||||
set -as terminal-features "tmux-256color:extkeys"
|
set -as terminal-features "tmux-256color:extkeys"
|
||||||
|
|
||||||
# -------------------------------------------------------------------
|
# -------------------------------------------------------------------
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
imports = [ ./desktop/spicetify.nix ];
|
||||||
|
|
||||||
|
home.packages = with pkgs; [
|
||||||
|
obsidian
|
||||||
|
obs-studio
|
||||||
|
kooha
|
||||||
|
vokoscreen-ng
|
||||||
|
gimp
|
||||||
|
font-manager
|
||||||
|
xournalpp
|
||||||
|
remmina
|
||||||
|
slack
|
||||||
|
signal-desktop
|
||||||
|
zoom-us
|
||||||
|
yaak
|
||||||
|
bun
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -10,7 +10,18 @@
|
|||||||
enableCompletion = true;
|
enableCompletion = true;
|
||||||
autosuggestion.enable = true;
|
autosuggestion.enable = true;
|
||||||
syntaxHighlighting.enable = true;
|
syntaxHighlighting.enable = true;
|
||||||
completionInit = "autoload -U compinit && compinit -u";
|
# A full compinit security-checks and rebuilds the dump on every shell
|
||||||
|
# start. Do that at most once a day and use the cached dump (-C) in
|
||||||
|
# between. Missing dump globs to nothing, so it takes the full path.
|
||||||
|
completionInit = ''
|
||||||
|
autoload -U compinit
|
||||||
|
_zcompdump_fresh() {
|
||||||
|
setopt local_options extendedglob
|
||||||
|
[[ -n ''${ZDOTDIR:-$HOME}/.zcompdump(#qNmh-24) ]]
|
||||||
|
}
|
||||||
|
if _zcompdump_fresh; then compinit -C; else compinit -u; fi
|
||||||
|
unfunction _zcompdump_fresh
|
||||||
|
'';
|
||||||
|
|
||||||
shellAliases = {
|
shellAliases = {
|
||||||
c = "cargo";
|
c = "cargo";
|
||||||
|
|||||||
@@ -5,6 +5,10 @@
|
|||||||
imports = [
|
imports = [
|
||||||
../common/programs/default.nix
|
../common/programs/default.nix
|
||||||
../common/programs/desktop
|
../common/programs/desktop
|
||||||
|
../common/programs/workstation-apps.nix
|
||||||
|
../common/programs/editors.nix
|
||||||
|
../common/programs/dev-workstation.nix
|
||||||
|
../common/programs/ai-gui.nix
|
||||||
../common/programs/zen-browser.nix
|
../common/programs/zen-browser.nix
|
||||||
../common/programs/hyprland
|
../common/programs/hyprland
|
||||||
../common/programs/kitty
|
../common/programs/kitty
|
||||||
@@ -20,15 +24,31 @@
|
|||||||
|
|
||||||
home.sessionVariables = {
|
home.sessionVariables = {
|
||||||
LIBVA_DRIVER_NAME = "nvidia";
|
LIBVA_DRIVER_NAME = "nvidia";
|
||||||
GDM_BACKEND = "nvidia-drm";
|
# Was GDM_BACKEND, which nothing reads (SDDM is the DM here).
|
||||||
|
GBM_BACKEND = "nvidia-drm";
|
||||||
__GLX_VENDOR_LIBRARY_NAME = "nvidia";
|
__GLX_VENDOR_LIBRARY_NAME = "nvidia";
|
||||||
|
|
||||||
|
# Firefox/Zen decode video in a separate RDD process whose sandbox denies
|
||||||
|
# /dev/nvidia*, so nvidia-vaapi-driver never initialises there and playback
|
||||||
|
# silently drops to software. Costs one sandbox layer; no narrower switch
|
||||||
|
# exists. Check with `nvidia-smi --query-gpu=utilization.decoder`.
|
||||||
|
MOZ_DISABLE_RDD_SANDBOX = "1";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Plain `nvdec` keeps frames in GPU memory and breaks some filters.
|
||||||
|
custom.mpv.hwdec = "nvdec-copy";
|
||||||
|
|
||||||
|
# The 4060 would render Cycles far faster, but nothing caches this build —
|
||||||
|
# flipping it on compiles Blender, OpenUSD, OpenSubdiv and OpenImageDenoise.
|
||||||
|
custom.blender.cuda = false;
|
||||||
|
|
||||||
custom.hyprland = {
|
custom.hyprland = {
|
||||||
yaziSize = "2400 1800";
|
yaziSize = "2400 1800";
|
||||||
cursorSize = 42;
|
cursorSize = 42;
|
||||||
# The screen actually shared in every call; skips the xdph picker entirely.
|
# The screen actually shared in every call; skips the xdph picker entirely.
|
||||||
shareOutput = "HDMI-A-1";
|
shareOutput = "HDMI-A-1";
|
||||||
|
verticalOutputs = [ "DP-2" ];
|
||||||
|
panelScale = 1.6;
|
||||||
};
|
};
|
||||||
|
|
||||||
custom.gaming = {
|
custom.gaming = {
|
||||||
@@ -47,7 +67,6 @@
|
|||||||
-- session the moment Hyprland starts so a cold boot lands on hyprlock, not
|
-- session the moment Hyprland starts so a cold boot lands on hyprlock, not
|
||||||
-- an open desktop. A brief flash before it paints is possible.
|
-- an open desktop. A brief flash before it paints is possible.
|
||||||
hl.exec_cmd("hyprlock")
|
hl.exec_cmd("hyprlock")
|
||||||
hl.exec_cmd("$HOME/.local/bin/hyprpaper-rotate")
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- ethui-dev
|
-- ethui-dev
|
||||||
@@ -110,12 +129,5 @@
|
|||||||
hl.config({ render = { direct_scanout = false } })
|
hl.config({ render = { direct_scanout = false } })
|
||||||
'';
|
'';
|
||||||
|
|
||||||
programs.noctalia.settings = {
|
|
||||||
shell.ui_scale = 1.25;
|
|
||||||
notification.monitors = [ "DP-1" ];
|
|
||||||
# NOTE: v5 has no per-monitor wallpaper directories; only directory_light /
|
|
||||||
# directory_dark. Re-add via Settings UI if upstream gains support.
|
|
||||||
};
|
|
||||||
|
|
||||||
programs.kitty.settings.font_size = 16;
|
programs.kitty.settings.font_size = 16;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,141 +0,0 @@
|
|||||||
default_profile = "default"
|
|
||||||
|
|
||||||
[acp]
|
|
||||||
allow_agent_install = false
|
|
||||||
allowed_agents = []
|
|
||||||
auto_stop_idle_secs = 0
|
|
||||||
compaction_reminder = false
|
|
||||||
compaction_reminder_percent = 75
|
|
||||||
default_agent = "claude"
|
|
||||||
max_concurrent_workers = 5
|
|
||||||
node_path = ""
|
|
||||||
offer_structured_in_new_session = false
|
|
||||||
rate_limit_auto_resume = false
|
|
||||||
replay_events = 0
|
|
||||||
restrict_agents = false
|
|
||||||
show_tool_durations = true
|
|
||||||
silent_orphan_grace_secs = 120
|
|
||||||
|
|
||||||
[auth]
|
|
||||||
persist_sessions = true
|
|
||||||
|
|
||||||
[diff]
|
|
||||||
context_lines = 3
|
|
||||||
split_view = false
|
|
||||||
|
|
||||||
[hooks]
|
|
||||||
|
|
||||||
[host_hooks]
|
|
||||||
|
|
||||||
[logging]
|
|
||||||
default_level = "info"
|
|
||||||
file_path = "debug.log"
|
|
||||||
keep_count = 5
|
|
||||||
max_size_mib = 50
|
|
||||||
output = "file"
|
|
||||||
rotation = "size"
|
|
||||||
show_spans = false
|
|
||||||
|
|
||||||
[logging.targets]
|
|
||||||
|
|
||||||
[sandbox]
|
|
||||||
auto_cleanup = true
|
|
||||||
container_runtime = "docker"
|
|
||||||
default_image = "ghcr.io/agent-of-empires/aoe-sandbox:latest"
|
|
||||||
default_terminal_mode = "host"
|
|
||||||
enabled_by_default = false
|
|
||||||
environment = [
|
|
||||||
"TERM",
|
|
||||||
"COLORTERM",
|
|
||||||
"FORCE_COLOR",
|
|
||||||
"NO_COLOR",
|
|
||||||
]
|
|
||||||
extra_volumes = []
|
|
||||||
mount_ssh = false
|
|
||||||
selinux_relabel = false
|
|
||||||
volume_ignores = []
|
|
||||||
volume_ignores_strategy = "anonymous"
|
|
||||||
|
|
||||||
[session]
|
|
||||||
agent_status_hooks = true
|
|
||||||
auto_resume_on_restart = true
|
|
||||||
auto_stop_idle_secs = 0
|
|
||||||
click_action = "live_send"
|
|
||||||
confirm_before_quit = false
|
|
||||||
confirm_delete = false
|
|
||||||
conversation_summary = false
|
|
||||||
default_attach_mode = "tmux"
|
|
||||||
delete_to_trash = false
|
|
||||||
favorites_first = true
|
|
||||||
inherit_host_environment = false
|
|
||||||
live_send_exit_chord = "C-q"
|
|
||||||
live_send_leader = "C-b"
|
|
||||||
live_send_on_view_switch = false
|
|
||||||
merge_hooks_into_selected_agent = true
|
|
||||||
mouse_capture = true
|
|
||||||
opencode_preassign_session_id = false
|
|
||||||
prevent_sleep_idle_grace_minutes = 15
|
|
||||||
prevent_sleep_when_active = false
|
|
||||||
restart_wake_message = "wake up: pick up what you were doing"
|
|
||||||
row_tag = "none"
|
|
||||||
show_session_colors = true
|
|
||||||
show_tips = true
|
|
||||||
smart_rename = true
|
|
||||||
smart_rename_agent = ""
|
|
||||||
snooze_duration_minutes = 30
|
|
||||||
strict_hotkeys = false
|
|
||||||
tie_workdir_to_name = true
|
|
||||||
trash_retention_days = 30
|
|
||||||
unread_indicator = true
|
|
||||||
yolo_mode_default = true
|
|
||||||
|
|
||||||
[session.agent_detect_as]
|
|
||||||
kimiclaude = "claude"
|
|
||||||
synclaude = "claude"
|
|
||||||
|
|
||||||
[session.custom_agents]
|
|
||||||
kimiclaude = "kimiclaude"
|
|
||||||
synclaude = "synclaude"
|
|
||||||
|
|
||||||
[skills]
|
|
||||||
auto_propagate = false
|
|
||||||
|
|
||||||
[sound]
|
|
||||||
enabled = false
|
|
||||||
|
|
||||||
[status_hooks]
|
|
||||||
enabled = false
|
|
||||||
|
|
||||||
[telemetry]
|
|
||||||
enabled = false
|
|
||||||
|
|
||||||
[theme]
|
|
||||||
color_mode = "truecolor"
|
|
||||||
idle_decay_minutes = 0
|
|
||||||
name = ""
|
|
||||||
|
|
||||||
[tmux]
|
|
||||||
clipboard = "auto"
|
|
||||||
mouse = "auto"
|
|
||||||
status_bar = "auto"
|
|
||||||
vt_live = true
|
|
||||||
|
|
||||||
[updates]
|
|
||||||
auto_update_plugins = false
|
|
||||||
update_check_mode = "notify"
|
|
||||||
|
|
||||||
[web]
|
|
||||||
notifications_enabled = true
|
|
||||||
notify_on_error = true
|
|
||||||
notify_on_idle = false
|
|
||||||
notify_on_waiting = true
|
|
||||||
notify_on_wake_fire = true
|
|
||||||
|
|
||||||
[worktree]
|
|
||||||
auto_cleanup = true
|
|
||||||
bare_repo_path_template = "./{branch}"
|
|
||||||
delete_branch_on_cleanup = false
|
|
||||||
enabled = true
|
|
||||||
init_submodules = true
|
|
||||||
path_template = "../{repo-name}-worktrees/{branch}"
|
|
||||||
workspace_path_template = "../{branch}-workspace-{session-id}"
|
|
||||||
@@ -1,247 +0,0 @@
|
|||||||
{
|
|
||||||
"permissions": {
|
|
||||||
"allow": [
|
|
||||||
"Bash",
|
|
||||||
"Edit",
|
|
||||||
"Write",
|
|
||||||
"NotebookEdit",
|
|
||||||
"WebFetch",
|
|
||||||
"WebSearch"
|
|
||||||
],
|
|
||||||
"deny": [
|
|
||||||
"Read(~/.ssh/**)",
|
|
||||||
"Read(*.pem)",
|
|
||||||
"Read(*.key)",
|
|
||||||
"mcp__dokploy__application-one",
|
|
||||||
"mcp__dokploy__mounts-listByServiceId",
|
|
||||||
"mcp__dokploy__mounts-one",
|
|
||||||
"mcp__dokploy__compose-one",
|
|
||||||
"mcp__dokploy__schedule-create",
|
|
||||||
"mcp__dokploy__schedule-update",
|
|
||||||
"mcp__dokploy__schedule-runManually"
|
|
||||||
],
|
|
||||||
"defaultMode": "auto"
|
|
||||||
},
|
|
||||||
"hooks": {
|
|
||||||
"PostToolUse": [
|
|
||||||
{
|
|
||||||
"matcher": "Write|Edit|MultiEdit",
|
|
||||||
"hooks": [
|
|
||||||
{
|
|
||||||
"type": "command",
|
|
||||||
"command": "~/.claude/hooks/comment-lint.py"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"matcher": "AskUserQuestion",
|
|
||||||
"hooks": [
|
|
||||||
{
|
|
||||||
"type": "command",
|
|
||||||
"command": "sh -c 'unset IFS; set -f; umask 077; [ -n \"$AOE_INSTANCE_ID\" ] || exit 0; case \"$AOE_INSTANCE_ID\" in *[!0-9a-zA-Z_-]*) exit 0 ;; esac; B=/tmp/aoe-hooks-1000; mkdir -p \"$B\" 2>/dev/null || exit 0; LS=$(LC_ALL=C ls -ldn \"$B\" 2>/dev/null) || exit 0; set -- $LS; M=\"$1\"; case \"$M\" in drwx------|drwx------.|drwx------+|drwx------@) ;; *) exit 0 ;; esac; ME=$(id -u 2>/dev/null) || exit 0; [ \"$3\" = \"$ME\" ] || exit 0; D=\"$B/$AOE_INSTANCE_ID\"; mkdir -p \"$D\" 2>/dev/null; LS=$(LC_ALL=C ls -ldn \"$D\" 2>/dev/null) || exit 0; set -- $LS; M=\"$1\"; case \"$M\" in drwx------|drwx------.|drwx------+|drwx------@) ;; *) exit 0 ;; esac; [ \"$3\" = \"$ME\" ] || exit 0; printf running > \"$D/status\" 2>/dev/null; exit 0 # aoe-hooks'"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"Notification": [
|
|
||||||
{
|
|
||||||
"hooks": [
|
|
||||||
{
|
|
||||||
"type": "command",
|
|
||||||
"command": "~/.claude/hooks/tmux-attention.sh"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"matcher": "permission_prompt|elicitation_dialog|agent_needs_input",
|
|
||||||
"hooks": [
|
|
||||||
{
|
|
||||||
"type": "command",
|
|
||||||
"command": "sh -c 'unset IFS; set -f; umask 077; [ -n \"$AOE_INSTANCE_ID\" ] || exit 0; case \"$AOE_INSTANCE_ID\" in *[!0-9a-zA-Z_-]*) exit 0 ;; esac; B=/tmp/aoe-hooks-1000; mkdir -p \"$B\" 2>/dev/null || exit 0; LS=$(LC_ALL=C ls -ldn \"$B\" 2>/dev/null) || exit 0; set -- $LS; M=\"$1\"; case \"$M\" in drwx------|drwx------.|drwx------+|drwx------@) ;; *) exit 0 ;; esac; ME=$(id -u 2>/dev/null) || exit 0; [ \"$3\" = \"$ME\" ] || exit 0; D=\"$B/$AOE_INSTANCE_ID\"; mkdir -p \"$D\" 2>/dev/null; LS=$(LC_ALL=C ls -ldn \"$D\" 2>/dev/null) || exit 0; set -- $LS; M=\"$1\"; case \"$M\" in drwx------|drwx------.|drwx------+|drwx------@) ;; *) exit 0 ;; esac; [ \"$3\" = \"$ME\" ] || exit 0; printf waiting > \"$D/status\" 2>/dev/null; exit 0 # aoe-hooks'"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"matcher": "idle_prompt|agent_completed",
|
|
||||||
"hooks": [
|
|
||||||
{
|
|
||||||
"type": "command",
|
|
||||||
"command": "sh -c 'unset IFS; set -f; umask 077; [ -n \"$AOE_INSTANCE_ID\" ] || exit 0; case \"$AOE_INSTANCE_ID\" in *[!0-9a-zA-Z_-]*) exit 0 ;; esac; B=/tmp/aoe-hooks-1000; mkdir -p \"$B\" 2>/dev/null || exit 0; LS=$(LC_ALL=C ls -ldn \"$B\" 2>/dev/null) || exit 0; set -- $LS; M=\"$1\"; case \"$M\" in drwx------|drwx------.|drwx------+|drwx------@) ;; *) exit 0 ;; esac; ME=$(id -u 2>/dev/null) || exit 0; [ \"$3\" = \"$ME\" ] || exit 0; D=\"$B/$AOE_INSTANCE_ID\"; mkdir -p \"$D\" 2>/dev/null; LS=$(LC_ALL=C ls -ldn \"$D\" 2>/dev/null) || exit 0; set -- $LS; M=\"$1\"; case \"$M\" in drwx------|drwx------.|drwx------+|drwx------@) ;; *) exit 0 ;; esac; [ \"$3\" = \"$ME\" ] || exit 0; printf idle > \"$D/status\" 2>/dev/null; exit 0 # aoe-hooks'"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"PreToolUse": [
|
|
||||||
{
|
|
||||||
"matcher": "Bash",
|
|
||||||
"hooks": [
|
|
||||||
{
|
|
||||||
"type": "command",
|
|
||||||
"command": "~/.claude/hooks/comms-lint.py"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"matcher": "",
|
|
||||||
"hooks": [
|
|
||||||
{
|
|
||||||
"type": "command",
|
|
||||||
"command": "~/.claude/hooks/tmux-reset.sh"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"matcher": "Bash",
|
|
||||||
"hooks": [
|
|
||||||
{
|
|
||||||
"type": "command",
|
|
||||||
"command": "rtk hook claude"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hooks": [
|
|
||||||
{
|
|
||||||
"type": "command",
|
|
||||||
"command": "sh -c 'unset IFS; set -f; umask 077; [ -n \"$AOE_INSTANCE_ID\" ] || exit 0; case \"$AOE_INSTANCE_ID\" in *[!0-9a-zA-Z_-]*) exit 0 ;; esac; B=/tmp/aoe-hooks-1000; mkdir -p \"$B\" 2>/dev/null || exit 0; LS=$(LC_ALL=C ls -ldn \"$B\" 2>/dev/null) || exit 0; set -- $LS; M=\"$1\"; case \"$M\" in drwx------|drwx------.|drwx------+|drwx------@) ;; *) exit 0 ;; esac; ME=$(id -u 2>/dev/null) || exit 0; [ \"$3\" = \"$ME\" ] || exit 0; D=\"$B/$AOE_INSTANCE_ID\"; mkdir -p \"$D\" 2>/dev/null; LS=$(LC_ALL=C ls -ldn \"$D\" 2>/dev/null) || exit 0; set -- $LS; M=\"$1\"; case \"$M\" in drwx------|drwx------.|drwx------+|drwx------@) ;; *) exit 0 ;; esac; [ \"$3\" = \"$ME\" ] || exit 0; IN=$(cat 2>/dev/null); S=running; case \"$IN\" in *\\\"tool_name\\\":\\\"AskUserQuestion\\\"*) S=waiting ;; esac; printf %s \"$S\" > \"$D/status\" 2>/dev/null; exit 0 # aoe-hooks'"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"SessionStart": [
|
|
||||||
{
|
|
||||||
"matcher": "startup|resume|clear",
|
|
||||||
"hooks": [
|
|
||||||
{
|
|
||||||
"type": "command",
|
|
||||||
"command": "~/.claude/hooks/git-autoupdate.sh"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hooks": [
|
|
||||||
{
|
|
||||||
"type": "command",
|
|
||||||
"command": "python3 ~/.claude/scripts/aoe-register-remote.py"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hooks": [
|
|
||||||
{
|
|
||||||
"type": "command",
|
|
||||||
"command": "/home/naps62/tea/rev/scripts/rev-hook-session-start.sh"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hooks": [
|
|
||||||
{
|
|
||||||
"type": "command",
|
|
||||||
"command": "sh -c '[ -n \"$AOE_INSTANCE_ID\" ] || exit 0; command -v aoe >/dev/null 2>&1 || exit 0; aoe __extract-session-id 2>/dev/null; exit 0 # aoe-hooks'"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"Stop": [
|
|
||||||
{
|
|
||||||
"hooks": [
|
|
||||||
{
|
|
||||||
"type": "command",
|
|
||||||
"command": "/home/naps62/tea/rev/scripts/rev-hook-stop.sh"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hooks": [
|
|
||||||
{
|
|
||||||
"type": "command",
|
|
||||||
"command": "sh -c 'unset IFS; set -f; umask 077; [ -n \"$AOE_INSTANCE_ID\" ] || exit 0; case \"$AOE_INSTANCE_ID\" in *[!0-9a-zA-Z_-]*) exit 0 ;; esac; B=/tmp/aoe-hooks-1000; mkdir -p \"$B\" 2>/dev/null || exit 0; LS=$(LC_ALL=C ls -ldn \"$B\" 2>/dev/null) || exit 0; set -- $LS; M=\"$1\"; case \"$M\" in drwx------|drwx------.|drwx------+|drwx------@) ;; *) exit 0 ;; esac; ME=$(id -u 2>/dev/null) || exit 0; [ \"$3\" = \"$ME\" ] || exit 0; D=\"$B/$AOE_INSTANCE_ID\"; mkdir -p \"$D\" 2>/dev/null; LS=$(LC_ALL=C ls -ldn \"$D\" 2>/dev/null) || exit 0; set -- $LS; M=\"$1\"; case \"$M\" in drwx------|drwx------.|drwx------+|drwx------@) ;; *) exit 0 ;; esac; [ \"$3\" = \"$ME\" ] || exit 0; printf idle > \"$D/status\" 2>/dev/null; exit 0 # aoe-hooks'"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"UserPromptSubmit": [
|
|
||||||
{
|
|
||||||
"hooks": [
|
|
||||||
{
|
|
||||||
"type": "command",
|
|
||||||
"command": "sh -c '[ -n \"$AOE_INSTANCE_ID\" ] || exit 0; command -v aoe >/dev/null 2>&1 || exit 0; aoe __extract-session-id 2>/dev/null; exit 0 # aoe-hooks'"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "command",
|
|
||||||
"command": "sh -c 'unset IFS; set -f; umask 077; [ -n \"$AOE_INSTANCE_ID\" ] || exit 0; case \"$AOE_INSTANCE_ID\" in *[!0-9a-zA-Z_-]*) exit 0 ;; esac; B=/tmp/aoe-hooks-1000; mkdir -p \"$B\" 2>/dev/null || exit 0; LS=$(LC_ALL=C ls -ldn \"$B\" 2>/dev/null) || exit 0; set -- $LS; M=\"$1\"; case \"$M\" in drwx------|drwx------.|drwx------+|drwx------@) ;; *) exit 0 ;; esac; ME=$(id -u 2>/dev/null) || exit 0; [ \"$3\" = \"$ME\" ] || exit 0; D=\"$B/$AOE_INSTANCE_ID\"; mkdir -p \"$D\" 2>/dev/null; LS=$(LC_ALL=C ls -ldn \"$D\" 2>/dev/null) || exit 0; set -- $LS; M=\"$1\"; case \"$M\" in drwx------|drwx------.|drwx------+|drwx------@) ;; *) exit 0 ;; esac; [ \"$3\" = \"$ME\" ] || exit 0; printf running > \"$D/status\" 2>/dev/null; exit 0 # aoe-hooks'"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"StopFailure": [
|
|
||||||
{
|
|
||||||
"hooks": [
|
|
||||||
{
|
|
||||||
"type": "command",
|
|
||||||
"command": "sh -c 'unset IFS; set -f; umask 077; [ -n \"$AOE_INSTANCE_ID\" ] || exit 0; case \"$AOE_INSTANCE_ID\" in *[!0-9a-zA-Z_-]*) exit 0 ;; esac; B=/tmp/aoe-hooks-1000; mkdir -p \"$B\" 2>/dev/null || exit 0; LS=$(LC_ALL=C ls -ldn \"$B\" 2>/dev/null) || exit 0; set -- $LS; M=\"$1\"; case \"$M\" in drwx------|drwx------.|drwx------+|drwx------@) ;; *) exit 0 ;; esac; ME=$(id -u 2>/dev/null) || exit 0; [ \"$3\" = \"$ME\" ] || exit 0; D=\"$B/$AOE_INSTANCE_ID\"; mkdir -p \"$D\" 2>/dev/null; LS=$(LC_ALL=C ls -ldn \"$D\" 2>/dev/null) || exit 0; set -- $LS; M=\"$1\"; case \"$M\" in drwx------|drwx------.|drwx------+|drwx------@) ;; *) exit 0 ;; esac; [ \"$3\" = \"$ME\" ] || exit 0; printf idle > \"$D/status\" 2>/dev/null; exit 0 # aoe-hooks'"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ElicitationResult": [
|
|
||||||
{
|
|
||||||
"hooks": [
|
|
||||||
{
|
|
||||||
"type": "command",
|
|
||||||
"command": "sh -c 'unset IFS; set -f; umask 077; [ -n \"$AOE_INSTANCE_ID\" ] || exit 0; case \"$AOE_INSTANCE_ID\" in *[!0-9a-zA-Z_-]*) exit 0 ;; esac; B=/tmp/aoe-hooks-1000; mkdir -p \"$B\" 2>/dev/null || exit 0; LS=$(LC_ALL=C ls -ldn \"$B\" 2>/dev/null) || exit 0; set -- $LS; M=\"$1\"; case \"$M\" in drwx------|drwx------.|drwx------+|drwx------@) ;; *) exit 0 ;; esac; ME=$(id -u 2>/dev/null) || exit 0; [ \"$3\" = \"$ME\" ] || exit 0; D=\"$B/$AOE_INSTANCE_ID\"; mkdir -p \"$D\" 2>/dev/null; LS=$(LC_ALL=C ls -ldn \"$D\" 2>/dev/null) || exit 0; set -- $LS; M=\"$1\"; case \"$M\" in drwx------|drwx------.|drwx------+|drwx------@) ;; *) exit 0 ;; esac; [ \"$3\" = \"$ME\" ] || exit 0; printf running > \"$D/status\" 2>/dev/null; exit 0 # aoe-hooks'"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"worktree": {
|
|
||||||
"baseRef": "fresh"
|
|
||||||
},
|
|
||||||
"enabledPlugins": {
|
|
||||||
"building@subvisual": true,
|
|
||||||
"rust-analyzer-lsp@claude-plugins-official": false,
|
|
||||||
"caveman@caveman": true
|
|
||||||
},
|
|
||||||
"extraKnownMarketplaces": {
|
|
||||||
"subvisual": {
|
|
||||||
"source": {
|
|
||||||
"source": "github",
|
|
||||||
"repo": "subvisual/harness"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"superpowers-marketplace": {
|
|
||||||
"source": {
|
|
||||||
"source": "github",
|
|
||||||
"repo": "obra/superpowers-marketplace"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"caveman": {
|
|
||||||
"source": {
|
|
||||||
"source": "github",
|
|
||||||
"repo": "JuliusBrussee/caveman"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"skipDangerousModePermissionPrompt": true,
|
|
||||||
"theme": "dark",
|
|
||||||
"editorMode": "vim",
|
|
||||||
"preferredNotifChannel": "auto",
|
|
||||||
"autoCompactEnabled": true,
|
|
||||||
"remoteControlAtStartup": false,
|
|
||||||
"inputNeededNotifEnabled": true,
|
|
||||||
"mcpServers": {
|
|
||||||
"playwright": {
|
|
||||||
"args": [
|
|
||||||
"-y",
|
|
||||||
"@playwright/mcp@latest"
|
|
||||||
],
|
|
||||||
"command": "npx",
|
|
||||||
"type": "stdio"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sandbox": {
|
|
||||||
"enabled": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+33
-31
@@ -4,14 +4,12 @@
|
|||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
claudeSettings = "home/yolo/claude-settings.json";
|
# ./opencode.json holds only yolo's overrides; everything else is inherited
|
||||||
|
# so agents, commands and skills keep coming from common. Attrsets merge
|
||||||
# ./claude-settings.json holds only what yolo overrides; everything else is
|
# key-by-key, lists are replaced whole.
|
||||||
# inherited so common changes reach this host. Attrsets merge key-by-key,
|
mergedOpencodeConfig = (pkgs.formats.json { }).generate "opencode.json" (
|
||||||
# lists are replaced whole (permissions.allow is yolo's, not a union).
|
lib.recursiveUpdate (lib.importJSON ../common/programs/opencode/opencode.json) (
|
||||||
mergedClaudeSettings = (pkgs.formats.json { }).generate "claude-settings.json" (
|
lib.importJSON ./opencode.json
|
||||||
lib.recursiveUpdate (lib.importJSON ../common/programs/claude/settings.json) (
|
|
||||||
lib.importJSON ./claude-settings.json
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
in
|
in
|
||||||
@@ -23,39 +21,43 @@ in
|
|||||||
../common/programs/kitty
|
../common/programs/kitty
|
||||||
../common/programs/gpg.nix
|
../common/programs/gpg.nix
|
||||||
../common/programs/aoe
|
../common/programs/aoe
|
||||||
|
../common/programs/maestro
|
||||||
|
../common/programs/rev
|
||||||
|
../common/programs/nix-autodeploy
|
||||||
../common/features/xdg.nix
|
../common/features/xdg.nix
|
||||||
./monitors.nix
|
./monitors.nix
|
||||||
./services.nix
|
./services.nix
|
||||||
./ssh.nix
|
./ssh.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
|
# Host-local: bash goes from "ask" to "allow" so unattended opencode sessions
|
||||||
|
# stop stalling on every git and grep.
|
||||||
|
# It also drops the prompt on branches under review, which is the tradeoff.
|
||||||
|
xdg.configFile."opencode/opencode.json".source = lib.mkForce mergedOpencodeConfig;
|
||||||
|
|
||||||
custom.hyprland.cursorSize = 32;
|
custom.hyprland.cursorSize = 32;
|
||||||
|
|
||||||
home = {
|
# Amber, and a different silhouette to Nordzy — this desktop is only ever seen
|
||||||
# Headless browser driver the agent tooling shells out to. Was a global npm
|
# inside a Moonlight window, so the cursor has to be tellable at a glance from
|
||||||
# install on the ubuntu box.
|
# the client's own. Same theme in both modes; darkman would otherwise swap it.
|
||||||
packages = [ pkgs.agent-browser ];
|
custom.hyprland.cursorPackage = pkgs.bibata-cursors;
|
||||||
|
custom.hyprland.cursorTheme = {
|
||||||
# Both default to ~/projects/nixos-config in common/programs; this clone
|
dark = "Bibata-Modern-Amber";
|
||||||
# lives under ~/tea. nh.flake sets NH_FLAKE, so without it `nh home switch`
|
light = "Bibata-Modern-Amber";
|
||||||
# with no argument resolves to a path that does not exist.
|
|
||||||
mutableFilesRepoPath = "/home/naps62/tea/nixos-config";
|
|
||||||
|
|
||||||
mutableFiles = {
|
|
||||||
# Host-local, not shared: this sets yolo_mode_default = true, which starts
|
|
||||||
# aoe sessions with permission checks skipped. Only correct on this box.
|
|
||||||
".config/agent-of-empires/config.toml".source = ./aoe-config.toml;
|
|
||||||
|
|
||||||
# Likewise host-local: carries skipDangerousModePermissionPrompt and the
|
|
||||||
# rev hook paths, neither of which belong on a workstation.
|
|
||||||
".claude/settings.json" = {
|
|
||||||
source = lib.mkForce mergedClaudeSettings;
|
|
||||||
upstreamPath = claudeSettings;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
programs.agentSkills.machine = "yolo";
|
# Headless browser driver the agent tooling shells out to. Was a global npm
|
||||||
|
# install on the ubuntu box.
|
||||||
|
home.packages = [ pkgs.agent-browser ];
|
||||||
|
|
||||||
|
# This is the one box that runs the agent-skills units; each starts a session,
|
||||||
|
# so a second machine enabling them would run the same job twice.
|
||||||
|
programs.agentSkills = {
|
||||||
|
machine = "yolo";
|
||||||
|
prDaemon.enable = true;
|
||||||
|
hourlog.enable = true;
|
||||||
|
weekReview.enable = true;
|
||||||
|
};
|
||||||
programs.nh.flake = "/home/naps62/tea/nixos-config";
|
programs.nh.flake = "/home/naps62/tea/nixos-config";
|
||||||
|
|
||||||
# Idle lock and dpms-off blank the virtual output: Sunshine then captures a
|
# Idle lock and dpms-off blank the virtual output: Sunshine then captures a
|
||||||
|
|||||||
@@ -4,7 +4,11 @@ _: {
|
|||||||
# Matches every output rather than naming one: the virtio-gpu connector name
|
# Matches every output rather than naming one: the virtio-gpu connector name
|
||||||
# varies by qemu display backend (Virtual-1 vs Virtual-0). Explicit mode, not
|
# varies by qemu display backend (Virtual-1 vs Virtual-0). Explicit mode, not
|
||||||
# `preferred` — this is the resolution Sunshine streams.
|
# `preferred` — this is the resolution Sunshine streams.
|
||||||
|
#
|
||||||
|
# 2160p is near the ceiling: virtio-gpu has no NVENC/VAAPI, so Sunshine falls
|
||||||
|
# back to x264, which measured 73fps here against 135fps at 1440p — a 60fps
|
||||||
|
# client has only ~20% margin.
|
||||||
wayland.windowManager.hyprland.extraConfig = ''
|
wayland.windowManager.hyprland.extraConfig = ''
|
||||||
hl.monitor({ output = "", mode = "2560x1440@60", position = "0x0", scale = 1 })
|
hl.monitor({ output = "", mode = "3840x2160@60", position = "0x0", scale = 1 })
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"permission": {
|
||||||
|
"bash": "allow"
|
||||||
|
}
|
||||||
|
}
|
||||||
+58
-112
@@ -3,12 +3,11 @@
|
|||||||
inputs,
|
inputs,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
# The user services this box exists to run, ported from hand-written units in
|
# The user services this box exists to run.
|
||||||
# ~/.config/systemd/user on the Ubuntu machine.
|
|
||||||
#
|
#
|
||||||
# NOT self-contained: every ExecStart under ~/.bun or ~/.local/bin is an
|
# maestro and rev come from their own flakes, so nix owns the build as well as
|
||||||
# imperatively-installed binary, and the WorkingDirectories are clones of
|
# the unit. aoe-web is still the odd one out: its unit is defined here and the
|
||||||
# separate repos. Nix owns the unit definitions here, nothing more.
|
# binary comes from the flake input.
|
||||||
let
|
let
|
||||||
# A user unit gets almost no PATH by default; these are the profile dirs the
|
# A user unit gets almost no PATH by default; these are the profile dirs the
|
||||||
# original units got for free from the system PATH on Ubuntu.
|
# original units got for free from the system PATH on Ubuntu.
|
||||||
@@ -19,133 +18,80 @@ let
|
|||||||
aoe = inputs.agent-of-empires.packages.${pkgs.system}.aoe-with-web;
|
aoe = inputs.agent-of-empires.packages.${pkgs.system}.aoe-with-web;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
# sem is here as well as on rev's unit: the shell uses it directly too.
|
||||||
home.packages = [
|
home.packages = [
|
||||||
sem
|
sem
|
||||||
pkgs.bun
|
# ACP adapter aoe's structured (web) sessions spawn as `claude-agent-acp`.
|
||||||
|
pkgs.claude-agent-acp
|
||||||
];
|
];
|
||||||
|
|
||||||
|
# maestro's and rev's units come from their flake modules, not from the
|
||||||
|
# hand-written set below.
|
||||||
|
#
|
||||||
|
# settings stays empty on purpose: ~/.config/maestro/config.toml is a
|
||||||
|
# hand-edited plain file, not nix-generated (module skips it iff `{}`).
|
||||||
|
# There is no `web.enable`: the daemon serves the UI on `daemon.bind_addr`.
|
||||||
|
services.maestro.enable = true;
|
||||||
|
|
||||||
|
# Everything under ~, three levels deep — the worktrees live at
|
||||||
|
# ~/<area>/<repo>/worktrees/<name>. sem gives entity-level diffs; without it
|
||||||
|
# rev falls back to line diffs.
|
||||||
|
services.rev = {
|
||||||
|
enable = true;
|
||||||
|
roots = [ "%h" ];
|
||||||
|
depth = 3;
|
||||||
|
semBin = "${sem}/bin/sem";
|
||||||
|
};
|
||||||
|
|
||||||
|
# One endpoint for every repo this config pins. All three apply straight
|
||||||
|
# away: a maestro restart drops the daemon but not the sessions it manages,
|
||||||
|
# so the interactive shells on this box survive it.
|
||||||
|
services.nixAutodeploy = {
|
||||||
|
enable = true;
|
||||||
|
flake = "/home/naps62/tea/nixos-config";
|
||||||
|
environmentFile = "%h/.config/nix-autodeploy/env";
|
||||||
|
repos = {
|
||||||
|
"yolo/rev".input = "rev";
|
||||||
|
"yolo/agent-skills".input = "agent-skills";
|
||||||
|
"naps62/maestro".input = "maestro";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
systemd.user.services = {
|
systemd.user.services = {
|
||||||
rev = {
|
aoe-web = {
|
||||||
Unit = {
|
Unit = {
|
||||||
Description = "rev — always-on local code review server";
|
Description = "aoe serve — Agent of Empires web dashboard";
|
||||||
After = [ "network.target" ];
|
After = [ "network.target" ];
|
||||||
# MUST stay 0: at RestartSec=2 a fast-crashing rev burns the default
|
# MUST stay 0: at RestartSec=2 a fast-crashing aoe burns the default
|
||||||
# 5-starts-per-10s budget, and systemd parks the unit in `failed` until
|
# 5-starts-per-10s budget, and systemd parks the unit in `failed` until
|
||||||
# a manual `systemctl --user reset-failed`.
|
# a manual `systemctl --user reset-failed`.
|
||||||
StartLimitIntervalSec = 0;
|
StartLimitIntervalSec = 0;
|
||||||
};
|
};
|
||||||
Service = {
|
Service = {
|
||||||
Type = "simple";
|
Type = "simple";
|
||||||
WorkingDirectory = "%h/tea/rev";
|
WorkingDirectory = "%h";
|
||||||
# nodejs_26, not pkgs.nodejs: rev's package.json sets engines >=26 and
|
# The fork removed dashboard auth entirely, so there is no --auth flag
|
||||||
# the nixpkgs default is 24.
|
# any more — the reverse proxy is the only access gate. --allowed-host
|
||||||
ExecStart = "${pkgs.nodejs_26}/bin/node server/index.ts";
|
# is what makes the rebinding gate accept a hostname under a wildcard
|
||||||
|
# bind (an IP literal needs no flag).
|
||||||
|
ExecStart = "${aoe}/bin/aoe serve --host 0.0.0.0 --port 8080 --behind-proxy --allowed-host aoe.n62.casa";
|
||||||
|
# TMUX_TMPDIR keeps the daemon on the same tmux server the shell and
|
||||||
|
# TUI use, instead of a second one under /tmp (same bug pr-daemon had).
|
||||||
Environment = [
|
Environment = [
|
||||||
"NODE_ENV=production"
|
|
||||||
"REV_ROOTS=%h"
|
|
||||||
"REV_DEPTH=3"
|
|
||||||
"REV_SEM_BIN=${sem}/bin/sem"
|
|
||||||
"PATH=${toolPath}"
|
"PATH=${toolPath}"
|
||||||
|
"TMUX_TMPDIR=%t"
|
||||||
];
|
];
|
||||||
Restart = "always";
|
Restart = "always";
|
||||||
RestartSec = 2;
|
RestartSec = 2;
|
||||||
};
|
# If this unit boots before any shell, the shared tmux server lands in
|
||||||
Install.WantedBy = [ "default.target" ];
|
# its cgroup; the default control-group kill would take every session
|
||||||
};
|
# down on restart.
|
||||||
|
|
||||||
rev-deploy = {
|
|
||||||
Unit = {
|
|
||||||
Description = "rev-deploy — Gitea webhook listener that deploys rev on push to main";
|
|
||||||
After = [ "network.target" ];
|
|
||||||
# Same restart-budget trap as `rev` above.
|
|
||||||
StartLimitIntervalSec = 0;
|
|
||||||
};
|
|
||||||
Service = {
|
|
||||||
Type = "simple";
|
|
||||||
WorkingDirectory = "%h/tea/rev";
|
|
||||||
ExecStart = "${pkgs.bun}/bin/bun scripts/deploy-webhook.ts";
|
|
||||||
EnvironmentFile = "%h/.config/rev/deploy.env";
|
|
||||||
Environment = [ "PATH=${toolPath}" ];
|
|
||||||
Restart = "always";
|
|
||||||
RestartSec = 2;
|
|
||||||
};
|
|
||||||
Install.WantedBy = [ "default.target" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
aoe-web = {
|
|
||||||
Unit = {
|
|
||||||
Description = "aoe serve — Agent of Empires web dashboard";
|
|
||||||
After = [ "network.target" ];
|
|
||||||
# Same restart-budget trap as `rev` above.
|
|
||||||
StartLimitIntervalSec = 0;
|
|
||||||
};
|
|
||||||
Service = {
|
|
||||||
Type = "simple";
|
|
||||||
WorkingDirectory = "%h";
|
|
||||||
# aoe refuses `--auth none` on a non-loopback bind unless --behind-proxy
|
|
||||||
# is set; --allowed-host is what makes the rebinding gate accept a
|
|
||||||
# hostname under a wildcard bind (an IP literal needs no flag).
|
|
||||||
ExecStart = "${aoe}/bin/aoe serve --host 0.0.0.0 --port 8080 --auth none --behind-proxy --allowed-host aoe.n62.casa";
|
|
||||||
Environment = [ "PATH=${toolPath}" ];
|
|
||||||
Restart = "always";
|
|
||||||
RestartSec = 2;
|
|
||||||
};
|
|
||||||
Install.WantedBy = [ "default.target" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
hourlog = {
|
|
||||||
Unit = {
|
|
||||||
Description = "Start the Friday hour log in a tmux session";
|
|
||||||
Documentation = [ "https://git.naps.pt/yolo/agent-skills" ];
|
|
||||||
ConditionPathIsDirectory = "%h/tea/agent-skills";
|
|
||||||
};
|
|
||||||
Service = {
|
|
||||||
Type = "oneshot";
|
|
||||||
ExecStart = "%h/tea/agent-skills/bin/hourlog-session.sh";
|
|
||||||
Environment = [ "PATH=${toolPath}" ];
|
|
||||||
# This unit may be what starts the tmux server; the default cgroup kill
|
|
||||||
# would take it back down as soon as ExecStart returns.
|
|
||||||
KillMode = "process";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
week-review = {
|
|
||||||
Unit = {
|
|
||||||
Description = "Start the weekly agent-skills review in a tmux session";
|
|
||||||
Documentation = [ "https://git.naps.pt/yolo/agent-skills" ];
|
|
||||||
ConditionPathIsDirectory = "%h/tea/agent-skills";
|
|
||||||
};
|
|
||||||
Service = {
|
|
||||||
Type = "oneshot";
|
|
||||||
ExecStart = "%h/tea/agent-skills/bin/week-review-session.sh";
|
|
||||||
Environment = [ "PATH=${toolPath}" ];
|
|
||||||
KillMode = "process";
|
KillMode = "process";
|
||||||
};
|
};
|
||||||
|
Install.WantedBy = [ "default.target" ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.user.timers = {
|
|
||||||
hourlog = {
|
|
||||||
Unit.Description = "Friday hour log, 18:00 Europe/Lisbon";
|
|
||||||
Timer = {
|
|
||||||
# Zone suffix pinned because the machine clock is UTC; keeps it at 18:00
|
|
||||||
# wall time across DST.
|
|
||||||
OnCalendar = "Fri 18:00 Europe/Lisbon";
|
|
||||||
Persistent = true;
|
|
||||||
AccuracySec = "1min";
|
|
||||||
};
|
|
||||||
Install.WantedBy = [ "timers.target" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
week-review = {
|
|
||||||
Unit.Description = "Weekly agent-skills review, Fridays 17:00 Europe/Lisbon";
|
|
||||||
Timer = {
|
|
||||||
OnCalendar = "Fri 17:00 Europe/Lisbon";
|
|
||||||
Persistent = true;
|
|
||||||
AccuracySec = "1min";
|
|
||||||
};
|
|
||||||
Install.WantedBy = [ "timers.target" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
# pr-daemon, hourlog and week-review are not here: their units ship with the
|
||||||
|
# scripts they run, in the agent-skills module. This host opts in with
|
||||||
|
# programs.agentSkills.*.enable in home/yolo/default.nix.
|
||||||
|
|||||||
@@ -3,6 +3,16 @@ _:
|
|||||||
# on the Ubuntu box.
|
# on the Ubuntu box.
|
||||||
{
|
{
|
||||||
programs.ssh.settings = {
|
programs.ssh.settings = {
|
||||||
|
# gpg-agent serves as the ssh agent here, and signing blocks forever on a
|
||||||
|
# pinentry prompt that has no TTY in headless/agent sessions — `ssh-add -l`
|
||||||
|
# works, but git push hangs right after "Server accepts key". The key file
|
||||||
|
# has no passphrase, so read it directly and skip the agent.
|
||||||
|
"github.com" = {
|
||||||
|
IdentityAgent = "none";
|
||||||
|
IdentitiesOnly = true;
|
||||||
|
IdentityFile = "~/.ssh/id_ed25519";
|
||||||
|
};
|
||||||
|
|
||||||
"grafana" = {
|
"grafana" = {
|
||||||
HostName = "10.6.10.30";
|
HostName = "10.6.10.30";
|
||||||
User = "root";
|
User = "root";
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
../common/features/bluetooth.nix
|
../common/features/bluetooth.nix
|
||||||
../common/features/ledger.nix
|
../common/features/ledger.nix
|
||||||
../common/features/smb-mounts.nix
|
../common/features/smb-mounts.nix
|
||||||
|
../common/features/transmission.nix
|
||||||
../common/features/home
|
../common/features/home
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -35,6 +36,12 @@
|
|||||||
share = "media";
|
share = "media";
|
||||||
mountPoint = "/mnt/media";
|
mountPoint = "/mnt/media";
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
# yolo VM's /home/naps62 (share defined in hosts/yolo/default.nix).
|
||||||
|
server = "10.7.10.2";
|
||||||
|
share = "home";
|
||||||
|
mountPoint = "/mnt/yolo";
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
boot.kernelParams = [
|
boot.kernelParams = [
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
{ pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
let
|
|
||||||
sddm-noctalia-theme = pkgs.callPackage ../../../../pkgs/sddm-noctalia-theme/package.nix { };
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
services.xserver = {
|
services.xserver = {
|
||||||
enable = true;
|
enable = true;
|
||||||
@@ -15,7 +12,7 @@ in
|
|||||||
services.displayManager.sddm = {
|
services.displayManager.sddm = {
|
||||||
enable = true;
|
enable = true;
|
||||||
wayland.enable = true;
|
wayland.enable = true;
|
||||||
theme = "sddm-noctalia";
|
theme = "sddm-astronaut-theme";
|
||||||
package = pkgs.kdePackages.sddm;
|
package = pkgs.kdePackages.sddm;
|
||||||
extraPackages = with pkgs.kdePackages; [
|
extraPackages = with pkgs.kdePackages; [
|
||||||
qtmultimedia
|
qtmultimedia
|
||||||
@@ -26,6 +23,6 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [
|
||||||
sddm-noctalia-theme
|
sddm-astronaut
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,13 @@
|
|||||||
portalPackage = inputs.hyprland.packages.${pkgs.stdenv.hostPlatform.system}.xdg-desktop-portal-hyprland;
|
portalPackage = inputs.hyprland.packages.${pkgs.stdenv.hostPlatform.system}.xdg-desktop-portal-hyprland;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# swayosd (the volume/brightness OSD, configured in home) writes
|
||||||
|
# /sys/class/backlight/*/brightness directly. The package ships a udev rule
|
||||||
|
# that chgrps those files to `video`; without both the rule and the group,
|
||||||
|
# brightness keys pop the OSD but change nothing.
|
||||||
|
services.udev.packages = [ pkgs.swayosd ];
|
||||||
|
users.users.naps62.extraGroups = [ "video" ];
|
||||||
|
|
||||||
# GTK/GNOME services still useful on Wayland
|
# GTK/GNOME services still useful on Wayland
|
||||||
programs.dconf.enable = true;
|
programs.dconf.enable = true;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
{ inputs, lib, ... }:
|
||||||
|
{
|
||||||
|
imports = [ inputs.nix-flatpak.nixosModules.nix-flatpak ];
|
||||||
|
|
||||||
|
services.flatpak = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
# mkOptionDefault so the module's default `flathub` remote is kept rather
|
||||||
|
# than replaced.
|
||||||
|
remotes = lib.mkOptionDefault [
|
||||||
|
{
|
||||||
|
name = "flathub-beta";
|
||||||
|
location = "https://flathub.org/beta-repo/flathub-beta.flatpakrepo";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
packages = [
|
||||||
|
# PrusaSlicer 3.x. As of 3.0 Prusa ships no Linux binary at all — Flathub
|
||||||
|
# is the only channel, and the alphas live in flathub-beta. Runs alongside
|
||||||
|
# pkgs.prusa-slicer (2.9.x, in home/common/programs/3d.nix): 3.x keeps its
|
||||||
|
# profiles in a separate PrusaSlicer3-dev config dir.
|
||||||
|
{
|
||||||
|
appId = "com.prusa3d.PrusaSlicer";
|
||||||
|
origin = "flathub-beta";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -47,6 +47,11 @@
|
|||||||
# the module's own systemd.user.services.sunshine definition.
|
# the module's own systemd.user.services.sunshine definition.
|
||||||
systemd.user.services.sunshine.environment.LD_LIBRARY_PATH = "/run/opengl-driver/lib";
|
systemd.user.services.sunshine.environment.LD_LIBRARY_PATH = "/run/opengl-driver/lib";
|
||||||
|
|
||||||
|
# hardware.uinput (pulled in by services.sunshine) makes /dev/uinput
|
||||||
|
# root:uinput 0660 and adds nobody to the group, so sunshine's virtual mouse
|
||||||
|
# and keyboard die with "Permission denied" and the stream takes no input.
|
||||||
|
users.groups.uinput.members = [ "naps62" ];
|
||||||
|
|
||||||
# DualSense/DualShock emulation. Sunshine presents a *real* PS5 HID (touchpad,
|
# DualSense/DualShock emulation. Sunshine presents a *real* PS5 HID (touchpad,
|
||||||
# motion, LEDs, rumble) via /dev/uhid, not plain uinput — a uinput pad can't
|
# motion, LEDs, rumble) via /dev/uhid, not plain uinput — a uinput pad can't
|
||||||
# carry those features. The kernel uhid node is root-only (0600) with no udev
|
# carry those features. The kernel uhid node is root-only (0600) with no udev
|
||||||
|
|||||||
@@ -11,6 +11,11 @@ _:
|
|||||||
# moonlight shows a black, artefacted picture rather than any error.
|
# moonlight shows a black, artefacted picture rather than any error.
|
||||||
systemd.user.services.sunshine.serviceConfig.LimitNOFILE = 65536;
|
systemd.user.services.sunshine.serviceConfig.LimitNOFILE = 65536;
|
||||||
|
|
||||||
|
# hardware.uinput (pulled in by services.sunshine) makes /dev/uinput
|
||||||
|
# root:uinput 0660 and adds nobody to the group, so sunshine's virtual mouse
|
||||||
|
# and keyboard die with "Permission denied" and the stream takes no input.
|
||||||
|
users.groups.uinput.members = [ "naps62" ];
|
||||||
|
|
||||||
services.sunshine = {
|
services.sunshine = {
|
||||||
enable = true;
|
enable = true;
|
||||||
autoStart = true;
|
autoStart = true;
|
||||||
|
|||||||
@@ -40,7 +40,10 @@ in
|
|||||||
};
|
};
|
||||||
mountPoint = lib.mkOption {
|
mountPoint = lib.mkOption {
|
||||||
type = lib.types.str;
|
type = lib.types.str;
|
||||||
description = "Local mount point, e.g. \"/mnt/retroarch\".";
|
# MUST NOT live under $HOME: starship and eww stat every entry of the
|
||||||
|
# home dir, so a mount point there triggers the automount on every
|
||||||
|
# prompt and blocks for mount-timeout while the VPN is down.
|
||||||
|
description = "Local mount point outside $HOME, e.g. \"/mnt/retroarch\".";
|
||||||
};
|
};
|
||||||
user = lib.mkOption {
|
user = lib.mkOption {
|
||||||
type = lib.types.str;
|
type = lib.types.str;
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
services.transmission = {
|
||||||
|
enable = true;
|
||||||
|
package = pkgs.transmission_4;
|
||||||
|
openRPCPort = true;
|
||||||
|
settings = {
|
||||||
|
rpc-bind-address = "0.0.0.0";
|
||||||
|
rpc-whitelist-enabled = false;
|
||||||
|
rpc-host-whitelist-enabled = false;
|
||||||
|
rpc-authentication-required = false;
|
||||||
|
download-dir = "/var/lib/transmission/Downloads";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -20,12 +20,18 @@
|
|||||||
../common/features/wine.nix
|
../common/features/wine.nix
|
||||||
../common/features/gaming
|
../common/features/gaming
|
||||||
../common/features/appimage.nix
|
../common/features/appimage.nix
|
||||||
|
../common/features/flatpak.nix
|
||||||
../common/features/smb-mounts.nix
|
../common/features/smb-mounts.nix
|
||||||
|
../common/features/transmission.nix
|
||||||
../common/features/home
|
../common/features/home
|
||||||
];
|
];
|
||||||
|
|
||||||
networking.hostName = "konishi";
|
networking.hostName = "konishi";
|
||||||
|
|
||||||
|
# Set here rather than in hardware-configuration.nix so it survives a
|
||||||
|
# nixos-generate-config regeneration; the list merges with that file's.
|
||||||
|
fileSystems."/".options = [ "noatime" ];
|
||||||
|
|
||||||
# NAS media share — reachable only over the wg-home VPN. Lazy automount, so it
|
# NAS media share — reachable only over the wg-home VPN. Lazy automount, so it
|
||||||
# never blocks boot and (re)mounts on first access once the VPN is up.
|
# never blocks boot and (re)mounts on first access once the VPN is up.
|
||||||
custom.smbMounts = [
|
custom.smbMounts = [
|
||||||
@@ -34,6 +40,12 @@
|
|||||||
share = "media";
|
share = "media";
|
||||||
mountPoint = "/mnt/media";
|
mountPoint = "/mnt/media";
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
# yolo VM's /home/naps62 (share defined in hosts/yolo/default.nix).
|
||||||
|
server = "10.7.10.2";
|
||||||
|
share = "home";
|
||||||
|
mountPoint = "/mnt/yolo";
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
# Arm Wake-on-LAN (magic packet) on the Intel igc NIC and re-apply it on every
|
# Arm Wake-on-LAN (magic packet) on the Intel igc NIC and re-apply it on every
|
||||||
|
|||||||
+38
-4
@@ -17,6 +17,7 @@
|
|||||||
../common/features/kdeconnect.nix
|
../common/features/kdeconnect.nix
|
||||||
../common/features/nix-ld.nix
|
../common/features/nix-ld.nix
|
||||||
../common/features/appimage.nix
|
../common/features/appimage.nix
|
||||||
|
../common/features/transmission.nix
|
||||||
../common/features/home
|
../common/features/home
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -30,11 +31,20 @@
|
|||||||
# this VM has a real 8G swap partition, and the host manages its own memory.
|
# this VM has a real 8G swap partition, and the host manages its own memory.
|
||||||
zramSwap.enable = lib.mkForce false;
|
zramSwap.enable = lib.mkForce false;
|
||||||
|
|
||||||
# The only out-of-band way in. `vga: virtio-gl` renders through a GL context
|
|
||||||
# with no QEMU console surface, so noVNC and screendump both go dark; this
|
|
||||||
# pairs with the VM's serial0 socket to keep `qm terminal` working. Listed
|
|
||||||
# last so it wins /dev/console and gets the getty.
|
|
||||||
boot.kernelParams = [
|
boot.kernelParams = [
|
||||||
|
# When the host pages this VM's memory out, KVM's async page fault parks
|
||||||
|
# the faulting task in an uninterruptible wait instead of stalling the
|
||||||
|
# whole vCPU. If the "page ready" wakeup is ever dropped, that task is
|
||||||
|
# wedged forever and SIGKILL cannot touch it — it took out maestro-web,
|
||||||
|
# nix activation generators and a dozen agent sessions, a few per day,
|
||||||
|
# until a reboot. Disabling async PF makes host page-ins stall the vCPU
|
||||||
|
# synchronously: slower under host memory pressure, but nothing hangs.
|
||||||
|
"no-kvmapf"
|
||||||
|
|
||||||
|
# The only out-of-band way in. `vga: virtio-gl` renders through a GL
|
||||||
|
# context with no QEMU console surface, so noVNC and screendump both go
|
||||||
|
# dark; this pairs with the VM's serial0 socket to keep `qm terminal`
|
||||||
|
# working. Listed last so it wins /dev/console and gets the getty.
|
||||||
"console=tty1"
|
"console=tty1"
|
||||||
"console=ttyS0,115200"
|
"console=ttyS0,115200"
|
||||||
];
|
];
|
||||||
@@ -58,6 +68,30 @@
|
|||||||
# virtio drivers; the agent itself is a separate service.
|
# virtio drivers; the agent itself is a separate service.
|
||||||
qemuGuest.enable = true;
|
qemuGuest.enable = true;
|
||||||
|
|
||||||
|
# Exposes /home/naps62 to arrakis/konishi (custom.smbMounts on both, mounted
|
||||||
|
# at ~/yolo). Guest auth — the home dir holds SSH keys and credentials, so
|
||||||
|
# the only guard is `hosts allow` limiting clients to the wireguard subnet
|
||||||
|
# (desktops connect from wg addresses, 10.10.*).
|
||||||
|
# Clients address this VM as 10.7.10.2; keep that DHCP lease reserved.
|
||||||
|
samba = {
|
||||||
|
enable = true;
|
||||||
|
openFirewall = true;
|
||||||
|
settings = {
|
||||||
|
global = {
|
||||||
|
"map to guest" = "bad user";
|
||||||
|
"hosts allow" = "10.10.0.0/16 127.0.0.1";
|
||||||
|
"hosts deny" = "ALL";
|
||||||
|
};
|
||||||
|
home = {
|
||||||
|
path = "/home/naps62";
|
||||||
|
"read only" = "no";
|
||||||
|
"guest ok" = "yes";
|
||||||
|
"force user" = "naps62";
|
||||||
|
"force group" = "users";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
# No physical seat: Sunshine is a user service and cannot capture until a
|
# No physical seat: Sunshine is a user service and cannot capture until a
|
||||||
# graphical session exists, so a cold boot must reach one unattended. No
|
# graphical session exists, so a cold boot must reach one unattended. No
|
||||||
# hyprlock on start (unlike konishi) — nobody could type the password in.
|
# hyprlock on start (unlike konishi) — nobody could type the password in.
|
||||||
|
|||||||
@@ -137,9 +137,12 @@ stdenv.mkDerivation (finalAttrs: {
|
|||||||
# The bundled Chromium/ANGLE dlopen()s the system libEGL.so.1 for GL; give it
|
# The bundled Chromium/ANGLE dlopen()s the system libEGL.so.1 for GL; give it
|
||||||
# libglvnd + NixOS's GPU driver path so it hardware-accelerates instead of
|
# libglvnd + NixOS's GPU driver path so it hardware-accelerates instead of
|
||||||
# falling back to software rendering.
|
# falling back to software rendering.
|
||||||
|
# Chromium maps XDG_CURRENT_DESKTOP=Hyprland to "other" and silently picks the
|
||||||
|
# plaintext `basic` keystore, so safeStorage reports unavailable and auth tokens
|
||||||
|
# never persist across restarts. Pin the libsecret backend explicitly.
|
||||||
makeWrapper $out/lib/claude-desktop/claude-desktop $out/bin/claude-desktop \
|
makeWrapper $out/lib/claude-desktop/claude-desktop $out/bin/claude-desktop \
|
||||||
"''${gappsWrapperArgs[@]}" \
|
"''${gappsWrapperArgs[@]}" \
|
||||||
--add-flags "--no-sandbox${lib.optionalString (deviceScaleFactor != null) " --force-device-scale-factor=${deviceScaleFactor}"}" \
|
--add-flags "--no-sandbox --password-store=gnome-libsecret${lib.optionalString (deviceScaleFactor != null) " --force-device-scale-factor=${deviceScaleFactor}"}" \
|
||||||
--prefix PATH : ${lib.makeBinPath [ xdg-utils ]} \
|
--prefix PATH : ${lib.makeBinPath [ xdg-utils ]} \
|
||||||
--prefix LD_LIBRARY_PATH : "${lib.makeLibraryPath [ libGL mesa ]}:/run/opengl-driver/lib"
|
--prefix LD_LIBRARY_PATH : "${lib.makeLibraryPath [ libGL mesa ]}:/run/opengl-driver/lib"
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
stdenvNoCC,
|
||||||
|
fetchurl,
|
||||||
|
autoPatchelfHook,
|
||||||
|
makeWrapper,
|
||||||
|
stdenv,
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
version = "0.84.2";
|
||||||
|
|
||||||
|
# Prebuilt Bun executables from the release page. Bump version + hashes from
|
||||||
|
# the SHA256SUMS asset:
|
||||||
|
# https://github.com/earendil-works/pi/releases
|
||||||
|
sources = {
|
||||||
|
x86_64-linux = {
|
||||||
|
asset = "pi-linux-x64.tar.gz";
|
||||||
|
hash = "sha256-kG++eH/SJcSsYk/n69Wx1Vpg4PXH71F5XSMVZPnuHBM=";
|
||||||
|
};
|
||||||
|
aarch64-linux = {
|
||||||
|
asset = "pi-linux-arm64.tar.gz";
|
||||||
|
hash = "sha256-0VNy2p5LTF/vn9Fb7XbX9fFyDdOf583g7GLltlrWPvE=";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
source =
|
||||||
|
sources.${stdenvNoCC.hostPlatform.system}
|
||||||
|
or (throw "pi: unsupported system ${stdenvNoCC.hostPlatform.system}");
|
||||||
|
in
|
||||||
|
stdenvNoCC.mkDerivation {
|
||||||
|
pname = "pi";
|
||||||
|
inherit version;
|
||||||
|
|
||||||
|
src = fetchurl {
|
||||||
|
url = "https://github.com/earendil-works/pi/releases/download/v${version}/${source.asset}";
|
||||||
|
inherit (source) hash;
|
||||||
|
};
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
autoPatchelfHook
|
||||||
|
makeWrapper
|
||||||
|
];
|
||||||
|
|
||||||
|
# libgcc, for the bundled native clipboard module.
|
||||||
|
buildInputs = [ (lib.getLib stdenv.cc.cc) ];
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
|
||||||
|
# The binary resolves its themes, bundled node_modules and wasm relative to
|
||||||
|
# itself, so the whole tree ships together and only `pi` gets a wrapper.
|
||||||
|
mkdir -p $out/share/pi
|
||||||
|
cp -r . $out/share/pi/
|
||||||
|
chmod +x $out/share/pi/pi
|
||||||
|
|
||||||
|
# Nix owns updates here; `pi update --self` would write into the store.
|
||||||
|
makeWrapper $out/share/pi/pi $out/bin/pi \
|
||||||
|
--set-default PI_SKIP_VERSION_CHECK 1
|
||||||
|
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = {
|
||||||
|
description = "Pi coding agent CLI";
|
||||||
|
homepage = "https://pi.dev";
|
||||||
|
changelog = "https://github.com/earendil-works/pi/releases/tag/v${version}";
|
||||||
|
license = lib.licenses.mit;
|
||||||
|
sourceProvenance = [ lib.sourceTypes.binaryNativeCode ];
|
||||||
|
platforms = lib.attrNames sources;
|
||||||
|
mainProgram = "pi";
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
{ pkgs, ... }:
|
|
||||||
|
|
||||||
pkgs.stdenv.mkDerivation {
|
|
||||||
pname = "sddm-noctalia-theme";
|
|
||||||
version = "1.0";
|
|
||||||
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "mahaveergurjar";
|
|
||||||
repo = "sddm";
|
|
||||||
rev = "noctalia";
|
|
||||||
sha256 = "sha256-e/gYI6znHXxlDCOVh4p265x3kO0nQUU897hCY1yEz88=";
|
|
||||||
};
|
|
||||||
|
|
||||||
installPhase = ''
|
|
||||||
mkdir -p $out/share/sddm/themes/sddm-noctalia
|
|
||||||
cp -r * $out/share/sddm/themes/sddm-noctalia/
|
|
||||||
|
|
||||||
# Patch for Qt6 SDDM greeter compatibility
|
|
||||||
# SDDM reads QtVersion from metadata.desktop to find the greeter binary;
|
|
||||||
# default is 5 (sddm-greeter), we need 6 (sddm-greeter-qt6)
|
|
||||||
substituteInPlace $out/share/sddm/themes/sddm-noctalia/metadata.desktop \
|
|
||||||
--replace-fail "Theme-Id=noctalia" "QtVersion=6
|
|
||||||
Theme-Id=noctalia"
|
|
||||||
|
|
||||||
'';
|
|
||||||
|
|
||||||
meta = with pkgs.lib; {
|
|
||||||
description = "Noctalia-themed SDDM login theme";
|
|
||||||
homepage = "https://github.com/mahaveergurjar/sddm/tree/noctalia";
|
|
||||||
license = licenses.gpl3;
|
|
||||||
platforms = platforms.linux;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user