{ lib, config, pkgs, inputs, ... }: let inherit (lib) mkIf; inherit (lib.metacfg) mkBoolOpt; cfg = config.metacfg.cli-apps.opencode; # Formatters opencode runs on save, each pinned to its exact store path. formatters = { nixfmt = { command = [ (lib.getExe pkgs.nixfmt-rfc-style) "$FILE" ]; extensions = [ ".nix" ]; }; prettier = { command = [ (lib.getExe pkgs.nodePackages.prettier) "--write" "$FILE" ]; extensions = [ ".md" ".yaml" ".yml" ".json" ".css" ".html" ".js" ".ts" ".jsx" ".tsx" ]; }; shfmt = { command = [ (lib.getExe pkgs.shfmt) "-w" "$FILE" ]; extensions = [ ".sh" ".bash" ]; }; ruff = { command = [ (lib.getExe pkgs.ruff) "format" "$FILE" ]; extensions = [ ".py" ]; }; taplo = { command = [ (lib.getExe pkgs.taplo) "format" "$FILE" ]; extensions = [ ".toml" ]; }; stylua = { command = [ (lib.getExe pkgs.stylua) "$FILE" ]; extensions = [ ".lua" ]; }; }; opencodeConfig = { "$schema" = "https://opencode.ai/config.json"; lsp = true; formatter = formatters; disabled_providers = [ "opencode" ]; provider.halo = { npm = "@ai-sdk/openai-compatible"; name = "Halo"; options.baseURL = "http://halo:8000/v1"; models.coder.name = "coder"; }; }; obsidianSkills = lib.mapAttrs' ( name: _: lib.nameValuePair ".agents/skills/${name}" { source = "${inputs.obsidian-skills}/skills/${name}"; recursive = true; } ) ( lib.filterAttrs (_: type: type == "directory") (builtins.readDir "${inputs.obsidian-skills}/skills") ); in { options.metacfg.cli-apps.opencode = { enable = mkBoolOpt true "Enable opencode config."; }; config = mkIf cfg.enable { # Also expose the formatters on PATH for interactive use. home.packages = [ pkgs.nixfmt-rfc-style pkgs.nodePackages.prettier pkgs.shfmt pkgs.ruff pkgs.taplo pkgs.stylua ]; # The agents/, commands/ and other files come from the repo dir; config.json # is generated from opencodeConfig above so formatter paths stay pinned. xdg.configFile."opencode" = { source = ../../../../config/opencode; recursive = true; }; xdg.configFile."opencode/config.json".source = (pkgs.formats.json { }).generate "opencode-config.json" opencodeConfig; home.file = { ".agents/skills" = { source = ../../../../config/agents/skills; recursive = true; }; } // obsidianSkills; }; }