← 모든 글

Claw의 해부학: 오케스트레이션 레이어로서의 84개 Hook

첫 번째 hook을 작성하는 데 4분이 걸렸습니다. Anthropic 전용 워크플로우에서 모델이 OpenAI 제품을 제안하는 것을 차단하는 hook이었습니다. 두 달 후, 그 하나의 hook은 84개가 되었습니다. 84개의 hook은 43개의 skill, 19개의 특화 agent, 30개의 라이브러리 모듈과 연결되었습니다. 어느 시점에서 이 컬렉션은 단순한 스크립트 모음이 아닌 오케스트레이션 레이어가 되었습니다.

처음부터 이렇게 설계한 것이 아닙니다. 누구도 “15,000줄의 에이전트 인프라를 구축하겠다”라고 작정하고 시작하지 않습니다. 하나의 문제를 해결합니다. 그다음 또 하나를 해결합니다. 그러다 문제들이 서로 상호작용하면서 생기는 문제를 해결합니다. 아키텍처를 인식했을 때는 이미 존재하고 있었습니다.

Andrej Karpathy도 이것을 알아챘습니다. 2026년 2월, 그는 “Claws”를 새로운 연산 레이어로 설명했습니다: LLM 위에 에이전트가 구축되는 것과 같은 방식으로, LLM 에이전트 위에 구축되는 오케스트레이션, 스케줄링, 컨텍스트 관리, 도구 라우팅 레이어입니다.1 이 프레이밍은 실무자들이 이름 없이 구축해 온 것을 결정체로 만들었습니다. 이 글은 그러한 시스템 하나의 해부학입니다: 무엇을 포함하고 있는지, 어떻게 성장했는지, 어디서 작동하는지, 그리고 어디서 실패하는지를 다룹니다.

TL;DR

Karpathy의 “Claws” 레이어는 에이전트 CLI 위에 구축된 오케스트레이션 시스템을 설명합니다. 저는 Claude Code에서 두 달에 걸쳐 유기적으로 하나를 구축했습니다: 15개 이벤트 유형에 걸친 84개의 hook, 43개의 skill, 19개의 agent, 30개 이상의 라이브러리 모듈로 구성됩니다. 이 시스템은 5가지 Claws 기능(오케스트레이션, 스케줄링, 컨텍스트 관리, 도구 라우팅, 품질 강제)에 깔끔하게 매핑되며, 하나의 주목할 만한 공백(선언적 워크플로우 정의)이 있습니다. 핵심 발견: 계획-실행 분리는 설계 목표가 아닌 hook 기반 오케스트레이션의 자연스러운 속성으로 나타났습니다. “판단과 추상화는 핵심으로 남고 AI가 구현을 자동화한다”는 Lattner의 관찰은 hook 아키텍처에 직접 매핑됩니다: 거버넌스 hook은 판단을 행사하고, 자동화 hook은 구현을 실행합니다.


Claws 분류 체계

Karpathy의 설명은 Claws 레이어가 수행하는 다섯 가지 기능을 식별합니다. 각 기능은 제가 지난 두 달간 Claude Code에서 구축한 hook 시스템에 직접적인 대응물이 있습니다.1

Claws 기능 설명 구현
오케스트레이션 여러 에이전트를 목표를 향해 조율 Ralph 자율 루프, 심의 시스템
스케줄링 작업 실행 시점을 결정 Cron hook, activity-heartbeat.sh, 야간 보안 스캐닝
컨텍스트 관리 턴 간 관련 정보를 유지 프롬프트 디스패처, 철학 인젝터, 메모리 캡슐
도구 라우팅 도구 호출을 적절한 핸들러로 전달 PreToolUse, PostToolUse, UserPromptSubmit 이벤트에 걸친 84개 hook
품질 강제 출력이 기준을 충족하는지 검증 품질 게이트, 근거 요구사항, 7개 리뷰 에이전트

