codex-notified is a small .NET 8 console application for the Codex notify hook.
It receives the JSON payload that Codex passes to the notify hook, parses it once into a typed model, enriches it with a deterministic human-readable summary, optionally delivers compact webhook notifications, and writes compact forensic log entries.
The project is intentionally simple:
- no GUI
- no external runtime dependencies
- no background services
- no AI dependency for summarization
- best-effort middleware behavior that should not break the Codex notify flow
The default Codex notify hook gives you raw event data, but it does not give you:
- stable local forensic logs
- compact headline/summary extraction
- webhook delivery for external services
- an easy extension point for future integrations
codex-notified fills that gap with a small middleware pipeline focused on:
- reliable parsing
- readable summaries
- small durable logs
- optional outbound notifications
- Parses the Codex notify payload exactly once
- Exposes a shared typed pipeline context for downstream middleware
- Generates a deterministic
headlineandsummary - Writes compact append-only daily log files
- Sends best-effort webhook notifications
- Keeps webhook failures non-fatal
- Supports development-time
dotnet runusage and published-DLL usage - Includes automated tests for parsing, summary generation, logging, config loading, and webhooks
Repository layout:
README.mdsrc/codex-notified.slnsrc/codex-notified/src/codex-notified.tests/
Application layout:
src/codex-notified/Config/src/codex-notified/Logging/src/codex-notified/Middleware/src/codex-notified/Models/src/codex-notified/Pipeline/
Test project:
src/codex-notified.tests/codex-notified.tests.csproj
Codex invokes the configured notify command and passes a single JSON argument. codex-notified receives that payload and runs it through a middleware pipeline.
Current middleware order:
ParsingMiddlewareSummaryMiddlewareWebhookMiddlewareLoggingMiddleware
Each middleware has a single responsibility:
ParsingMiddleware- parses the incoming JSON into a structured notification model
SummaryMiddleware- derives a short deterministic
headlineandsummary
- derives a short deterministic
WebhookMiddleware- sends compact best-effort webhook payloads
LoggingMiddleware- appends a compact log entry to the daily log file
The middleware pipeline passes around a shared typed context.
Important context data:
RawInput- original notify JSON string from
args[0]
- original notify JSON string from
Notification- parsed typed payload and runtime metadata
Summary- derived
headline/summary
- derived
Diagnostics- internal informational notes
Failures- captured middleware failures
WebhookDispatchResults- compact record of outbound webhook attempts
Items- general extension dictionary for future middleware
Downstream middleware should work from the typed context rather than reparsing the raw JSON.
The parsed notification envelope contains:
PayloadTypeThreadIdTurnIdCwdClientInputMessagesLastAssistantMessage
RuntimeContextTimestampUtcCommandLineCurrentDirectoryProcessIdArgumentCount
EnvironmentVariablesMiddlewareFailures
Notes:
InputMessagesis modeled asstring[]- values are preserved as received
- the parsed payload stays separate from derived summary fields
SummaryMiddleware creates a human-readable summary without using AI.
Summary rules:
- primary input is
last-assistant-message - headline is the first meaningful line or sentence
- summary prefers the first meaningful paragraph
- markdown noise is stripped
- low-value sections such as verification/test headings are ignored when possible
- if assistant text is missing, the middleware falls back to structured metadata
This keeps summaries:
- cheap
- local
- predictable
- stable for automation and notification use
LoggingMiddleware writes compact structured log entries.
Log behavior:
- append-only
- one daily log file
- separator lines around each entry
- primary location under the user profile
- temp-directory fallback if the primary location cannot be written
Primary log directory:
- macOS/Linux:
~/.codex-notify-logs - Windows:
%USERPROFILE%\.codex-notify-logs
Fallback directory:
Path.GetTempPath()/codex-notify-logs
Daily file format:
log-YYYY-MM-DD.log
Each entry is compact and based on structured metadata only.
Included fields:
- event type
- thread id
- turn id
- cwd
- client
- input message count
- assistant message length
- headline
- summary
- summary source
- timestamp
- process id
- webhook dispatch results
- middleware failures
Not logged:
- full raw JSON payload
- full
input-messages - full assistant message body
- full environment variable dump
================================================================
{
"type": "agent-turn-complete",
"threadId": "thread-summary",
"turnId": "turn-summary",
"cwd": "/tmp/demo",
"client": "Codex Desktop",
"inputMessageCount": 1,
"assistantMessageLength": 126,
"headline": "Implemented the summary middleware.",
"summary": "Implemented the summary middleware.",
"summarySource": "assistant-message",
"timestampUtc": "2026-03-17T22:48:16.44212+00:00",
"processId": 95059
}
WebhookDispatchResults:
- local [ok]: dispatched
MiddlewareFailures:
(none)
================================================================
WebhookMiddleware sends compact best-effort webhook notifications to one or more configured targets.
Delivery policy:
- HTTP
POST - small JSON payload
- short timeout
- no retries
- failures are recorded but do not stop the notify pipeline
This design is deliberate: the logger and parser are the primary job, while webhooks are an optional outward integration.
Webhook targets are configured in a custom tool-owned section inside Codex config.
Example:
[[codex_notified.webhooks]]
name = "pushcut"
enabled = true
url = "https://api.pushcut.io/YOUR_ENDPOINT"
notification_types = ["agent-turn-complete"]
timeout_ms = 1500
[codex_notified.webhooks.headers]
Authorization = "Bearer YOUR_TOKEN"Supported config locations:
~/.codex/config.toml.codex/config.tomlin the current project directory
Notes:
- unknown custom config tables are not part of the official Codex config contract
- local verification with
codex-cli 0.104.0showed this custom section is tolerated - malformed webhook entries are ignored individually rather than failing the whole tool
Example outbound payload:
{
"notificationType": "agent-turn-complete",
"subject": "Implemented the summary middleware.",
"summary": "Implemented the summary middleware.",
"threadId": "verify-thread",
"turnId": "verify-turn",
"timestampUtc": "2026-03-17T22:48:16.44212+00:00",
"cwd": "/tmp/demo",
"client": "Codex Desktop",
"headline": "Implemented the summary middleware."
}Suggested uses:
- Pushcut
- Webhook.site
- custom internal notification relays
- Make / Zapier / automation gateways
Requirements:
- .NET 8 SDK or runtime
- Codex with
notifyhook support
Clone the repository and build:
git clone <your-repo-url>
cd codex-notified
dotnet build src/codex-notified.slnRun tests:
dotnet test src/codex-notified.slnPublish the app:
dotnet publish src/codex-notified/codex-notified.csproj -c Release -o src/codex-notified/publishThere are two recommended ways to wire codex-notified into Codex.
Use the published DLL for a stable setup:
notify = ["dotnet", "/absolute/path/to/codex-notified/src/codex-notified/publish/codex-notified.dll"]This is the preferred option for:
- stable daily use
- lower startup cost
- fewer rebuilds
On a development machine, you can run directly from source so changes compile automatically when the notify hook is invoked:
notify = [
"dotnet",
"run",
"--project",
"./src/codex-notified/codex-notified.csproj",
"--"
]This is convenient while developing middleware, but slower than the published DLL path because the project may rebuild on each invocation.
A practical combined configuration might look like this:
notify = [
"dotnet",
"run",
"--project",
"./src/codex-notified/codex-notified.csproj",
"--"
]
[[codex_notified.webhooks]]
name = "webhook-site"
enabled = true
url = "https://webhook.site/YOUR_TOKEN"
notification_types = ["agent-turn-complete"]
timeout_ms = 1500The automated test suite covers:
- valid payload parsing
- parse failures
- deterministic summary generation
- fallback summary behavior
- pipeline ordering
- logging behavior
- file-log fallback behavior
- webhook config parsing
- webhook dispatch behavior
- webhook failure handling
Run the full suite with:
dotnet test src/codex-notified.slnTo add new behavior:
- create a new middleware in
src/codex-notified/Middleware/ - use the shared typed context
- avoid reparsing raw JSON
- keep failures non-fatal unless the middleware is truly mandatory
- register the middleware in
ProgramEntry
Good future middleware ideas:
- desktop notification middleware
- richer local state export
- metrics/telemetry middleware
- SaaS-specific webhook adapters
- archive/export middleware
This project tries to stay:
- production-safe
- easy to audit
- easy to extend
- cheap to run
- useful as a local automation bridge
Key principles:
- parsing happens once
- middleware consume structured data
- summaries are deterministic
- logs stay compact
- webhook delivery is best-effort
- failures are captured, not fatal
- webhook config uses a custom section in Codex config rather than an officially documented Codex config key
- webhook delivery is intentionally not durable or retried
- summaries are heuristic, not semantic/AI summaries
- current implementation is optimized for local/dev automation, not high-volume server dispatch
Add your preferred license here.
Contributions are welcome.
A good first workflow is:
- update or add middleware
- add tests in
src/codex-notified.tests/ - run
dotnet test src/codex-notified.sln - update this README when behavior or config changes