Skip to content

Programs

Source directory: modules/programs/

1password.nix

modules/programs/1password.nix

Options: enable

Options declaration (Nix)
  options.security.onepassword = {
    enable = mkEnableOption {
      description = "Enable 1Password integration";
      default = false;
    };
  }

chrome-pwa-icons.nix

modules/programs/chrome-pwa-icons.nix

Chrome PWA Icon Sync

Chromium-based browsers install PWAs as .desktop files referencing icons by bare name (Icon=chrome--Profile_) but store the actual PNG files only inside ~/.config/google-chrome/Profile /Web Applications/Manifest Resources//Icons/. That path is not on any XDG icon search path, so launchers (COSMIC, GNOME) fall back to a generic placeholder.

This module installs a per-user oneshot service + timer that symlinks every Chrome-downloaded PWA icon into ~/.local/share/icons/hicolor/x/apps/ and refreshes the GTK icon cache. Idempotent, fast, and reversible.

Tracked in issue #397.

  • Enable option: Chrome PWA icon sync into the XDG hicolor tree
Options declaration (Nix)
  options.modules.programs.chrome-pwa-icons = {
    enable = lib.mkEnableOption "Chrome PWA icon sync into the XDG hicolor tree";

    user = lib.mkOption {
      type = lib.types.str;
      example = "alice";
      description = ''
        User whose Chrome profiles will be scanned and whose
        ~/.local/share/icons/hicolor tree will receive the symlinks.
      '';
    };

    syncIntervalMinutes = lib.mkOption {
      type = lib.types.ints.between 0 1440;
      default = 15;
      description = ''
        How often the timer fires while the user is logged in. Set to 0 to
        disable the timer (the service still runs once at login).
      '';
    };
  }

claude-code-managed.nix

modules/programs/claude-code-managed.nix

Claude Code managed-settings.json

Renders /etc/claude-code/managed-settings.json — Claude Code's highest- precedence config layer. The CLI reads this file but NEVER writes to it, making the read-only nix-store backing both safe and correct.

Use this for settings the user must not be able to disable from the CLI (PARR hooks, baseline permissions, apiKeyHelper). User-scope preferences like statusLine and enabledPlugins should NOT live here — see the init- template pattern in home/development/claude-code-lsp.nix instead.

Reference: https://code.claude.com/docs/en/settings.md Tracked in issue #398.

  • Enable option: Claude Code managed-settings.json (read-only baseline)
  • Enable option: Claude Code notification hooks (Notification/Stop/SubagentStop)