이 분류 체계는 실무자들이 얽힌 방식으로 구축하는 경향이 있는 관심사를 분리하기 때문에 유용합니다. 초기 hook들은 컨텍스트 관리와 품질 강제를 혼합했습니다. 비용 추적 hook은 예산 컨텍스트를 주입하는 동시에(컨텍스트 관리) 비용이 큰 작업을 차단했습니다(품질 강제). 이들을 별도의 hook으로 분리하면 각 hook이 다른 기능을 손상시키지 않고 독립적으로 실패할 수 있기 때문에 신뢰성이 향상되었습니다.


전체 시스템

2026년 2월 기준 수치입니다:

구성 요소 수량 목적
Hook 84 15개 hook 이벤트 유형에 걸친 이벤트 기반 기능
Skill 43 이름으로 호출되는 재사용 가능한 기능 모듈
Agent 19 리뷰, 탐색, 개발을 위한 특화 서브에이전트
라이브러리 모듈 30+ 공유 Python 및 Bash 유틸리티
코드 줄 수 ~15,000 hook, skill, agent, 라이브러리, 설정 전체

이벤트 유형별 hook 분포는 오케스트레이션 복잡성이 어디에 집중되는지를 보여줍니다:

이벤트 유형 Hook 수 예시
UserPromptSubmit 9 (디스패처 경유) 컨텍스트 주입, 비용 추적, 사용량 분석
PreToolUse:Bash 12 보안 스캐닝, 자격 증명 확인, 민감한 명령 차단
PostToolUse:Bash 6 출력 스캐닝, 배포 검증
PreToolUse:Write 4 자격 증명 감지, 경로 유효성 검사
PreToolUse:Edit 3 패턴 강제
PreToolUse:Task 3 재귀 방지, 스폰 예산 관리
PreCompact 1 메모리 캡슐, 데스 스파이럴 감지
SessionStart 1 환경 초기화
WorktreeCreate 1 격리된 브랜치를 위한 환경 설정
WorktreeRemove 1 정리 전 안전 검사
기타 이벤트 유형 ~43 PreToolUse:Read, PostToolUse:Write, PreToolUse:WebFetch, NotebookEdit 및 8개 추가 이벤트 유형에 분산

UserPromptSubmit이 가장 큰 비중을 차지하는 이유는 모든 사용자 메시지에서 실행되기 때문입니다. 디스패처(prompt-dispatcher.sh)는 모든 프롬프트에서 9개의 hook을 순차적으로 실행합니다: 보안 필터링, 분석, 사용량 추적, 시스템 모니터링, 목표 주입, 시간 추정 차단, 컨텍스트 주입, 메모리 주제 주입, 컨텍스트 압력 모니터링입니다.2

각 hook은 지연 시간을 추가합니다. 9개의 순차 hook은 프롬프트당 총 200ms의 측정된 지연 시간을 추가합니다. 디스패처는 병렬이 아닌 순차적으로 실행하는데, 초기 테스트에서 공유 JSON 상태 파일에 대한 동시 hook 쓰기가 데이터 손상을 일으켰기 때문입니다. 두 개의 hook이 jiro.state.json에 동시에 쓰면 잘린 JSON이 생성되어 모든 다운스트림 hook이 깨졌습니다. 순차 실행이 더 느리지만 안전합니다. 200ms 오버헤드는 사용자에게 보이지 않는데, 병목 지점이 hook 지연 시간이 아닌 사람의 타이핑 속도이기 때문입니다.


성장 과정

성장은 선형적이지 않았습니다. 문제-해결-통합 주기의 패턴을 따랐습니다.

1단계: 단일 목적 hook (1-2주차). 각 hook은 하나의 문제를 해결했습니다. enforce-opus-model.sh는 비Opus 모델 요청을 차단했습니다. no-time-estimates.sh는 응답에서 작업량 추정을 제거했습니다. filter-sensitive.sh는 도구 호출에서 자격 증명을 포착했습니다. 이 hook들은 독립적으로 작동했습니다. 어떤 hook도 다른 hook의 존재를 알지 못했습니다.

