263 lines
9.6 KiB
Nix
263 lines
9.6 KiB
Nix
{ inputs, config, ... }:
|
|
let
|
|
hmModules = config.flake.modules.homeManager;
|
|
nixosModules = config.flake.modules.nixos;
|
|
in
|
|
{
|
|
flake.modules.nixos.ai =
|
|
{ pkgs, ... }:
|
|
let
|
|
context7Headers = pkgs.writeShellScript "context7-http-headers" ''
|
|
set -euo pipefail
|
|
|
|
CONTEXT7_KEY_FILE="''${XDG_CONFIG_HOME:-$HOME/.config}/context7/api-key"
|
|
[[ -r "$CONTEXT7_KEY_FILE" ]]
|
|
CONTEXT7_KEY="$(< "$CONTEXT7_KEY_FILE")"
|
|
|
|
exec ${pkgs.jq}/bin/jq --null-input --compact-output \
|
|
--arg authorization "Bearer $CONTEXT7_KEY" \
|
|
'{ Authorization: $authorization }'
|
|
'';
|
|
|
|
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;
|
|
notify = [
|
|
"${pkgs.llm-agents.agent-deck}/bin/agent-deck"
|
|
"codex-notify"
|
|
];
|
|
|
|
tui = {
|
|
status_line = [
|
|
"model-with-reasoning"
|
|
"current-dir"
|
|
"context-remaining"
|
|
"five-hour-limit"
|
|
"weekly-limit"
|
|
"git-branch"
|
|
];
|
|
status_line_use_colors = true;
|
|
};
|
|
|
|
mcp_servers = {
|
|
context7 = {
|
|
url = "https://mcp.context7.com/mcp";
|
|
http_headers_helper = "${context7Headers}";
|
|
};
|
|
nixos = {
|
|
command = "${pkgs.uv}/bin/uvx";
|
|
args = [ "mcp-nixos" ];
|
|
startup_timeout_sec = 60.0;
|
|
tools.nix.approval_mode = "approve";
|
|
};
|
|
openaiDeveloperDocs.url = "https://developers.openai.com/mcp";
|
|
};
|
|
};
|
|
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, ... }:
|
|
{
|
|
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.llm-agents.codex
|
|
pkgs.llm-agents.pi
|
|
pkgs.llm-agents.claude-code
|
|
pkgs.llm-agents.agent-deck
|
|
pkgs.llm-agents.herdr
|
|
pkgs.tmux
|
|
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%"
|
|
'';
|
|
|
|
home.file.".codex/AGENTS.md".text = ''
|
|
# Environment
|
|
|
|
This is Nix; use `nix run` for missing commands.
|
|
|
|
- Default Nix commands to `--quiet`; inspect logs only for failing derivations.
|
|
- Never emit full package, derivation, closure, GC, or store-tree listings. Capture them in `/tmp`, summarize or filter, then inspect targeted excerpts.
|
|
- For store sources, locate files first, then read exact ranges; avoid broad `rg -C` searches.
|
|
|
|
# Work
|
|
|
|
- Inspect the relevant implementation and follow project conventions.
|
|
- Prefer the simplest complete solution.
|
|
- Identify and address root causes rather than masking symptoms.
|
|
- Prefer existing capabilities and defaults. Add custom code, wrappers, helpers, defensive checks, fallbacks, compatibility layers, or abstractions only for a concrete need.
|
|
- Delete unnecessary code; keep related logic together.
|
|
- Use types, schemas, and interfaces to prevent invalid states where practical.
|
|
- Keep changes focused; preserve behavior unless requested or fixing a confirmed defect.
|
|
- Verify unfamiliar, version-sensitive, or consequential APIs against current documentation; prefer context7.
|
|
- Run the most relevant checks; report only verification performed.
|
|
|
|
# Reviews and refactoring
|
|
|
|
- Inspect complete relevant context, not just the obvious file or diff.
|
|
- Find unnecessary or duplicated code, redundant state, avoidable checks, reimplemented capabilities, and repeated defaults.
|
|
- Ask whether defensive code protects a realistic state or hides an unclear invariant.
|
|
- Optimize conceptual complexity, not line count.
|
|
- Separate confirmed problems from optional improvements; explain important tradeoffs.
|
|
|
|
# Context
|
|
|
|
Every action must justify its context. Minimize tools and skills; prefer targeted queries and bounded output. Ask for readily available large output instead of retrieving it.
|
|
|
|
# Remote state
|
|
|
|
GitHub and all other repository remotes are strictly read-only. Fetching,
|
|
cloning, and reading metadata, issues, pull requests, checks, and diffs are
|
|
allowed. Never push or mutate remote repositories, issues, pull requests,
|
|
reviews, comments, labels, assignments, projects, workflows, releases,
|
|
settings, keys, secrets, or variables. Local files and local Git state may
|
|
be modified as authorized.
|
|
'';
|
|
|
|
home.file = {
|
|
".agents/plugins/marketplace.json".text = builtins.toJSON {
|
|
name = "nix-managed";
|
|
plugins = [
|
|
{
|
|
name = "ponytail";
|
|
source = {
|
|
source = "local";
|
|
path = "./.codex/plugins/ponytail";
|
|
};
|
|
policy = {
|
|
installation = "AVAILABLE";
|
|
authentication = "ON_INSTALL";
|
|
};
|
|
category = "Productivity";
|
|
}
|
|
];
|
|
};
|
|
".agents/skills/context7-mcp".source = ./skills/context7-mcp;
|
|
".agents/skills/nixos-maintainer".source = ./skills/nixos-maintainer;
|
|
".codex/plugins/ponytail".source = inputs.ponytail;
|
|
};
|
|
};
|
|
}
|