{ lib, config, pkgs, inputs, ... }: let inherit (lib) mkIf; inherit (lib.metacfg) mkBoolOpt; cfg = config.metacfg.cli-apps.opencode; opencodeConfig = { "$schema" = "https://opencode.ai/config.json"; lsp = true; # Auto-format on save is disabled: opencode reformats files between the # model's edits, which desyncs its view and breaks follow-up edits. The # formatters remain available on PATH (home.packages) for manual use. formatter = false; 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; }; }