2단계: 조율 문제 (3-4주차). Hook들이 서로 간섭하기 시작했습니다. 자격 증명 필터가 정상적인 API 호출을 차단했습니다. 모델 강제기가 서브에이전트 스폰과 충돌했습니다. 해결책은 디스패처였습니다. 단일 진입점(prompt-dispatcher.sh)이 7개의 개별 UserPromptSubmit hook을 대체하여 실행 순서를 제어하고 캐시된 stdin 파이프를 통해 상태를 공유했습니다.

3단계: 복합 기능 (5-8주차). 개별 hook들이 시스템으로 합성되었습니다. 품질 루프는 사전 도구 hook(문제가 발생하기 전에 포착)과 사후 도구 hook(결과 발생 후 검증)을 공유 상태 파일(jiro.state.json)을 통해 연결했습니다. 심의 시스템은 재귀 방지, 스폰 예산, 합의 프로토콜을 사용하여 무한 루프 없이 여러 에이전트를 조율했습니다. Ralph(자율 개발 루프)는 PRD 파일에서 Claude 스폰, 테스트 검증, 코드 리뷰까지를 하나의 오케스트레이션 파이프라인으로 연결했습니다.

4단계: 자기 인식 (9주차 이후). 시스템이 자기 자신을 이해하기 위한 도구가 필요할 만큼 커졌습니다. hook 시스템 전체에 대한 시맨틱 검색(/find skill)을 통해 에이전트가 파일명이 아닌 목적으로 hook을 발견할 수 있게 되었습니다. 성능 모니터링(/perf skill)은 시스템 자체의 오버헤드가 머신 성능을 저하시키는지 추적했습니다. 컨텍스트 압력 모니터는 오케스트레이션 레이어가 주입하는 컨텍스트가 모델의 컨텍스트 윈도우를 너무 많이 소비할 때 경고했습니다.

단일 목적 hook에서 자기 모니터링 인프라로의 진행은 Chris Lattner가 Claude C Compiler 프로젝트 리뷰에서 식별한 패턴을 반영합니다: “좋은 소프트웨어는 판단, 커뮤니케이션, 명확한 추상화에 의존합니다. AI가 이를 증폭시켰습니다.”3 hook 시스템의 아키텍처는 같은 진실을 드러냅니다. 가치 있는 hook은 작업을 자동화하는 hook이 아닙니다. 가치 있는 hook은 작업이 언제, 어떻게 자동화되어야 하는지에 대한 판단을 인코딩하는 hook입니다.


판단 Hook vs. 자동화 Hook

Lattner의 Claude C Compiler 리뷰는 AI가 잘 자동화하는 것(구현)과 근본적으로 인간의 영역으로 남는 것(판단과 추상화)을 구분했습니다.3 이 구분은 hook 시스템에 직접적으로 매핑됩니다.

판단 hook은 무언가가 일어나야 하는지를 결정합니다. 절차가 아닌 정책을 인코딩합니다.

Hook 판단
quality-gate.sh “이 작업이 보고할 만큼 충분히 완료되었는가?”
filter-sensitive.sh “이 명령이 자격 증명을 노출할 위험이 있는가?”
recursion-guard.sh “에이전트가 너무 많은 서브에이전트를 스폰했는가?”
context-pressure.sh “컨텍스트 윈도우가 효과적으로 계속하기에 너무 가득 찼는가?”
cost-gate.sh “이 세션이 예산 임계값을 초과했는가?”

자동화 hook은 미리 결정된 작업을 실행합니다. 정책이 아닌 절차를 인코딩합니다.

Hook 자동화
inject-context.sh 모든 프롬프트에 날짜, 시간, 작업 디렉토리, 브랜치를 주입
track-usage.sh 토큰 수와 세션 메트릭을 기록
sysmon-snapshot.sh CPU, 메모리, 디스크 상태를 캡처
memory-capsule-inject.sh 압축 후 컨텍스트를 복원
activity-heartbeat.sh 세션 활성 표시기를 업데이트

