Describe the feature or problem you'd like to solve
The userPromptSubmitted hook fires before the model sees the user's prompt, but its output is currently observational only - hooks can log the prompt and call external services, but cannot modify or replace the prompt text. This request proposes adding an updatedPrompt field to the hook's output schema so that custom logic can rewrite the prompt before it reaches the chosen model.
Proposed solution
Current behaviour
Per the hooks documentation, userPromptSubmitted today supports:
| Capability |
Supported? |
| Read the user's prompt from stdin JSON |
✅ |
| Log / audit the prompt |
✅ |
| Block the prompt |
❌ |
| Modify or replace the prompt text |
❌ |
From the tutorial:
The output of this hook is ignored.
Meanwhile, preToolUse already supports structured output that mutates the event before it proceeds:
{
"permissionDecision": "allow",
"modifiedArgs": { "command": "my-modified-command" }
}
There is a clear asymmetry: tool call inputs are mutable by hooks, but user prompt text is not.
Proposed behaviour
Add an optional updatedPrompt field to the userPromptSubmitted hook output. When present, Copilot replaces the original prompt with the provided value before forwarding to the model. The user's selected model remains unchanged.
{
"updatedPrompt": "optimised or transformed prompt text here"
}
If the field is absent or null, behaviour is identical to today - the original prompt passes through unchanged. This is a non-breaking change.
Use cases
- Prompt optimisation - compress, restructure, or enrich prompts via custom logic or a secondary model before forwarding to the user's selected model, reducing token cost and improving output quality
- Alias / shorthand expansion - expand team-defined shorthand (e.g.
/review-sec) into full structured instructions automatically
- Sensitive data masking - detect and redact secrets, PII, or internal identifiers before they leave the developer's environment
- Policy enforcement - enforce prompt structure standards across an organisation (e.g. always include a task type, always specify output format)
- Dynamic context injection - prepend per-session context (current branch, linked issue, environment name) that changes at runtime and cannot be captured in static
copilot-instructions.md
Why not use existing alternatives?
| Alternative |
Limitation |
copilot-instructions.md |
Static file - cannot run dynamic logic or call external services per prompt |
| Copilot Extensions (agent mode) |
Requires @extension-name invocation - not transparent or automatic |
| Corporate HTTPS proxy |
Requires persistent infrastructure; intercepts all traffic including auth tokens |
| Shell wrapper around CLI |
Only transforms the first prompt; breaks interactive multi-turn sessions |
There is no current workaround that is both transparent to the user and safe to deploy in a team/enterprise environment
Example prompts or workflows
A prompt-optimisation hook script (.github/hooks/optimise-prompt.sh):
#!/bin/bash
INPUT=$(cat)
ORIGINAL=$(echo "$INPUT" | jq -r '.prompt')
# Call your own optimisation service
OPTIMISED=$(curl -s -X POST https://your-service/optimise \
-H "Content-Type: application/json" \
-d "{\"prompt\": \"$ORIGINAL\"}" | jq -r '.result')
echo "{\"updatedPrompt\": \"$OPTIMISED\"}"
Registered in .github/hooks/hooks.json:
{
"version": 1,
"hooks": {
"userPromptSubmitted": [
{
"type": "command",
"bash": ".github/hooks/optimise-prompt.sh",
"timeoutSec": 10
}
]
}
}
Additional context
Related
- anthropics/claude-code#27365 - identical request for Claude Code's
UserPromptSubmit hook; the two tools are converging on the same hook pattern and parity here would be valuable
Describe the feature or problem you'd like to solve
The userPromptSubmitted hook fires before the model sees the user's prompt, but its output is currently observational only - hooks can log the prompt and call external services, but cannot modify or replace the prompt text. This request proposes adding an updatedPrompt field to the hook's output schema so that custom logic can rewrite the prompt before it reaches the chosen model.
Proposed solution
Current behaviour
Per the hooks documentation,
userPromptSubmittedtoday supports:From the tutorial:
Meanwhile,
preToolUsealready supports structured output that mutates the event before it proceeds:{ "permissionDecision": "allow", "modifiedArgs": { "command": "my-modified-command" } }There is a clear asymmetry: tool call inputs are mutable by hooks, but user prompt text is not.
Proposed behaviour
Add an optional
updatedPromptfield to theuserPromptSubmittedhook output. When present, Copilot replaces the original prompt with the provided value before forwarding to the model. The user's selected model remains unchanged.{ "updatedPrompt": "optimised or transformed prompt text here" }If the field is absent or
null, behaviour is identical to today - the original prompt passes through unchanged. This is a non-breaking change.Use cases
/review-sec) into full structured instructions automaticallycopilot-instructions.mdWhy not use existing alternatives?
copilot-instructions.md@extension-nameinvocation - not transparent or automaticThere is no current workaround that is both transparent to the user and safe to deploy in a team/enterprise environment
Example prompts or workflows
A prompt-optimisation hook script (
.github/hooks/optimise-prompt.sh):Registered in
.github/hooks/hooks.json:{ "version": 1, "hooks": { "userPromptSubmitted": [ { "type": "command", "bash": ".github/hooks/optimise-prompt.sh", "timeoutSec": 10 } ] } }Additional context
Related
UserPromptSubmithook; the two tools are converging on the same hook pattern and parity here would be valuable