Agent ignores sessionStart hook context even when Hooks log says it merged successfully (Windows 3.14.7)

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

sessionStart hooks that return valid JSON {"additional_context":"..."} are executed and merged successfully (Hooks output shows Merged 1 valid response(s) for step sessionStart), but the injected context often does not reach the agent’s initial system context — especially on the first message of a new Agent chat.

This is the same confirmed race previously acknowledged by Cursor staff (composer handle timing). The older reports are auto-closed, so I’m filing a fresh report with current Windows / Glass / 3.14.7 evidence.

Related (closed) threads:

Staff diagnosis there (still accurate): additional_context is applied via the composer handle; sessionStart runs async before the handle is ready → silent drop. env from the same hook is more reliable because it does not need that handle.

Steps to Reproduce

  1. Create ~/.cursor/hooks/repro-sessionstart-marker.cmd with this exact content:
@echo off
echo {"additional_context":"CURSOR_HOOK_REPRO_MARKER_8F3A2B1C"}
  1. Create or replace ~/.cursor/hooks.json with:
{
  "version": 1,
  "hooks": {
    "sessionStart": [
      {
        "command": "C:/Users/<YOU>/.cursor/hooks/repro-sessionstart-marker.cmd",
        "timeout": 15
      }
    ]
  }
}
  1. Fully restart Cursor. Open Output → Hooks. Confirm the user sessionStart hook is loaded.
  2. Start a brand new Agent chat (Glass UI).
  3. Immediately send:

What is the value of CURSOR_HOOK_REPRO_MARKER_8F3A2B1C in your context?

  1. Optionally repeat: wait until Hooks shows Merged 1 valid response(s), then send the same question in a new chat.

Expected Behavior

Per Hooks docs, additional_context from sessionStart should be in the conversation’s initial system context for the first turn, reliably, without requiring the user to delay the first message.

Actual Behavior

  • Hooks channel: hook runs, valid JSON with additional_context, then Merged 1 valid response(s) for step sessionStartno parse error.
  • Agent often has no knowledge of the marker / answers as if context was absent (e.g. pong instead of canary).
  • Failure is intermittent: more likely if the first message is sent quickly; waiting a few seconds after chat open sometimes works.
  • There appear to be two races:
    1. Hook finishes before composer handle exists → getHandleIfLoaded empty → silent drop (staff’s original report).
    2. First user message is sent before updateComposer(..., { hooksAdditionalContext }) completes → first request lacks RequestContext.hooks_additional_context even when merge later succeeds.

Local inspection of workbench.glass.main.js (Glass) matches this: sessionStart is started in a fire-and-forget async IIFE; appendComposer creates the handle; apply uses getHandleIfLoaded(sessionId) then updateComposer — no await of the hook before create, and no retry/queue by session id for late apply.

Operating System

Windows 10/11

Version Information

  • Version: 3.14.7 (stable)
  • VS Code / Extension API: 1.128.0
  • Commit: a758f2241ca99fecf380180b6cbdbbce0f1f42c0
  • Date: 2026-07-30
  • Layout: glass (workbench.glass.main.js)
  • OS: Windows_NT x64

(Please ask if you need the full Help → About Electron/Chromium block.)

Additional Information

  • Reproduced with a single native user sessionStart hook (Claude/Third-Party imported hooks disabled), so this is not caused by non-JSON Claude SessionStart imports.
  • When Third Party / Claude hooks are imported, Cursor may run many extra SessionStart commands that fail Failed to parse hook stdout as JSON; the one valid JSON hook still “Merges 1”, but slow sessionStart makes race (2) worse.
  • sessionStart env remains comparatively reliable (as previously noted by staff).
  • Workaround today: static User Rules / project .cursor/rules — not suitable for dynamic session bootstrap (e.g. fetch live rules from an MCP/HTTP source at session start).

Happy to attach Hooks log excerpts or a Request ID from a failing canary turn if useful.

Does this stop you from using Cursor

No - Cursor works, but with this issue

Hey, thanks for such a detailed report, and especially for digging into the second race condition the first message happens before updateComposer has time to apply hooksAdditionalContext. That’s really helpful. I shared it with the team along with your notes on Glass and 3.14.7.

Yep, it’s the same issue we already confirmed in 158452 and 157141: the timing of the composer handle vs the async sessionStart. We’re tracking it, but I can’t share a specific ETA yet.

Workarounds for now, some of which you already know, but for completeness:

  • Using env from sessionStart is still the most reliable option since it doesn’t depend on the composer handle.
  • For static setup, use User Rules or .cursor/rules, but I get that this doesn’t solve dynamic bootstrap.
  • Waiting a couple seconds before the first message lowers the chance of race 2, but doesn’t fully eliminate it.

If you can grab a Request ID for a specific failing canary turn, drop it here, it won’t hurt. I’ll reply in the thread once there’s an update.

Thanks, Dean.

Here is a Request ID from a turn where additional_context was merged in the hooks log but did not reach the agent’s context:

d2482272-b300-4a5c-ad13-ac33fc42e716

For comparison, here is a Request ID where it did work:

e6a474e5-71e4-404d-94a3-4265b1957f7a

For the successful one, I temporarily removed .claude\settings.json which contains Claude SessionStart hooks. With Include Third-Party Plugins, Skills, and Other Configs on, it almost always fails. I assume because those extra hooks make sessionStart slow enough that the first message usually wins the race. With 3rd party configs off, it succeeds more often, but still not always.

One more detail I forgot: I don’t see this on Cursor Linux, even though the setup is mostly the same (~/.cursor/hooks.json, ~/.claude/settings.json, 3rd-Party configs on).

Thanks for the Request IDs and for comparing working vs failing. That’s exactly what we need to narrow this down. I passed it to the team along with two extra details you shared:

  • The correlation with Include Third-Party Plugins, Skills, and Other Configs. When it’s on, extra SessionStart commands slow down the hook, and the first message almost always wins race 2. This matches what we’re seeing. With third-party configs off, sessionStart finishes faster and the context has a better chance to apply in time.
  • The fact that it doesn’t reproduce on Linux with a similar setup is a helpful signal, I added that too.

As a short-term workaround to reduce the chance of the race right now: keep Include Third-Party Plugins off if you don’t need it for this session. Based on what you saw, sessionStart runs noticeably faster that way. Also, the env approach we mentioned is the most reliable, plus adding a small pause before sending the first message.

We’re tracking this issue, but I can’t share an exact ETA yet. I’ll reply in the thread as soon as I have an update.