Options declaration (Nix)
  options.modules.programs.claude-code-managed = {
    enable = lib.mkEnableOption "Claude Code managed-settings.json (read-only baseline)";

    settings = lib.mkOption {
      type = lib.types.attrsOf lib.types.anything;
      default = { };
      example = lib.literalExpression ''
        {
          permissions.deny = [ "Bash(rm -rf /*)" ];
          apiKeyHelper = "/run/wrappers/bin/op-claude-key";
        }
      '';
      description = ''
        Settings to write into /etc/claude-code/managed-settings.json.
        Claude Code reads this with highest precedence and never writes back.
        Anything here is effectively unmodifiable from the CLI/UI.
      '';
    };

    parrProtocol.enable = lib.mkOption {
      type = lib.types.bool;
      default = true;
      description = ''
        Inject the PARR (Plan, Act, Reflect, Revise) UserPromptSubmit hook.
        Equivalent to the previous programs.claudeCode.hooks.enableParrProtocol
        option, but enforced from managed scope so the user cannot disable it
        by editing ~/.claude/settings.json.
      '';
    };

    baselineAllow.enable = lib.mkOption {
      type = lib.types.bool;
      default = true;
      description = ''
        Auto-approve a curated baseline of safe, read-only / build / test /
        format commands (nix build/eval/fmt, just validate/test-*, read-only
        git, statix/deadnix/alejandra) via managed-scope permissions.allow, so
        routine repo operations never trigger a permission prompt. System-
        mutating commands (deploys, nixos-rebuild, git commit/push, sudo, rm)
        are deliberately excluded and still require explicit approval.
      '';
    };

    formatOnEdit.enable = lib.mkOption {
      type = lib.types.bool;
      default = true;
      description = ''
        Run nixpkgs-fmt (the repo's pre-commit formatter) on any .nix file
        Claude Code edits, via a managed-scope PostToolUse hook. Keeps touched
        files commit-clean automatically. No-ops on non-.nix paths and never
        fails the tool.
      '';
    };

    # Notification submodule — surfaces Claude Code lifecycle events as
    # desktop toasts and/or tmux popups/status flashes via the
    # `claude-notify` helper rendered above. Defaults match the use case
    # from the original conversation: high-signal Notification → both
    # toast and popup, rate-limited Stop/SubagentStop → status flash.
    notifications = {
      enable = lib.mkEnableOption "Claude Code notification hooks (Notification/Stop/SubagentStop)";

      events = {
        notification = lib.mkOption {
          type = lib.types.bool;
          default = true;
          description = ''
            Fire claude-notify on the Notification hook (Claude wants user
            attention, e.g. waiting on permission or completing a long
            run). High signal — recommended always on.
          '';
        };
        stop = lib.mkOption {
          type = lib.types.bool;
          default = true;
          description = ''
            Fire claude-notify on the Stop hook (every assistant turn).
            Rate-limited by `rateLimitSeconds` so quick back-and-forth
            doesn't spam the status bar.
          '';
        };
        subagentStop = lib.mkOption {
          type = lib.types.bool;
          default = true;
          description = ''
            Fire claude-notify on the SubagentStop hook (spawned subagent
            finished). Rate-limited like Stop.
          '';
        };
      };
# … truncated — see source link above

claude-router-cli.nix

modules/programs/claude-router-cli.nix

Claude Code router CLI — switches repos between local Ollama (via LiteLLM on p620) and cloud Anthropic API per repository.

Phase 3 of docs/plans/2026-05-22-ollama-p620-litellm-design.md. Depends on Phase 1 (Ollama on p620) + Phase 2 (LiteLLM proxy on p620).

What this module installs:

  1. claude-router CLI on system PATH: claude-router use-ollama — writes /.claude/settings.json with ANTHROPIC_BASE_URL pointing at the right router URL (loopback on p620, Tailscale on razer) claude-router use-claude — removes the override (back to api.anthropic.com) claude-router use-default — alias for use-claude claude-router status — prints which backend the current repo uses

  2. claude-router-key helper script for Claude Code's apiKeyHelper: inspects ANTHROPIC_BASE_URL and emits the right bearer key:

  3. router URL → /run/agenix/api-router- (LiteLLM bearer)
  4. default URL → /run/agenix/api-anthropic (cloud Anthropic) This is auto-wired into modules.programs.claude-code-managed.settings.apiKeyHelper.

  5. Slash command markdown files at /etc/claude-code/commands/ for users who want the slash-command UX. Home Manager users can symlink them into ~/.claude/commands/ (a HM stanza is provided in the user's profile for olafkfreund — see Users/olafkfreund/profile.nix).

Network endpoint selection happens at write-time in claude-router use-ollama: - on p620 → http://127.0.0.1:4000 (loopback, sub-ms) - elsewhere → https://p620..ts.net/router (Tailscale)

The bearer key for the router and the key for cloud Anthropic are BOTH agenix-managed; the user never types them.

  • Enable option: claude-router CLI + apiKeyHelper for routing Claude Code between local Ollama and cloud Anthropic
Options declaration (Nix)
  options.modules.programs.claude-router-cli = {
    enable = lib.mkEnableOption "claude-router CLI + apiKeyHelper for routing Claude Code between local Ollama and cloud Anthropic";

    routerHostKey = lib.mkOption {
      type = lib.types.str;
      default = "api-router-${config.networking.hostName}";
      description = ''
        Name of the agenix secret holding this host's bearer key for the
        LiteLLM router. Defaults to api-router-<hostname>.
      '';
    };
  }

dconf.nix

modules/programs/dconf.nix

No option declarations; see source for implementation.

default.nix

modules/programs/default.nix

No option declarations; see source for implementation.

droidcam.nix

modules/programs/droidcam.nix

Options: enable

Options declaration (Nix)
  options.media.droidcam = {
    enable = mkEnableOption {
      description = "Enable Droicam";
      default = false;
    };
  }

firefox.nix

modules/programs/firefox.nix

No option declarations; see source for implementation.

gnupg.nix

modules/programs/gnupg.nix

Options: enable

Options declaration (Nix)
  options.security.gnupg = {
    enable = mkEnableOption {
      default = false;
      description = "Enable GnuPG";
    };
  }

nix-ld.nix

modules/programs/nix-ld.nix

No option declarations; see source for implementation.

stream_deck.nix

modules/programs/stream_deck.nix

Options: enable

Options declaration (Nix)
  options.program.streamcontroller = {
    enable = mkEnableOption {
      description = "Enable Streamcontroller";
      default = false;
    };
  }

wshowkeys.nix

modules/programs/wshowkeys.nix

No option declarations; see source for implementation.

yt-x.nix

modules/programs/yt-x.nix

  • Enable option: yt-x terminal YouTube browser

Options: enable

Options declaration (Nix)
  options.features.programs.yt-x = {
    enable = mkEnableOption "yt-x terminal YouTube browser";
  }