feat(opencode): add opencode configuration

This commit is contained in:
2026-03-26 22:30:44 +01:00
parent 773d28e40b
commit 3dc0fb36c2
5 changed files with 187 additions and 26 deletions
+3 -2
View File
@@ -2,7 +2,6 @@
config,
lib,
pkgs,
inputs,
...
}:
with lib; let
@@ -12,6 +11,7 @@ in {
imports = [
./claude.nix
./ollama.nix
./opencode.nix
];
options.home.dev.ai = {
@@ -29,8 +29,9 @@ in {
mcpServers = mkDefault cfg.mcpServers;
};
ollama.enable = mkDefault cfg.enable;
opencode.enable = mkDefault cfg.enable;
};
packages = [pkgs.lmstudio pkgs.opencode];
packages = [pkgs.lmstudio];
};
programs.mcp = mkIf (cfg.mcpServers != {}) {
enable = true;
+105
View File
@@ -0,0 +1,105 @@
{
config,
lib,
inputs,
pkgs,
...
}:
with lib; let
inherit (pkgs.stdenv.hostPlatform) system;
cfg = config.home.dev.ai.opencode;
defaultPackageCli = inputs.opencode.packages.${system}.opencode;
defaultPackageDesktop = inputs.opencode.packages.${system}.desktop;
corsString = cors:
{
null = "";
string = v: trim v;
path = v: trim (readFile v);
}
.${
if cors == null
then "null"
else typeOf cors
};
corsList = domains: lists.remove "" (lists.forEach (strings.splitString "," domains) trim);
corsDomains = domains:
lists.flatten (
lists.forEach (lists.remove "" (lists.forEach (strings.splitString "," domains) trim)) (domain: [
"--cors"
domain
])
);
in {
options.home.dev.ai.opencode = {
enable = mkEnableOption "Enables OpenCode";
package = mkOption {
type = types.package;
default = defaultPackageCli;
description = "The CLI package for OpenCode";
};
settings = mkOption {
type = types.json;
default = {};
};
tui = mkOption {
type = types.json;
default = {};
};
desktop = {
enable = mkEnableOption "Enables the desktop app";
package = mkOption {
type = types.package;
default = defaultPackageDesktop;
description = "The desktop package for OpenCode";
};
};
web = {
enable = mkEnableOption "Enables OpenCode web";
extraArgs = mkOption {
type = types.listOf types.str;
default = [];
example = [
"--hostname"
"0.0.0.0"
];
};
cors = mkOption {
type = types.nullOr (types.either types.str types.path);
default = null;
example = "opencode.example.com,code.example.com";
description = ''
Either a string containing the domain allowed to connect to OpenCodes web instance, or a file containing the target value. The latter is useful when using secret management if you dont want to publicize the hostname of your OpenCode instance.
If you want to use multiple domains, you can separate them with a comma.
'';
};
mdns = {
enable = mkEnableOption "Enables mDNS with OpenCode";
hostname = mkOption {
type = types.nullOr types.str;
default = null;
example = "opencode.local";
};
};
};
};
config.programs.opencode = mkIf cfg.enable {
inherit (cfg) enable tui;
enableMcpIntegration = true;
extraPackages = with pkgs; [uv];
settings = let
cors = corsString cfg.web.cors;
in
{
server = mkIf cfg.web.mdns.enable {
mdns = true;
mdnsDomain = mkIf (cfg.web.mdns.hostname != null) cfg.web.mdns.hostname;
cors = corsList cfg.web.cors;
};
}
// cfg.settings;
web = {
inherit (cfg.web) enable extraArgs;
};
};
}
+52
View File
@@ -0,0 +1,52 @@
{config, ...}: {
home.dev.ai = {
enable = true;
opencode = {
tui = {
mouse = true;
theme = "nord";
attention = {
enabled = true;
notifications = true;
};
keybinds = {
leader = "ctrl+x";
"command_list" = "<leader><leader>";
};
};
settings = {
autoupdate = false;
provider = {
ollama = {
npm = "@ai-sdk/openai-compatible";
name = "Ollama (marpa)";
options.baseURL = "http://marpa:11434/v1";
};
models = {
"qwen3.5:9b".name = "Qwen 3.5 Medium";
"gemma4:e4b".name = "Gemma E4B";
"qwen2.5-coder:1.5b-base".name = "Qwen 2.5 Coder Light";
};
};
permission = {
"*" = "ask";
read = {
"*" = "allow";
"*.env" = "deny";
"*.env.*" = "deny";
"*.env.example" = "allow";
};
};
formatter.nixfmt = {
command = ["nix" "fmt" "$FILE"];
extensions = [".nix"];
};
};
web = {
enable = true;
cors = config.sops.secrets."opencode/cors".path;
mdns.enable = true;
};
};
};
}
+2 -1
View File
@@ -5,6 +5,7 @@
...
}: {
imports = [
./ai.nix
./light-home.nix
./packages.nix
./email.nix
@@ -56,6 +57,7 @@
emailPassword = {};
"mopidy/bandcamp" = {};
"mopidy/spotify" = {};
"opencode/cors" = {};
};
home = {
@@ -86,7 +88,6 @@
};
};
dev = {
ai.claude.enable = true;
editors.emacs.package = emacsPackage;
vcs.jj.signing.enable = true;
};