헌법 문서, 에이전트 파일, 스킬 파일, 배선표, 그리고 검문소. 텍스트 파일 다섯 개로 최소 하네스를 세우는 실제 순서 — 아홉 작업장에서 공통으로 검증된 골격만 남겼다.
§ 00 · 첫 파일 — 헌법 60줄
저장소 루트에 CLAUDE.md라는 이름의 파일을 만든다. 이 이름의 파일은 세션이 열릴 때마다 자동으로 로드된다 — 하네스의 주춧돌이 되는 관례다. 처음 적을 것은 세 가지뿐이다. 이 프로젝트가 무엇인지 다섯 줄. 절대 하지 말 것 몇 가지 — 이를테면 “확인 안 된 것을 완료라고 보고하지 마라”, “본선(main) 가지에 직접 밀어 넣지 마라”. 그리고 검증 명령 — 테스트는 무엇으로 돌리고 빌드는 무엇으로 확인하는지.
길이는 60줄 안팎에서 시작하고, 그 근처를 유지한다. 이유는 단순하다 — 규칙서가 길수록 규칙 하나하나가 받는 주의는 옅어진다. 공개된 측정들이 서늘하다. 규칙 열 개면 대부분 지키고, 쉰 개면 절반을 무시하고, 백 개면 무엇이 중요한지 판단하지 못한다. 규칙서가 300줄을 넘으면 기계는 규칙을 골라서 무시하기 시작한다. 실측도 이를 증명한다. 한 작업장은 헌법이 500줄을 넘긴 뒤 규칙 무시가 잦아지자 150줄로 다이어트하고, 잘라낸 내용을 별도 지식 폴더로 옮겼다. 가장 큰 작업장은 헌법을 73줄로 유지하는 대신 “줄 수 상한을 어기면 커밋 직전 센서가 경고하는” 장치까지 달았다. 헌법은 지도만 남기고, 상세는 링크 너머로.
한 가지 함정을 처음부터 피하라. 문서에 개수를 적지 마라 — “센서 7개”, “테스트 24개” 같은 숫자는 적는 순간부터 썩기 시작한다. 파일은 늘고 문서는 안 고쳐지니까. 실측된 처방은 두 가지다. 숫자 대신 세는 명령을 적거나(“개수는 ls로 실측하라”), 커밋 직전에 실측값을 문서에 자동으로 덮어쓰는 스크립트를 달거나. 어느 쪽이든 원칙은 같다 — 문서가 현실을 주장하게 하지 말고, 현실을 가리키게 하라.
§ 01 · 두 번째 파일 — 에이전트
.claude/agents/ 폴더를 만들고 그 안에 일꾼 하나당 마크다운 파일 하나를 둔다. 파일 맨 위, 세 개의 대시(---)로 감싼 머리말에 네 줄을 적는다. name: 일꾼 이름(예: 검수관). description: 언제 부르는지(예: “완료 선언을 검증할 때. 코드는 수정하지 않고 판정만 한다”). tools: 쥐여줄 도구(예: Read, Bash, Grep — 수정 도구는 일부러 뺀다). model: 쓸 모델(05편에서 다룬다).
본문의 골격은 아홉 작업장에서 거의 동일하게 반복된다. 맨 위에 절대 제약 블록 — 반드시/권장/선택 세 등급의 라벨을 붙인 금지·의무 목록. 이어서 역할 서술과 “작업 전 반드시 읽을 정본 문서” 목록. 그리고 맨 아래에 다시 한번, 제출 직전 자기검문 목록 — “실측 없이 완료라고 적지 않았는가”, “출력 원문을 붙였는가”. 위와 아래에 같은 제약을 두 번 박는 이중 앵커다. 긴 문서에서 기계가 가장 잘 지키는 위치가 처음과 끝이라는, 여러 작업장에서 확인된 경험칙의 산물이다.
첫 일꾼으로 무엇을 만들까. 실측이 주는 답은 명확하다 — 검증자부터 만들어라. 구현을 잘하는 일꾼보다, 구현이 진짜 됐는지를 너 대신 재 주는 일꾼이 먼저다. 수정 도구를 뺀 검사 전담 일꾼 하나가 생기는 순간, “다 됐습니다”라는 보고는 “검수관을 통과했습니다”라는 보고로 바뀐다. 그 차이가 하네스의 시작이다.
§ 02 · 세 번째 파일 — 스킬
.claude/skills/ 아래에 폴더를 하나 만들고 그 안에 SKILL.md를 둔다. 머리말은 두 줄이면 시작된다 — name과 description. description에는 발동 조건을 구체적으로 적는다. 여기에 트리거 키워드 배열을 더 얹는 작업장들도 있다 — “완료했습니다”, “전부 통과”, “문제없습니다” 같은 어구 스무 개를 나열해 두고, 그 말이 나오려는 순간 스킬이 끼어들게 만드는 것이다.
첫 스킬은 정해져 있다시피 하다. 완료 선언 게이트. 본문에 이렇게 적는다 — 완료를 선언하기 전에 ① 타입 검사 ② 테스트 ③ 빌드를 실제로 실행한다. 각 명령의 출력 원문을 보고에 붙인다. 그리고 금지 세 줄 — 실측 없는 완료 주장 금지. 일부만 검증하고 전체가 통과했다고 말하기 금지. 이전 세션의 결과를 지금의 증거로 둔갑시키기 금지. 이 세 줄은 여러 작업장에서 실제 사고를 겪은 뒤 박제된 문장들이고, 효과는 수치로도 잰다 — 앞서 말한 그 벤치마크 역전극에서 최대 기여 요소가 바로 이 “제출 전 자기검문” 패턴 하나였다.
마지막으로 보고 템플릿을 스킬 안에 붙여 둔다 — 판정, 실행한 명령, 출력 원문, 남은 문제, 이 네 칸짜리 골격이면 된다. 보고의 형식이 고정되면 얼버무림이 어려워진다. 빈칸은 채워지거나, 비어 있다는 사실 자체가 드러나거나 — 둘 중 하나이기 때문이다.
§ 03 · 네 번째, 다섯 번째 파일 — 배선표와 검문소
네 번째 파일은 배선표, .claude/settings.json이다. “어느 순간에 어느 스크립트를 돌릴 것인가”를 연결한다. 실측에서 가장 흔한 최소 배선은 세 가닥이다. 세션 시작 → 기억이 최신인지 검사하는 스크립트. 파일 수정 직후 → 타입 검사를 조용히 돌리는 스크립트. 세션 종료 → 오늘 커밋이 있는데 기록을 안 남겼으면 경고하는 스크립트. 스크립트 본체는 .claude/scripts/에 둔다 — 03편의 방법으로 기계에게 짜게 하면 된다.
배선의 규율 하나. 훅은 웬만하면 차단하지 않는다 — 실측된 훅 스크립트의 절대다수가 “무슨 일이 있어도 통과(exit 0)”로 끝난다. 훅 자신의 결함이 작업 전체를 멈춰 세우면 안 되기 때문이다. 다만 훅의 진짜 가치는 따로 있다. 채팅으로 “하지 마”라고 부탁하는 것은 기계가 무시할 수 있는 가장 약한 제약이지만, 훅은 기계의 의도와 무관하게 작동한다 — 그래서 가장 신뢰도 높은 제약이다. 평소의 훅은 속삭이고, 무는 것은 다섯 번째 파일의 몫이다.
다섯 번째 파일이 진짜 검문소다. .githooks/ 폴더에 pre-push라는 셸 스크립트를 만든다 — 원격 저장소로 밀어올리기 직전에 자동 실행되는 git의 관례다. 내용은 센서 3단 — 타입 검사, 테스트, 빌드 — 을 차례로 돌리고 하나라도 실패하면 종료 코드 1로 푸시 자체를 거부하는 것. 활성화는 터미널에서 단 한 줄, git config core.hooksPath .githooks — 이것만은 사용자가 직접 한 번 실행한다. 이 순간부터 “테스트가 깨진 채로 배포되는” 사고는 구조적으로 불가능해진다. 기계가 게을러서가 아니라, 문이 잠겨 있어서.
Read this note at sass.studio.