I agree we need hooks but for sounds you can do something like
notify = ["bash", "-lc", "afplay /System/Library/Sounds/Blow.aiff"]in config.toml (adjust if you’re not on mac)
For Windows:
config.toml:
notify = ["powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "C:\\Users\\User\\.codex\\notify.ps1"]
notify.ps1:
param([string]$NotificationJson)
try { $n = $NotificationJson | ConvertFrom-Json } catch { exit 0 }
if ($n.type -ne 'agent-turn-complete') { exit 0 }
$wav = Join-Path $env:WINDIR 'Media\Windows Exclamation.wav'
# Spawn a detached PowerShell to play the sound synchronously, but without blocking Codex
$cmd = "(New-Object System.Media.SoundPlayer '$wav').PlaySync()"
Start-Process -WindowStyle Hidden -FilePath "powershell.exe" -ArgumentList @(
"-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", $cmd
) | Out-Null
Seperate ps1 was necessary for me, because otherwise it would have syntax errors on codex’ side. Works on WSL, too - if you have WSL interop path disabled, use absolute path for powershell: /mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe
Experimentally merged into v0.114!!
- Get 0.114 version
- Add
hooks.jsonin.codexor wherever the config directory is. - Run
codex -c features.codex_hooks=true - Hooks get triggered before/after sending a prompt
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "echo 'session started' >> /tmp/codex.log",
"statusMessage": "Initializing session...",
"timeout": 10
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "echo 'turn ended' >> /tmp/codex.log",
"statusMessage": "Wrapping up turn...",
"timeout": 10
}
]
}
]
}
}
12 replies