Harness Engineering · Part 4 · Chapter 13

먼저 빈 파일을
하나 만든다

좋은 Harness를 처음부터 설계하려 들지 않는다. 빈 파일 하나를 만들고, Agent가 처음 틀리는 순간을 기다린다. 한 번의 실수가 한 줄의 규칙이 되고, 그 한 줄들이 시간이 지나며 프로젝트의 지도가 된다. Harness의 시작은 지식의 과시가 아니라 실패를 기억하는 습관이다.

대상: 원문 §13 「从空白开始:你的第一个Harness」 범위: PDF 61–67쪽 68쪽부터 §14 시작 원문만 사용 · 외부 검증 없음
한 번에 완성하려는 마음은 대개 미래의 실패를 상상해 규칙을 쌓게 한다. 이 장은 반대로 간다. 실제로 틀린 것만 기억하고, 실제로 필요한 것만 남긴다.
01

세 도구, 세 개의 입구 — 시작점은 모두 빈 지시 파일이다

Claude Code, Codex CLI, Cursor는 파일명과 로딩 규칙이 다르지만 출발 철학은 같다. Agent가 반복해서 읽을 수 있는 지시 파일을 프로젝트 가까이에 두고, 프로젝트가 실제로 요구하는 규칙을 그곳에 축적한다.

Claude Code

CLAUDE.md

프로젝트 루트에 파일을 두면 매 세션 시작 시 자동으로 읽는다. 별도 등록이나 명령은 필요하지 않는다. 일반 Markdown이며 세 단계 상속을 지원한다.

touch CLAUDE.md
Global · ~/.claude/CLAUDE.md
Project · 프로젝트 루트 CLAUDE.md
Subdirectory · 하위 디렉터리 규칙이 상위 규칙을 덮음
Codex CLI

AGENTS.md

프로젝트 루트에서 현재 작업 디렉터리까지 단계적으로 탐색한다. 각 계층에서 AGENTS.override.mdAGENTS.md → fallback 이름을 확인하고, 루트에서 잎 방향으로 합친다.

touch AGENTS.md
가까운 디렉터리 규칙이 먼 규칙보다 우선
원문: 약 100줄을 권장
백과사전보다 지도로 사용하고 상세 문서는 docs/로 연결
Cursor

.cursor/rules/*.mdc

예전의 단일 .cursorrules는 deprecated로 설명되고, 현재 방식으로 여러 .mdc 규칙 파일을 두는 구조가 제시된다. Markdown에 YAML frontmatter를 더한다.

mkdir -p .cursor/rules
touch .cursor/rules/project.mdc

---
description: 프로젝트 공통 규범
globs: "**/*"
alwaysApply: true
---

# 규칙...
glob scoping으로 파일·디렉터리별 규칙 적용 가능
Global 넓고 일반적인 규칙
Project 프로젝트 고유 규칙
Local 가까운 맥락이 더 구체적으로 덮음
파일명은 다르지만 철학은 같다. 멀리 있는 일반 규칙보다 가까이 있는 구체적 맥락을 우선한다. Harness는 거대한 중앙 명령서보다 작업 가까이에 놓인 작은 지도를 선호한다.
02

파일을 만들었으면 아무것도 쓰지 않는다

“그래서 첫 줄에 무엇을 쓸까”라는 질문에 원문은 의외의 답을 준다. 아무것도 쓰지 않는다. 먼저 Agent가 실제로 어떻게 실패하는지 본다.

EMPTY INSTRUCTION FILE 미래의 실패를 미리 상상해 채우지 않는다.

실수 기반 Harness

Mitchell Hashimoto의 Ghostty 사례처럼, Agent가 한 번 실수하면 같은 실수를 다시 하기 어렵게 만드는 해결책을 공학화한다. 원문은 Ghostty의 AGENTS.md 각 줄이 과거 Agent의 실제 오류와 연결되어 있다고 설명한다.

실제 실패 원인 확인 한 줄 추가 재발 방지
파일이 살아 있다는 뜻은 계속 길어진다는 뜻만이 아니다. 실제 실패를 근거로 자라고, 필요 없어진 규칙은 다시 잘라낼 수 있다는 뜻이다.
빈 파일은 준비가 부족한 상태가 아니다. 아직 증명되지 않은 규칙을 넣지 않은 상태다. 경험이 한 줄의 필요성을 증명할 때만 문장이 생긴다.
03

React 프로젝트에서 처음 생길 법한 10개의 규칙

