atagen

roundabout

public
Star0
Watch0
fdad58f8133a77a20c44d0e1472cb73a5128ef2c
1
ssh://brewery@pls.lobotomise.me:33/atagen/roundabout.git

Blame: nix/nixos-module.nix

052a1a49371catagen2026-09-27 03:59 UTC1
self:
052a1a49371catagen2026-09-27 03:59 UTC2
{
052a1a49371catagen2026-09-27 03:59 UTC3
  config,
052a1a49371catagen2026-09-27 03:59 UTC4
  lib,
052a1a49371catagen2026-09-27 03:59 UTC5
  pkgs,
052a1a49371catagen2026-09-27 03:59 UTC6
  ...
052a1a49371catagen2026-09-27 03:59 UTC7
}:
052a1a49371catagen2026-09-27 03:59 UTC8
052a1a49371catagen2026-09-27 03:59 UTC9
let
052a1a49371catagen2026-09-27 03:59 UTC10
  cfg = config.programs.roundabout;
052a1a49371catagen2026-09-27 03:59 UTC11
  toml = pkgs.formats.toml { };
052a1a49371catagen2026-09-27 03:59 UTC12
  plugin = pkgs.callPackage ./plugin.nix { roundabout = cfg.package; };
4e5ca2e20401atagen2026-09-28 11:42 UTC13
  codexPlugin = pkgs.callPackage ./codex-plugin.nix { roundabout = cfg.package; };
4e5ca2e20401atagen2026-09-28 11:42 UTC14
  ompPlugin = pkgs.callPackage ./omp-plugin.nix { roundabout = cfg.package; };
