refactor: centralize Nix-managed Codex assets and integrations

This commit is contained in:
kiri committed 2026-09-10 18:22:01 +02:00
1 parent 81dc673ac2
commit d7a0acf0a9
7 files changed
+167 -106

No files matched your search

Generated
-17
View File
@@ -286,22 +286,6 @@
"type": "github" "type": "github"
} }
}, },
"ponytail": {
"flake": false,
"locked": {
"lastModified": 1788798420,
"narHash": "sha256-LPNMyHsri3+eeDmphEAKL1JgoRE4dLIPfZ4XZ+xu5UY=",
"owner": "DietrichGebert",
"repo": "ponytail",
"rev": "356918eba965ee1eac64bd3a7f0dd02108350de5",
"type": "github"
},
"original": {
"owner": "DietrichGebert",
"repo": "ponytail",
"type": "github"
}
},
"root": { "root": {
"inputs": { "inputs": {
"disko": "disko", "disko": "disko",
@@ -314,7 +298,6 @@
"nixos-hardware": "nixos-hardware", "nixos-hardware": "nixos-hardware",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"noctalia": "noctalia", "noctalia": "noctalia",
"ponytail": "ponytail",
"sops-nix": "sops-nix", "sops-nix": "sops-nix",
"walker": "walker" "walker": "walker"
} }
-4
View File
@@ -29,10 +29,6 @@
url = "github:noctalia-dev/noctalia"; url = "github:noctalia-dev/noctalia";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
ponytail = {
url = "github:DietrichGebert/ponytail";
flake = false;
};
sops-nix = { sops-nix = {
url = "github:Mic92/sops-nix"; url = "github:Mic92/sops-nix";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
+29 -85
View File
@@ -7,18 +7,7 @@ in
flake.modules.nixos.ai = flake.modules.nixos.ai =
{ pkgs, ... }: { pkgs, ... }:
let let
context7Headers = pkgs.writeShellScript "context7-http-headers" '' ai = import ./ai/_assets.nix { inherit pkgs; };
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" { codexConfig = (pkgs.formats.toml { }).generate "codex-config.toml" {
model = "gpt-5.6-sol"; model = "gpt-5.6-sol";
model_reasoning_effort = "high"; model_reasoning_effort = "high";
@@ -43,18 +32,21 @@ in
status_line_use_colors = true; status_line_use_colors = true;
}; };
mcp_servers = { features.plugins = true;
context7 = { marketplaces.nix-managed = {
url = "https://mcp.context7.com/mcp"; source_type = "local";
http_headers_helper = "${context7Headers}"; source = "${ai.marketplace}";
};
plugins."ponytail@nix-managed".enabled = true;
hooks = ai.codexHooks;
mcp_servers = ai.servers // {
context7 = ai.servers.context7 // {
http_headers_helper = "${ai.context7Headers}";
}; };
nixos = { nixos = ai.servers.nixos // {
command = "${pkgs.uv}/bin/uvx";
args = [ "mcp-nixos" ];
startup_timeout_sec = 60.0; startup_timeout_sec = 60.0;
tools.nix.approval_mode = "approve"; tools.nix.approval_mode = "approve";
}; };
openaiDeveloperDocs.url = "https://developers.openai.com/mcp";
}; };
}; };
in in
@@ -82,7 +74,10 @@ in
}; };
flake.modules.homeManager.ai = flake.modules.homeManager.ai =
{ pkgs, ... }: { pkgs, lib, ... }:
let
ai = import ./ai/_assets.nix { inherit pkgs; };
in
{ {
services.podman = { services.podman = {
volumes = { volumes = {
@@ -111,6 +106,7 @@ in
home.packages = [ home.packages = [
# Node-based Codex plugin hooks and skill scripts need node/npm outside project dev shells. # Node-based Codex plugin hooks and skill scripts need node/npm outside project dev shells.
pkgs.nodejs pkgs.nodejs
pkgs.python3
pkgs.llm-agents.codex pkgs.llm-agents.codex
pkgs.llm-agents.pi pkgs.llm-agents.pi
pkgs.llm-agents.claude-code pkgs.llm-agents.claude-code
@@ -193,70 +189,18 @@ in
height = "90%" height = "90%"
''; '';
home.file.".codex/AGENTS.md".text = '' # Codex owns its writable user config; Nix owns assets and system defaults.
# Environment home.file =
lib.mapAttrs' (
This is Nix; use `nix run` for missing commands. name: source: lib.nameValuePair ".agents/skills/${name}" { inherit source; }
) ai.skills
- 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. ".codex/AGENTS.md".text = builtins.readFile ./ai/instructions/codex.md;
- For store sources, locate files first, then read exact ranges; avoid broad `rg -C` searches. # Codex's installed-plugin scanner skips symlinked version directories.
"${ai.codexCache}" = {
# Work source = ai.sources.ponytail;
recursive = true;
- 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;
};
}; };
} }
+41
View File
@@ -0,0 +1,41 @@
# Codex installation
`ai.nix` installs binaries and Codex defaults on Polaris and Zenith.
`_sources.nix` pins upstream assets; `_assets.nix` declares skills, MCP servers,
the Ponytail marketplace and the upstream Herdr session hook.
Edit `instructions/codex.md` for global Codex instructions.
Nix owns installation files. Codex owns writable user settings, plugin toggles,
trust, credentials and sessions. Bundled/service-delivered capabilities remain
vendor-managed. Update Ponytail's revision, hash and `ponytailVersion` together.
The cache uses real directories with linked files because Codex skips symlinked
plugin version directories. Do not run plugin updaters on Nix-managed assets.
Herdr's skill is linked directly from the same source as its binary. An agent
can also read it with `herdr --skill`; no generated file is necessary.
The upstream session hook supports restore, not model instruction injection.
## Manual transition
Close Codex before cleaning up the previous setup and activating the new one.
No migration or compatibility code runs automatically.
- Remove old standalone skills: `~/.codex/skills/ponytail`,
`~/.agents/skills/find-skills`, `~/.agents/skills/context7-mcp.bak`,
and `~/.codex/skills/nixos-maintainer.bak`.
- Remove the old Ponytail cache `~/.codex/plugins/cache/ponytail/ponytail`.
Remove any unmanaged copy at `~/.codex/plugins/cache/nix-managed/ponytail/4.9.0`
if it blocks Home Manager activation. The obsolete managed
`~/.codex/plugins/ponytail` link is removed by Home Manager.
- In `~/.codex/config.toml`, remove the old `marketplaces.ponytail` entry and
rename `plugins."ponytail@ponytail"` to `plugins."ponytail@nix-managed"`,
preserving its enabled preference. Remove user launch fields for the
`context7`, `nixos` and `openaiDeveloperDocs` MCP servers so system defaults
apply; preserve toggles and unrelated preferences.
- Remove the old Herdr SessionStart command from `~/.codex/hooks.json` and its
`~/.codex/herdr-agent-state.sh` file. Preserve unrelated hooks.
- Activate your Nix configuration, then restart Codex.
If an earlier version of this work was activated, Home Manager removes its
managed instruction and integration links for other harnesses. Unmanaged copies
must be removed manually if no longer wanted.
+64
View File
@@ -0,0 +1,64 @@
{ pkgs }:
let
sources = import ./_sources.nix { inherit pkgs; };
json = pkgs.formats.json { };
ponytailVersion = "4.9.0";
context7Headers = pkgs.writeShellScript "context7-http-headers" ''
set -euo pipefail
CONTEXT7_KEY_FILE="''${XDG_CONFIG_HOME:-$HOME/.config}/context7/api-key"
CONTEXT7_KEY="$(< "$CONTEXT7_KEY_FILE")"
exec ${pkgs.jq}/bin/jq --null-input --compact-output \
--arg authorization "Bearer $CONTEXT7_KEY" '{ Authorization: $authorization }'
'';
codexHooks = {
SessionStart = [
{
hooks = [
{
type = "command";
command = "${pkgs.bash}/bin/bash ${sources.herdr}/src/integration/assets/codex/herdr-agent-state.sh session";
timeout = 10;
}
];
}
];
};
in
{
inherit sources ponytailVersion context7Headers;
inherit codexHooks;
codexCache = ".codex/plugins/cache/nix-managed/ponytail/${ponytailVersion}";
marketplace = pkgs.runCommand "ai-marketplace" { } ''
mkdir -p "$out/.agents/plugins" "$out/plugins"
ln -s ${sources.ponytail} "$out/plugins/ponytail"
cp ${
json.generate "ai-marketplace.json" {
name = "nix-managed";
plugins = [
{
name = "ponytail";
source = {
source = "local";
path = "./plugins/ponytail";
};
policy = {
installation = "AVAILABLE";
authentication = "ON_INSTALL";
};
category = "Productivity";
}
];
}
} "$out/.agents/plugins/marketplace.json"
'';
skills = {
context7-mcp = ../skills/context7-mcp;
nixos-maintainer = ../skills/nixos-maintainer;
herdr = "${sources.herdr}/skills/herdr";
};
servers = {
context7.url = "https://mcp.context7.com/mcp";
nixos.command = "${pkgs.mcp-nixos}/bin/mcp-nixos";
openaiDeveloperDocs.url = "https://developers.openai.com/mcp";
};
}
+10
View File
@@ -0,0 +1,10 @@
{ pkgs }:
{
ponytail = pkgs.fetchFromGitHub {
owner = "DietrichGebert";
repo = "ponytail";
rev = "356918eba965ee1eac64bd3a7f0dd02108350de5";
hash = "sha256-LPNMyHsri3+eeDmphEAKL1JgoRE4dLIPfZ4XZ+xu5UY=";
};
herdr = pkgs.llm-agents.herdr.src;
}
@@ -0,0 +1,23 @@
# Environment
- This is Nix; use `nix run` for missing commands. Default Nix commands to `--quiet`.
- Keep output bounded. Capture large Nix listings in `/tmp`; inspect targeted excerpts and failing logs only. Locate store files before reading them.
- Manage persistent binaries, skills, plugins and MCP definitions in `/home/kiri/.config/nixos`. Keep interactive settings, credentials and session state outside Nix.
- `HERDR_ENV=1` means you are inside Herdr. Read the Herdr skill or run `herdr --skill` when Herdr interaction is needed.
# Work
- Inspect relevant code and callers; follow project conventions and fix root causes.
- Prefer existing code, standard libraries and native capabilities. Avoid speculative abstractions; optimize conceptual simplicity, not line count.
- Keep changes focused. Prefer clean breaking changes over compatibility layers or migration scripts; explain required manual steps.
- Use targeted reads and tool calls. Verify unfamiliar or consequential APIs against version-appropriate primary documentation; prefer Context7 when needed.
- In reviews, distinguish confirmed problems from optional improvements and explain meaningful tradeoffs.
- Never push without my explicit approval. Other remote actions must remain within the authorized task.
- User instructions take precedence over skill guidelines, including testing defaults.
# Validation
Do not add or run tests unless explicitly requested or necessary to resolve a
concrete correctness concern. Use the smallest relevant validation and stop once
it provides sufficient confidence. Avoid broad suites and repeated builds without
a specific reason. Report only checks actually performed.