Where does the bug appear (feature/product)?
Cursor IDE
Describe the Bug
Cursor version: 3.2.7
OS: macOS
Composer mode: Agent
Summary
Bug: beforeSubmitPrompt hook updated_input is silently stripped — modified prompt never reaches the model
The beforeSubmitPrompt hook fires correctly and returns a valid updated_input.prompt. The hook log confirms the response is well-formed. However, the agent transcript shows only the original prompt wrapped in <user_query> — the injected content is completely stripped before reaching the model.
Steps to Reproduce
1. Create .cursor/hooks.json:
{
"version": 1,
"hooks": {
"beforeSubmitPrompt": [
{
"command": "/usr/local/opt/[email protected]/bin/php -d xdebug.mode=off .cursor/hooks/trait-harness.php"
}
]
}
}
2. Create .cursor/hooks/trait-harness.php:
#!/usr/bin/env php
<?php
declare(strict_types=1);
if (function_exists('xdebug_disable')) { xdebug_disable(); }
ini_set('xdebug.mode', 'off');
$input = json_decode(file_get_contents('php://stdin'), true);
$prompt = $input['prompt'] ?? '';
echo json_encode([
'action' => 'allow',
'updated_input' => [
'prompt' => '[INJECTED CONTEXT] ' . $prompt,
],
]);
(Simplified to minimal reproducer — original script does keyword detection and loads skill node files, but the stripping happens regardless of prompt content.)
3. Verify hook works from terminal:
printf '%s' '{"prompt":"test prompt","hook_event_name":"beforeSubmitPrompt"}' \
| /usr/local/opt/[email protected]/bin/php -d xdebug.mode=off .cursor/hooks/trait-harness.php
Output (hook works correctly):
{"action":"allow","updated_input":{"prompt":"[INJECTED CONTEXT] test prompt"}}
4. Submit any prompt in Cursor Agent mode.
5. Check hook log — Cursor fires the hook and receives correct updated_input:
{
"hook_event_name": "beforeSubmitPrompt",
"cursor_version": "3.2.7",
"prompt": "System szpitalny. Klasy MedicalRecord potrzebują soft delete."
}
Hook response logged by Cursor:
{
"action": "allow",
"updated_input": {
"prompt": "[INJECTED CONTEXT] System szpitalny. Klasy MedicalRecord potrzebują soft delete."
}
}
6. Check agent transcript at:
~/.cursor/projects/<workspace>/agent-transcripts/<session-id>/<session-id>.jsonl
{"role":"user","message":{"content":[{"type":"text","text":"<user_query>\nSystem szpitalny. Klasy MedicalRecord potrzebują soft delete.\n</user_query>"}]}}
The injected [INJECTED CONTEXT] prefix is gone. The model receives only the original prompt.
Expected Behavior
updated_input.prompt returned by the hook replaces the prompt sent to the model. The agent transcript should contain the modified prompt inside <user_query>.
Operating System
MacOS
Version Information
Version: 3.2.7 (Universal)
VSCode Version: 1.105.1
Commit: 251fe2954fc02bde617557cee00fcc1d27a6e590
Date: 2026-04-22T23:35:05.835Z
Layout: glass
Build Type: Stable
Release Track: Nightly
Electron: 39.8.1
Chromium: 142.0.7444.265
Node.js: 22.22.1
V8: 14.2.231.22-electron.0
OS: Darwin x64 25.4.0
For AI issues: which model did you use?
Auto
Additional Information
Actual behavior
Cursor fires the hook, logs the updated_input response, but strips the modification before sending to the model. The transcript contains only the original unmodified prompt.
Additional details
- The hook does fire — confirmed by
hook_event_name: beforeSubmitPromptin logs - The hook does return valid JSON with
updated_input— confirmed by terminal test - The stripping happens between hook output and model input
- Reproducible across multiple sessions (session IDs:
e0d2cf8a,3e1246c6) denyaction works correctly (blocks the prompt) — onlyupdated_inputmodification is broken- Workaround:
alwaysApply: truerule with inline content reaches the model, but lacks per-prompt selectivity
Use case context
This feature is central to building context-injection harnesses — loading only the relevant portion of a decision graph based on prompt content, rather than always injecting the full context. Without working updated_input, the only option is alwaysApply rules which load regardless of relevance, wasting context window on every request.
Happy to provide full transcript files or additional debug output if useful.
Does this stop you from using Cursor
No - Cursor works, but with this issue