codex: add lifecycle hooks option

Manage CODEX_HOME/hooks.json directly while covering the generated file in the existing TOML test.
This commit is contained in:
Austin Horstman
2026-06-25 14:21:12 -05:00
parent 1c64122e70
commit 64221f9c87
3 changed files with 91 additions and 0 deletions
+36
View File
@@ -153,6 +153,39 @@ in
'';
};
hooks = lib.mkOption {
inherit (jsonFormat) type;
default = { };
description = ''
Lifecycle hook events written to {file}`CODEX_HOME/hooks.json`.
This option uses the same event structure as
{option}`programs.codex.settings.hooks` and writes it under the
top-level `hooks` key expected by Codex's JSON hooks file.
Hooks can also be configured inline through
{option}`programs.codex.settings.hooks`; prefer using only one hook
representation per layer.
'';
example = lib.literalExpression ''
{
PreToolUse = [
{
matcher = "^Bash$";
hooks = [
{
type = "command";
command = "/usr/local/bin/codex-pre-tool-use";
timeout = 30;
statusMessage = "Checking Bash command";
}
];
}
];
}
'';
};
plugins = lib.mkOption {
type = with lib.types; listOf (either package path);
default = [ ];
@@ -535,6 +568,9 @@ in
lib.mkIf (cfg.context != "") {
text = cfg.context;
};
"${configDir}/hooks.json" = lib.mkIf (cfg.hooks != { }) {
source = jsonFormat.generate "codex-hooks" { inherit (cfg) hooks; };
};
}
// lib.optionalAttrs (cfg.contextOverride != null) (
lib.listToAttrs [ (mkTextOrPathEntry "${configDir}/AGENTS.override.md" cfg.contextOverride) ]
+27
View File
@@ -0,0 +1,27 @@
{
"hooks": {
"PreToolUse": [
{
"hooks": [
{
"command": "/usr/local/bin/codex-pre-tool-use",
"statusMessage": "Checking Bash command",
"timeout": 30,
"type": "command"
}
],
"matcher": "^Bash$"
}
],
"Stop": [
{
"hooks": [
{
"command": "/usr/local/bin/codex-stop",
"type": "command"
}
]
}
]
}
}
@@ -29,6 +29,31 @@ in
- Temporarily prefer terse answers
- Use exact dates in status notes
'';
hooks = {
PreToolUse = [
{
matcher = "^Bash$";
hooks = [
{
type = "command";
command = "/usr/local/bin/codex-pre-tool-use";
timeout = 30;
statusMessage = "Checking Bash command";
}
];
}
];
Stop = [
{
hooks = [
{
type = "command";
command = "/usr/local/bin/codex-stop";
}
];
}
];
};
};
nmt.script = ''
assertFileExists home-files/.codex/config.toml
@@ -43,6 +68,9 @@ in
- Temporarily prefer terse answers
- Use exact dates in status notes
''}
assertFileExists home-files/.codex/hooks.json
assertFileContent home-files/.codex/hooks.json \
${./hooks.json}
assertFileNotRegex home-path/etc/profile.d/hm-session-vars.sh 'CODEX_HOME'
'';
}