main
  1{
  2  den,
  3  inputs,
  4  ...
  5}: {
  6  den.aspects.dev.agents.crush = {
  7    includes = [den.aspects.dev.agents];
  8
  9    persistHome = {config, ...}: {
 10      directories = [
 11        "${config.xdg.config.directory}/crush"
 12      ];
 13    };
 14
 15    cacheHome = {config, ...}: {
 16      directories = [
 17        "${config.xdg.data.directory}/crush"
 18      ];
 19    };
 20
 21    hjem = {
 22      pkgs,
 23      lib,
 24      config,
 25      ...
 26    }: let
 27      mkJailedAgent =
 28        (import ../_jail.nix {
 29          inherit pkgs;
 30          jail = inputs.jail-nix.lib.init pkgs;
 31        }).mkJailedAgent;
 32
 33      crush = pkgs.crush.overrideAttrs {
 34        patches = [
 35          # `--reasoning-levels` for crushrc `model add`, from https://github.com/charmbracelet/crush/pull/3857
 36          # TODO: drop once upstreamed.
 37          ./reasoning-level.patch
 38        ];
 39      };
 40
 41      checkPath = pkgs.callPackage ./hooks/check_path/_package.nix {};
 42
 43      agent = mkJailedAgent {
 44        name = "crush";
 45        pkg = crush;
 46        configPaths = [
 47          "${config.xdg.config.directory}/crush"
 48          "${config.xdg.data.directory}/crush"
 49        ];
 50        extraPkgs = [
 51          pkgs.nur.repos.hpcesia.dcg
 52        ];
 53      };
 54    in {
 55      packages = [agent.jailed agent.unjailed];
 56
 57      xdg.config.files = {
 58        "crush/crush.json" = {
 59          type = "copy";
 60          permissions = "0600";
 61          generator = (pkgs.formats.json {}).generate "crush.json";
 62          value = {
 63            "$schema" = "https://charm.land/crush.json";
 64          };
 65        };
 66
 67        "crush/crushrc" = {
 68          type = "copy";
 69          permissions = "0600";
 70          text = ''
 71            set -a; source ./.env; set +a
 72
 73            option global-context-path "${config.xdg.config.directory}/agents/AGENTS.md"
 74            option skill-path "${config.xdg.config.directory}/agents/skills"
 75
 76            mcp add deepwiki --type http \
 77              --url "https://mcp.deepwiki.com/mcp"
 78
 79            permissions allow ls glob
 80
 81            hook add PreToolUse \
 82              --name "check-path" \
 83              --matcher '^(view|grep|edit|write|multiedit|download|lsp_replace_symbol|lsp_rename|bash)$' \
 84              --command "${lib.getExe checkPath}"
 85
 86            hook add PreToolUse \
 87              --name "dcg" \
 88              --matcher '^bash$' \
 89              --command "${lib.getExe pkgs.nur.repos.hpcesia.dcg}"
 90
 91            source ${./provider-cline.sh}
 92          '';
 93        };
 94      };
 95    };
 96  };
 97
 98  den.aspects.dev.agents.crush.themes = {
 99    catppuccin = {
100      hjem = {
101        xdg.config.files = {
102          "crush/themes/catppuccin-mocha.json" = {
103            type = "copy";
104            permissions = "0644";
105            source = ./themes/catppuccin-mocha.json;
106          };
107
108          "crush/crush.json" = {
109            # crushrc has no theme option, so the theme is set here.
110            value = {
111              options.tui.active_theme = "catppuccin-mocha";
112            };
113          };
114        };
115      };
116    };
117  };
118
119  perSystem = {pkgs, ...}: {
120    devshells.default = {
121      packages = [
122        pkgs.go
123        pkgs.gopls
124      ];
125    };
126  };
127}