원문은 빈 파일에서 출발해 앞선 열 번의 실패가 어떻게 규칙으로 바뀌는지 구체적으로 보여준다. 중요한 것은 규칙 내용보다 그 규칙이 생긴 이유다. 열 개 모두 실제 문제에 대한 대응으로 만들어진다.

FAILURE 01

잘못된 테스트 명령

Agent가 npm test를 실행했지만 프로젝트는 Vitest를 사용한다.

# 테스트
- 실행: pnpm vitest run
- 단일 파일: pnpm vitest run src/path/to/test.ts
FAILURE 02

잘못된 패키지 관리자

npm 설치로 package-lock.jsonpnpm-lock.yaml이 충돌한다.

# 패키지 관리
- pnpm만 사용
- npm / yarn 금지
- 설치: pnpm add <package>
FAILURE 03

프로젝트 구조를 모름

공유 컴포넌트를 잘못된 디렉터리에 배치한다.

# 프로젝트 구조
src/components/ — 공유 UI
src/features/   — 기능별 비즈니스 코드
src/lib/        — 유틸 / 외부 래퍼
src/api/        — API 요청 계층
FAILURE 04

TypeScript enum 사용

팀 규칙은 enum 대신 literal union type을 사용한다.

# 코드 스타일
- TypeScript enum 금지
- literal union type 사용

X enum Status { Active, Inactive }
O type Status = 'active' | 'inactive'
FAILURE 05

main에 직접 push

Agent가 변경을 끝내자마자 주 브랜치로 직접 밀어 넣는다.

# Git 규범
- main 직접 push 금지
- feature/ 브랜치 생성 → PR → merge
- commit: type(scope): description
FAILURE 06

500줄짜리 거대 컴포넌트

가독성과 변경 가능성이 빠르게 무너진다.

# 아키텍처 원칙
- 컴포넌트 파일 200줄 이하
- 150줄 초과 시 분리 검토
- 비즈니스 로직은 custom hook으로 추출
FAILURE 07

불필요한 의존성 추가

간단한 기능 하나 때문에 큰 라이브러리를 새로 설치한다.

# 의존성 관리
- 새 의존성 전 기존 도구 확인
- native API / 기존 라이브러리 우선
- date-fns 사용
- moment / dayjs 추가 금지
FAILURE 08

lint 없이 제출

코드가 동작하는 것처럼 보이면 검증 없이 제출하려 한다.

# 제출 전 검사
- pnpm lint & pnpm type-check
- lint 오류 수정 필수
- eslint-disable로 우회 금지
FAILURE 09

빈약한 오류 처리

빈 catch와 console.log가 곳곳에 남는다.

# 오류 처리
- 빈 catch 금지
- src/lib/error.ts의 AppError 사용
- 사용자 메시지는 친절하게
- 기술 세부 노출 금지
FAILURE 10

API 호출이 컴포넌트에 흩어짐

요청 로직이 UI 안으로 스며들어 계층이 무너진다.

# API 계층
- 모든 요청은 src/api/ 모듈에서 수행
- src/lib/api-client.ts의 apiClient 사용
- 컴포넌트에서 fetch 직접 호출 금지

열 개의 규칙 가운데 미리 상상해서 만든 규칙은 하나도 없다.
규칙은 과거의 실패가 다음 실패를 막기 위해 남긴 흔적이다.

좋은 규칙은 일반론보다 사건에 가깝다. “왜 이 줄이 존재하는가”에 실제 실패 하나를 가리킬 수 있을 때 그 규칙은 프로젝트의 경험을 압축한 지식이 된다.
04

천천히 자라기 싫다면, 딱 세 가지만 먼저 둔다

원문은 완전히 빈 파일이 불안한 독자를 위해 세 개의 시작 원칙만 제시한다. 지도, 실수, 독립 평가. 그 이상은 실제 사용이 요구할 때 추가한다.

Advice 01

지도는 주되 설명서는 주지 않는다

프로젝트 구조, 파일 관계, 핵심 제약을 알려준다. 모든 단계와 행동을 미리 고정하지 않는다. Agent에게 필요한 것은 방향감이지 매 순간의 세세한 동작 지시가 아니다. 원문은 OpenAI의 약 100줄 AGENTS.md 사례를 다시 연결한다.

Advice 02

한 번 틀릴 때 한 줄을 추가한다

Mitchell Hashimoto의 핵심 방식이다. 예측하지 않고 실제 실패가 일어난 뒤 규칙을 더한다. 몇 달이 지나면 그 파일은 자신의 코드베이스와 실패 이력에 맞춘 고유 Harness가 된다.

Advice 03

AI에게 다른 AI의 결과를 검사하게 한다