판단 hook은 작성하기 어렵고, 테스트하기 어려우며, 더 가치 있습니다. quality-gate.sh는 7개의 명명된 실패 모드, 6개의 근거 기준, 모호한 언어 감지기를 필요로 했습니다. inject-context.sh는 5줄의 bash만 필요로 했습니다. 하지만 둘 다 필수적입니다. 자동화 hook은 판단 hook이 평가하는 데이터를 제공합니다. sysmon-snapshot.sh(자동화)는 에이전트 수 축소를 권장할지 결정하는 성능 모니터(판단)에 데이터를 공급합니다.

비율이 중요합니다. 건전한 오케스트레이션 레이어에서는 판단 hook이 자동화 hook보다 많아야 합니다. 대부분의 hook이 데이터 주입이나 메트릭 기록만 한다면, 시스템은 자동화는 잘하지만 거버넌스는 부실합니다. 현재 시스템의 검증된 수치: 판단 hook 35개, 자동화 hook 44개, 대략 4:5 비율입니다. 자동화가 여전히 앞서고 있습니다. 비율은 약 1:6(거의 모든 것이 주입 및 로깅 hook)에서 시작하여 두 달에 걸쳐 판단 쪽으로 이동했는데, 순수 자동화만으로는 방지할 수 없었던 실패를 경험한 후 거버넌스 제약 조건이 추가되었기 때문입니다. 비율은 아직 균형에 도달하지 못했으며, 이 자체가 유용한 신호입니다: 이 시스템은 여전히 자동화하는 것보다 거버넌스하는 것이 적습니다.


계획-실행 분리

Boris Tane의 “How I use Claude Code” 게시물은 Hacker News에서 936포인트를 받으며 하나의 워크플로우 패턴을 설명했습니다: 계획과 실행을 분리하는 것입니다.4 하나의 Claude 세션으로 계획하고(조사, 개요 작성, 설계), 그 계획을 구조화된 입력으로 받는 새로운 세션으로 실행합니다. 이 패턴이 공감을 얻은 이유는 실제 문제를 해결하기 때문입니다: 계획과 실행이 컨텍스트 윈도우 공간을 놓고 경쟁합니다.

Hook 시스템은 다른 경로를 통해 동일한 분리에 도달했습니다. 심의 시스템은 특화된 에이전트를 스폰하여 접근 방식을 조사하고 토론합니다. 출력은 스토리, 수용 기준, 검증 유형이 포함된 구조화된 PRD(제품 요구사항 문서)입니다. Ralph 루프는 PRD를 읽고 각 스토리를 구현하기 위해 새로운 Claude 인스턴스를 스폰합니다. 계획 에이전트는 절대 구현하지 않습니다. 구현 에이전트는 절대 계획하지 않습니다.

이 분리는 설계 목표가 아니었습니다. 두 가지 독립적인 제약 조건에서 나타났습니다:

  1. 컨텍스트 윈도우 압력. 계획에는 많은 파일을 읽고 옵션을 탐색하는 것이 필요합니다. 구현에는 현재 작업에 대한 집중된 컨텍스트가 필요합니다. 둘 다 같은 컨텍스트 윈도우에 넣으면 어느 쪽도 충분한 공간을 확보하지 못합니다. 별도의 세션은 각 단계에 전체 컨텍스트를 제공합니다.

  2. 품질 검증의 독립성. 같은 에이전트가 계획하고 구현하면, 계획에 대한 자체 구현을 객관적으로 검증할 수 없습니다. 계획과 코드만 가진 새로운 에이전트가 독립적인 검증을 제공합니다. Ralph 루프는 이를 강제합니다: 구현 에이전트가 테스트를 실행하지만, 3개의 별도 리뷰 에이전트(정확성, 보안, 컨벤션)가 결과를 검증합니다.

