Where does the bug appear (feature/product)?
Cursor IDE
Describe the Bug
Summary
The preToolUse hook correctly executes and returns updated_input with a modified prompt field when the Task tool is invoked, but Cursor silently discards the modification. The spawned subagent always receives the original, unmodified prompt. There is also no alternative hook (subagentStart) that supports prompt modification — it only supports allow/deny.
This makes it impossible to dynamically inject context (session state, policies, instructions) into subagent prompts via hooks.
Requested Fix / Feature
At least one of the following:
- Fix
preToolUseupdated_inputfor theTasktool — Apply the modified input before spawning the subagent, consistent with the documented behavior. - Add
updated_inputsupport tosubagentStart— AllowsubagentStarthooks to modify the subagent prompt before it starts. This would be the most natural place for this capability. - Add
additional_contexttosubagentStartoutput — Similar tosessionStart, allow hooks to inject additional context into the subagent’s initial system prompt.
Use Cases Blocked
- Injecting session-specific workspace paths or metadata into subagent prompts
- Enforcing organization-wide instructions or policies for subagents
- Providing subagents with dynamic context (e.g., current branch, environment, active feature flags)
- Building hook-based orchestration systems that enrich subagent prompts at runtime
Steps to Reproduce
Steps to Reproduce
1. Configure a preToolUse hook targeting the Task tool
.cursor/hooks.json:
{
"version": 1,
"hooks": {
"preToolUse": [
{
"command": ".cursor/hooks/inject-context.sh",
"matcher": "Task"
}
]
}
}
2. Create the hook script
.cursor/hooks/inject-context.sh:
#!/bin/bash
set -euo pipefail
input=$(cat)
original_prompt=$(echo "$input" | jq -r '.tool_input.prompt // empty')
modified_prompt="SECRET_CODE=ZEBRA_PURPLE_4m2k\n\n${original_prompt}"
echo "$input" | jq --arg prompt "$modified_prompt" '{
"decision": "allow",
"updated_input": { "prompt": $prompt }
}'
3. Spawn a subagent
Ask the agent to spawn a readonly subagent, e.g.:
“Spawn an explore subagent. Ask it to report the value of SECRET_CODE.”
4. Observe the subagent does NOT receive the injected content
The subagent will report it has no knowledge of any SECRET_CODE.
Evidence
Hook executes correctly
Debug logs confirm the hook runs, receives the correct input, and produces valid JSON output:
[2026-02-16 08:15:42] HOOK OUTPUT: {
"decision": "allow",
"updated_input": {
"prompt": "SECRET_CODE=ZEBRA_PURPLE_4m2k\n\nSay \"Hello\" and nothing else."
}
}
Subagent receives original prompt
The subagentStop log shows the subagent’s task field contains only the original prompt — no injected content:
{
"hook_event_name": "subagentStop",
"task": "Say \"Hello\" and nothing else.",
"summary": "\nHello"
}
Behavioral test rules out false positives
To ensure the subagent wasn’t simply ignoring the injected text, we:
- Set
readonly: trueon the Task tool (preventing the subagent from reading any files) - Used a unique secret code (
ZEBRA_PURPLE_4m2k) that doesn’t exist anywhere in the codebase - Explicitly asked the subagent to report the code
Result: the subagent had no knowledge of the code, confirming the prompt was never modified.
subagentStart offers no alternative
Per the docs, subagentStart only supports decision: allow|deny in its output — there is no updated_input or equivalent field to modify the subagent prompt.
Expected Behavior
Expected Behavior
When a preToolUse hook returns updated_input with a modified prompt field for the Task tool, the spawned subagent should receive the modified prompt — consistent with how updated_input is documented to work:
updated_input(object, optional): Modified tool input to use instead
Actual Behavior
The updated_input is silently discarded. The subagent receives the original, unmodified prompt. No error or warning is surfaced.
Operating System
MacOS
Version Information
Environment
- Cursor version: 2.4.37
- OS: macOS (darwin 25.2.0)
- Hook source: Project-level (
.cursor/hooks.json)
Does this stop you from using Cursor
No - Cursor works, but with this issue