생성한 Agent에게 자기 결과를 다시 맡기지 않는다. 가장 단순한 방법은 새 대화를 열고 결과를 붙여 넣어 다른 Agent에게 문제를 모두 찾게 하는 것이다. 원문은 이를 Anthropic Evaluator의 가장 가벼운 형태로 제시한다.

새 대화의 의미는 모델을 바꾸는 데 있지 않다. 앞선 생성 과정의 자기합리화와 작업 기억에서 벗어나 결과 자체를 다시 보게 하는 데 있다.
세 원칙은 각각 다른 실패를 막는다. 지도는 길 잃음을 막고, 실수 기반 규칙은 재발을 막으며, 독립 평가는 자기확신을 막는다.
05

도구별 시작점 빠른 비교

원문 마지막 표는 Claude Code, Codex CLI, Cursor에 더해 GitHub Copilot까지 함께 비교한다. 파일 위치·형식·계층·자동 로딩·강제 제약·시작 길이를 한눈에 정리한다.

차원 Claude Code Codex CLI Cursor GitHub Copilot
파일명 CLAUDE.md AGENTS.md .cursor/rules/*.mdc copilot-instructions.md
위치 프로젝트 루트 프로젝트 루트 .cursor/rules/ .github/
형식 순수 Markdown 순수 Markdown Markdown + YAML frontmatter 순수 Markdown
계층 전역 → 프로젝트 → 하위 디렉터리 override → agents → team_guide 전역 → 프로젝트 · glob 지원 전역 → 프로젝트
자동 로딩 예 · 매 세션 예 · 시작 시 탐색 예 · 활성화 조건에 따라
Hard Constraint Hooks · deny Sandbox 없음 없음
원문 표의 “최신 동향” v2.1.90 /powerup 교육 Desktop App + GPT-5.3 Background Agents Agent Mode 출시
권장 시작 길이 20–50줄 50–100줄 .mdc 20–30줄 20–50줄
위 “최신 동향”과 제품별 세부 상태는 첨부 문서의 표를 그대로 요약한 것이다. 현재 시점의 제품 상태를 외부에서 재검증하거나 갱신하지 않았다.
비교표의 목적은 가장 좋은 도구를 고르는 데 있지 않다. 지금 쓰는 도구에서 가장 작은 지시 파일 하나를 어디에 만들면 되는지 찾는 데 있다.
06

첫 Harness는 오늘 완성하는 것이 아니라 오늘 시작하는 것이다

장의 마지막 지시는 짧다. 사용 중인 도구를 고르고, 해당하는 빈 파일을 만들고, 일을 시작한다. Agent가 틀리면 한 줄을 더한다.

도구를 고른다

Claude Code, Codex CLI, Cursor 또는 현재 사용하는 Agent 환경.

빈 지시 파일을 만든다

처음부터 규칙 백과사전을 복사해 넣지 않는다.

실제 작업을 시작한다

Agent가 프로젝트에서 무엇을 잘못 이해하는지 관찰한다.

실수 하나에 규칙 하나

그 규칙이 쌓인 파일이 결국 프로젝트의 첫 Harness가 된다.

시작할 때 필요한 것은 완성된 아키텍처가 아니다. 빈 파일 하나, 실제로 틀리는 Agent 하나, 그리고 그 실패를 잊지 않으려는 한 줄이면 충분하다.

길은 먼저 그려지는 것이 아니라
여러 번 오가면서 비로소 길이 되기도 한다.

첫 규칙도 그렇다.
틀리지 않은 것을 금지하지 않고,
겪지 않은 실패를 미리 문서화하지 않는다.

한 번의 잘못을 한 줄로 남기고,
그 한 줄이 다음의 선택을 조금 더 바르게 한다.

몇 달 뒤 돌아보면
빈 파일은 더 이상 빈 파일이 아니다.
그 프로젝트가 AI와 함께 일하며 배운 역사의 압축본이 되어 있다.

이 웹페이지는 첨부 문서 《Harness Engineering》의 §13 「从空白开始:你的第一个Harness / From Scratch: Your First Harness」 (PDF 61–67쪽)에만 근거해 재구성했다. 68쪽에서 §14가 시작되는 것을 확인해 범위를 분리했다. Claude Code·Codex CLI·Cursor의 시작 파일과 로딩 구조, 빈 파일에서 출발하는 실수 기반 방법론, React 프로젝트의 10개 구체적 규칙, 세 가지 시작 조언, 마지막 도구 비교표와 권장 시작 길이를 원문 맥락 안에서 보존했다. 외부 자료를 통한 제품 버전 확인·사실 수정·내용 확장은 수행하지 않았다.