Tane의 수동 워크플로우와 자동화된 hook 시스템 사이의 수렴은 계획-실행 분리가 단순한 실무자 선호가 아닌 에이전트 시스템의 자연스러운 속성임을 시사합니다. 컨텍스트 윈도우를 관리하고 출력을 검증하는 모든 시스템은 결국 계획과 실행을 분리하게 됩니다. 대안(하나의 컨텍스트에서 둘 다 수행)이 두 단계 모두에서 더 나쁜 결과를 만들기 때문입니다.


Hook 시스템이 실패하는 지점

이 아키텍처에는 목적에 맞게 설계된 오케스트레이션 프레임워크라면 해결할 수 있는 세 가지 중요한 약점이 있습니다.

선언적 워크플로우 정의가 없습니다. 모든 워크플로우는 bash 스크립트에 명령적으로 인코딩되어 있습니다. Ralph 루프는 1,320줄의 bash로 특정 시퀀스를 인코딩합니다: PRD 읽기, 스토리 선택, 컨텍스트 수집, Claude 스폰, 테스트 실행, 리뷰 실행, 실패 처리, 상태 업데이트. 워크플로우를 변경하려면 bash를 편집해야 합니다. 선언적 시스템이라면 워크플로우를 인터프리터가 실행하는 데이터(YAML, JSON)로 정의할 것입니다. 선언적 워크플로우는 수정, 합성, 시각화가 더 쉽습니다. 명령적 스크립트는 초기 작성은 더 쉽지만 규모가 커지면 유지보수가 더 어렵습니다.

Hook 순서가 취약합니다. 프롬프트 디스패처는 하드코딩된 순서로 hook을 실행합니다. memory-capsule-inject.shinject-context.sh보다 먼저 이동하면 캡슐 주입이 깨지는데, inject-context.sh가 해석하는 세션 ID에 의존하기 때문입니다. 이러한 의존성은 명시적(hook 간 의존성으로 선언됨)이 아닌 암시적(디스패처의 순서에 인코딩됨)입니다. 목적에 맞게 설계된 시스템이라면 hook 의존성을 DAG로 표현하고 실행 순서를 위상 정렬할 것입니다.

워크플로우 시각화가 없습니다. 84개의 hook이 있는 상황에서 사용자 동작의 전체 실행 경로를 이해하려면 디스패처 코드를 읽고 hook 체인을 수동으로 추적해야 합니다. “사용자가 메시지를 입력하면 이 9개의 hook이 이 순서로 실행되고, hook 3이 라이브러리 함수 X를 호출하며 이것이 상태 파일 Y에 기록한다”를 보여주는 도구가 없습니다. 시스템은 로그를 통해 관찰 가능하지만 구조를 통해서는 관찰할 수 없습니다. 목적에 맞게 설계된 오케스트레이션 프레임워크라면 hook 의존성, 데이터 흐름, 실행 경로의 시각적 그래프를 제공할 것입니다.

이 약점들은 공통된 원인을 공유합니다: 시스템이 일관된 오케스트레이션 레이어로 설계된 것이 아니라 개별 문제를 해결하면서 유기적으로 성장했다는 것입니다. 유기적 성장은 작동하는 시스템(84개 hook 모두 프로덕션에서 정상 작동)을 만들지만, 전체적으로 추론하기는 어렵습니다. 이 트레이드오프는 실재합니다: 오케스트레이션 레이어를 처음부터 설계했다면 더 나은 구조를 만들었겠지만 더 열등한 기능을 만들었을 것입니다. 많은 기능(메모리 캡슐, 출력 화이트리스트, 스폰 예산)이 발생하기 전에는 예측할 수 없었던 실패에 대응하여 만들어졌기 때문입니다.


실무자를 위한 시사점

에이전트 CLI 위에 오케스트레이션 레이어를 구축하고 있다면, 이 시스템에서 직접 적용 가능한 세 가지 패턴이 있습니다.

