On Windows, Chinese prompt in hooks stdin becomes "?" while execution.log shows correct text

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

Title: On Windows, Chinese prompt in hooks stdin becomes “???” while execution.log shows correct text

Environment:

  • OS: Windows 10/11 (Chinese locale)
  • Cursor version: 2.2.29 (also reproduced on 2.2.20)
  • Hook type: beforeSubmitPrompt
  • Config file: C:\Users<username>.cursor\hooks.json

Issue:
When I type a Chinese prompt in Cursor, for example:
测试一条中文,不用回答

I can see the correct Chinese text in:
Settings → Hooks → execution.log
for the corresponding hook invocation. This suggests Cursor’s internal representation of prompt is correct (proper Unicode/UTF‑8).

However, inside my hook process (reading from stdin), the JSON payload’s prompt field has already turned into a series of question marks. For example:

“prompt”: “???”

I verified this by:

  • Writing stdin directly to a file (no extra processing), and
  • Later by reading stdin in PowerShell and logging the raw JSON.

In the hex dump of that JSON, the prompt segment looks like:

22 70 72 6F 6D 70 74 22 3A 22 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 22
=> “prompt”:“???”

So at the point the hook process receives data over stdin, all non‑ASCII Chinese characters have already been replaced by ASCII 0x3F (?). There are no remaining UTF‑8 multibyte sequences to recover the original Chinese text.

At the same time, the same hook execution entry in execution.log shows the full correct Chinese prompt, e.g.:
“prompt”: “测试一条中文,不用回答”

This strongly suggests:

  • Inside Cursor, the prompt string is correct (Unicode),
  • But when writing the JSON payload to the hook child process via stdin on Windows, some encoding layer is using a non‑UTF‑8 code page and replacing unrepresentable characters with ?.

Current hooks.json (example):

{
“version”: 1,
“hooks”: {
“beforeSubmitPrompt”: [
{
“command”: “powershell.exe”,
“args”: [
“-NoProfile”,
“-ExecutionPolicy”,
“Bypass”,
“-File”,
“hooks\record-chat.ps1”
]
}
]
}
}

In record-chat.ps1 I:

  • Read all of stdin via [Console]::OpenStandardInput() / StreamReader (UTF‑8 aware),
  • ConvertFrom-Json to parse the payload,
  • Write payload.prompt to C:\Users\<username>\.cursor\chat_history.txt using UTF‑8 (no BOM).

But by the time the script runs, payload.prompt is already "????...", so the corruption happens before my hook code.

I also tried a pure batch (.bat) hook that just dumps stdin to a file; the JSON there already has "prompt":"????...", consistent with the above.

Expected behavior:

  • The JSON payload written to the hook’s stdin on Windows should preserve the exact same prompt text as shown in execution.log, i.e. full Chinese text encoded as UTF‑8, not downgraded to ?.

Suspected root cause:

  • On Windows, when spawning the hook process and writing to its stdin, Cursor (or a lower‑level library) is encoding the JSON using the system code page (e.g. 936/GBK or 437) instead of UTF‑8, and any characters not representable in that code page are replaced with ? (0x3F).
  • execution.log prints the in‑memory Unicode string directly, so it shows correct Chinese.

Questions / Requests:

  1. Can you confirm what encoding Cursor uses when sending the hook JSON payload to stdin on Windows?
  2. Is there any known limitation where a non‑UTF‑8 code page is used for hooks on Windows?
  3. Could this be changed/fixed so that hooks always receive UTF‑8 JSON on stdin (matching what execution.log shows), regardless of system code page?

I can provide:

  • Full record-chat.ps1,
  • The hooks.json used,
  • Screenshots of execution.log with correct Chinese prompt,
  • And the raw JSON captured from stdin where prompt is "????...".

Steps to Reproduce

When I type a Chinese prompt in Cursor, for example:
测试一条中文,不用回答

I can see the correct Chinese text in:
Settings → Hooks → execution.log
for the corresponding hook invocation. This suggests Cursor’s internal representation of prompt is correct (proper Unicode/UTF‑8).

However, inside my hook process (reading from stdin), the JSON payload’s prompt field has already turned into a series of question marks. For example:

“prompt”: “???”

I verified this by:

  • Writing stdin directly to a file (no extra processing), and
  • Later by reading stdin in PowerShell and logging the raw JSON.

Operating System

Windows 10/11

Current Cursor Version (Menu → About Cursor → Copy)

Version: 2.2.29 (user setup)
VSCode Version: 1.105.1
Commit: 656af3704923280dedba3ccd49cfaf9b9d456e90
Date: 2025-12-17T03:49:27.355Z
Electron: 37.7.0
Chromium: 138.0.7204.251
Node.js: 22.20.0
V8: 13.8.258.32-electron.0
OS: Windows_NT x64 10.0.26100

Does this stop you from using Cursor

No - Cursor works, but with this issue

Hey!

Thanks for the report. :folded_hands:

I believe that this was reported here already:

And I’ve linked this thread to the internal ticket.

This topic was automatically closed 22 days after the last reply. New replies are no longer allowed.