AI 코딩 에이전트의 작업 상태를 휴대폰으로 보는 개인 도구를 만들었다. 커밋 주석에 따르면 Windows Cursor 훅에서는 프롬프트·모델·stop 이벤트가 수집기에 닿지 않았다. PowerShell을 중첩 호출하던 구조를 바꾸고, 파이프 전달 테스트를 추가했다.

에이전트 상태를 휴대폰으로 보내는 훅
AI 코딩 에이전트 작업 모니터는 PC 수집기에서 서버로 이벤트를 보낸다. Android 앱에서 상태와 사용량을 보고 상시 알림을 받는다.
기록은 10월 22일의 단일 루트 커밋에 묶여 있다. 중간 시도의 시각은 확인할 수 없다.
공식 생명주기 훅을 우선 사용한다. Cursor 사용자 훅은 ~/.cursor/hooks.json에 등록하며 stdin으로 JSON을 받는다.
훅은 세 단계로 동작한다.
- stdin에서 이벤트 JSON을 읽는다.
- PC에 상주하는 수집기로 HTTP 요청을 보낸다.
- 표준 출력(stdout)에
{}를 쓰고 종료한다.
전달에 실패해도 Cursor 작업은 막지 않는다. 설계 문서에 처음부터 적어 둔 조건이다.

PowerShell을 한 번 더 거치던 초기 계획
10월 21일 계획은 전달용 .ps1을 훅에 등록하는 방식이었다. sessionStart·stop·sessionEnd에 powershell -NoProfile -File을 등록하도록 적었다.
Windows의 EncodedCommand는 경로 인용 문제를 피하려는 분기다. 명령을 UTF-16LE·Base64로 바꾸며 Codex와 Grok에서는 유지했다.
Go 분기를 발췌했다. 한국어 주석은 원본 코드가 아닌 글쓴이의 생략 표시다.
// EncodedCommand avoids path-quoting differences in Windows hook runners.
script := "& '" + strings.ReplaceAll(exe, "'", "''") + "' --forward-hook " + tool + extraArgs
encoded := utf16.Encode([]rune(script))
// ... UTF-16LE 바이트로 바꾸는 부분 생략
return "powershell.exe -NoProfile -NonInteractive -EncodedCommand " +
base64.StdEncoding.EncodeToString(raw)
-File과 EncodedCommand는 모두 별도 PowerShell을 호출한다. 다만 수정 직전 Cursor에 어느 형식이 등록돼 있었는지는 확인되지 않는다.
Cursor 입력이 사라진 원인은 커밋 주석에 있다
프롬프트·모델·stop이 전달되지 않았다는 설명은 커밋 코드 주석에 있다. Cursor 공식 문서에는 Windows PowerShell 실행 방식이 없다.
고친 Cursor 분기를 보자. 영어 주석은 원문 그대로 남겼다.
if tool == "cursor" {
// Cursor on Windows already runs hooks in PowerShell and pipes the payload
// with `$input | <command>`. A nested powershell.exe consumes that pipeline,
// so the collector never sees the prompt, model, or stop event.
return "& " + powershellQuote(exe) + " --forward-hook " + tool + extraArgs
}
Cursor는 Windows에서 이미 PowerShell로 훅을 실행하고, $input | 명령 형태로 페이로드를 흘려보낸다. 그 안에서 powershell.exe를 또 띄우면 중첩된 셸이 파이프를 먹어 버린다.

이는 커밋 주석의 설명이며 현장 로그는 없다. stop의 completed 상태로 완료를 판단하니 해당 이벤트 누락도 문제가 된다.
Cursor는 실행 파일을 직접 호출하도록 수정했다
Cursor 훅은 호출 연산자 &로 실행 파일을 직접 부른다. 경로 안의 작은따옴표는 두 번 쓴다.
- Windows Cursor:
& '실행 파일' --forward-hook cursor로 직접 호출 - Windows Codex·Grok: 기존 EncodedCommand 유지
- 재설치: 옛 전달 항목만 제거하고 사용자 훅과 기존 설정 보존
원본 설정은 최초 한 번만 백업한다. 전달부는 stdin을 최대 1 MiB 읽고 UTF-8 BOM을 제거한다.
Go 전달부의 시작이다. 한국어 주석은 JSON 처리와 1.2초 제한 전송을 생략한 표시다.
func forwardHook(source, execution string) {
defer func() { _, _ = os.Stdout.WriteString("{}") }()
raw, err := io.ReadAll(io.LimitReader(os.Stdin, 1<<20))
if err != nil {
return
}
raw = bytes.TrimPrefix(raw, []byte{0xEF, 0xBB, 0xBF})
// ... JSON 파싱, 실행 환경 표시 후 로컬 수집기로 전달 (1.2초 제한)
}
defer로 종료 시 항상 {}를 출력한다. BOM 제거는 대비 코드이며 실제 Cursor가 BOM을 보냈다는 기록은 없다.
PowerShell 파이프로 입력을 검증했다
공백 있는 경로에 시험용 실행 파일을 만든다. PowerShell 파이프로 모델 정보와 한글 입력이 도착하는지 검사한다.
PowerShell 테스트 실행문을 줄이면 이렇다. 경로는 ...로 가렸다.
$OutputEncoding = [System.Text.Encoding]::UTF8
Get-Content -LiteralPath '...\payload.json' -Raw -Encoding UTF8 |
& { $input | & '...\with spaces\fixture.exe' --forward-hook cursor '...\received.bin' }
훅 명령에 powershell이나 EncodedCommand가 들어 있으면 바로 실패한다. 받은 파일에 model_id와 "한글 요청"이 그대로 있어야 통과한다.

Codex의 cmd.exe stdin과 재설치 시 사용자 훅 보존도 검증했다. Go 테스트와 vet는 통과했지만 Windows Cursor IDE 실기는 미검증이다.
서버와 앱에 도달한 실기기 작업은 WSL Codex 확장이었다. Windows Cursor 실동작을 검증한 것은 아니다.
이번에 배운 것
- 훅 실행 셸을 다시 호출하기 전에 stdin 경로부터 확인한다.
- cmd.exe와 PowerShell 파이프는 실행 환경을 나눠 시험한다.
- 재설치 과정에서도 사용자가 만든 훅과 설정을 보존한다.
다음에는 Windows Cursor IDE의 시작·종료를 확인할 계획이다. 테스트 통과와 실기기 확인은 별개다.
자주 묻는 질문
Q. Cursor 훅 실패가 에이전트 작업을 멈추나?
A. 공식 문서에 따르면 기본 설정에서는 종료 코드 2만 작업을 막고, 다른 비정상 종료는 그대로 진행한다. failClosed를 켜면 달라진다. 이 도구는 항상 {}를 출력하고 끝나도록 만들었다.
관련 글: 업데이트 후 관리자 권한을 물려받던 에디터, 작업 스케줄러로 권한 낮춰 재실행
참고: Cursor Docs: Hooks
'프로젝트 > AI 작업 모니터' 카테고리의 다른 글
| Cursor 기존 대화 초안 입력, 열린 목록은 활성 대화가 아니었다 (0) | 2026.10.23 |
|---|---|
| IDE 확장으로 수집기 교체, 새 PC 등록 없이 운영 서버로 옮겼다 (0) | 2026.10.23 |
| 폰에서 IDE로 보낸 지시, 응답이 사라져도 두 번 실행하지 않게 (0) | 2026.10.23 |
| IDE 대화 폰 중계, '보내는 중' 줄이 안 사라지고 제목이 바뀌었다 (0) | 2026.10.23 |