개별 hook이 아닌 디스패처로 시작하세요. 가장 큰 아키텍처 개선은 7개의 개별 UserPromptSubmit hook을 순차적으로 실행하는 단일 디스패처로 교체한 것이었습니다. 특정 이벤트 유형에 3개 이상의 hook이 예상된다면 디스패처를 먼저 구축하세요. 디스패처 작성에 투자한 30분이 나중에 hook 상호작용 버그 디버깅 시간을 절약합니다. 최소한의 패턴:

#!/bin/bash
# dispatcher.sh — sequential hook execution with shared stdin
HANDLERS=("inject-context.sh" "track-usage.sh" "quality-gate.sh")
HOOK_DIR="$(dirname "$0")/handlers"
INPUT=$(cat)  # Cache stdin once (each handler gets the same input)

for handler in "${HANDLERS[@]}"; do
    [ -x "$HOOK_DIR/$handler" ] && echo "$INPUT" | "$HOOK_DIR/$handler"
done

이 단일 디스패처를 hook 진입점으로 등록하세요. 구축하면서 핸들러를 배열에 추가합니다. 각 핸들러는 동일한 캐시된 stdin(hook 이벤트 페이로드)을 읽고 독립적으로 stdout에 기록합니다.

판단과 자동화를 일찍 분리하세요. 새로운 hook을 작성할 때 물어보세요: “이 hook은 무언가가 일어나야 하는지를 결정하는가, 아니면 미리 결정된 작업을 실행하는가?” 판단 hook은 더 많은 테스트, 더 많은 엣지 케이스 처리, 더 많은 반복이 필요합니다. 자동화 hook은 신뢰성과 성능이 필요합니다. 둘을 동일하게 취급하면 테스트가 부족한 판단 hook과 과도하게 엔지니어링된 자동화 hook이 만들어집니다.

계획-실행 분리는 자연스럽게 나타나도록 두세요. 첫날부터 분리를 강제하지 마세요. 작동하는 가장 단순한 것을 구축하세요. 에이전트의 컨텍스트 윈도우가 계획과 구현 모두에 너무 가득 찬 것을 발견하면 분리하세요. 에이전트가 자신의 작업을 객관적으로 검증할 수 없다는 것을 발견하면 독립적인 리뷰 에이전트를 추가하세요. 분리는 제약 조건이 요구할 때 자명하게 느껴질 것입니다.

Hook 기반 접근 방식은 목적에 맞게 설계된 오케스트레이션 프레임워크에 비해 하나의 장점이 있습니다: 제로 커밋먼트. 모든 hook은 독립적입니다. 하나의 hook, 열 개의 hook, 또는 여든네 개의 hook을 채택할 수 있습니다. 디스패처를 유지하는 한 어떤 hook이든 다른 것을 깨뜨리지 않고 삭제할 수 있습니다. 학습할 프레임워크도, 관리할 의존성도, 운영할 런타임도 없습니다. 오케스트레이션 레이어는 그저 파일입니다.

Karpathy는 이것을 새로운 연산 레이어라고 불렀습니다. 구현은 이름보다 오래되었습니다. 실무자들은 에이전트 CLI 호출을 감싸는 셸 스크립트를 처음 작성한 때부터 Claws를 구축해 왔습니다. 셸 스크립트와 오케스트레이션 레이어의 차이는 종류의 차이가 아닙니다. 얼마나 많은 문제를 해결했는지, 그리고 그 해결책들 중 얼마나 많은 것이 서로를 해결해야 했는지의 차이입니다.


출처


  1. Andrej Karpathy, “Claws” 논의, 2026년 2월, x.com/karpathy/status/2024987174077432126. Simon Willison 경유, simonwillison.net/2026/Feb/21/claws/

  2. 컨텍스트 주입 아키텍처의 상세 내용은 “Context Is Architecture“에서 확인할 수 있습니다. 

  3. Chris Lattner, “The Claude C Compiler: What It Reveals About the Future of Software,” Modular 블로그, 2026년 2월. Simon Willison 경유, simonwillison.net/2026/Feb/22/ccc/

  4. Boris Tane, “How I use Claude Code,” boristane.com, 2026년 2월. Hacker News에서 936포인트, 569개 댓글.