Compare commits

...

42 Commits

Author SHA1 Message Date
0173034295 chore(git): ignore .agents directory globally 2026-04-17 12:09:28 -04:00
bf6921e90a chore: move to agnostic agents 2026-04-17 11:35:29 -04:00
fa0bdae70d fix(nvim): use gopls remote mode to avoid spawning new server 2026-04-16 21:07:10 -04:00
6b3b59ce7f docs(skills): tighten update-package-hashes guidance 2026-04-16 17:25:51 -04:00
6e2db8169b chore(slack-cli): bump to 0a94842 2026-04-16 17:25:49 -04:00
2383d5e7e7 update slack-cli to 7cc6b740485e45cda8eb7ab44f82f8b45e536418 2026-04-16 17:07:02 -04:00
f483db70da docs: strengthen automatic execution guidance for git-commit skill 2026-04-16 17:06:16 -04:00
82f975eb43 chore(slack-cli): bump to b0660478 2026-04-16 16:57:27 -04:00
ceff33273d feat(llama-swap): add Qwen3.6-35B-A3B model configuration 2026-04-16 16:20:00 -04:00
4ab22c0433 docs: reference update-package-hashes skill in AGENTS.md 2026-04-16 15:50:32 -04:00
34005bbbe7 build(pi-coding-agent): bump to 0.67.5 2026-04-16 15:50:32 -04:00
bce45888ba docs: add update-package-hashes skill 2026-04-16 15:50:32 -04:00
eba712e7b9 chore(darwin): hide standard desktop icons on work MBP 2026-04-16 13:47:42 -04:00
088e1effa2 build(pi-coding-agent): bump version to 0.67.4 2026-04-16 13:07:45 -04:00
61407659a3 chore(packages/llama-cpp): bump to b8815 and add spirv-headers dependency 2026-04-16 13:02:06 -04:00
3ec336866a feat(slack-cli): add slack-cli package and enable on work MacBook
Add Python-based slack-cli package that reads Slack messages from local
Chromium IndexedDB cache. Includes pinned dependencies for dfindexeddb,
python-snappy, and zstd. Enable on mac-va-mbp-work home config.
2026-04-16 12:16:50 -04:00
a758d6b10c style(sketchybar): update background to grey and widen item padding 2026-04-16 10:15:28 -04:00
f9abe8023e fix(pi): exclude literal '.pi' from replacement in system prompt
Use negative lookbehind to avoid replacing '.pi' in paths like '.pi/agent'
2026-04-16 10:02:03 -04:00
feb528de5d feat(sketchybar): add blur effect to individual item backgrounds
Add per-item blur_radius=30 with background.clip=0.5 to create a
frosted-glass effect on each component pill while keeping the bar
itself fully transparent. Bump bg alpha from 0x20 to 0x30 so the
blur is visible through the semi-transparent backgrounds.
2026-04-16 10:02:03 -04:00
ea794a6772 feat(pi): add address-gh-review skill and enforce title case comments
- Add new address-gh-review skill with SKILL.md and gh_review.sh script
  for fetching and addressing unresolved GitHub PR review comments
- Update AGENTS.md comment style to require Title Case for block titles
2026-04-16 10:01:55 -04:00
e049aad113 docs(pi): add principles and comment style guidelines to AGENTS.md 2026-04-16 09:04:33 -04:00
21f5987c6e feat(home/services): add sketchybar status bar module for macOS
Add Home Manager module for sketchybar with clock, battery, volume,
and Wi-Fi items. Enable on mac-va-mbp-work, replacing nunc service.
2026-04-16 08:55:33 -04:00
d6f92ac9d9 feat(nunc): add nunc floating clock overlay package and service
- Add packages/nunc derivation built from Gitea with swiftPackages
- Add home module reichard.services.nunc with configurable settings
  and launchd agent for macOS
- Enable nunc service on mac-va-mbp-work
- Tweak mac-va-mbp-work defaults: hide menu bar, disable auto
  brightness, hide Finder desktop icons
2026-04-15 18:39:04 -04:00
d5224d79ac fix: darwin, feat: work vm auto connect 2026-04-15 11:01:58 -04:00
c72759d426 chore(work-vm): NAT to localhost 2026-04-15 09:40:39 -04:00
397faba95b chore(git-commit): execute commits automatically without confirmation 2026-04-14 20:36:30 -04:00
a9f762b1fe chore(pi-coding-agent): bump to 0.67.2 2026-04-14 20:33:11 -04:00
d935b7c004 chore: update flake 2026-04-14 20:29:51 -04:00
1b340d43e0 add: codexis & pi 2026-04-10 15:50:12 -04:00
d5942d9fb0 chore: update llama-cpp 2026-04-06 16:07:16 -04:00
79137b7f62 fix: pi + tmux, ld for uv 2026-04-06 16:02:20 -04:00
8cf42eae8f feat(systems): add work vm 2026-04-06 14:15:11 -04:00
393c31f241 fix(nvim): lsp sqls 2026-04-03 09:57:45 -04:00
f7c85ed889 chore: add common 2026-03-22 12:39:04 -04:00
16d2c97ce8 chore: add sqls config file ref 2026-03-19 13:32:04 -04:00
7b6d15c850 feat(terminal): add hey-intern LLM-powered shell command generator
Add a new shell function that uses an LLM API to generate shell commands
from natural language queries. The command displays the generated command
for user confirmation before execution and adds it to history.

- Generates shell commands from natural language via LLM
- Displays command for user review before execution
- Automatically adds executed commands to bash history
- Uses qwen3-coder-next-80b-instruct model
2026-03-16 13:04:04 -04:00
540506a45e chore: update pi-coding-agent 2026-03-15 15:26:14 -04:00
454b93ba2a chore: add zk & fix golsp 2026-03-15 09:49:59 -04:00
9415fa937c chore: add common packages 2026-03-15 09:48:04 -04:00
9c453ab93e refactor(neovim): improve git-config.lua with helper functions and new feature
- Extract git_cmd and git_cmd_list for reusable git command execution
- Add yank helper for consistent clipboard copying with notifications
- Enhance get_git_info to include abs_path and file_dir
- Add get_blame_info to retrieve detailed blame information with file hash
- Implement copy_commit_url for copying direct commit URLs
- Convert keymaps to use function references

New: <Leader>gC copies GitHub commit URL with file hash fragment
2026-03-09 13:42:47 -04:00
90eed0378e chore(llama): update llama-cpp and remove deprecated models
- Upgrade llama-cpp from version 8196 to 8229
- Remove GPT OSS CSEC (20B) - Thinking model config
- Remove Qwen3 Next (80B) - Instruct model config
- Increment -ncmoe parameter for Qwen3 Coder Next (80B) model
2026-03-07 08:55:00 -05:00
36873c324b refactor(hyprland): adjust brightness step size and format code
- Change brightness key bindings from 10% to 4%/5% for finer control
- Reformat hyprland module to use one parameter per line
2026-03-07 08:25:00 -05:00
45 changed files with 1382 additions and 631 deletions

View File

