194 lines
6.6 KiB
Nix
194 lines
6.6 KiB
Nix
{ inputs, config, ... }:
|
|
let
|
|
hmModules = config.flake.modules.homeManager;
|
|
nixosModules = config.flake.modules.nixos;
|
|
in
|
|
{
|
|
flake.modules.nixos.ai =
|
|
{ pkgs, ... }:
|
|
let
|
|
ai = import ./_support/assets.nix { inherit pkgs; };
|
|
codexConfig = (pkgs.formats.toml { }).generate "codex-config.toml" {
|
|
model = "gpt-5.6-sol";
|
|
model_reasoning_effort = "high";
|
|
plan_mode_reasoning_effort = "high";
|
|
service_tier = "default";
|
|
approvals_reviewer = "auto_review";
|
|
features.hooks = true;
|
|
tui = {
|
|
status_line = [
|
|
"model-with-reasoning"
|
|
"current-dir"
|
|
"context-remaining"
|
|
"five-hour-limit"
|
|
"weekly-limit"
|
|
"git-branch"
|
|
];
|
|
status_line_use_colors = true;
|
|
};
|
|
|
|
features.plugins = true;
|
|
# The Nix package lacks the codex-package.json layout the daemon requires.
|
|
features.daemon_auto_start = false;
|
|
hooks = ai.codexHooks;
|
|
mcp_servers = ai.servers // {
|
|
context7 = ai.servers.context7 // {
|
|
http_headers_helper = "${ai.context7Headers}";
|
|
};
|
|
nixos = ai.servers.nixos // {
|
|
startup_timeout_sec = 60.0;
|
|
tools.nix.approval_mode = "approve";
|
|
};
|
|
};
|
|
};
|
|
in
|
|
{
|
|
imports = [ nixosModules.podman ];
|
|
|
|
home-manager.sharedModules = [ hmModules.ai ];
|
|
|
|
environment.etc."codex/config.toml".source = codexConfig;
|
|
|
|
nixpkgs.overlays = [ inputs.llm-agents.overlays.shared-nixpkgs ];
|
|
|
|
nix.settings = {
|
|
extra-substituters = [ "https://cache.numtide.com" ];
|
|
extra-trusted-public-keys = [
|
|
"niks3.numtide.com-1:DTx8wZduET09hRmMtKdQDxNNthLQETkc/yaX7M4qK0g="
|
|
];
|
|
};
|
|
|
|
services.ollama = {
|
|
enable = true;
|
|
package = pkgs.ollama-vulkan;
|
|
loadModels = [ "nomic-embed-text" ];
|
|
};
|
|
};
|
|
|
|
flake.modules.homeManager.ai =
|
|
{ pkgs, lib, ... }:
|
|
let
|
|
ai = import ./_support/assets.nix { inherit pkgs; };
|
|
in
|
|
{
|
|
services.podman = {
|
|
volumes = {
|
|
grounded-docs-config = { };
|
|
grounded-docs-data = { };
|
|
};
|
|
|
|
containers.grounded-docs = {
|
|
image = "ghcr.io/arabold/docs-mcp-server:2.4.0";
|
|
network = "host";
|
|
volumes = [
|
|
"grounded-docs-config.volume:/config"
|
|
"grounded-docs-data.volume:/data"
|
|
];
|
|
environment = {
|
|
DOCS_MCP_APP_TELEMETRY_ENABLED = "false";
|
|
DOCS_MCP_EMBEDDING_MODEL = "openai:nomic-embed-text";
|
|
DOCS_MCP_EMBEDDINGS_VECTOR_DIMENSION = "768";
|
|
OPENAI_API_BASE = "http://127.0.0.1:11434/v1";
|
|
OPENAI_API_KEY = "ollama";
|
|
};
|
|
exec = "--protocol http --host 127.0.0.1 --port 6280";
|
|
};
|
|
};
|
|
|
|
home.packages = [
|
|
# Node-based Codex plugin hooks and skill scripts need node/npm outside project dev shells.
|
|
pkgs.nodejs
|
|
pkgs.python3
|
|
inputs.llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.codex
|
|
pkgs.bubblewrap
|
|
inputs.llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.chatgpt
|
|
inputs.llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.pi
|
|
inputs.llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.claude-code
|
|
inputs.llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.herdr
|
|
pkgs.ctx7
|
|
];
|
|
|
|
xdg.configFile."herdr/config.toml".text = ''
|
|
onboarding = false
|
|
|
|
[ui]
|
|
agent_panel_sort = "spaces"
|
|
prompt_new_tab_name = false
|
|
|
|
[ui.toast]
|
|
delivery = "off"
|
|
|
|
[keys]
|
|
# Super belongs to Niri; Ctrl navigation belongs to Neovim.
|
|
focus_pane_left = ["prefix+h", "ctrl+alt+h"]
|
|
focus_pane_down = ["prefix+j", "ctrl+alt+j"]
|
|
focus_pane_up = ["prefix+k", "ctrl+alt+k"]
|
|
focus_pane_right = ["prefix+l", "ctrl+alt+l"]
|
|
next_workspace = "ctrl+alt+u"
|
|
previous_workspace = "ctrl+alt+i"
|
|
navigate_workspace_down = "u"
|
|
navigate_workspace_up = "i"
|
|
workspace_picker = ["prefix+w", "ctrl+alt+o"]
|
|
goto = ["prefix+g", "ctrl+alt+g"]
|
|
previous_agent = "ctrl+alt+p"
|
|
next_agent = "ctrl+alt+n"
|
|
previous_tab = ["prefix+p", "ctrl+alt+["]
|
|
next_tab = ["prefix+n", "ctrl+alt+]"]
|
|
new_tab = ["prefix+c", "ctrl+alt+enter"]
|
|
split_vertical = ["prefix+v", "ctrl+alt+v"]
|
|
split_horizontal = ["prefix+minus", "ctrl+alt+minus"]
|
|
zoom = ["prefix+z", "ctrl+alt+f"]
|
|
detach = ["prefix+q", "ctrl+alt+q"]
|
|
|
|
swap_pane_left = ["prefix+shift+h", "ctrl+alt+shift+h"]
|
|
swap_pane_down = ["prefix+shift+j", "ctrl+alt+shift+j"]
|
|
swap_pane_up = ["prefix+shift+k", "ctrl+alt+shift+k"]
|
|
swap_pane_right = ["prefix+shift+l", "ctrl+alt+shift+l"]
|
|
resize_pane_left = "ctrl+alt+shift+left"
|
|
resize_pane_down = "ctrl+alt+shift+down"
|
|
resize_pane_up = "ctrl+alt+shift+up"
|
|
resize_pane_right = "ctrl+alt+shift+right"
|
|
resize_mode = ["prefix+r", "ctrl+alt+r"]
|
|
cycle_pane_next = ["prefix+tab", "ctrl+alt+tab"]
|
|
cycle_pane_previous = ["prefix+shift+tab", "ctrl+alt+shift+tab"]
|
|
last_pane = "ctrl+alt+backspace"
|
|
close_pane = ["prefix+x", "ctrl+alt+x"]
|
|
rename_pane = ["prefix+shift+p", "ctrl+alt+shift+p"]
|
|
copy_mode = ["prefix+[", "ctrl+alt+y"]
|
|
edit_scrollback = ["prefix+e", "ctrl+alt+e"]
|
|
|
|
close_tab = ["prefix+shift+x", "ctrl+alt+shift+x"]
|
|
rename_tab = ["prefix+shift+t", "ctrl+alt+shift+a"]
|
|
move_tab_previous = "ctrl+alt+shift+["
|
|
move_tab_next = "ctrl+alt+shift+]"
|
|
new_workspace = ["prefix+shift+n", "ctrl+alt+shift+enter"]
|
|
rename_workspace = ["prefix+shift+w", "ctrl+alt+shift+w"]
|
|
close_workspace = ["prefix+shift+d", "ctrl+alt+shift+d"]
|
|
open_worktree = "ctrl+alt+w"
|
|
new_worktree = ["prefix+shift+g", "ctrl+alt+shift+b"]
|
|
|
|
toggle_sidebar = ["prefix+b", "ctrl+alt+b"]
|
|
help = ["prefix+?", "ctrl+alt+slash"]
|
|
settings = ["prefix+s", "ctrl+alt+s"]
|
|
reload_config = ["prefix+shift+r", "ctrl+alt+shift+r"]
|
|
|
|
[[keys.command]]
|
|
key = "ctrl+alt+shift+g"
|
|
type = "popup"
|
|
command = "lazygit"
|
|
description = "Lazygit"
|
|
width = "90%"
|
|
height = "90%"
|
|
'';
|
|
|
|
# Codex owns its writable user config; Nix owns assets and system defaults.
|
|
home.file =
|
|
lib.mapAttrs' (
|
|
name: source: lib.nameValuePair ".agents/skills/${name}" { inherit source; }
|
|
) ai.skills
|
|
// {
|
|
".codex/AGENTS.md".text = builtins.readFile ./instructions/codex.md;
|
|
};
|
|
};
|
|
}
|