UserPromptSubmit and SessionStart hooks fire simultaneously on first prompt

Resolved 💬 5 comments Opened Mar 20, 2026 by disrupt-labs-core Closed Apr 10, 2026
💡 Likely answer: A maintainer (eternal-openai, contributor) responded on this thread — see the highlighted reply below.

Bug

When both SessionStart and UserPromptSubmit hooks are registered, they fire simultaneously on the first prompt. On subsequent prompts, only UserPromptSubmit fires (expected).

Expected behavior

SessionStart should complete before UserPromptSubmit fires on the first prompt, or they should not overlap — since the first prompt is both a session start event and a prompt submit event.

Steps to reproduce

  1. Register both hooks in .codex/hooks.json:
{
  "hooks": {
    "SessionStart": [
      {
        "hooks": [{ "type": "command", "command": "echo 'SessionStart fired'", "timeout": 10 }]
      }
    ],
    "UserPromptSubmit": [
      {
        "hooks": [{ "type": "command", "command": "echo 'UserPromptSubmit fired'", "timeout": 10 }]
      }
    ]
  }
}
  1. Start Codex CLI with codex -c features.codex_hooks=true
  2. Send the first prompt — both hooks fire simultaneously
  3. Send a second prompt — only UserPromptSubmit fires

Environment

  • Codex CLI v0.116.0
  • macOS

View original on GitHub ↗

5 Comments

mvanhorn · 5 months ago

I've prepared a fix for this in branch mvanhorn:fix/session-start-hook-timing.

The fix fires SessionStart hooks eagerly during session creation (right after SessionConfigured is emitted) instead of deferring them to the first turn. The hook outcome (should_stop + additional_contexts) is stored on SessionState and consumed by the first turn, preserving the existing context injection behavior while fixing the timing.

Key changes:

  • hook_runtime.rs: new run_session_start_hooks_eager() fires hooks at init time using send_event_raw (no TurnContext needed)
  • hook_runtime.rs: run_pending_session_start_hooks() checks for a stored eager outcome before falling back to deferred execution
  • state/session.rs: new EagerSessionStartHookOutcome type and field
  • codex.rs: session init calls eager hooks instead of setting pending_session_start_source

Builds cleanly with cargo check -p codex-core. Branch is at https://github.com/mvanhorn/codex/tree/fix/session-start-hook-timing

(PR creation is blocked by org OAuth policy - will submit via web UI.)

eternal-openai contributor · 4 months ago

@abhinav-oai and I had a chance to look at this, and SessionStarts do run before UserPromptSubmits. They still wait for the first prompt as the official start of session, but ordering is enforced. So the practical way to test that is to put a sleep into a SessionStart hook, and notice that the UserPromptSubmit hooks don't run until that sleep is complete. So I think this works

oxysoft · 3 months ago

Indexed this hook ticket in the umbrella tracker: #21753

Goal: collect the scattered Codex hook requests and bugs into one parity matrix for Full Claude Code Hook Parity (29+), while preserving this issue as the detailed thread for its specific behavior.

Morriz · 3 months ago

why would SessionStart not fire when the agent is ready to receive input (a valid use case we have and want this event for)? UserPromptSubmit is the event that gets triggered on you guessed it, the moment a user submits a prompt. So imo it's completely missing the goal when those timings are the same?

Claude Code does it correct, so why not honor the same?

Morriz · 3 months ago

can we re-open this please @eternal-openai ?