main
  1{
  2  den,
  3  inputs,
  4  ...
  5}: {
  6  den.aspects.dev.agents.goose = {
  7    includes = [den.aspects.dev.agents];
  8
  9    persistHome = {config, ...}: {
 10      directories = [
 11        "${config.xdg.config.directory}/goose"
 12      ];
 13    };
 14
 15    cacheHome = {config, ...}: {
 16      directories = [
 17        "${config.xdg.state.directory}/goose"
 18      ];
 19    };
 20
 21    hjem = {
 22      pkgs,
 23      lib,
 24      config,
 25      ...
 26    }: let
 27      goose-cli = pkgs.goose-cli.overrideAttrs (oldAttrs: {
 28        nativeBuildInputs = oldAttrs.nativeBuildInputs ++ [pkgs.installShellFiles];
 29        postInstall = ''
 30          installShellCompletion --cmd goose \
 31            --bash <($out/bin/goose completion bash) \
 32            --fish <($out/bin/goose completion fish) \
 33            --nushell <($out/bin/goose completion nu) \
 34            --zsh <($out/bin/goose completion zsh)
 35        '';
 36      });
 37
 38      configPath = "${config.xdg.config.directory}/goose/config.yaml";
 39
 40      desiredConfig = (pkgs.formats.yaml {}).generate "goose-config.yaml" {
 41        GOOSE_TELEMETRY_ENABLED = false;
 42        GOOSE_MODE = "smart_approve";
 43      };
 44
 45      mkJailedAgent =
 46        (import ./_jail.nix {
 47          inherit pkgs;
 48          jail = inputs.jail-nix.lib.init pkgs;
 49        }).mkJailedAgent;
 50
 51      agent = mkJailedAgent {
 52        name = "goose";
 53        pkg = goose-cli;
 54        configPaths = [
 55          "${config.xdg.config.directory}/goose"
 56          "${config.xdg.state.directory}/goose"
 57        ];
 58      };
 59    in {
 60      packages = [agent.jailed agent.unjailed];
 61
 62      xdg.config.files."goose/permission.yaml" = {
 63        type = "copy";
 64        permissions = "0644";
 65        generator = (pkgs.formats.yaml {}).generate "goose-permission.yaml";
 66        value = {
 67          user = {
 68            always_allow = [
 69              "tree"
 70              "todo__todo_write"
 71            ];
 72            ask_before = [
 73              "write"
 74              "edit"
 75            ];
 76            never_allow = [
 77            ];
 78          };
 79        };
 80      };
 81
 82      systemd.services.goose-config = {
 83        description = "Merge the Nix-managed Goose config into the existing config";
 84
 85        wantedBy = ["default.target"];
 86        restartTriggers = [desiredConfig];
 87        path = [pkgs.coreutils pkgs.yq-go];
 88
 89        serviceConfig = {
 90          Type = "oneshot";
 91          RemainAfterExit = true;
 92          UMask = "0077";
 93        };
 94
 95        script = ''
 96          mkdir -p "$(dirname ${lib.escapeShellArg configPath})"
 97          touch ${lib.escapeShellArg configPath}
 98          yq eval-all '. as $item ireduce ({}; . * $item)' \
 99            ${lib.escapeShellArg configPath} ${desiredConfig} \
100            > ${lib.escapeShellArg configPath}.tmp
101          mv ${lib.escapeShellArg configPath}.tmp ${lib.escapeShellArg configPath}
102        '';
103      };
104    };
105  };
106}