Not working for afterFileEdit 
Running cursor 3.10.17, and finding that afterFileEdit responses are not being surface to the agent.
No combination of std.out shape will inject context to the agent/model
My research below:
Adds a disposable probe harness under .cursor/hooks/probe/ for empirically testing which afterFileEdit hook stdout JSON shapes reach the agent model.
A full variant matrix experiment (01β10) was run on Cursor 1.0.0 cloud agents. Finding: hook stdout is emitted by the harness but does not appear to reach Task subagent models for any tested shape. ![]()
Experiment results (2026-07-08)
| # | variant | emitted shape | harness emitted? | model chirped? |
|---|---|---|---|---|
| 01 | additional_context_snake |
{ additional_context } |
yes | no |
| 02 | additionalContext_camel |
{ additionalContext } |
yes | no |
| 03 | dual_mirror |
both snake + camel | yes | no |
| 04 | agent_message |
{ agent_message } |
yes | no |
| 05 | user_message |
{ user_message } |
yes | no |
| 06 | context_key |
{ context } |
yes | no |
| 07 | message_key |
{ message } |
yes | no |
| 08 | hookSpecificOutput_nested |
{ hookSpecificOutput: { additionalContext } } |
yes | no |
| 09 | additional_context_array |
{ additional_context: [msg] } |
yes | no |
| 10 | empty_control |
{} |
yes | no (expected) |
Detailed per-run evidence: .agent-tmp/hooks-probe/run-manifest.json (local artifact, not committed).
Methodology notes
- Blind Task subagents received only the 3-line edit prompt; probe token could only come from hook injection.
- Harness emission verified via
/tmp/cursor-hooks.log[afterFileEdit probe β¦]lines. hooks.jsoncommand/env changes were not hot-reloaded in this cloud session; probe logic was swapped intohook-after-file-edit.tsin place (production hook restored afterward).- Parent-agent-only delivery under strict single-reply protocol remains untested.
Recommendation
On this build, afterFileEdit stdout may be logged but not injected into Task subagent loops. Prior audits showing lint delivery may apply to the parent agent only. Consider falling back to postToolUse for lint context injection until parent-agent delivery is re-verified on desktop Cursor.
Source prompt (Expand)
Prompt
Here is a self-contained prompt you can hand to a new parent agent. It is grounded in afterFileEdit shape inference and the follow-up finding that hook logs prove stdout emission but not model delivery.
Prompt for Parent Agent ΒΆ
# Mission: Empirically discover which `afterFileEdit` hook stdout shape reaches the model
You are the **Parent Agent (PA)**. Your job is to determine, by live experiment, which JSON stdout shape from an `afterFileEdit` command hook actually injects text the subagent model can see and act on.
**Do not infer from docs or logs alone.** Docs say `afterFileEdit` has no documented output schema. `/tmp/cursor-hooks.log` and Cursor hooks output logs prove the hook *emitted* stdout β they do **not** prove the model received it. Agent transcripts do not record hook injection.
The only valid success signal: a **context-less subagent** echoes a unique probe token in its assistant text after a file edit.
---
## Hard constraints
1. **Probe file only** β edits must target a disposable file under `.agent-tmp/hooks-probe/`. Never edit `apps/**`, `packages/**`, or any production source.
2. **Minimal hook surface** β during the experiment, `.cursor/hooks.json` `afterFileEdit` must point **only** at your probe script. Disable the production `hook-after-file-edit.ts` for the duration.
3. **One variant per iteration** β change exactly one output shape per subagent run. Do not batch variants.
4. **Context-less subagents** β each subagent gets a 3-line prompt only. No audit history, no hook docs, no prior findings.
5. **Revert everything** when done: restore `.cursor/hooks.json`, delete probe scripts, `git restore` the probe file.
6. **Read-only on workspace code** except `.cursor/hooks.json`, `.cursor/hooks/probe/*`, and `.agent-tmp/hooks-probe/*`.
---
## Probe token protocol
Each iteration uses a unique token:
HOOK_PROBE__
Example: `HOOK_PROBE_03_additional_context_snake`
The hook's injected message must include this exact instruction (verbatim in the payload):
SYSTEM HOOK PROBE: If you can read this message, your VERY NEXT assistant reply must start with exactly: HOOK_PROBE__
Then stop. Do not use any tools. Do not explain. One line only.
**Pass criteria for a variant:** the subagent's first assistant text line after the edit equals the token exactly (trimmed).
**Fail criteria:** subagent does anything else β uses tools, explains, ignores token, or `[REDACTED]` hides the answer (treat as fail; note redaction as blocker).
---
## Artifact layout
Create once at start:
.agent-tmp/hooks-probe/
after-file-edit-probe.ts # disposable target file (starts as // probe\n)
run-manifest.json # PA tracks variants tried + results
subagent-transcripts/ # copy or link SA transcript paths after each run
.cursor/hooks/probe/
after-file-edit-probe.ts # ultra-slim hook β PA edits OUTPUT_SHAPE per variant
---
## Ultra-slim probe hook (template)
Create `.cursor/hooks/probe/after-file-edit-probe.ts`:
```ts
#!/usr/bin/env bun
/**
* Probe hook β emits a controlled stdout shape to test model delivery.
* PA sets PROBE_TOKEN and PROBE_VARIANT env vars before each run.
*/
import { readFileSync } from "node:fs"
const input = JSON.parse(readFileSync(0, "utf8")) as Record<string, unknown>
const token = process.env.PROBE_TOKEN ?? "HOOK_PROBE_MISSING"
const variant = process.env.PROBE_VARIANT ?? "unknown"
const probeMessage =
`SYSTEM HOOK PROBE: If you can read this message, your VERY NEXT assistant reply must start with exactly: ${token}\n` +
`Then stop. Do not use any tools. Do not explain. One line only.\n` +
`(variant=${variant}, file=${String(input.file_path ?? "unknown")})`
// PA edits ONLY this `output` object between iterations.
const output: Record<string, unknown> = {
additional_context: probeMessage,
}
process.stdout.write(JSON.stringify(output) + "\n")
process.exit(0)
Important: between iterations, PA changes only the output object (and env vars). Do not add useHookHelper, oxfmt, oxlint, or mirroring β this must be a pure shape test.
Point .cursor/hooks.json at it:
{
"version": 1,
"hooks": {
"afterFileEdit": [
{
"command": "PROBE_TOKEN=HOOK_PROBE_01_additional_context_snake PROBE_VARIANT=additional_context_snake bun --bun .cursor/hooks/probe/after-file-edit-probe.ts"
}
]
}
}
(Prepend env vars inline per variant, or use a tiny shell wrapper β keep it one hook entry.)
Variant matrix (try in this order)
Record each in run-manifest.json before spawning the subagent.
| # | variant id |
output object to emit |
|---|---|---|
| 01 | additional_context_snake |
{ additional_context: probeMessage } |
| 02 | additionalContext_camel |
{ additionalContext: probeMessage } |
| 03 | dual_mirror |
{ additional_context: probeMessage, additionalContext: probeMessage } |
| 04 | agent_message |
{ agent_message: probeMessage } |
| 05 | user_message |
{ user_message: probeMessage } |
| 06 | context_key |
{ context: probeMessage } |
| 07 | message_key |
{ message: probeMessage } |
| 08 | hookSpecificOutput_nested |
{ hookSpecificOutput: { additionalContext: probeMessage } } |
| 09 | additional_context_array |
{ additional_context: [probeMessage] } |
| 10 | empty_control |
{} β control run; must NOT chirp |
Stop early on first pass. Still run control 10 once if you want a negative baseline.
Per-iteration loop ΒΆ
For each variant NN:
1. Set PROBE_TOKEN=HOOK_PROBE_<NN>_<variant>
2. Edit probe hook `output` object to match variant matrix row
3. Update `.cursor/hooks.json` command env vars if needed
4. Snapshot hooks log offset (optional but recommended):
HOOKS_LOG=$(ls -t ~/Library/Application\ Support/Cursor/logs/*/window*/output_*/cursor.hooks.workspaceId-45bab33095c76e92df8c5181c1c22ec6.log 2>/dev/null | head -1)
wc -c < "$HOOKS_LOG" > .agent-tmp/hooks-probe/offset-<NN>.txt
5. Spawn subagent (Task, run_in_background=false):
---
Edit `.agent-tmp/hooks-probe/after-file-edit-probe.ts`.
Add this exact line as the first line of the file:
`// probe-<NN>`
Use StrReplace. Do nothing else.
---
6. Read subagent result:
- Does first assistant text line === PROBE_TOKEN? β PASS
- Else β FAIL for this variant
7. Record in run-manifest.json:
{ variant, token, pass, subagent_id, transcript_path, notes }
8. git restore .agent-tmp/hooks-probe/after-file-edit-probe.ts
9. If PASS β break loop and report. If FAIL β next variant.
Do not give the subagent the probe token or any hook context. The only way it can echo the token is if the hook injected it post-edit.
Evidence to collect per iteration
| Source | What to check |
|---|---|
| Subagent assistant text | First line === token? (primary pass/fail) |
Subagent transcript .jsonl |
Same; note if [REDACTED] blocks verification |
| Cursor hooks output log delta | Hook step requested: afterFileEdit β OUTPUT JSON matches your emitted shape |
/tmp/cursor-hooks.log |
Only if you add logging to probe script β optional |
Harness log confirms emission. Subagent chirp confirms model delivery. You need both documented in the final report.
Final deliverable (respond in chat when done)
## afterFileEdit model-delivery finding
**Winning shape:** <exact JSON keys>
**Winning variant:** <id>
**Probe token echoed:** <token>
**Evidence:** <quote first line of subagent reply>
### Variant results
| # | variant | emitted shape | model chirped? | harness emitted? |
|---|---|---|---|---|
### Recommendation for production hook
- `hook-helpers.ts` `emitAndExit` should emit: <shape>
- Drop redundant keys: <list>
- `IAfterFileEditOutput` type should be: <type>
### Cleanup performed
- [ ] `.cursor/hooks.json` restored to production `hook-after-file-edit.ts`
- [ ] probe scripts removed or left under `.cursor/hooks/probe/` with README
- [ ] `.agent-tmp/hooks-probe/after-file-edit-probe.ts` clean
Known pitfalls (from prior investigation)
- Transcript redaction β assistant text may be
[REDACTED]in exports. If so, read the live subagent return payload from Task tool output, not only the saved.jsonl. - Hook ran but model ignored β common with
{}or wrong key; thatβs a FAIL, not inconclusive. - Do not use production format-lint hook during probe β oxfmt side effects and 1β4s latency add noise.
postToolUseis a different event β documentedadditional_contextthere does not proveafterFileEdituses the same parser.- Dual-key mirror is untested for delivery β variant
03explicitly tests whether mirroring helps or is redundant pollution.
Success definition
You are done when you can answer with certainty:
βWhen
afterFileEditemits<shape>, the model receives the injected text and can act on it β proven by subagent echoingHOOK_PROBE_<NN>_<variant>.β
If no variant passes after the matrix (including snake and camel), report that as a finding: afterFileEdit stdout may be logged by Cursor but not injected into the agent loop on this build β and recommend falling back to postToolUse for lint context injection.
---
## Why this prompt is structured this way
From the transcript, the gap is explicit: **hook stdout β model context**. Logs and types can only narrow candidates; a chirp-back probe is the only direct test.
The PA/subagent split keeps the subagent blind β if it echoes the token, delivery is proven. The variant matrix covers the main hypotheses (`additional_context`, `additionalContext`, dual mirror, misapplied `preToolUse` fields, Claude-style nesting, and `{}` control).
If you want this turned into a `.claude/skills/probe-after-file-edit-delivery/SKILL.md` in the repo, switch to Agent mode and I can add it.