Claude Code 하네스를 「월간 스캔 + spec.md」로 자기 개선시키기 —— type:"prompt" Hook의 오검출을
요약
본 기사는 Claude Code 하네스(harness)가 시간이 지남에 따라 발생하는 오검출(false positive) 문제를 해결하기 위한 자율 개선 메커니즘을 소개한다. 핵심은 `type: "prompt"` 후크의 모호한 동작을 GPT-5.4를 이용한 코드 리뷰와, Hook의 변경 의도를 명시하는 `spec.md` 문서를 병행 관리하여 '의도와 구현의 괴리'를 정기적으로 검사하는 것이다.
핵심 포인트
- Claude Code는 후크(hooks)를 통해 특정 이벤트 발생 시 셸 커맨드나 추가 프롬프트를 자동 실행할 수 있다.
- 특히 `type: "prompt"` 후크는 사용자가 인지하기 어려울 정도로 답변에 조용히 삽입되어 오검출 위험이 높다.
- 오검출 방지를 위해, Hook의 동작을 GPT-5.4 같은 외부 LLM에게 정기적으로 리뷰시키고(코드 리뷰), 변경 의도를 `spec.md` 파일로 명시하여 관리해야 한다.
- 월간 스캔 플로우는 `settings.json`과 `spec.md`를 비교하며, 미기재되거나 열화된 Hook을 자동으로 검출하는 지속적인 메커니즘이다.
Claude Code는 ~/.claude/settings.json에 후크(hooks)를 등록함으로써, 특정 이벤트를 트리거로 임의의 셸 커맨드(shell command)를 자동 실행할 수 있습니다.
하지만 후크 설정이 늘어나면 「의도하지 않은 타이밍에 발화하는」 오검출(false positive)이 조용히 쌓여갑니다.
본 기사에서는 아래의 두 가지 메커니즘을 조합하여 하네스(harness)를 자율 개선시킨 사례를 소개합니다.
월간 스캔 (spec.md 리뷰): 30일마다 설정 파일을 구조 리뷰하여 괴리 및 열화를 검출
GPT-5.4에 의한 코드 리뷰: codex-review 스킬을 사용하여 type: "prompt" 후크의 오검출을 발견
settings.json의 hooks 섹션은 다음과 같은 구조를 가집니다.
{
"hooks": {
"UserPromptSubmit": [
...
후크에는 여러 가지 type이 있습니다.
| type | 동작 |
|---|---|
command | 셸 커맨드(shell command)를 실행. exit 1로 Claude의 처리를 중단할 수 있음 |
prompt | Claude 자신에게 추가 프롬프트(prompt)를 삽입 (이 부분이 함정) |
type: "prompt"는 「사용자의 입력에 지시를 덮어쓰고 싶을 때」 사용합니다. 예를 들어 「git push를 포함한 지시가 오면, 정말 의도한 것인지 확인하게 한다」와 같은 사용법이 상정됩니다.
필자의 환경에서는 스케줄 태스크(scheduled task)의 자동 기동이나 스킬 관리의 일련의 플로우를 「하네스(harness)」라고 부르며 운용하고 있습니다.
어느 월간 스캔에서, UserPromptSubmit에 등록한 type: "prompt" 후크가 의도하지 않은 문자열 패턴에도 반응하는 문제를 발견했습니다.
구체적으로는 다음과 같은 matcher를 설정하고 있었습니다.
{
"matcher": "deploy",
"hooks": [
...
이 설정의 의도는 「deploy라는 단어를 포함하는 프롬프트가 오면 배포 확인을 촉구한다」는 것입니다.
하지만 실제로는 다음과 같이 전혀 관계없는 문맥에서도 발화하고 있었습니다.
- 「Cloudflare Workers의 배포 전략을 알려줘」
- 「deploy hook의 동작을 확인하고 싶어」
- 「
vercel deploy의 문서 URL을 조사해줘」
type: "prompt"는 type: "command"와 달리, 추가 프롬프트가 조용히 삽입될 뿐이므로 사용자가 알아차리기 어렵다는 점이 까다롭습니다. Claude의 답변이 미세하게 변해도 「그런가 보다」 하고 넘어가 버리게 됩니다.
월간 스캔 플로우에서는 /codex-review 스킬을 사용하여 settings.json의 차이점(diff)을 GPT-5.4가 리뷰하도록 하고 있습니다.
# codex-review 스킬 호출 예시
cd ~/.claude
codex --model gpt-5.4 "settings.json의 hooks 섹션을 리뷰하고, 오검출 리스크가 있는 matcher를 지적해 주세요"
GPT-5.4는 다음과 같은 리포트를 출력했습니다 (요약).
[HIGH] matcher: "deploy" — 부분 일치(partial match)이므로, 단어 "deploy"를 포함하는
모든 프롬프트에 발화합니다.
의도하는 대상이 "실제 배포 조작"이라면,
...
이 지적을 바탕으로, deploy의 matcher를 구체적인 커맨드 이름으로 분할했습니다.
{
"hooks": {
"UserPromptSubmit": [
...
오검출을 방지하는 지속적인 메커니즘으로서, **「변경 의도의 spec.md」**를 후크와 나란히 관리하고 있습니다.
~/.claude/
settings.json ← 실제 설정
docs/
...
hooks-spec.md에는 다음과 같이 기술합니다.
## UserPromptSubmit / vercel deploy
**목적**: vercel deploy 커맨드를 포함한 지시가 왔을 때, 프로덕션(production) 배포 전에 스테이징(staging) 확인을 촉구함
**상정 발화**:
...
월간 스캔에서는 이 spec.md와 settings.json을 [비교합니다/사용합니다]
의 diff를 가져와서, "명세서에 적혀 있지 않은 Hook이 늘어나지 않았는지", "30일 이상 업데이트되지 않은 Hook이 실제 상태와 일치하는지"를 체크합니다.
스케줄 태스크(Scheduled Task)로 등록할 스캔의 골격을 보여줍니다.
import json
from pathlib import Path
from datetime import datetime, timedelta
...
type: "prompt"
Hook은 조용히 삽입되기 때문에, 오검출(False Positive)을 알아차리기 어렵습니다 -
matcher
는 **구체적인 커맨드 이름(Command Name)**까지 좁힙니다 (단어 단위는 오검출의 원인이 됩니다) - Hook과 병행하여
spec.md (변경 의도의 명세서)
를 관리함으로써, 월간 스캔이 기능하게 됩니다 - GPT-5.4 등의 외부 리뷰어에게
settings.json
을 정기적으로 리뷰하게 하면, 스스로는 알아차리지 못하는 오검출 패턴을 발견할 수 있습니다 - 스캔 결과는
settings.json
과의 diff로 시각화하여, 미기재된 Hook을 자동 검출합니다.
하네스(Harness)는 만들고 끝나는 것이 아니라, 정기적으로 "의도와 구현의 괴리"를 체크하는 메커니즘을 가짐으로써, 장기간에 걸쳐 건전하게 계속 기능합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기