refactor: centralize Nix-managed Codex assets and integrations
This commit is contained in:
1 parent
81dc673ac2
commit
d7a0acf0a9
7 files changed
+167
-106
No files matched your search
Generated
-17
@@ -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"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -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.
|
||||||
@@ -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";
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -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.
|
||||||
Reference in new issue
Block a user