@@ -0,0 +1,70 @@
---
name: update-package-hashes
description: Update a package in packages/ to a new version and refresh its hashes (src, vendorHash, npmDepsHash, cargoHash, etc.) WITHOUT compiling the package. Use when the user asks to bump, update, or upgrade a specific package under packages/. Requires package name and target version/rev.
---
# Update Package Hashes (Without Building)
Require the user to supply the **package name** and **target version/rev/tag**. Ask if missing.
## Hard Rules — Read First
1. **Never run `nix build .#<pkg>`** or `.#packages.<system>.<pkg>`. That compiles the package. Only realise **FOD sub-attributes** (`.src`, `.goModules`, `.npmDeps`, `.cargoDeps`) — those are pure downloads, not builds.
2. **Never** use `nix-prefetch-git`, `nix-prefetch-url`, `nix hash path`, `git clone` + manual hashing, `builtins.fetchGit`, or any other ad-hoc method to compute hashes. They produce hashes in formats that don't match what `fetchgit`/`fetchFromGitHub`/etc. expect, and you will waste time chasing mismatches.
3. There are exactly **two** correct ways to get a hash, both listed below. If neither fits, stop and ask the user — don't improvise.
## The Only Two Methods
### Method A — `nurl` (preferred for `src` on any git forge)
`nurl` works for **any git URL**, not just GitHub: `gitea.va.reichard.io`, `gitlab`, `codeberg`, `sourcehut`, plain `https://...git`, all fine. It downloads the source and prints a complete fetcher expression with the correct hash.
```bash
nix run nixpkgs#nurl -- <git-url> <rev-or-tag>
```
Examples:
```bash
nix run nixpkgs#nurl -- https://github.com/owner/repo v1.2.3
nix run nixpkgs#nurl -- https://gitea.va.reichard.io/evan/slack-cli.git 0a9484257a2adc414aa4cdab4fb9539a37e04d1f
```
Copy the `hash = "sha256-..."` line into the package's `src` block.
### Method B — FOD mismatch trick (for everything else)
For `vendorHash`, `npmDepsHash`, `cargoHash`, `cargoLock.outputHashes.<crate>`, or any `src` using a custom fetcher (`leaveDotGit`, `postFetch`, `fetchSubmodules`, etc. — applies to `llama-cpp` and `llama-swap`), realise the **specific FOD sub-attribute** and read the `got:` line from the error.
```bash
nix build .#<name>.src --no-link 2>&1 | tee /tmp/hash.log # for src
nix build .#<name>.goModules --no-link 2>&1 | tee /tmp/hash.log # for vendorHash
nix build .#<name>.npmDeps --no-link 2>&1 | tee /tmp/hash.log # for npmDepsHash
nix build .#<name>.cargoDeps --no-link 2>&1 | tee /tmp/hash.log # for cargoHash
grep -E '^[[:space:]]*got:' /tmp/hash.log | tail -1 | awk '{print $2}'
```
Setting the hash to `sha256-AAAA...` (44 A's) or leaving the old one in place both work — the build will fail at the FOD with `got: sha256-...` which is the correct value.
**Note:** `.src`, `.goModules`, etc. are sub-attributes of the derivation. They download but do not compile. `nix build .#<name>` (without the `.src` suffix) compiles — never do that.
## Flow
1. Edit `packages/<name>/default.nix` — bump `version` / `rev` / `tag`. Check for sibling `.nix` files (e.g. `ui.nix`) that may also need bumping.
2. Get the new `src` hash with **Method A** (`nurl`). If the package uses a custom fetcher, use **Method B** on `.src` instead.
3. For each dependency hash (`vendorHash` / `npmDepsHash` / `cargoHash` / etc.), use **Method B** on the matching sub-attribute.
4. **Opaque `outputHash` FODs** (e.g. opencode's `node_modules` which runs `bun install`) — do NOT attempt locally. Leave as-is and flag for CI in the summary.
5. Show `git diff -- packages/<name>/` and list any hashes left for CI.
## Resolving Tags Without Cloning
```bash
git ls-remote <url> refs/tags/<tag>
```
## Don't Touch What Didn't Change
Skip pinned sub-dependencies whose inputs didn't change — e.g. `slack-cli`'s `python-snappy` / `zstd-python` PyPI tarballs are pinned by the upstream `dfindexeddb`, not by the slack-cli rev.
## Optional Shortcut
`nix-update --flake <name> --version <v>` sometimes handles everything for simple packages. Try it first; fall back to the methods above if it fails.

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
.codexis
.DS_Store
_scratch
result

119
AGENTS.md Normal file
View File

@@ -0,0 +1,119 @@
# NixOS Configuration — Agent Guide
This is a multi-host NixOS/nix-darwin configuration managed with [Snowfall Lib](https://github.com/snowfallorg/lib). It declaratively configures NixOS (Linux), nix-darwin (macOS), and Home Manager across many machines from a single flake.
## Snowfall Lib Conventions
Snowfall Lib auto-discovers everything by directory convention — there is no manual wiring. The namespace is `reichard`, so all custom options live under `reichard.*` (e.g. `reichard.services.tailscale`, `reichard.programs.terminal.nvim`). Modules use `lib.reichard.enabled` / `lib.reichard.disabled` helpers from `lib/module/default.nix`.
**Important:** Files must be tracked by git (`git add`) for the flake to see them.
## Layout
### `flake.nix`
Entrypoint. Defines inputs (nixpkgs, home-manager, sops-nix, disko, apple-silicon, snowfall-lib, etc.) and calls `snowfall-lib.mkFlake`. All system and home modules are auto-discovered from the directory structure below.
### `systems/`
System-level NixOS and nix-darwin configurations, organized by architecture:
- `systems/aarch64-linux/` — ARM Linux hosts (e.g. Asahi MacBook, Oracle Cloud nodes, headscale)
- `systems/x86_64-linux/` — x86 Linux hosts (desktop, thinkpad, utility servers, Kubernetes nodes)
- `systems/aarch64-darwin/` — macOS hosts (work and personal MacBooks)
- `systems/aarch64-raw-efi/` — Raw EFI image builds (terminal image via nixos-generators)
- `systems/x86_64-vmware/` — VMware images (RKE2 node)
Each host is a directory with a `default.nix` that composes modules via the `reichard.*` option namespace (e.g. `reichard.services.tailscale = enabled;`). Some hosts include `hardware-configuration.nix` or firmware directories.
### `homes/`
Home Manager configurations, organized by `<arch>/<user>@<host>/default.nix`. Each home config enables per-host programs and services (e.g. Neovim, Firefox, Hyprland, git, tmux) via the `reichard.*` namespace, same as system modules.
### `modules/`
Reusable NixOS, Home Manager, and Darwin modules. This is where most of the configuration logic lives.
- **`modules/nixos/`** — NixOS system modules:
- `common/` — Packages applied to all NixOS systems
- `home/` — Home Manager integration (useGlobalPkgs, useUserPackages)
- `nix/` — Nix daemon settings, registries, binary caches, distributed builds
- `user/` — User account creation
- `security/sops/` — sops-nix secret decryption (age-based)
- `system/` — Boot, networking, NetworkManager, disko disk partitioning
- `services/` — Headscale, Tailscale, llama-swap (LLM model server), OpenSSH, RKE2, printing, Avahi, cloud-init, Sunshine, etc.
- `hardware/` — OpenGL, Asahi (Apple Silicon), battery/UPower
- `programs/graphical/wms/hyprland/` — System-level Hyprland WM setup
- `display-managers/sddm/` — SDDM display manager
- `virtualisation/` — Podman, libvirtd
- **`modules/home/`** — Home Manager modules:
- `common/` — Packages applied to all home configs (sqlite, jq, ripgrep, ncdu, jnv)
- `user/` — Home Manager user identity
- `security/sops/` — Per-user secret decryption
- `services/` — Fusuma (touchpad gestures), swww (wallpaper), SSH agent, poweralertd
- `programs/terminal/` — CLI tools: bash, tmux, btop, git, k9s, zk, aws, Neovim, opencode, claude-code, pi
- `programs/graphical/` — GUI apps: Firefox (with extensions overlay), Ghostty, Hyprland (home-level), Remmina, GIMP, Wireshark, Ghidra, Strawberry
- **`modules/darwin/`** — nix-darwin modules: user, OpenSSH, sops
### `modules/home/programs/terminal/nvim/` — Neovim Configuration
This is the full Neovim setup, frequently modified. The `default.nix` declares:
- All plugins (via nixpkgs vimPlugins + custom `buildVimPlugin` for codecompanion.nvim, none-ls-extras, llama.vim)
- LSP servers and formatters as `extraPackages`
- A generated `nix-vars.lua` that injects Nix store paths for LSP binaries
The actual Neovim Lua configuration lives in `config/lua/`:
- `init.lua` — Main loader
- `base.lua` — Core Vim settings and keymaps
- `lsp-config.lua` — LSP server setup (uses paths from `nix-vars.lua`)
- `cmp-config.lua` — nvim-cmp completion
- `llm-config.lua` — LLM integration (codecompanion, llama.vim)
- `snacks-config.lua` — Snacks.nvim dashboard/picker
- `dap-config.lua` — Debug Adapter Protocol (Go, etc.)
- `diagnostics-config.lua`, `ts-config.lua`, `lualine-config.lua`, `noice-config.lua`, `git-config.lua`, `which-key-config.lua`, etc.
When editing the Neovim config, note that **plugin declarations** happen in `default.nix` (Nix), while **plugin configuration** happens in the Lua files under `config/lua/`. LSP binary paths are bridged via the auto-generated `nix-vars.lua`.
### `packages/`
Custom package derivations, auto-discovered by Snowfall Lib and available as `pkgs.reichard.<name>`:
- `codexis/` — Go: code indexer using tree-sitter (built from gitea via `fetchgit`)
- `llama-cpp/` — LLaMA C++ inference engine
- `llama-swap/` — Go: LLM model swap proxy (with UI sub-derivation)
- `opencode/` — Go: terminal coding tool
- `pi-coding-agent/` — Node.js: coding agent CLI
- `qwen-code/` — Qwen code assistant
- `stable-diffusion-cpp/` — Stable Diffusion C++ inference
### `overlays/`
Nixpkgs overlays. Currently just `firefox-addons/` which imports the rycee Firefox addons repository.
### `secrets/`
sops-encrypted secrets (age keys). Managed via `.sops.yaml` which defines per-host and per-user key groups:
- `keys.yaml` — Master key definitions
- `common/evanreichard.yaml` — User-level secrets (shared across personal machines)
- `common/systems.yaml` — System-level secrets (e.g. builder SSH keys)
### `shells/`
Dev shell definitions. `shells/default/` provides the default `nix develop` environment for working on this repo.
### `lib/`
Shared library helpers. `lib/module/default.nix` exports `mkOpt`, `mkBoolOpt`, `enabled`, and `disabled` — used throughout all modules for consistent option declarations.
## Common Tasks
- **Adding a new system:** Create `systems/<arch>/<hostname>/default.nix` and optionally `homes/<arch>/<user>@<hostname>/default.nix`. Compose existing modules via `reichard.*` options.
- **Adding a new module:** Create `modules/{nixos,home,darwin}/<category>/<name>/default.nix` with an `enable` option under the `reichard` namespace. It will be auto-discovered.
- **Adding a new package:** Create `packages/<name>/default.nix`. Run `git add` so the flake sees it. Reference it in modules as `pkgs.reichard.<name>`.
- **Editing Neovim plugins:** Modify `modules/home/programs/terminal/nvim/default.nix` (plugin list, extraPackages, nix-vars).
- **Editing Neovim config (Lua):** Modify files under `modules/home/programs/terminal/nvim/config/lua/`.
- **Managing secrets:** Edit `.sops.yaml` for key groups, use `sops` CLI to encrypt/decrypt files in `secrets/`.
- **Building/testing:** `nix build .#packages.<arch>.<name>` for packages, `nix build .#nixosConfigurations.<host>.config.system.build.toplevel` for full system builds.
- **Bumping a package version / refreshing hashes:** Use the `update-package-hashes` skill at `.pi/skills/update-package-hashes/`.

98
flake.lock generated
View File

@@ -8,11 +8,11 @@
]
},
"locked": {
"lastModified": 1770051625,
"narHash": "sha256-TvePW8C3Bh/yC2cjCWBy2kjeCtfLDj/lsB4dLnfOYn0=",
"lastModified": 1776147994,
"narHash": "sha256-c5F8jYiB0fjWsP4j/yeszqszA3laflzDj6/pmoJTeG4=",
"owner": "nix-community",
"repo": "nixos-apple-silicon",
"rev": "7b90aeb40c4eeecc7b53caf23d6acb05d99fcd4f",
"rev": "81439a7fb8067ab43641efd79c84607701da1ccd",
"type": "github"
},
"original": {
@@ -28,11 +28,11 @@
]
},
"locked": {
"lastModified": 1767634391,
"narHash": "sha256-owcSz2ICqTSvhBbhPP+1eWzi88e54rRZtfCNE5E/wwg=",
"lastModified": 1772129556,
"narHash": "sha256-Utk0zd8STPsUJPyjabhzPc5BpPodLTXrwkpXBHYnpeg=",
"owner": "nix-darwin",
"repo": "nix-darwin",
"rev": "08585aacc3d6d6c280a02da195fdbd4b9cf083c2",
"rev": "ebec37af18215214173c98cf6356d0aca24a2585",
"type": "github"
},
"original": {
@@ -51,11 +51,11 @@
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1770325739,
"narHash": "sha256-TPDWnhzKW/1+FPMiagZ9mZiQN0aKcGC09yYSUBuv8Mo=",
"lastModified": 1775584659,
"narHash": "sha256-NA5oZRunqxD+4LNdU7ZKJHqwuazKyAmBjO4OHXL14X4=",
"owner": "determinatesystems",
"repo": "determinate",
"rev": "1b3259b71c81508ffd409114525df6a55c0f337f",
"rev": "21dcaa011d3d35cf42a04e988eaac9b28c97a707",
"type": "github"
},
"original": {
@@ -67,37 +67,37 @@
"determinate-nixd-aarch64-darwin": {
"flake": false,
"locked": {
"narHash": "sha256-zK2dgNHh/p92rk5jN+Y1LOMn0HEdTsS+7XXwb2g52oM=",
"narHash": "sha256-qLWfYk9qkb21wKCDWnhMfqBFjcdBBJkNUKBlvdHSLgA=",
"type": "file",
"url": "https://install.determinate.systems/determinate-nixd/tag/v3.15.2/macOS"
"url": "https://install.determinate.systems/determinate-nixd/tag/v3.17.3/macOS"
},
"original": {
"type": "file",
"url": "https://install.determinate.systems/determinate-nixd/tag/v3.15.2/macOS"
"url": "https://install.determinate.systems/determinate-nixd/tag/v3.17.3/macOS"
}
},
"determinate-nixd-aarch64-linux": {
"flake": false,
"locked": {
"narHash": "sha256-ckvZP0zFcbzLXWYOJUqYXkKBt0b2IZcQEr7YjEVtwOI=",
"narHash": "sha256-0BmprPIRTopvJ2QdImOMP+TujAPVgRdl0bUL3vhqGIY=",
"type": "file",
"url": "https://install.determinate.systems/determinate-nixd/tag/v3.15.2/aarch64-linux"
"url": "https://install.determinate.systems/determinate-nixd/tag/v3.17.3/aarch64-linux"
},
"original": {
"type": "file",
"url": "https://install.determinate.systems/determinate-nixd/tag/v3.15.2/aarch64-linux"
"url": "https://install.determinate.systems/determinate-nixd/tag/v3.17.3/aarch64-linux"
}
},
"determinate-nixd-x86_64-linux": {
"flake": false,
"locked": {
"narHash": "sha256-8dLtm8FJrpyBmrNpspJj30/6I5HGEfjjXuFqURcZ8pk=",
"narHash": "sha256-+Q85cySxr0FB/cr97hk/WWYgeJY+iC4OH+FjGYygIbU=",
"type": "file",
"url": "https://install.determinate.systems/determinate-nixd/tag/v3.15.2/x86_64-linux"
"url": "https://install.determinate.systems/determinate-nixd/tag/v3.17.3/x86_64-linux"
},
"original": {
"type": "file",
"url": "https://install.determinate.systems/determinate-nixd/tag/v3.15.2/x86_64-linux"
"url": "https://install.determinate.systems/determinate-nixd/tag/v3.17.3/x86_64-linux"
}
},
"disko": {
@@ -105,11 +105,11 @@
"nixpkgs": "nixpkgs_3"
},
"locked": {
"lastModified": 1769524058,
"narHash": "sha256-zygdD6X1PcVNR2PsyK4ptzrVEiAdbMqLos7utrMDEWE=",
"lastModified": 1773889306,
"narHash": "sha256-PAqwnsBSI9SVC2QugvQ3xeYCB0otOwCacB1ueQj2tgw=",
"owner": "nix-community",
"repo": "disko",
"rev": "71a3fc97d80881e91710fe721f1158d3b96ae14d",
"rev": "5ad85c82cc52264f4beddc934ba57f3789f28347",
"type": "github"
},
"original": {
@@ -126,11 +126,11 @@
},
"locked": {
"dir": "pkgs/firefox-addons",
"lastModified": 1770091431,
"narHash": "sha256-9Sqq/hxq8ZDLRSzu+edn0OfWG+FAPWFpwMKaJobeLec=",
"lastModified": 1776199335,
"narHash": "sha256-ImihxU7ReZZuNdrASq8qzOmmO/UQtkuqQ9V9KKb1dD0=",
"owner": "rycee",
"repo": "nur-expressions",
"rev": "4f827ff035c6ddc58d04c45abe5b777d356b926a",
"rev": "95066e56aaa948f170747f57a20c99511a953eed",
"type": "gitlab"
},
"original": {
@@ -278,11 +278,11 @@
]
},
"locked": {
"lastModified": 1769580047,
"narHash": "sha256-tNqCP/+2+peAXXQ2V8RwsBkenlfWMERb+Uy6xmevyhM=",
"lastModified": 1775425411,
"narHash": "sha256-KY6HsebJHEe5nHOWP7ur09mb0drGxYSzE3rQxy62rJo=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "366d78c2856de6ab3411c15c1cb4fb4c2bf5c826",
"rev": "0d02ec1d0a05f88ef9e74b516842900c41f0f2fe",
"type": "github"
},
"original": {
@@ -301,12 +301,12 @@
"nixpkgs-regression": "nixpkgs-regression"
},
"locked": {
"lastModified": 1768960381,
"narHash": "sha256-32oMe1y+kwvIJNiJsIvozTuSmDxcwST06i+0ak+L4AU=",
"rev": "45ce621408cb8c9a724193d5fe858eb839662db8",
"revCount": 24453,
"lastModified": 1775583600,
"narHash": "sha256-/shs/3GA4R3rxhhqpPbEMnDZKbCvf3VpwnHB75nkTcI=",
"rev": "e9b4735be7b90cf49767faf5c36f770ac1bdc586",
"revCount": 24880,
"type": "tarball",
"url": "https://api.flakehub.com/f/pinned/DeterminateSystems/nix-src/3.15.2/019bde75-b4ee-74b2-a812-28dc2ee83d58/source.tar.gz"
"url": "https://api.flakehub.com/f/pinned/DeterminateSystems/nix-src/3.17.3/019d6913-e8c2-7128-ba76-3dc4f6b58158/source.tar.gz"
},
"original": {
"type": "tarball",
@@ -397,11 +397,11 @@
},
"nixpkgs-unstable": {
"locked": {
"lastModified": 1770115704,
"narHash": "sha256-KHFT9UWOF2yRPlAnSXQJh6uVcgNcWlFqqiAZ7OVlHNc=",
"lastModified": 1775710090,
"narHash": "sha256-ar3rofg+awPB8QXDaFJhJ2jJhu+KqN/PRCXeyuXR76E=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "e6eae2ee2110f3d31110d5c222cd395303343b08",
"rev": "4c1018dae018162ec878d42fec712642d214fdfa",
"type": "github"
},
"original": {
@@ -413,12 +413,12 @@
},
"nixpkgs_2": {
"locked": {
"lastModified": 1768783163,
"narHash": "sha256-tLj4KcRDLakrlpvboTJDKsrp6z2XLwyQ4Zmo+w8KsY4=",
"rev": "bde09022887110deb780067364a0818e89258968",
"revCount": 930106,
"lastModified": 1775464765,
"narHash": "sha256-nex6TL2x1/sVHCyDWcvl1t/dbTedb9bAGC4DLf/pmYk=",
"rev": "83e29f2b8791f6dec20804382fcd9a666d744c07",
"revCount": 975711,
"type": "tarball",
"url": "https://api.flakehub.com/f/pinned/DeterminateSystems/nixpkgs-weekly/0.1.930106%2Brev-bde09022887110deb780067364a0818e89258968/019bd9ed-5f0b-7074-afb0-8bb5e13a7598/source.tar.gz"
"url": "https://api.flakehub.com/f/pinned/DeterminateSystems/nixpkgs-weekly/0.1.975711%2Brev-83e29f2b8791f6dec20804382fcd9a666d744c07/019d6689-cde2-7061-b044-e0ef61ade488/source.tar.gz"
},
"original": {
"type": "tarball",
@@ -427,11 +427,11 @@
},
"nixpkgs_3": {
"locked": {
"lastModified": 1769330179,
"narHash": "sha256-yxgb4AmkVHY5OOBrC79Vv6EVd4QZEotqv+6jcvA212M=",
"lastModified": 1773628058,
"narHash": "sha256-hpXH0z3K9xv0fHaje136KY872VT2T5uwxtezlAskQgY=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "48698d12cc10555a4f3e3222d9c669b884a49dfe",
"rev": "f8573b9c935cfaa162dd62cc9e75ae2db86f85df",
"type": "github"
},
"original": {
@@ -443,11 +443,11 @@
},
"nixpkgs_4": {
"locked": {
"lastModified": 1770056022,
"narHash": "sha256-yvCz+Qmci1bVucXEyac3TdoSPMtjqVJmVy5wro6j/70=",
"lastModified": 1776067740,
"narHash": "sha256-B35lpsqnSZwn1Lmz06BpwF7atPgFmUgw1l8KAV3zpVQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "d04d8548aed39902419f14a8537006426dc1e4fa",
"rev": "7e495b747b51f95ae15e74377c5ce1fe69c1765f",
"type": "github"
},
"original": {
@@ -501,11 +501,11 @@
]
},
"locked": {
"lastModified": 1770110318,
"narHash": "sha256-NUVGVtYBTC96WhPh4Y3SVM7vf0o1z5W4uqRBn9v1pfo=",
"lastModified": 1776119890,
"narHash": "sha256-Zm6bxLNnEOYuS/SzrAGsYuXSwk3cbkRQZY0fJnk8a5M=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "f990b0a334e96d3ef9ca09d4bd92778b42fd84f9",
"rev": "d4971dd58c6627bfee52a1ad4237637c0a2fb0cd",
"type": "github"
},
"original": {

View File

@@ -65,6 +65,7 @@
homes.modules = with inputs; [
sops-nix.homeManagerModules.sops
./modules/home/common
];
systems.modules = {

View File

@@ -24,6 +24,7 @@ in
terminal = {
bash = {
enable = true;
customProfile = builtins.readFile ./vm-init.sh;
customFastFetchLogo = ./prophet.txt;
};
aws = enabled;
@@ -35,9 +36,15 @@ in
nvim = enabled;
opencode = enabled;
pi = enabled;
zk = enabled;
};
};
services = {
# nunc = enabled;
sketchybar = enabled;
};
security = {
sops = enabled;
};
@@ -47,9 +54,10 @@ in
programs.jq = enabled;
programs.pandoc = enabled;
home.packages = with pkgs; [
colima
# colima
docker
keycastr
reichard.slack-cli
_1password-cli
];
}

View File

@@ -0,0 +1,39 @@
echo "
██████╗██████╗ ██████╗ ██╗ ██╗██████╗ ███████╗████████╗██████╗ ██╗██╗ ██╗███████╗
██╔════╝██╔══██╗██╔═══██╗██║ ██║██╔══██╗██╔════╝╚══██╔══╝██╔══██╗██║██║ ██╔╝██╔════╝
██║ ██████╔╝██║ ██║██║ █╗ ██║██║ ██║███████╗ ██║ ██████╔╝██║█████╔╝ █████╗
██║ ██╔══██╗██║ ██║██║███╗██║██║ ██║╚════██║ ██║ ██╔══██╗██║██╔═██╗ ██╔══╝
╚██████╗██║ ██║╚██████╔╝╚███╔███╔╝██████╔╝███████║ ██║ ██║ ██║██║██║ ██╗███████╗
╚═════╝╚═╝ ╚═╝ ╚═════╝ ╚══╝╚══╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═╝╚══════╝
EVASION SYSTEM - Because IT can't handle Nix 
"
# Start VM
utmctl=/Applications/UTM.app/Contents/MacOS/utmctl
vm="lin-va-mbp-work-vm"
if ! "$utmctl" status "$vm" | grep -q "started"; then
echo " [*] CrowdStrike Evasion VM Starting..."
"$utmctl" start "$vm"
fi
# Wait for VM & Start Tunnel
if ! pgrep -f "ssh -N -D 1080 adios-cs" > /dev/null; then
echo " [*] VM Starting..."
until nc -z -w 2 192.168.64.3 22 &> /dev/null; do
sleep 2
done
echo " [✓] VM Started"
echo " [*] VM SOCKS Proxy Starting..."
ssh -N -D 1080 adios-cs &> /dev/null &
disown
echo " [✓] VM SOCKS Proxy Started"
else
echo " [✓] VM SOCKS Proxy Already Running"
fi
echo -e " [*] Connecting..."
# Connect to VM
mosh --ssh="ssh -q" adios-cs -- tmux new-session -A -s main

View File

@@ -0,0 +1,39 @@
{ lib
, config
, namespace
, ...
}:
let
inherit (lib.${namespace}) enabled;
in
{
home.stateVersion = "25.11";
reichard = {
user = {
enable = true;
inherit (config.snowfallorg.user) name;
};
services = {
ssh-agent = enabled;
};
programs = {
terminal = {
bash = {
enable = true;
customFastFetchLogo = ./prophet.txt;
};
btop = enabled;
claude-code = enabled;
direnv = enabled;
git = enabled;
k9s = enabled;
nvim = enabled;
pi = enabled;
tmux = enabled;
};
};
};
}

View File

@@ -0,0 +1,19 @@
                :+++++++=.        
                 =++++++++:       
                  -++++++++:      
                   -++++++++-     
                    :++++++++-    
          .-=======. :++++++++=   
         :********+   .++++++++=  
        -********=     .=+++++++=.
       -********-        =++++++++
      =********-          =++++++:
     =********:            -++++. 
    +********.              -+=.  
  .+*******+.                     
 .+*******+. :%#%%%%%%%%%%#%-     
:********=    +%%%%%%%%%%%%*      
********=      =%%%%%%%%%%+       
.+*****-        -%%%%%%%%=        
  +***-           ......          
   =*:                            

View File

@@ -0,0 +1,12 @@
{ pkgs, ... }:
{
home.packages = with pkgs; [
sqlite-interactive
jnv
jq
ncdu
ripgrep
reichard.codexis
];
}

View File

@@ -1,8 +1,9 @@
{ lib
, pkgs
, config
, namespace
, ...
{
lib,
pkgs,
config,
namespace,
...
}:
let
inherit (lib) types mkIf;
@@ -92,8 +93,8 @@ in
",XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"
",XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"
",XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"
",XF86MonBrightnessUp, exec, brightnessctl s 10%+"
",XF86MonBrightnessDown, exec, brightnessctl s 10%-"
",XF86MonBrightnessUp, exec, brightnessctl s 4%+"
",XF86MonBrightnessDown, exec, brightnessctl s 5%-"
# macOS Keyboard Brightness
"$menuMod, XF86MonBrightnessUp, exec, brightnessctl -d kbd_backlight s 10%+"

View File

@@ -0,0 +1,75 @@
#!/usr/bin/env bash
MODEL="qwen3-coder-next-80b-instruct"
SYSTEM_PROMPT="You are a shell command expert. Given a natural language query, generate a single shell command that accomplishes the task."
# Colors
CYAN='\033[0;36m'
YELLOW='\033[1;33m'
GREEN='\033[0;32m'
RESET='\033[0m'
hey-intern() {
local query="$*"
# Help
if [ -z "$query" ]; then
echo "Usage: hey-intern \"your query here\"" >&2
return 1
fi
# Execute LLM Request
response=$(curl -s -X POST "https://llm-api.va.reichard.io/v1/chat/completions" \
-H "Content-Type: application/json" \
-d "$(jq -n \
--arg model "$MODEL" \
--arg system "$SYSTEM_PROMPT" \
--arg user "$query" \
'{
model: $model,
temperature: 0.2,
messages: [
{role: "system", content: $system},
{role: "user", content: $user}
],
tools: [{
type: "function",
function: {
name: "generate_shell_command",
description: "Generate a shell command to answer a query",
parameters: {
type: "object",
properties: {
command: {type: "string", description: "The shell command to execute"}
},
required: ["command"]
}
}
}]
}')" | jq -r '.choices[0].message.tool_calls[0].function.arguments // empty')
# Extract Command
local command=$(echo "$response" | jq -r '.command // empty')
if [ -n "$command" ]; then
echo -e "\n ${CYAN}${command}${RESET}\n"
read -p "$(echo -e "${YELLOW}Would you like to run this command? [y/N]${RESET} ")" -n 1 -r
echo ""
if [[ $REPLY =~ ^[Yy]$ ]]; then
echo -e "${GREEN}Running...${RESET}\n"
history -s "$command"
eval "$command"
fi
else
echo "Failed to generate a valid command from the response." >&2
echo "Raw response: $response" >&2
return 1
fi
}
# Export Script
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
hey-intern "$@"
fi

View File

@@ -14,6 +14,7 @@ in
{
options.${namespace}.programs.terminal.bash = with lib.types; {
enable = mkEnableOption "bash";
customProfile = mkOpt str "" "custom profile";
customFastFetchLogo = mkOpt (nullOr path) null "custom fast fetch logo path";
};
@@ -37,6 +38,8 @@ in
bind "set show-mode-in-prompt on"
set -o vi || true
source <(fzf --bash)
VISUAL=vim
EDITOR="$VISUAL"
@@ -45,7 +48,10 @@ in
fi
[[ -f ~/.bash_custom ]] && . ~/.bash_custom
'';
source ${./config/hey-intern.sh}
''
+ cfg.customProfile;
};
programs.powerline-go = {
@@ -72,6 +78,8 @@ in
'';
};
programs.fzf.enable = true;
home.packages = with pkgs; [
bashInteractive
fastfetch

View File

@@ -16,7 +16,6 @@ in
config = mkIf cfg.enable {
programs.claude-code = {
enable = true;
package = pkgs.reichard.claude-code;
mcpServers = {
gopls = {
type = "stdio";

View File

@@ -1,3 +1,4 @@
_scratch
.direnv
.envrc
.agents

View File

@@ -18,50 +18,107 @@ require("gitsigns").setup({
})
local function git_cmd(dir, cmd)
return vim.fn.system("git -C " .. vim.fn.escape(dir, " ") .. " " .. cmd)
end
local function git_cmd_list(dir, cmd)
return vim.fn.systemlist("git -C " .. vim.fn.escape(dir, " ") .. " " .. cmd)
end
local function yank(message)
vim.fn.setreg("+", message)
vim.notify("Copied:\n\t" .. message, vim.log.levels.INFO)
end
local function get_git_info()
local abs_path = vim.fn.expand("%:p")
local git_root = vim.fn.systemlist(
"git -C " .. vim.fn.escape(vim.fn.fnamemodify(abs_path, ":h"), " ") .. " rev-parse --show-toplevel"
)[1]
local file_dir = vim.fn.fnamemodify(abs_path, ":h")
local git_root = git_cmd_list(file_dir, "rev-parse --show-toplevel")[1]
if vim.v.shell_error ~= 0 then
vim.notify("Failed to get git info", vim.log.levels.ERROR)
return
end
local git_repo = vim.fn.system("git remote get-url origin"):match("([^/:]+/[^/.]+)%.?[^/]*$"):gsub("\n", "")
local git_branch = vim.fn.system("git rev-parse --abbrev-ref HEAD"):gsub("\n", "")
local git_repo = git_cmd(file_dir, "remote get-url origin"):match("([^/:]+/[^/.]+)%.?[^/]*$"):gsub("\n", "")
local git_branch = git_cmd(file_dir, "rev-parse --abbrev-ref HEAD"):gsub("\n", "")
return {
abs_path = abs_path,
file_dir = file_dir,
file = vim.fn.fnamemodify(abs_path, ":s?" .. git_root .. "/??"),
branch = git_branch,
repo = git_repo,
}
end
local function copy_git_link()
local git_info = get_git_info()
if git_info == nil then
vim.notify("Failed to get git info", vim.log.levels.ERROR)
local function get_blame_info(file_dir, abs_path, line_num)
local blame_output = git_cmd_list(
file_dir,
"blame -L " .. line_num .. "," .. line_num .. " --porcelain " .. vim.fn.escape(abs_path, " ")
)
if vim.v.shell_error ~= 0 then
vim.notify("Failed to get git blame", vim.log.levels.ERROR)
return
end
local commit_hash = blame_output[1]:match("^(%S+)")
local original_line = blame_output[1]:match("^%S+ (%d+)")
local commit_file = nil
for _, line in ipairs(blame_output) do
local f = line:match("^filename (.+)$")
if f then
commit_file = f
break
end
end
if not commit_hash or not commit_file then
vim.notify("Failed to extract commit info", vim.log.levels.ERROR)
return
end
return {
hash = commit_hash,
line = tonumber(original_line),
file = commit_file,
file_hash = vim.fn.system("echo -n " .. vim.fn.shellescape(commit_file) .. " | sha256sum | cut -d' ' -f1"):gsub("\n",
""),
}
end
local function copy_git_link()
local git_info = get_git_info()
if not git_info then return end
local start_line = vim.fn.line("v")
local end_line = vim.fn.line(".")
local message = string.format(
yank(string.format(
"https://github.com/%s/blob/%s/%s#L%d-L%d",
git_info.repo,
git_info.branch,
git_info.file,
start_line,
end_line
)
vim.fn.setreg("+", message)
vim.notify("Copied:\n\t" .. message, vim.log.levels.INFO)
git_info.repo, git_info.branch, git_info.file, start_line, end_line
))
end
-- Create KeyMaps
vim.keymap.set("v", "<Leader>gy", function() copy_git_link() end, { desc = "Copy GitHub Link" })
local function copy_commit_url()
local git_info = get_git_info()
if not git_info then return end
local blame = get_blame_info(git_info.file_dir, git_info.abs_path, vim.fn.line("."))
if not blame then return end
yank(string.format(
"https://github.com/%s/commit/%s#diff-%sR%d",
git_info.repo, blame.hash, blame.file_hash, blame.line
))
end
-- Keymaps
vim.keymap.set("v", "<Leader>gy", copy_git_link, { desc = "Copy GitHub Link" })
vim.keymap.set("n", "<Leader>gC", copy_commit_url, { desc = "Copy Commit URL" })
vim.keymap.set('n', '<leader>go', '<cmd>DiffviewOpen<CR>', { desc = "Open Diff - Current" })
vim.keymap.set('n', '<leader>gO', '<cmd>DiffviewOpen origin/main...HEAD<CR>', { desc = "Open Diff - Main" })
vim.keymap.set('n', '<leader>gh', '<cmd>DiffviewFileHistory<CR>', { desc = "Diff History" })

View File

@@ -97,6 +97,7 @@ local default_config = {
capabilities = require("cmp_nvim_lsp").default_capabilities(),
on_attach = on_attach,
}
local setup_lsp = function(name, config)
local final_config = vim.tbl_deep_extend("force", default_config, config or {})
@@ -158,9 +159,26 @@ setup_lsp("lua_ls", {
-- Unison LSP Configuration
setup_lsp("unison")
-- Lua LSP Configuration
-- SQL Configuration
-- NOTE: root_markers resolves root_dir but Neovim does NOT use root_dir as
-- the process cwd (cmd_cwd defaults to Neovim's cwd). We use cmd as a
-- function so we can read root_dir from the resolved config and build an
-- absolute path to .sqls.yml.
setup_lsp("sqls", {
cmd = { nix_vars.sqls },
on_attach = on_attach_no_formatting,
root_markers = { ".sqls.yml", ".git" },
cmd = function(dispatchers, config)
local cmd = { nix_vars.sqls }
if config.root_dir then
local config_file = config.root_dir .. "/.sqls.yml"
if vim.fn.filereadable(config_file) == 1 then
cmd = { nix_vars.sqls, "-config", config_file }
end
end
return vim.lsp.rpc.start(cmd, dispatchers, {
cwd = config.root_dir,
})
end,
})
-- Nix LSP Configuration
@@ -189,8 +207,8 @@ setup_lsp("gopls", {
callback = organize_go_imports,
})
end,
cmd = { nix_vars.gopls },
filetypes = { "go" },
cmd = { "gopls", "-remote=auto" },
settings = {
gopls = {
buildFlags = { "-tags=e2e" },
@@ -226,6 +244,12 @@ none_ls.setup({
none_ls.builtins.formatting.prettier,
none_ls.builtins.formatting.prettier.with({ filetypes = { "template" } }),
none_ls.builtins.formatting.nixpkgs_fmt, -- TODO: nixd native LSP?
none_ls.builtins.formatting.sql_formatter.with({
extra_args = {
"--config",
'{"tabWidth":4,"keywordCase":"upper","language":"sql"}',
}
}),
require("none-ls.formatting.autopep8").with({
filetypes = { "starlark", "python" },
extra_args = { "--max-line-length", "100" },

View File

@@ -133,7 +133,6 @@ in
go
golangci-lint
golangci-lint-langserver
gopls
lua-language-server
nil
nodePackages.eslint
@@ -149,6 +148,7 @@ in
nixpkgs-fmt
nodePackages.prettier
stylua
sql-formatter
# Tools
ripgrep
@@ -176,7 +176,6 @@ in
bash = "${pkgs.bashInteractive}/bin/bash",
clangd = "${pkgs.clang-tools}/bin/clangd",
golintls = "${pkgs.golangci-lint-langserver}/bin/golangci-lint-langserver",
gopls = "${pkgs.gopls}/bin/gopls",
luals = "${pkgs.lua-language-server}/bin/lua-language-server",
sveltels = "${pkgs.nodePackages.svelte-language-server}/bin/svelteserver",
tsls = "${pkgs.nodePackages.typescript-language-server}/bin/typescript-language-server",

View File

@@ -31,3 +31,33 @@ bash(command="cat > file.txt << 'EOF'\ncontent\nEOF")
```bash
write(path="file.txt", content="content")
```
## Principles
1. **KISS / YAGNI** - Keep solutions simple and straightforward. Don't introduce abstractions, generics, or indirection unless there is a concrete, immediate need. Prefer obvious code over clever code.
2. **Maintain AGENTS.md** - If the project has an `AGENTS.md`, keep it up to date as conventions or architecture evolve. However, follow the **BLUF** (Bottom Line Up Front) principle: keep it concise, actionable, and context-size conscious. Don't overload it with information that belongs in code comments or external docs.
## Style
### Comment Style
A logical "block" of code (doesn't have to be a scope, but a cohesive group of statements responsible for something) should have a comment above it with a short "title". The title must be in **Title Case**. For example:
```go
// Map Component Results
for _, comp := range components {
results[comp.Name] = comp.Result
}
```
If the block is more complicated or non-obvious, explain _why_ it does what it does after the title:
```go
// Map Component Results - This is needed because downstream consumers
// expect a name-keyed lookup. Without it, the renderer would fall back
// to O(n) scans on every frame.
for _, comp := range components {
results[comp.Name] = comp.Result
}
```

View File

@@ -0,0 +1,19 @@
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
export default function replacePiWithClaudeCodeExtension(pi: ExtensionAPI) {
pi.on("before_agent_start", async (event) => {
// Replace "pi" With "claude code" - Exclude Literal ".pi" (e.g. Paths)
const transformedSystemPrompt = event.systemPrompt.replace(
/(?<!\.)pi/gi,
"claude code",
);
if (transformedSystemPrompt === event.systemPrompt) {
return undefined;
}
return {
systemPrompt: transformedSystemPrompt,
};
});
}

View File

@@ -0,0 +1,64 @@
---
name: address-gh-review
description: 'Fetch and address unresolved GitHub PR review comments. Use when user asks to handle PR reviews, address review feedback, mentions "/address-gh-review", or wants to see what reviewers requested. Fetches unresolved threads, presents an actionable summary, and lets the user select which items to address.'
---
# GitHub PR Review
## Overview
Fetch unresolved review threads from the current PR, consolidate them into actionable items, and address selected items — each as a separate commit.
## Prerequisites
- `gh` CLI authenticated and in a repo with an open PR on the current branch
- The `git-commit` skill available for committing changes
## Workflow
### 1. Fetch Review Comments
Run the bundled script to get unresolved threads:
```bash
bash gh_review.sh
```
If the script fails (no PR, not authenticated, etc.), report the error and stop.
### 2. Consolidate into Actionable Items
Parse the output and group into actionable items. Combine threads that ask for the same change (e.g. multiple reviewers commenting on the same function about the same concern). Keep items separate when they require distinct code changes.
Present a numbered list to the user:
```
## Unresolved Review Items
1. **src/auth/login.ts:42** — Add rate limiting to prevent brute force attacks (alice-dev)
2. **src/utils/validators.ts:89** — Use stricter type checking for email validation (bob-coder)
3. **src/api/users.ts:156** — Add error handling for null responses (alice-dev, charlie-reviewer)
```
### 3. Ask User for Selection
**Always ask before proceeding.** Prompt the user to select which items to address:
```
Which items would you like me to address? (e.g. "1,3", "all", or "none")
```
**Do not proceed until the user responds.** Respect "none" — just stop.
### 4. Address Each Item
For each selected item, in order:
1. Read the relevant file and understand the context around the referenced line
2. Implement the requested change
3. Run relevant linting/tests if applicable (e.g. `quicklint`)
4. Commit using the `git-commit` skill — **one commit per item**
### 5. Summary
After all selected items are addressed, print a brief summary of what was done.

View File

@@ -0,0 +1,71 @@
#!/usr/bin/env bash
# Fetch unresolved PR review threads, formatted for LLM consumption.
# Omits diff hunks (the LLM can read files from the repo directly).
# Groups comments into threads so conversation context is preserved.
set -euo pipefail
err() { echo "error: $1" >&2; exit 1; }
# Verify gh CLI is installed
command -v gh >/dev/null 2>&1 || err "'gh' CLI not found. Install it from https://cli.github.com"
# Verify we're inside a git repository
git rev-parse --is-inside-work-tree >/dev/null 2>&1 || err "not inside a git repository"
# Verify the remote is a GitHub repo
gh repo view --json name -q .name >/dev/null 2>&1 || err "this repo does not appear to be hosted on GitHub"
# Verify we're on a PR branch
PR_NUM=$(gh pr view --json number -q .number 2>/dev/null) || err "no pull request found for the current branch"
# Fetch current user, repo owner, and repo name
ME=$(gh api user -q .login 2>/dev/null) || err "failed to fetch GitHub user - are you authenticated? Run 'gh auth login'"
OWNER=$(gh repo view --json owner -q .owner.login 2>/dev/null) || err "failed to determine repository owner"
REPO=$(gh repo view --json name -q .name 2>/dev/null) || err "failed to determine repository name"
# Fetch unresolved review threads via GraphQL
OUTPUT=$(gh api graphql -f query='
query {
repository(owner: "'"$OWNER"'", name: "'"$REPO"'") {
pullRequest(number: '"$PR_NUM"') {
reviewThreads(first: 100) {
nodes {
isResolved
comments(first: 100) {
nodes {
author { login }
body
path
line
}
}
}
}
}
}
}' --jq '
[
.data.repository.pullRequest.reviewThreads.nodes[]
| select(.isResolved == false)
| {
file: .comments.nodes[0].path,
line: .comments.nodes[0].line,
comments: [
.comments.nodes[]
| select(.author.login != "'"$ME"'")
| {author: .author.login, body: .body}
]
}
| select(.comments | length > 0)
]
| .[]
| "## \(.file):\(.line)\n\(.comments | map("- **\(.author)**: \(.body)") | join("\n"))\n"
' 2>/dev/null) || err "GraphQL query failed - check your permissions and token scopes"
# Format output
if [[ -z "$OUTPUT" ]]; then
echo "No unresolved review comments found."
else
echo "$OUTPUT" | sed 's/\\n/\n/g'
fi

View File

@@ -1,6 +1,6 @@
---
name: git-commit
description: 'Execute git commit with conventional commit message analysis, intelligent staging, and message generation. Use when user asks to commit changes, create a git commit, or mentions "/commit". Supports: (1) Auto-detecting type and scope from changes, (2) Generating conventional commit messages from diff, (3) Interactive commit with optional type/scope/description overrides, (4) Intelligent file staging for logical grouping'
description: 'Execute git commit with conventional commit message analysis, intelligent staging, and message generation. Use when user asks to commit changes, create a git commit, mentions "/commit", or simply says "do it". Automatically commits without confirmation. Supports: (1) Auto-detecting type and scope from changes, (2) Generating conventional commit messages from diff, (3) Optional type/scope/description overrides, (4) Intelligent file staging for logical grouping'
---
# Git Commit with Conventional Commits
@@ -9,6 +9,20 @@ description: 'Execute git commit with conventional commit message analysis, inte
Create standardized, semantic git commits using the Conventional Commits specification. Analyze the actual diff to determine appropriate type, scope, and message.
## Automatic Execution — CRITICAL
**When this skill is invoked, EXECUTE THE COMMIT IMMEDIATELY. Do NOT ask for confirmation. Do NOT say "I'm ready" or "let me know when you want to proceed." Do NOT wait for further input. Do NOT acknowledge and then wait.**
The skill is invoked when the user says "commit", "do it", "/commit", "make a commit", "create a commit", or any similar phrase. The moment you recognize this intent, analyze the diff and run `git commit`. That's it.
**Zero prompts. Zero confirmation requests. Zero hand-holding.**
Only skip the commit if:
- Nothing is staged or modified (say "Nothing to commit" and stop)
- Secrets appear to be about to be committed (refuse and stop)
For everything else — just commit.
## Conventional Commit Format
```

View File

@@ -48,6 +48,10 @@ in
source = ./config/prompts;
recursive = true;
};
".pi/agent/extensions" = {
source = ./config/extensions;
recursive = true;
};
};
};
}

View File

@@ -45,7 +45,11 @@ in
set -g status-position top
set -g mouse on
setw -g mode-keys vi
set -g default-terminal "tmux-256color"
set -ag terminal-overrides ",xterm-256color:Tc:Ms=\\E]52;c%p1%.0s;%p2%s\\7"
set -g extended-keys-format csi-u
set -g extended-keys on
set -sg escape-time 0
# Start Index 1
set -g base-index 1

View File

@@ -0,0 +1,22 @@
{ lib
, config
, namespace
, ...
}:
let
inherit (lib) mkIf;
cfg = config.${namespace}.programs.terminal.zk;
in
{
options.${namespace}.programs.terminal.zk = {
enable = lib.mkEnableOption "enable zk";
};
config = mkIf cfg.enable {
programs.zk = {
enable = true;
};
programs.fzf.enable = true;
};
}

View File

@@ -0,0 +1,109 @@
{ config
, lib
, pkgs
, namespace
, ...
}:
let
cfg = config.${namespace}.services.nunc;
in
{
options.${namespace}.services.nunc = {
enable = lib.mkEnableOption "nunc floating clock overlay";
settings = lib.mkOption {
type = lib.types.submodule {
options = {
fontSize = lib.mkOption {
type = lib.types.number;
default = 12;
description = "Font size for the clock display.";
};
verticalPadding = lib.mkOption {
type = lib.types.number;
default = 9;
description = "Vertical padding around the clock text.";
};
horizontalPadding = lib.mkOption {
type = lib.types.number;
default = 20;
description = "Horizontal padding around the clock text.";
};
position = lib.mkOption {
type = lib.types.enum [
"top_left"
"top_center"
"top_right"
"bottom_left"
"bottom_center"
"bottom_right"
];
default = "top_right";
description = "Position of the clock overlay on screen.";
};
offsetX = lib.mkOption {
type = lib.types.number;
default = -12;
description = "Horizontal offset from the base position.";
};
offsetY = lib.mkOption {
type = lib.types.number;
default = 4;
description = "Vertical offset from the base position.";
};
dateFormat = lib.mkOption {
type = lib.types.str;
default = "EEE MMM d HH:mm:ss";
description = "Date format string (NSDateFormatter / Unicode TR35 format).";
};
};
};
default = { };
description = "Nunc configuration. Written to ~/.config/nunc/config.json.";
};
};
config = lib.mkIf cfg.enable {
assertions = [
{
assertion = pkgs.stdenv.isDarwin;
message = "reichard.services.nunc is only supported on macOS (Darwin).";
}
];
home.packages = [ pkgs.reichard.nunc ];
home.file.".config/nunc/config.json" = {
text = builtins.toJSON {
inherit (cfg.settings)
fontSize
verticalPadding
horizontalPadding
position
offsetX
offsetY
dateFormat
;
};
};
launchd.agents.nunc = {
enable = true;
config = {
Label = "io.reichard.nunc";
Program = "${pkgs.reichard.nunc}/bin/nunc";
RunAtLoad = true;
KeepAlive = true;
ProcessType = "Interactive";
StandardOutPath = "${config.home.homeDirectory}/Library/Logs/nunc/nunc.out.log";
StandardErrorPath = "${config.home.homeDirectory}/Library/Logs/nunc/nunc.err.log";
};
};
};
}

View File

@@ -0,0 +1,178 @@
{ config
, lib
, pkgs
, namespace
, ...
}:
let
cfg = config.${namespace}.services.sketchybar;
colors = {
white = "0xddffffff";
white_dim = "0x99ffffff";
bg = "0x1a808080";
transparent = "0x00000000";
green = "0xff8ceb34";
yellow = "0xffe8d44d";
red = "0xffed4f51";
};
sketchybarConfig = ''
#!/usr/bin/env bash
COLOR_BG="${colors.bg}"
COLOR_WHITE="${colors.white}"
COLOR_WHITE_DIM="${colors.white_dim}"
COLOR_GREEN="${colors.green}"
COLOR_YELLOW="${colors.yellow}"
COLOR_RED="${colors.red}"
COLOR_TRANSPARENT="${colors.transparent}"
FONT_FACE="SF Pro"
NERD_FONT="Symbols Nerd Font Mono:Regular:16.0"
PADDING=6
# Bar - transparent, top
sketchybar --bar \
height=36 \
position=top \
color=$COLOR_TRANSPARENT \
shadow=off \
sticky=on \
topmost=off \
padding_left=0 \
padding_right=12 \
y_offset=3
# Defaults
sketchybar --default \
icon.font="$NERD_FONT" \
icon.color=$COLOR_WHITE \
icon.padding_left=$(($PADDING + 2)) \
icon.padding_right=2 \
label.font="$FONT_FACE:Medium:13.0" \
label.color=$COLOR_WHITE \
label.padding_left=2 \
label.padding_right=$(($PADDING + 2)) \
background.color=$COLOR_BG \
background.corner_radius=6 \
background.clip=0.5 \
background.height=32 \
background.padding_left=4 \
blur_radius=30 \
background.padding_right=4
# Right side items (rightmost leftmost)
# Clock
sketchybar --add item clock right \
--set clock \
icon=󰃰 \
icon.color=$COLOR_WHITE_DIM \
update_freq=1 \
script="${pkgs.writeShellScript "sketchybar-clock" ''
sketchybar --set $NAME label="$(date '+%a %b %-d %H:%M:%S')"
''}"
# Battery
sketchybar --add item battery right \
--set battery \
update_freq=30 \
script="${pkgs.writeShellScript "sketchybar-battery" ''
PERCENTAGE="$(pmset -g batt | grep -Eo "\d+%" | head -1)"
CHARGING="$(pmset -g batt | grep -c "AC Power")"
PCT="''${PERCENTAGE//\%/}"
if [ "$CHARGING" -gt 0 ]; then
ICON="󰂄"
COLOR="${colors.green}"
elif [ "$PCT" -ge 80 ]; then
ICON="󰁹"
COLOR="${colors.green}"
elif [ "$PCT" -ge 60 ]; then
ICON="󰂀"
COLOR="${colors.green}"
elif [ "$PCT" -ge 40 ]; then
ICON="󰁾"
COLOR="${colors.yellow}"
elif [ "$PCT" -ge 20 ]; then
ICON="󰁼"
COLOR="${colors.yellow}"
else
ICON="󰁺"
COLOR="${colors.red}"
fi
sketchybar --set $NAME icon="$ICON" icon.color="$COLOR" label="$PERCENTAGE"
''}" \
--subscribe battery power_source_change system_woke
# Volume
sketchybar --add item volume right \
--set volume \
script="${pkgs.writeShellScript "sketchybar-volume" ''
VOL="$(osascript -e 'output volume of (get volume settings)')"
MUTED="$(osascript -e 'output muted of (get volume settings)')"
if [ "$MUTED" = "true" ]; then
ICON="󰖁"
elif [ "$VOL" -ge 60 ]; then
ICON="󰕾"
elif [ "$VOL" -ge 30 ]; then
ICON="󰖀"
elif [ "$VOL" -gt 0 ]; then
ICON="󰕿"
else
ICON="󰖁"
fi
sketchybar --set $NAME icon="$ICON" label="''${VOL}%"
''}" \
--subscribe volume volume_change
# Wi-Fi
sketchybar --add item wifi right \
--set wifi \
icon=󰖩 \
icon.color=$COLOR_WHITE_DIM \
update_freq=10 \
script="${pkgs.writeShellScript "sketchybar-wifi" ''
EN="$(networksetup -listallhardwareports | awk '/Wi-Fi|AirPort/{getline; print $NF}')"
if ipconfig getsummary "$EN" | grep -Fxq " Active : FALSE"; then
sketchybar --set $NAME icon=󰖪 label="Off"
else
SSID="$(networksetup -listpreferredwirelessnetworks "$EN" | sed -n '2s/^\t//p')"
if [ -n "$SSID" ]; then
sketchybar --set $NAME icon=󰖩 label="$SSID"
else
sketchybar --set $NAME icon=󰖪 label="Off"
fi
fi
''}"
sketchybar --update
'';
in
{
options.${namespace}.services.sketchybar = {
enable = lib.mkEnableOption "sketchybar status bar";
};
config = lib.mkIf cfg.enable {
assertions = [
{
assertion = pkgs.stdenv.isDarwin;
message = "reichard.services.sketchybar is only supported on macOS (Darwin).";
}
];
programs.sketchybar = {
enable = true;
extraPackages = [
pkgs.sketchybar-app-font
];
config = sketchybarConfig;
service.enable = true;
};
};
}

View File

@@ -1,4 +1,9 @@
{ config, pkgs, lib, namespace, ... }:
{ config
, pkgs
, lib
, namespace
, ...
}:
let
inherit (lib) mkIf;

View File

@@ -73,51 +73,6 @@ in
};
};
# https://huggingface.co/mradermacher/GPT-OSS-Cybersecurity-20B-Merged-i1-GGUF/tree/main
"gpt-oss-csec-20b-thinking" = {
name = "GPT OSS CSEC (20B) - Thinking";
macros.ctx = "131072";
cmd = ''
${llama-cpp}/bin/llama-server \
--port ''${PORT} \
-m /mnt/ssd/Models/GPT-OSS/GPT-OSS-Cybersecurity-20B-Merged.i1-MXFP4_MOE.gguf \
-c ''${ctx} \
--temp 1.0 \
--top-p 1.0 \
--top-k 40 \
-dev CUDA0
'';
metadata = {
type = [ "text-generation" ];
};
};
# https://huggingface.co/unsloth/Qwen3-Next-80B-A3B-Instruct-GGUF/tree/main
"qwen3-next-80b-instruct" = {
name = "Qwen3 Next (80B) - Instruct";
macros.ctx = "262144";
cmd = ''
${llama-cpp}/bin/llama-server \
--port ''${PORT} \
-m /mnt/ssd/Models/Qwen3/Qwen3-Next-80B-A3B-Instruct-UD-Q2_K_XL.gguf \
-c ''${ctx} \
--temp 0.7 \
--min-p 0.0 \
--top-p 0.8 \
--top-k 20 \
--repeat-penalty 1.05 \
-ctk q8_0 \
-ctv q8_0 \
-fit off
'';
metadata = {
type = [
"text-generation"
"coding"
];
};
};
# https://huggingface.co/unsloth/Qwen3-Coder-Next-GGUF/tree/main
"qwen3-coder-next-80b-instruct" = {
name = "Qwen3 Coder Next (80B) - Instruct";
@@ -132,7 +87,7 @@ in
--min-p 0.01 \
--top-k 40 \
-fit off \
-ncmoe 18 \
-ncmoe 19 \
-ts 78,22
'';
@@ -169,6 +124,32 @@ in
};
};
# https://huggingface.co/unsloth/Qwen3.6-35B-A3B-GGUF/tree/main
"qwen3.6-35b-thinking" = {
name = "Qwen3.6 (35B) - Thinking";
macros.ctx = "262144";
cmd = ''
${llama-cpp}/bin/llama-server \
--port ''${PORT} \
-m /mnt/ssd/Models/Qwen3.6/Qwen3.6-35B-A3B-UD-IQ4_XS.gguf \
-c ''${ctx} \
--temp 0.6 \
--top-p 0.95 \
--top-k 20 \
--min-p 0.0 \
--presence-penalty 0.0 \
--repeat-penalty 1.0 \
-dev CUDA0 \
-fit off
'';
metadata = {
type = [
"text-generation"
"coding"
];
};
};
# https://huggingface.co/bartowski/Qwen_Qwen3.5-27B-GGUF/tree/main
"qwen3.5-27b-thinking" = {
name = "Qwen3.5 (27B) - Thinking";

View File

@@ -1,8 +1,4 @@
{ inputs, ... }:
final: _prev: {
firefox-addons = import inputs.firefox-addons {
inherit (final) fetchurl;
inherit (final) lib;
inherit (final) stdenv;
};
firefox-addons = inputs.firefox-addons.packages.${final.system};
}

12
overlays/fish/default.nix Normal file
View File

@@ -0,0 +1,12 @@
# Workaround for aarch64-darwin codesigning bug (nixpkgs#208951 / #507531):
# fish binaries from the binary cache occasionally have invalid ad-hoc
# signatures on Apple Silicon. Forcing a local rebuild ensures codesigning
# is applied on this machine with a valid signature.
{ inputs, ... }:
final: prev: {
fish = prev.fish.overrideAttrs (_old: {
# Bust the cache key so fish is always built locally rather than
# substituted from the binary cache where the signature may be stale.
NIX_FORCE_LOCAL_REBUILD = "darwin-codesign-fix";
});
}

View File

@@ -1,25 +0,0 @@
# claude-code
Nix package for [@anthropic-ai/claude-code](https://www.npmjs.com/package/@anthropic-ai/claude-code).
## Updating
1. Fetch the tarball and generate a `package-lock.json`:
```bash
mkdir /tmp/claude-update && cd /tmp/claude-update
npm pack @anthropic-ai/claude-code@<version>
tar -xf anthropic-ai-claude-code-<version>.tgz
cd package
npm install --package-lock-only --ignore-scripts
```
2. Copy the lockfile into the package directory:
```bash
cp package-lock.json /path/to/nixpkgs/pkgs/by-name/cl/claude-code/package-lock.json
```
3. Update the `version` and `hash` fields in `package.nix`. Set `hash` to `lib.fakeHash` temporarily, then build to get the correct hash:
4. Do the same for `npmDepsHash`:

View File

@@ -1,61 +0,0 @@
{ lib
, buildNpmPackage
, fetchzip
, writableTmpDirAsHomeHook
, versionCheckHook
,
}:
buildNpmPackage (finalAttrs: {
pname = "claude-code";
version = "2.1.59";
src = fetchzip {
url = "https://registry.npmjs.org/@anthropic-ai/claude-code/-/claude-code-${finalAttrs.version}.tgz";
hash = "sha256-Dam9aJ0qBdqU40ACfzGQHuytW6ur0fMLm8D5fIKd1TE=";
};
npmDepsHash = "sha256-K+8xoBc3apvxQ9hCpYywqgBcfLxMWSxacgJcMH8mK7E=";
strictDeps = true;
postPatch = ''
cp ${./package-lock.json} package-lock.json
'';
dontNpmBuild = true;
env.AUTHORIZED = "1";
# `claude-code` tries to auto-update by default, this disables that functionality.
# https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/overview#environment-variables
# The DEV=true env var causes claude to crash with `TypeError: window.WebSocket is not a constructor`
postInstall = ''
wrapProgram $out/bin/claude \
--set DISABLE_AUTOUPDATER 1 \
--unset DEV
'';
doInstallCheck = true;
nativeInstallCheckInputs = [
writableTmpDirAsHomeHook
versionCheckHook
];
versionCheckKeepEnvironment = [ "HOME" ];
versionCheckProgramArg = "--version";
passthru.updateScript = ./update.sh;
meta = {
description = "Agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster";
homepage = "https://github.com/anthropics/claude-code";
downloadPage = "https://www.npmjs.com/package/@anthropic-ai/claude-code";
license = lib.licenses.unfree;
maintainers = with lib.maintainers; [
malo
markus1189
omarjatoi
xiaoxiangmoe
];
mainProgram = "claude";
};
})

View File

@@ -1,334 +0,0 @@
{
"name": "@anthropic-ai/claude-code",
"version": "2.1.59",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@anthropic-ai/claude-code",
"version": "2.1.59",
"license": "SEE LICENSE IN README.md",
"bin": {
"claude": "cli.js"
},
"engines": {
"node": ">=18.0.0"
},
"optionalDependencies": {
"@img/sharp-darwin-arm64": "^0.34.2",
"@img/sharp-darwin-x64": "^0.34.2",
"@img/sharp-linux-arm": "^0.34.2",
"@img/sharp-linux-arm64": "^0.34.2",
"@img/sharp-linux-x64": "^0.34.2",
"@img/sharp-linuxmusl-arm64": "^0.34.2",
"@img/sharp-linuxmusl-x64": "^0.34.2",
"@img/sharp-win32-arm64": "^0.34.2",
"@img/sharp-win32-x64": "^0.34.2"
}
},
"node_modules/@img/sharp-darwin-arm64": {
"version": "0.34.5",
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz",
"integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-darwin-arm64": "1.2.4"
}
},
"node_modules/@img/sharp-darwin-x64": {
"version": "0.34.5",
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz",
"integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-darwin-x64": "1.2.4"
}
},
"node_modules/@img/sharp-libvips-darwin-arm64": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz",
"integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==",
"cpu": [
"arm64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"darwin"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-darwin-x64": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz",
"integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==",
"cpu": [
"x64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"darwin"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linux-arm": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz",
"integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==",
"cpu": [
"arm"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linux-arm64": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz",
"integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==",
"cpu": [
"arm64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linux-x64": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz",
"integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==",
"cpu": [
"x64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linuxmusl-arm64": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz",
"integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==",
"cpu": [
"arm64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linuxmusl-x64": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz",
"integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==",
"cpu": [
"x64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-linux-arm": {
"version": "0.34.5",
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz",
"integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==",
"cpu": [
"arm"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linux-arm": "1.2.4"
}
},
"node_modules/@img/sharp-linux-arm64": {
"version": "0.34.5",
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz",
"integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linux-arm64": "1.2.4"
}
},
"node_modules/@img/sharp-linux-x64": {
"version": "0.34.5",
"resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz",
"integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linux-x64": "1.2.4"
}
},
"node_modules/@img/sharp-linuxmusl-arm64": {
"version": "0.34.5",
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz",
"integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linuxmusl-arm64": "1.2.4"
}
},
"node_modules/@img/sharp-linuxmusl-x64": {
"version": "0.34.5",
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz",
"integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linuxmusl-x64": "1.2.4"
}
},
"node_modules/@img/sharp-win32-arm64": {
"version": "0.34.5",
"resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz",
"integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==",
"cpu": [
"arm64"
],
"license": "Apache-2.0 AND LGPL-3.0-or-later",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-win32-x64": {
"version": "0.34.5",
"resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz",
"integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==",
"cpu": [
"x64"
],
"license": "Apache-2.0 AND LGPL-3.0-or-later",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
}
}
}

View File

@@ -1,10 +0,0 @@
#!/usr/bin/env nix-shell
#!nix-shell --pure --keep NIX_PATH -i bash --packages nodejs nix-update git cacert
set -euo pipefail
version=$(npm view @anthropic-ai/claude-code version)
# Update version and hashes
AUTHORIZED=1 NIXPKGS_ALLOW_UNFREE=1 nix-update claude-code --version="$version" --generate-lockfile
nix-update vscode-extensions.anthropic.claude-code --use-update-script --version "$version"

View File

@@ -0,0 +1,27 @@
{ lib
, buildGoModule
, fetchgit
}:
buildGoModule rec {
pname = "codexis";
version = "unstable-2026-04-10";
src = fetchgit {
url = "https://gitea.va.reichard.io/evan/codexis.git";
rev = "39fcfc296857f52b962388e454f8161ff0442d23";
hash = "sha256-B1VKY82tBxkd/L71Lq8Hh+1whQ03DzddkTcR82a+YXk=";
};
vendorHash = "sha256-8B1utE6bicIn1YO0qIcZhF7RaIK5cOu1/vm41EG+yyQ=";
subPackages = [ "." ];
meta = {
description = "Code index database tool using tree-sitter";
homepage = "https://gitea.va.reichard.io/evan/codexis";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ evanreichard ];
mainProgram = "codexis";
};
}

View File

@@ -1,31 +0,0 @@
# This patch modifies the json-schema-to-grammar.cpp file to handle 'not: {}' constructs
# specifically inside additionalProperties.
#
# Author: https://github.com/evanreichard
diff --git a/common/json-schema-to-grammar.cpp b/common/json-schema-to-grammar.cpp
index c3b4e5d..ea24bc3 100644
--- a/common/json-schema-to-grammar.cpp
+++ b/common/json-schema-to-grammar.cpp
@@ -858,10 +858,19 @@ public:
properties.emplace_back(prop.key(), prop.value());
}
}
+ json additionalProps = schema.contains("additionalProperties") ? schema["additionalProperties"] : json();
+ if (additionalProps.is_object() && additionalProps.contains("not")) {
+ const auto& not_val = additionalProps["not"];
+ if (not_val.is_object() && not_val.empty()) {
+ additionalProps.erase("not");
+ if (additionalProps.empty()) {
+ additionalProps = false;
+ }
+ }
+ }
return _add_rule(rule_name,
_build_object_rule(
- properties, required, name,
- schema.contains("additionalProperties") ? schema["additionalProperties"] : json()));
+ properties, required, name, additionalProps));
} else if ((schema_type.is_null() || schema_type == "object" || schema_type == "string") && schema.contains("allOf")) {
std::unordered_set<std::string> required;
std::vector<std::pair<std::string, json>> properties;

View File

@@ -7,12 +7,12 @@
vulkanSupport = true;
}).overrideAttrs
(oldAttrs: rec {
version = "8196";
version = "8815";
src = pkgs.fetchFromGitHub {
owner = "ggml-org";
repo = "llama.cpp";
tag = "b${version}";
hash = "sha256-GZRHiyT8mvhV5RTczDRnCSh31UxRZ3F8tEBC1l8oFNQ=";
hash = "sha256-QJsGBHLdvFfMXZJSk9D76b7v6DP06NaTYztHv41o/CA=";
leaveDotGit = true;
postFetch = ''
git -C "$out" rev-parse --short HEAD > $out/COMMIT
@@ -20,6 +20,11 @@
'';
};
# Add SPIR-V Headers for Vulkan Backend
# Newer llama.cpp requires spirv/unified1/spirv.hpp which isn't
# pulled in by vulkan-headers alone.
buildInputs = (oldAttrs.buildInputs or [ ]) ++ [ pkgs.spirv-headers ];
# Auto CPU Optimizations
cmakeFlags = (oldAttrs.cmakeFlags or [ ]) ++ [
"-DGGML_CUDA_ENABLE_UNIFIED_MEMORY=1"

View File

@@ -1,28 +0,0 @@
# This patch modifies the json-schema-to-grammar.cpp file to handle 'not: {}' constructs.
#
# Author: https://github.com/simaotwx
# Reference: https://github.com/ggml-org/llama.cpp/issues/14227#issuecomment-3547740835
diff --git a/common/json-schema-to-grammar.cpp b/common/json-schema-to-grammar.cpp
index 478aa1be7..ec0b3b73e 100644
--- a/common/json-schema-to-grammar.cpp
+++ b/common/json-schema-to-grammar.cpp
@@ -822,7 +822,17 @@ public:
return _add_rule(rule_name, _resolve_ref(schema["$ref"]));
} else if (schema.contains("oneOf") || schema.contains("anyOf")) {
std::vector<json> alt_schemas = schema.contains("oneOf") ? schema["oneOf"].get<std::vector<json>>() : schema["anyOf"].get<std::vector<json>>();
- return _add_rule(rule_name, _generate_union_rule(name, alt_schemas));
+ std::vector<json> filtered_schemas;
+ for (const auto& alt : alt_schemas) {
+ if (alt.is_object() && alt.contains("not")) {
+ const auto& not_val = alt["not"];
+ if (not_val.is_object() && not_val.empty()) {
+ continue;
+ }
+ }
+ filtered_schemas.push_back(alt);
+ }
+ return _add_rule(rule_name, _generate_union_rule(name, filtered_schemas));
} else if (schema_type.is_array()) {
std::vector<json> schema_types;
for (const auto & t : schema_type) {

48
packages/nunc/default.nix Normal file
View File

@@ -0,0 +1,48 @@
{ lib
, swiftPackages
, fetchgit
,
}:
swiftPackages.stdenv.mkDerivation rec {
pname = "nunc";
version = "unstable-2026-04-15";
src = fetchgit {
url = "https://gitea.va.reichard.io/evan/Nunc.git";
rev = "95d95840aa0bc7b595293c6c5c9f53d120a90cca";
hash = "sha256-UXBKcEuNnVO7WzuvmVqXMiJH7uvjLkcWiqBO0BhynsU=";
};
nativeBuildInputs = [
swiftPackages.swift
swiftPackages.swiftpm
];
buildInputs = [
swiftPackages.Foundation
swiftPackages.XCTest
];
buildPhase = ''
runHook preBuild
swift build -c release
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir -p $out/bin
cp .build/release/Nunc $out/bin/nunc
runHook postInstall
'';
meta = {
description = "Minimal floating clock overlay for macOS";
homepage = "https://gitea.va.reichard.io/evan/Nunc";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ evanreichard ];
mainProgram = "nunc";
platforms = lib.platforms.darwin;
};
}

View File

@@ -14,16 +14,16 @@
buildNpmPackage rec {
pname = "pi-coding-agent";
version = "0.54.0";
version = "0.67.5";
src = fetchFromGitHub {
owner = "badlogic";
repo = "pi-mono";
rev = "v${version}";
hash = "sha256-j8h8KKt/1m47Y6/KA8g213gooq0n2fAqBVkKhHsBCGw=";
hash = "sha256-Pw2f/6rKGWzmSdswungerrGrR6i9tUVFNiA4xaNygsQ=";
};
npmDepsHash = "sha256-L2kP2VpRNg+YeZjvXyn+Soly2wlff4jpZ5qa3T43quE=";
npmDepsHash = "sha256-L53UEVQNsLoSkmP9L9AZQ74iThdMFBgtnLaXqZHqBRw=";
nativeBuildInputs = [ pkg-config ];

View File

@@ -0,0 +1,90 @@
{ lib
, fetchgit
, fetchurl
, python312
, snappy
,
}:
let
pythonPackages = python312.pkgs;
# ── Python Dependency Overrides ──────────────────────────────
#
# dfindexeddb pins python-snappy==0.6.1 and zstd==1.5.5.1.
# nixpkgs ships newer versions, so we build the exact pins
# from PyPI source tarballs.
python-snappy = pythonPackages.buildPythonPackage rec {
pname = "python-snappy";
version = "0.6.1";
format = "setuptools";
src = fetchurl {
url = "https://files.pythonhosted.org/packages/98/7a/44a24bad98335b2c72e4cadcdecf79f50197d1bab9f22f863a274f104b96/python-snappy-0.6.1.tar.gz";
hash = "sha256-tqEHqwYgasxTWdTFYyvZsi1EhwKnmzFpsMYuD7gIuyo=";
};
buildInputs = [ snappy ];
doCheck = false;
};
zstd-python = pythonPackages.buildPythonPackage rec {
pname = "zstd";
version = "1.5.5.1";
format = "setuptools";
src = fetchurl {
url = "https://files.pythonhosted.org/packages/source/z/zstd/zstd-1.5.5.1.tar.gz";
hash = "sha256-HvmAq/Dh4HKwKNLXbvlbR2YyZRyWIlzzC2Gcbu9iVnI=";
};
doCheck = false;
};
dfindexeddb = pythonPackages.buildPythonPackage rec {
pname = "dfindexeddb";
version = "20260210";
format = "setuptools";
src = fetchurl {
url = "https://files.pythonhosted.org/packages/source/d/dfindexeddb/dfindexeddb-20260210.tar.gz";
hash = "sha256-4ahEe4Lpoh0oqGR6kI7J1HEGfvKVEzu3qQ+3ykgFd/Y=";
};
propagatedBuildInputs = [
python-snappy
zstd-python
];
doCheck = false;
};
in
pythonPackages.buildPythonApplication {
pname = "slack-cli";
version = "0.1.0";
format = "pyproject";
src = fetchgit {
url = "https://gitea.va.reichard.io/evan/slack-cli.git";
rev = "0a9484257a2adc414aa4cdab4fb9539a37e04d1f";
hash = "sha256-FbzE1yRdVIhmhqrxtT3C/Pomqv8iAjI9ydQGBZr+UgY=";
};
build-system = [ pythonPackages.setuptools ];
dependencies = [ dfindexeddb ];
doCheck = false;
meta = {
description = "Read Slack messages from local Chromium IndexedDB cache";
homepage = "https://gitea.va.reichard.io/evan/slack-cli";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ evanreichard ];
mainProgram = "slack-cli";
platforms = lib.platforms.darwin;
};
}

View File

@@ -28,12 +28,21 @@
KeyRepeat = 2;
NSWindowShouldDragOnGesture = true;
AppleICUForce24HourTime = true;
_HIHideMenuBar = true;
};
WindowManager = {
HideDesktop = true;
StandardHideDesktopIcons = true;
};
finder = {
CreateDesktop = false;
};
};
system.activationScripts.postActivation.text = ''
sudo defaults write /Library/Preferences/com.apple.iokit.AmbientLightSensor "Automatic Display Enabled" -bool false
'';
security.pam.services.sudo_local.touchIdAuth = true;
reichard = { };

View File

@@ -0,0 +1,80 @@
{ namespace
, lib
, modulesPath
, ...
}:
let
inherit (lib.${namespace}) enabled;
in
{
imports = [
(modulesPath + "/profiles/qemu-guest.nix")
];
system.stateVersion = "25.11";
time.timeZone = "America/New_York";
programs.nix-ld.enable = true;
# System Config
reichard = {
nix = enabled;
system = {
boot = {
enable = true;
silentBoot = true;
};
disk = {
enable = true;
diskPath = "/dev/vda";
};
networking = {
enable = true;
useStatic = {
interface = "enp0s1";
address = "192.168.64.3";
defaultGateway = "192.168.64.1";
nameservers = [ "192.168.64.1" ];
};
};
};
services = {
openssh = enabled;
mosh = enabled;
};
virtualisation = {
podman = enabled;
};
};
# Trust Interface & NAT All Ports
networking = {
firewall.trustedInterfaces = [ "enp0s1" ];
nftables.enable = true;
nftables.ruleset = ''
table ip nat {
chain prerouting {
type nat hook prerouting priority dstnat; policy accept;
iifname "enp0s1" meta l4proto tcp dnat ip to 127.0.0.1
iifname "enp0s1" meta l4proto udp dnat ip to 127.0.0.1
}
}
'';
};
# Allow NAT
boot.kernel.sysctl = {
"net.ipv4.conf.all.route_localnet" = 1;
};
fileSystems."/mnt/host-share" = {
device = "share";
fsType = "virtiofs";
options = [ "defaults" ];
};
}