Cowork (Windows): UserPromptSubmit hooks now execute, but stdout/additionalContext is discarded — wire hook output into context at parity with Claude Code
Preflight Checklist
- [x] I have searched existing requests and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)
Problem Statement
Follow-up to #63360 (closed stale, "open a new issue if still relevant" — it is) and related to #40495.
State has advanced since those reports: Cowork now EXECUTES UserPromptSubmit hooks — but discards their output, so the primary use case (per-prompt context injection) still doesn't work.
Verified 2026-07-03, Cowork desktop on Windows, hook configured in ~/.claude/settings.json invoking a PowerShell script that (a) appends a timestamped line to a log file and (b) emits reminder text:
What works:
- Hook fires once per user prompt (confirmed via the timestamped log the hook itself writes)
- Does NOT fire on a fresh session's opening prompt
- Settings edits propagate with lag inside a running session (a stale snapshot of the old command fired once after replacement)
- Windows note: hook commands run through a bash-style shell, not cmd (%VAR% does not expand); invoking via
powershell -NoProfile -File <script.ps1>works
What doesn't:
- Hook output never reaches the model. Tested both channels: plain stdout, and structured JSON
{"hookSpecificOutput":{"hookEventName":"UserPromptSubmit","additionalContext":"..."}}. The fire is logged, the model's context contains nothing from the hook on that turn (asked the model directly to report; negative across multiple sessions and prompts).
Why it matters: per-prompt injection is the main reason users configure UserPromptSubmit — re-anchoring standing instructions in long sessions as the initial context ages. Cowork sessions run long and suffer instruction drift at least as much as Claude Code sessions. Execution already works, so this appears to be only the return-path wiring.
Proposed Solution
Wire UserPromptSubmit hook output into the conversation in Cowork at parity with Claude Code:
- Plain stdout added as context, and/or the documented
hookSpecificOutput.additionalContextJSON channel - Ideally also honor the decision/block channel (exit code 2 / "decision" field) and fire on the session-opening prompt
- Bonus: a way to inspect configured hooks from within Cowork (equivalent of Claude Code's /hooks)
Alternative Solutions
- Manually invoking a "recalibrate" skill that re-reads standing rules mid-session — works but depends on the user noticing drift; the hook exists precisely to remove that dependency
- Running the same workflow in Claude Code CLI where injection is documented to work — abandons the Cowork workflow entirely
- Putting rules in CLAUDE.md / project instructions — loads once at session start and decays as context grows, which is the problem UserPromptSubmit injection solves
Priority
Medium - Would be very helpful
Feature Category
Configuration and settings
Use Case Example
Scenario — standing-instruction reinforcement over a long Cowork session:
- User's preferences include rules that matter on every turn (verification-before-stating, formatting constraints, scope discipline).
- A UserPromptSubmit hook emits a 5-line refresher as additionalContext on each prompt.
- Early in a session the initial instructions dominate; 40+ turns in, they've aged out of salience. The hook keeps them freshest-in-context on every turn, at ~60 tokens per prompt.
- Today in Cowork: the hook fires (log proves it), the refresher never arrives, and the model drifts exactly as if no hook existed.
Additional Context
Environment: Cowork desktop app on Windows 11, verified 2026-07-03. Hook: ~/.claude/settings.json UserPromptSubmit -> powershell -NoProfile -ExecutionPolicy Bypass -File <script.ps1>; script appends ISO-timestamped lines to a log and emits the JSON additionalContext payload (validated standalone — emits correct JSON when run directly).
Prior reports: #63360 (macOS, May 2026 — hooks didn't fire at all; closed stale as not planned), #40495 (sandbox platform mismatch breaks settings resolution). The Windows behavior above suggests execution has since been partially wired — this request is for the remaining output/injection path.