052a1a49371catagen2026-09-27 03:59 UTC15
in
052a1a49371catagen2026-09-27 03:59 UTC16
{
052a1a49371catagen2026-09-27 03:59 UTC17
  options.programs.roundabout = {
052a1a49371catagen2026-09-27 03:59 UTC18
    enable = lib.mkEnableOption "roundabout, build admission for agents";
052a1a49371catagen2026-09-27 03:59 UTC19
052a1a49371catagen2026-09-27 03:59 UTC20
    package = lib.mkOption {
052a1a49371catagen2026-09-27 03:59 UTC21
      type = lib.types.package;
052a1a49371catagen2026-09-27 03:59 UTC22
      default = self.packages.${pkgs.stdenv.hostPlatform.system}.roundabout;
052a1a49371catagen2026-09-27 03:59 UTC23
      defaultText = lib.literalExpression "roundabout.packages.\${system}.roundabout";
052a1a49371catagen2026-09-27 03:59 UTC24
      description = "the roundabout package";
052a1a49371catagen2026-09-27 03:59 UTC25
    };
052a1a49371catagen2026-09-27 03:59 UTC26
052a1a49371catagen2026-09-27 03:59 UTC27
    socketActivation = lib.mkOption {
052a1a49371catagen2026-09-27 03:59 UTC28
      type = lib.types.bool;
052a1a49371catagen2026-09-27 03:59 UTC29
      default = true;
052a1a49371catagen2026-09-27 03:59 UTC30
      description = ''
052a1a49371catagen2026-09-27 03:59 UTC31
        let a systemd user socket own `$XDG_RUNTIME_DIR/roundabout.sock` and start the
052a1a49371catagen2026-09-27 03:59 UTC32
        daemon on demand. when disabled, the first client spawns daemon instead
052a1a49371catagen2026-09-27 03:59 UTC33
      '';
052a1a49371catagen2026-09-27 03:59 UTC34
    };
052a1a49371catagen2026-09-27 03:59 UTC35
052a1a49371catagen2026-09-27 03:59 UTC36
    settings = lib.mkOption {
052a1a49371catagen2026-09-27 03:59 UTC37
      inherit (toml) type;
052a1a49371catagen2026-09-27 03:59 UTC38
      default = { };
052a1a49371catagen2026-09-27 03:59 UTC39
      example = lib.literalExpression ''
052a1a49371catagen2026-09-27 03:59 UTC40
        {
052a1a49371catagen2026-09-27 03:59 UTC41
          budget.ram = "16GiB";
052a1a49371catagen2026-09-27 03:59 UTC42
          enforce.unwrapped = "wrap";
052a1a49371catagen2026-09-27 03:59 UTC43
          artifacts.stop = "block";
052a1a49371catagen2026-09-27 03:59 UTC44
        }
052a1a49371catagen2026-09-27 03:59 UTC45
      '';
052a1a49371catagen2026-09-27 03:59 UTC46
      description = ''
052a1a49371catagen2026-09-27 03:59 UTC47
        written to `/etc/roundabout/config.toml`, which anyone without a
052a1a49371catagen2026-09-27 03:59 UTC48
        `~/.config/roundabout/config.toml` of their own gets. see readme
052a1a49371catagen2026-09-27 03:59 UTC49
      '';
052a1a49371catagen2026-09-27 03:59 UTC50
    };
052a1a49371catagen2026-09-27 03:59 UTC51
052a1a49371catagen2026-09-27 03:59 UTC52
    claude = {
052a1a49371catagen2026-09-27 03:59 UTC53
      hooks = lib.mkOption {
052a1a49371catagen2026-09-27 03:59 UTC54
        type = lib.types.attrs;
052a1a49371catagen2026-09-27 03:59 UTC55
        readOnly = true;
052a1a49371catagen2026-09-27 03:59 UTC56
        default = import ./hooks.nix {
052a1a49371catagen2026-09-27 03:59 UTC57
          inherit lib;
052a1a49371catagen2026-09-27 03:59 UTC58
          roundabout = cfg.package;
052a1a49371catagen2026-09-27 03:59 UTC59
        };
052a1a49371catagen2026-09-27 03:59 UTC60
        defaultText = lib.literalMD "roundabout's hooks, keyed by event";
052a1a49371catagen2026-09-27 03:59 UTC61
        description = ''
052a1a49371catagen2026-09-27 03:59 UTC62
          hooks in `settings.json` shape, for whatever writes your claude config.
052a1a49371catagen2026-09-27 03:59 UTC63
          lists concatenate under the json format type, so they sit alongside
052a1a49371catagen2026-09-27 03:59 UTC64
          hooks you already have
052a1a49371catagen2026-09-27 03:59 UTC65
        '';
052a1a49371catagen2026-09-27 03:59 UTC66
      };
052a1a49371catagen2026-09-27 03:59 UTC67
052a1a49371catagen2026-09-27 03:59 UTC68
      skill = lib.mkOption {
052a1a49371catagen2026-09-27 03:59 UTC69
        type = lib.types.path;
052a1a49371catagen2026-09-27 03:59 UTC70
        readOnly = true;
052a1a49371catagen2026-09-27 03:59 UTC71
        default = "${plugin}/plugins/roundabout/skills/roundabout";
052a1a49371catagen2026-09-27 03:59 UTC72
        defaultText = lib.literalMD "the roundabout skill directory";
052a1a49371catagen2026-09-27 03:59 UTC73
        description = "the skill directory, for configs that manage `~/.claude/skills` themselves";
052a1a49371catagen2026-09-27 03:59 UTC74
      };
052a1a49371catagen2026-09-27 03:59 UTC75
052a1a49371catagen2026-09-27 03:59 UTC76
      plugin = lib.mkOption {
052a1a49371catagen2026-09-27 03:59 UTC77
        type = lib.types.package;
052a1a49371catagen2026-09-27 03:59 UTC78
        readOnly = true;
052a1a49371catagen2026-09-27 03:59 UTC79
        default = plugin;
052a1a49371catagen2026-09-27 03:59 UTC80
        defaultText = lib.literalMD "the roundabout plugin marketplace";
052a1a49371catagen2026-09-27 03:59 UTC81
        description = "hooks and skill as a marketplace, for `claude plugin marketplace add`";
052a1a49371catagen2026-09-27 03:59 UTC82
      };
052a1a49371catagen2026-09-27 03:59 UTC83
    };
4e5ca2e20401atagen2026-09-28 11:42 UTC84
4e5ca2e20401atagen2026-09-28 11:42 UTC85
    codex = {
4e5ca2e20401atagen2026-09-28 11:42 UTC86
      hooks = lib.mkOption {
4e5ca2e20401atagen2026-09-28 11:42 UTC87
        type = lib.types.attrs;
4e5ca2e20401atagen2026-09-28 11:42 UTC88
        readOnly = true;
4e5ca2e20401atagen2026-09-28 11:42 UTC89
        default = import ./codex-hooks.nix {
4e5ca2e20401atagen2026-09-28 11:42 UTC90
          inherit lib;
4e5ca2e20401atagen2026-09-28 11:42 UTC91
          roundabout = cfg.package;
4e5ca2e20401atagen2026-09-28 11:42 UTC92
        };
4e5ca2e20401atagen2026-09-28 11:42 UTC93
        defaultText = lib.literalMD "roundabout's Codex hooks, keyed by event";
4e5ca2e20401atagen2026-09-28 11:42 UTC94
        description = "hooks in Codex hooks.json shape, for configs that manage Codex themselves";
4e5ca2e20401atagen2026-09-28 11:42 UTC95
      };
4e5ca2e20401atagen2026-09-28 11:42 UTC96
4e5ca2e20401atagen2026-09-28 11:42 UTC97
      skill = lib.mkOption {
4e5ca2e20401atagen2026-09-28 11:42 UTC98
        type = lib.types.path;
4e5ca2e20401atagen2026-09-28 11:42 UTC99
        readOnly = true;
4e5ca2e20401atagen2026-09-28 11:42 UTC100
        default = "${codexPlugin}/plugins/roundabout/skills/roundabout";
4e5ca2e20401atagen2026-09-28 11:42 UTC101
        defaultText = lib.literalMD "the roundabout skill directory for Codex";
4e5ca2e20401atagen2026-09-28 11:42 UTC102
        description = "the skill directory, for configs that manage Codex skills themselves";
4e5ca2e20401atagen2026-09-28 11:42 UTC103
      };
4e5ca2e20401atagen2026-09-28 11:42 UTC104
4e5ca2e20401atagen2026-09-28 11:42 UTC105
      plugin = lib.mkOption {
4e5ca2e20401atagen2026-09-28 11:42 UTC106
        type = lib.types.package;
4e5ca2e20401atagen2026-09-28 11:42 UTC107
        readOnly = true;
4e5ca2e20401atagen2026-09-28 11:42 UTC108
        default = codexPlugin;
4e5ca2e20401atagen2026-09-28 11:42 UTC109
        defaultText = lib.literalMD "the roundabout Codex plugin marketplace";
4e5ca2e20401atagen2026-09-28 11:42 UTC110
        description = "hooks and skill as a marketplace for Codex";
4e5ca2e20401atagen2026-09-28 11:42 UTC111
      };
4e5ca2e20401atagen2026-09-28 11:42 UTC112
    };
4e5ca2e20401atagen2026-09-28 11:42 UTC113
4e5ca2e20401atagen2026-09-28 11:42 UTC114
    omp = {
4e5ca2e20401atagen2026-09-28 11:42 UTC115
      plugin = lib.mkOption {
4e5ca2e20401atagen2026-09-28 11:42 UTC116
        type = lib.types.package;
4e5ca2e20401atagen2026-09-28 11:42 UTC117
        readOnly = true;
4e5ca2e20401atagen2026-09-28 11:42 UTC118
        default = ompPlugin;
4e5ca2e20401atagen2026-09-28 11:42 UTC119
        defaultText = lib.literalMD "the roundabout OMP plugin";
4e5ca2e20401atagen2026-09-28 11:42 UTC120
        description = "the extension and skill for omp plugin link";
4e5ca2e20401atagen2026-09-28 11:42 UTC121
      };
4e5ca2e20401atagen2026-09-28 11:42 UTC122
4e5ca2e20401atagen2026-09-28 11:42 UTC123
      skill = lib.mkOption {
4e5ca2e20401atagen2026-09-28 11:42 UTC124
        type = lib.types.path;
4e5ca2e20401atagen2026-09-28 11:42 UTC125
        readOnly = true;
4e5ca2e20401atagen2026-09-28 11:42 UTC126
        default = "${ompPlugin}/skills/roundabout";
4e5ca2e20401atagen2026-09-28 11:42 UTC127
        defaultText = lib.literalMD "the roundabout skill directory for OMP";
4e5ca2e20401atagen2026-09-28 11:42 UTC128
        description = "the skill directory, for configs that manage OMP skills themselves";
4e5ca2e20401atagen2026-09-28 11:42 UTC129
      };
4e5ca2e20401atagen2026-09-28 11:42 UTC130
    };
052a1a49371catagen2026-09-27 03:59 UTC131
  };
052a1a49371catagen2026-09-27 03:59 UTC132
052a1a49371catagen2026-09-27 03:59 UTC133
  config = lib.mkIf cfg.enable {
052a1a49371catagen2026-09-27 03:59 UTC134
    environment.systemPackages = [ cfg.package ];
052a1a49371catagen2026-09-27 03:59 UTC135
052a1a49371catagen2026-09-27 03:59 UTC136
    # a real file rather than the usual /etc/static symlink, so a rebuild
052a1a49371catagen2026-09-27 03:59 UTC137
    # renames over it where the daemon's inotify watch can see
052a1a49371catagen2026-09-27 03:59 UTC138
    environment.etc."roundabout/config.toml" = lib.mkIf (cfg.settings != { }) {
052a1a49371catagen2026-09-27 03:59 UTC139
      source = toml.generate "roundabout-config.toml" cfg.settings;
052a1a49371catagen2026-09-27 03:59 UTC140
      mode = "0444";
052a1a49371catagen2026-09-27 03:59 UTC141
    };
052a1a49371catagen2026-09-27 03:59 UTC142
052a1a49371catagen2026-09-27 03:59 UTC143
    systemd.user.sockets.roundabout = lib.mkIf cfg.socketActivation {
052a1a49371catagen2026-09-27 03:59 UTC144
      description = "roundabout build admission socket";
052a1a49371catagen2026-09-27 03:59 UTC145
      wantedBy = [ "sockets.target" ];
052a1a49371catagen2026-09-27 03:59 UTC146
      listenStreams = [ "%t/roundabout.sock" ];
052a1a49371catagen2026-09-27 03:59 UTC147
      socketConfig.SocketMode = "0600";
052a1a49371catagen2026-09-27 03:59 UTC148
    };
052a1a49371catagen2026-09-27 03:59 UTC149
052a1a49371catagen2026-09-27 03:59 UTC150
    systemd.user.services.roundabout = lib.mkIf cfg.socketActivation {
052a1a49371catagen2026-09-27 03:59 UTC151
      description = "roundabout build admission daemon";
052a1a49371catagen2026-09-27 03:59 UTC152
      serviceConfig.ExecStart = "${lib.getExe cfg.package} daemon";
052a1a49371catagen2026-09-27 03:59 UTC153
    };
052a1a49371catagen2026-09-27 03:59 UTC154
  };
052a1a49371catagen2026-09-27 03:59 UTC155
}