beforeSubmitPrompt hook lacks reliable current mode signal (Ask vs Agent), making mode-based command safety gates unreliable

beforeSubmitPrompt hook lacks reliable current mode signal (Ask vs Agent), making mode-based command safety gates unreliable

Summary

I’m trying to enforce a simple safety policy via hooks:

  • /code-review must run only in Ask mode
  • all other slash commands must run only in Agent mode

In practice, beforeSubmitPrompt does not expose a reliable current mode signal for this decision, so the hook cannot act as a dependable circuit breaker.

Expected behavior

A hook should be able to deterministically tell the current mode (Ask/Agent) for each submitted prompt, so it can allow/deny command execution safely.

Actual behavior

In beforeSubmitPrompt payloads, mode information is inconsistent/unreliable (sometimes misleading, sometimes missing), so mode-based enforcement becomes either:

  • fail-open (unsafe), or
  • fail-closed (blocks valid usage)

Minimal repro

  1. Create .cursor/hooks.json with a beforeSubmitPrompt command hook and failClosed: true.
  2. Hook script reads stdin JSON and logs mode-like keys (mode, session_mode, current_mode, interaction_mode, composer_mode) + prompt command.
  3. Hook logic:
    • deny /code-review unless mode is Ask
    • deny other slash commands unless mode is Agent
  4. Start fresh session and run:
    • Agent mode: /code-review ... (should deny)
    • Ask mode: /code-review ... (should allow)

Observed:

  • mode keys are not consistently present/reliable per prompt
  • composer_mode may show agent even when running from Ask UI context
  • mode can be missing entirely

Result: reliable policy cannot be implemented using hooks with confidence, and while it’s possible to work around using a 1 liner in the prompt, that’s only a suggestion and wastes context. I might be wrong, but I believe that this is a platform responsibility imo.

Why this matters

Hooks are the only practical place to build hard safety guardrails around command execution. Without reliable mode context in beforeSubmitPrompt, hooks can’t be trusted as a safety circuit breaker for mode-restricted commands.

Requested fix

Please expose a stable, documented, per-prompt field in beforeSubmitPrompt input, e.g.:

  • current_mode: "ask" | "agent" | "plan" | "debug"

(or equivalent, with clear semantics), guaranteed for every call.

Bonus: include command metadata (resolved slash command file/ID) so hooks can enforce command-specific policy without brittle prompt parsing.

Current workaround

I had to fall back to soft guardrails in command markdown (“if not Ask/Agent, stop”) instead of hard hook enforcement.

See also (similar, but not the same) : Add additional_context to beforeSubmitPrompt hook output

Hey, thanks for the detailed report. Your use case makes sense, using the hook as a safety gate for mode-restricted commands is valid.

On the current state: in the beforeSubmitPrompt payload, there is a composer_mode field. It should reflect the mode you had selected at the moment you hit submit. To figure out if this is a bug or just an older build, a few questions:

  • What Cursor version are you on Help -> About? What OS?
  • Can you share a real example of what the hook sees on stdin with the prompt masked for two cases: Ask plus /code-review, and Agent plus any slash command? I want to confirm: is composer_mode present, and what value does it have?
  • About the fresh session scenario, can you clarify: do you switch the mode in the UI before sending the first message, or do you send right away? There’s some edge behavior where a new composer starts in the default mode until you explicitly pick one. I want to check if your case falls into that.

Once I see the payload, I can either point out what regressed or file it as an internal bug. Bonus request about resolved slash command file or ID in the payload is a separate signal, I’ll note it as a feature request in this thread so it doesn’t get lost.

Hi @dea

Update; I was unable to reproduce the issue with further testing; I think (I am not certain) that earlier testing was possibly showing fewer fields ; when I set up a new smaller project just for testing, I am now consistently seeing composer_mode, cursor_version, model etc. What slowed me down detecting this, was that i was also looking for “ask” mode; which I am now seeing consistently as “chat”.
Going forward, I think It would be valuable to be able to have this as a documented property we can use as this seems like a 101 getting started …super important place to put pre-prompt checks.
i.e. long way around of me saying I think this is closed, apart from the suggestion of making the fields officially stable and available to code against in hooks! ;D
Thanks for the quick response
Alan

Alan, thanks for coming back with an update. Glad it matches up in a clean project.

On the main point: you’re right that chat as the name for Ask mode isn’t obvious, and the beforeSubmitPrompt payload schema (including composer_mode, cursor_version, model) isn’t described in the public docs right now. I’ll pass this to the team as a docs request, it’s honestly the first thing you want handy when writing mode-aware hooks.

The composer_mode field in beforeSubmitPrompt is stable and is set at submit time, so you can write policies based on it. For future reference, the values you’ll see include chat (Ask) and agent, and plan and debug modes map there too.

I’m closing this as resolved, but if you hit a case again where composer_mode is missing or doesn’t match what’s selected in the UI, send the payload and the version here and we’ll take a look.