GitHub 트렌딩 딥다이브 · 2026-06-23

Loom 딥다이브
— AI 코딩 에이전트를 '한 번 쓰고 끝'에서 '반복 가능한 출하 라인'으로 바꾸는 딜리버리 하네스

valkor-ai/loom. Claude Code·Codex·OpenCode 같은 이미 쓰고 있는 코딩 에이전트를 갈아치우지 않고, 그 바깥에 둘러 하나의 목표를 기획 → 설계 → 구현 → 검증 → 수리 → 프리뷰 → 인수인계라는 반복 가능한 루프로 만들어 주는 딜리버리 하네스(delivery harness)다. 모든 진행 상태(요구사항·태스크 계약·테스트 결과·수리 노트·인수인계 리포트)를 프로젝트 폴더의 .loom/ 아래 JSON 파일로 남겨, 다음 세션·다른 에이전트·다른 CLI가 처음부터 다시 시작하지 않고 이어받게 한다. (저장소: valkor-ai/loom · 언어 TypeScript 65% + JavaScript 35% · Node ≥ 20 · commander + zod · 라이선스 Apache-2.0 · ★ 약 100 — TrendShift 라이브 멘션)

목차
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석 (목표 하나가 '천 한 장'으로 짜이기까지)
  5. 디렉토리 구조 해부
  6. 학습 포인트 (기술별)
  7. 하드웨어 / 시스템 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

"코딩 에이전트는 '코드를 쓸' 줄은 안다. Loom은 그 에이전트가 '약속한 결과물까지 끝까지 배달'하게 만든다."

한 줄로

Loom은 에이전트가 흩뿌리는 단발 행동(실)을 한 장의 천(신뢰할 수 있는 출하)으로 짜 주는 '베틀'이다.

이름 그대로 Loom(베틀)입니다. 보통 AI 코딩 에이전트에게 "이거 만들어 줘"라고 하면, 데모는 한 번 그럴듯하게 나옵니다. 그런데 그걸 믿고 출시할 수 있는 제품으로 만들려면 — 요구사항을 분명히 하고, 구조를 정하고, 일을 잘게 쪼개고, 구현하고, 검사하고, 실패를 고치고, 다시 검증하고, 미리보기로 확인하고, 증거를 모아 넘겨야 합니다. 에이전트는 긴 작업 중에 맥락이 압축(compaction)되면 길을 잃고, 절반만 하고 "다 됐다"고 선언하고, 자기 결과를 자기가 검사하며 편향됩니다. Loom은 그 위에 '상태를 가진 작업 지시 체계'를 둘러, 흩어진 실을 끊기지 않는 한 장의 천으로 엮습니다.

용어
딜리버리 하네스 (delivery harness)
하네스(harness)는 원래 말에 씌우는 '마구(馬具)' 또는 작업자에게 채우는 '안전벨트+작업 지시 장치'를 뜻합니다. 소프트웨어에서는 "핵심 부품을 갈아치우지 않고, 그 바깥에 둘러 통제·반복·안전을 더하는 골격"입니다. Loom은 모델(LLM)이나 에디터를 대체하지 않습니다. 대신 그 에이전트를 "하나의 배달 목표를 끝까지 책임지는 반복 루프" 안에 넣습니다. '테스트 하네스(test harness)'가 코드를 감싸 자동 검사를 돌리듯, 딜리버리 하네스는 에이전트를 감싸 출하 과정 전체를 돌립니다.
용어
동적 워크플로 (dynamic workflows)
Loom의 부제는 "Dynamic workflows for agentic software delivery"입니다. 모든 작업에 똑같은 고정 순서를 강요하는 게 아니라, 목표의 성격에 따라 거쳐야 할 단계(경로)를 그때그때 고른다는 뜻입니다. 작은 수정이면 짧은 경로, 새 기능이면 요구사항 정리·아키텍처·태스크 분할까지 긴 경로. 그렇게 고른 경로를 상태로 굳혀(durable) 중단·재개가 가능하게 만드는 것이 핵심입니다.

좀 더 구체적으로, Loom은 TypeScript로 만든 명령줄 도구(CLI)입니다. npm installnpm run plugin:install-claude(또는 codex/opencode)로 어댑터를 깔면, 에이전트 안에서 Codex는 @loom build ..., Claude Code·opencode는 /loom build ...처럼 부를 수 있습니다. 그러면 Loom이 그 프로젝트에 .loom/ 폴더를 만들고, "지금 이 에이전트가 다음에 해야 할 단 하나의 행동"을 계산해 돌려줍니다. 사용자는 대부분 continue(이어가기)만 반복해 부르면 됩니다 — 내부 단계 이름을 외울 필요가 없습니다.

이 문서가 파고드는 건 사용법이 아니라 그 안의 설계입니다 — "어떻게 에이전트가 멋대로 굴지 못하게 강제하나(지시 봉투 + 훅)", "왜 상태를 데이터베이스가 아니라 파일로 두나", "어떻게 한 번 검증한 걸 다시 안 믿고 또 검증하나". 에이전트 하네스·상태 머신·계약 기반 설계를 처음 공부하는 사람에게 살아 있는 교본입니다.

2왜 주목받는가

"2026년 에이전트 코딩의 진짜 난제는 '코드 생성'이 아니라 '끝까지 믿고 배달하기'다. Loom은 그 지점을 정조준한다."

먼저, 긴 에이전트 작업은 어디서 무너지는가

"웹사이트·앱을 자동 생성"은 이제 기본기가 됐습니다. 더 어려운 문제는 신뢰할 수 있는 배달입니다 — 맥락이 압축돼도 정렬을 유지하고, 수십 턴을 거쳐도 요구사항을 보존하고, 자기 일을 편향 없이 검증하고, 실패를 고치고, 중단된 지점부터 정확히 재개하기. README는 이 붕괴를 다섯 가지 실패 모드로 정리하고, 각각에 Loom의 대응을 붙입니다.

실패 모드증상Loom의 대응
부분 완성
(partial completion)
절반만 해 놓고 "다 됐다"고 선언바운디드 태스크 · 명시적 결과 파일 · continue 라우팅 · 최종응답 가드로 조기 종료 차단
목표 표류
(goal drift)
턴이 길어지며 원래 목표에서 벗어남확정된 범위 · 아키텍처 계약 · 태스크 계획 · 압축 컨텍스트 팩으로 목표 보존
자기검증 편향
(self-check bias)
만든 사람이 만든 걸 검사 → 통과시켜 줌리뷰 · 검증 · 수리 요청 · 증거 기록으로 구현과 검증을 분리
토큰 낭비
(token waste)
매 턴 레포 전체를 다시 읽음프로젝트 요약 · 태스크 그래프 · 런타임 상태 · 테스트 결과를 저장해 재독 감소
인수인계 공백
(handoff gaps)
"끝났다"는데 무엇이 어떤 상태인지 모름배달 리포트 · 프리뷰 점검 · 로그 · 수리 이력으로 최종 상태를 사람·에이전트가 들여다보게
함정
"다 됐어요"의 함정 — 에이전트는 절반에서 멈춘다

긴 작업에서 가장 흔한 실패는 테스트가 통과했거나 소스 수정이 끝났다는 이유로 "완료"를 선언하는 것입니다. 하지만 그건 완료가 아닙니다. Loom의 어댑터 규약(SKILL.md)은 못 박습니다: "통과한 테스트, 끝난 소스 수정, 내부 할 일 목록, 다음 태스크가 보이는 것 — 어느 것도 완료가 아니다. 결과 파일이 resultFile 위치에 존재하고 submitCommand가 성공해야만 완료다."

해결
프롬프트 파일이 아니라 '상태를 가진 CLI 프로토콜'

흔한 접근은 CLAUDE.md·AGENTS.md·.cursorrules 같은 거대한 프롬프트 파일입니다. 유용하지만 점점 길어지고, 상태가 없어 중단되면 처음으로 돌아갑니다. Loom은 그 위에 ① 상태 저장(.loom/), ② 에이전트-중립 CLI, ③ 검증·수리·프리뷰·인수인계를 1급(first-class) 단계로 더합니다. 즉 "무엇을 하라"는 글이 아니라 "지금 무엇을 했고, 다음에 무엇을 해야 하는지"를 기억하는 기계입니다.

이미 비슷한 도구가 많은데, Loom의 차별점은?

"에이전트 하네스·스킬"은 2026년 가장 붐비는 카테고리입니다(superpowers, gstack, ECC, loop-library 등 이미 이 폴더에 여럿 정리돼 있습니다). 그 속에서 Loom의 자리는 분명합니다.

관점Loom프롬프트 파일 방식
(CLAUDE.md / .cursorrules)
형태상태를 가진 CLI 프로토콜정적 텍스트 프롬프트
중단 후 재개.loom/ 상태로 이어받기맥락이 날아가면 처음부터
검증구현과 분리된 리뷰·수리·증거에이전트 자기 판단에 의존
에이전트 호환중립 — Claude Code·Codex·opencode 동일 프로토콜도구마다 따로 작성
조기 완료가드 플래그로 강제 차단막을 장치 없음
증거배달 리포트·로그·프리뷰로 검사 가능대화 로그뿐

요약하면 Loom의 셀링 포인트는 넷입니다. ① 상태의 영속성(중단·압축·에이전트 교체를 견딤), ② 에이전트-중립(하나의 배달 프로토콜을 여러 에이전트에), ③ 검증을 1급으로(구현자와 검증자를 분리, "wired 증거"까지 요구), ④ 행동 강제(지시 봉투의 가드 플래그 + Claude Code 훅이 에이전트가 멋대로 기획·조기종료·잡담하는 것을 막음)입니다.

비유

맨몸 에이전트 = 재능 있지만 산만한 신입. 시키면 잘 만들지만, 길어지면 처음 요구를 잊고, "대충 됐죠?"라며 절반에서 손을 떼고, 자기가 짠 코드를 자기가 "이상 없음" 처리합니다.

Loom = 그 신입에게 붙은 빈틈없는 출하 관리자(PM). "지금 단계는 이거, 다음은 이거"를 칠판(.loom/)에 적어 두고, "결과 파일 제출 전엔 완료 아님", "네가 짠 건 다른 단계에서 검사함", "버튼이 진짜로 API를 부르는지 증거 가져와"라고 못 박습니다. 관리자가 자리를 비워도(세션 종료) 칠판이 남아 다음 사람이 이어받습니다.

'토큰 15.8% 절감'을 곧이곧대로 믿어도 되나

솔직하게 짚겠습니다. README의 벤치마크는 11개 케이스에서 "Codex + Loom이 Codex 단독 대비 토큰 15.8% 절감, 완료율은 둘 다 100% 유지"(468,067 → 394,037 토큰)라고 밝힙니다. 하지만 이건 개발팀이 자체 실행한 수치이고, 11개 중 8개에서만 Loom이 더 쌌으며 3개는 오히려 토큰을 더 썼습니다(백엔드 준비 +9.9% 등). 게다가 완료율 향상이 아니라 '이어가기·인수인계 작업의 토큰 효율'이 이득의 본질입니다(원래도 둘 다 100% 완료). 또 아직 프로덕션 배포는 지원하지 않고(로컬 Docker Compose 프리뷰만), 별 약 100개의 신생 프로젝트입니다. 방향성은 설득력 있지만 — "상태·검증·재개를 1급으로 둔다"는 발상은 에이전트 작업이 길어질수록 더 중요해지는 정공법 — 수치는 작업·레포에 따라 편차가 큼을 전제로 보셔야 합니다.

3기술 스택 전체 지도

"코드의 65%가 TypeScript다. 하지만 진짜 핵심은 'zod로 짠 계약'과 '에이전트가 따를 수밖에 없는 JSON 지시 봉투'에 있다."

Loom은 화면도 GPU도 데이터베이스도 없는 순수 Node.js CLI 엔진입니다. 언어 통계는 TypeScript 65.1% / JavaScript 34.9%인데, TypeScript는 src/의 엔진(약 5만 줄·106개 파일)이고 JavaScript는 어댑터 접착 코드·설치 스크립트·테스트 하네스입니다. 무게중심이 "상태를 안전하게 정의·검증·라우팅하는 코어"에 완전히 쏠려 있습니다.

① 코어 엔진 (CLI · 계약 · 검증)

기술역할한 줄 설명
TypeScript
(ES2022, strict)
전체 엔진 언어tscdist/cli.js를 빌드. strict:true로 타입을 빡빡하게 잠근다.
commander ^12CLI 프레임워크init/status/plan/continue/review/deploy/knowledge… 40여 개 하위 명령·플래그를 만든다. 모든 명령이 --project-root --json --compact 지원.
zod ^3스키마 · 검증이 프로젝트의 심장. 설정·계약·태스크·리뷰 등 모든 아티팩트를 zod 스키마로 정의하고 런타임 검증한다. schemaVersion으로 버전까지 관리.
yaml ^2설정 파싱사람이 읽기 좋은 설정/참조 문서 처리.
Node.js ≥ 20런타임외부 서비스 0. 상태는 전부 로컬 파일(JSON).
용어
zod
TypeScript용 스키마 선언 + 런타임 검증 라이브러리. "이 데이터는 이런 모양이어야 한다"를 코드로 적으면(z.object({...})), 실행 중에 들어온 값이 그 모양인지 검사하고 동시에 타입까지 뽑아 줍니다. Loom처럼 에이전트가 만든 JSON(계획·태스크·리뷰 결과)을 받아 다루는 도구에서는, "에이전트가 형식을 어긴 산출물"을 즉시 잡아내는 방어선이 됩니다. Loom의 contracts.ts(약 2,000줄)·schemas.ts가 전부 zod로 짜여 있습니다.

② 지식 수집 계층 (로컬 문서를 컨텍스트로)

기술역할
pdf-parsePDF 문서에서 텍스트 추출 — 요구사항·스펙 PDF를 읽어 들인다.
mammothWord(DOCX) 문서를 텍스트로 변환.
yauzlzip 압축 해제 — 문서 묶음 입력 처리.

이 셋은 loom knowledge 명령군을 떠받칩니다. 사용자가 PDF·DOCX·zip로 된 자료를 주면 Loom이 로컬에서 파싱·색인해, 에이전트가 배달 중 참고할 수 있는 지식으로 만듭니다(외부 API·임베딩 서비스 없이).

③ 어댑터 계층 (에이전트마다 다른 '입구')

어댑터호출 방식설치되는 것
Claude Code/loom …플러그인 패키지 · skills/loom/SKILL.md · (loom-workflow-guard.js) · 런처
Codex@loom …Codex 로컬 플러그인 + 공유 런처
opencode/loom …슬래시 명령 · 플러그인 훅 · 참조 문서 · 런처
(공통)~/.loom/bin/loom-cli(안정 런처) · ~/.loom/adapters/<agent> 메타데이터
용어
에이전트-중립 (agent-neutral) · 런처 (launcher)
에이전트-중립이란 같은 배달 프로토콜을 Claude Code든 Codex든 opencode든 똑같이 쓴다는 뜻입니다. 비결은 런처입니다 — npm run plugin:install-*~/.loom/bin/loom-cli라는 작은 Node 실행기를 깔아 두고, 모든 어댑터가 셸 PATHloom이 있든 없든 이 런처를 통해 같은 dist/cli.js를 부릅니다. 그래서 "한 번 빌드한 엔진"을 여러 에이전트가 공유합니다.

④ 배포 프리뷰 · 빌드

항목내용
Docker + Composeloom deploy가 쓰는 로컬 프리뷰 수단. 타깃 프로젝트용 Dockerfile/Compose를 Loom이 생성해 빌드·기동·헬스체크·로그·수리까지 본다. (프로덕션 배포는 아직 미지원)
빌드tsc -p tsconfig.json && chmod +x dist/cli.js. bin"loom": "./dist/cli.js".
테스트tests/ 아래 architecture·brainstorm·deploy·knowledge·protocol·task·review 등 ~13개 스위트. node tests/run-suite.js <suite>로 실행.
저장소 자신엔 Dockerfile 없음Loom은 남의 프로젝트를 위한 컨테이너 구성을 만들지, 자기 것을 싣지 않는다.

4아키텍처 심화 분석 (목표 하나가 '천 한 장'으로 짜이기까지)

"핵심은 단 하나의 발상 — 에이전트는 스스로 순서를 정하지 않는다. CLI가 '다음 한 수'를 적힌 봉투로 건네고, 에이전트는 그대로 둔다."

전체 흐름 한 장

사용자: /loom build "방문자 등록 시스템" │ ▼ ┌────────────────────────────────────────────┐ │ loom-cli (commander) ── 에이전트-중립 CLI │ └───────┬───────────────────────────┬────────┘ │ ① 저장 상태를 읽는다 │ ④ '지시 봉투'를 돌려준다 ▼ ▼ ╔═══════════════════════╗ { instruction: { ║ .loom/ (상태=진실) ║ mode: "execute_task", ║ config·status·메트릭 ║ resultFile: "...", ║ deliveries/<id>/ ║ submitCommand: "...", ║ ├ requirements/ ║ finalResponseGuard, ◀ 조기 종료 금지 ║ ├ brainstorms/ ║ mustNotReportProgress,◀ 잡담 금지 ║ ├ contracts/(PGC) ║ stopOnlyWhen: [...] } } ║ ├ artifacts/(AAC) ║ │ ║ ├ tasks/ reviews/ ║ ▼ ║ ├ repairs/ decisions/║ ┌──────────────────────────┐ ║ └ operations/lease ║ │ 에이전트(Claude Code 등) │ ╚═══════▲═══════════════╝ │ - 봉투의 명령 그대로 실행 │ │ │ - 결과를 resultFile에 기록 │ │ ⑤ continue 라우터 │ - submitCommand로 제출 │ └───────────────────┤ - 다시 continue … │ ② 다음 route action 계산 └──────────────────────────┘ ③ command→argv 매핑 ⑥ Claude Code 훅이 네이티브 Plan Mode를 차단

한 바퀴는 이렇게 돕니다. 사용자가 에이전트 안에서 /loom build … 또는 /loom continue를 부르면, continue 라우터가 .loom/의 저장 상태를 읽어 "지금 활성 단계에서 다음에 할 단 하나의 route action"을 정합니다. 그 route action을 실제 CLI 하위명령으로 매핑하고, 에이전트가 따라야 할 지시 봉투(instruction envelope)를 JSON으로 돌려줍니다. 에이전트는 봉투대로 실행→결과 파일 기록→제출하고 다시 continue를 부릅니다. Claude Code에서는 이 에이전트의 네이티브 기획 모드를 막아, Loom의 순서를 우회하지 못하게 합니다.

설계 패턴 ① — '지시 봉투': 에이전트에게서 '판단'을 뺏는다

가장 핵심적인 발상입니다. 보통 에이전트는 "무엇을 할지"를 스스로 정합니다. Loom은 그 자유를 의도적으로 줄입니다. CLI가 돌려주는 봉투에는 단순 데이터만 있는 게 아니라 행동을 강제하는 플래그가 가득합니다.

// 지시 봉투(CliSuccessEnvelope)의 actionRequired — 행동 강제 플래그
actionRequired: {
  mode: "execute_task",        // 지금 모드(태스크 실행/후보 생성/리뷰…)
  autoContinue: true,            // 멈추지 말고 이어가라
  mustRunImmediately: true,      // 즉시 실행(설명부터 늘어놓지 마라)
  mustNotReportProgress: true,   // "진행 중입니다" 같은 잡담 금지
  mustNotAskBeforeExecuting: true,
  resultFile: ".loom/.../result.json",   // 결과는 반드시 여기에
  submitCommand: "loom record-result …", // 이걸 성공시켜야
  completionBarrier: "...",   // 이 장벽을 넘기 전엔 완료 아님
  finalResponseGuard: "...", // 조기 "다 됐다" 차단
  forbiddenStops: [...],         // 여기서 멈추면 안 됨
  stopOnlyWhen: ["user_gated","blocked","done","failed"]
}

이 플래그들이 2장에서 본 "다 됐어요 함정"과 "잡담·조기 질문"을 데이터 차원에서 막습니다. 어댑터의 SKILL.md와 Claude Code 훅이 이 봉투를 읽어 강제 집행합니다.

설계 패턴 ② — 상태는 파일, 진실의 원천은 .loom/

Loom은 데이터베이스를 쓰지 않습니다. 한 배달의 모든 것이 .loom/deliveries/<deliveryId>/ 아래 버전드 JSON으로 쌓입니다. 폴더 이름만 봐도 파이프라인이 그대로 읽힙니다.

단계(폴더)무엇을 담나
requirements/요구사항 컨텍스트 · 정규화 텍스트 · 키워드 힌트 · 입력/추출 문서
brainstorms/요구사항 명료화(질문/결정/확정) — 무엇을 만들지 합의
contracts/ (PGC)기술 베이스라인 · 기획 계약(Planning Contract)
artifacts/architecture/ (AAC)아키텍처 계약(Architecture Artifact Contract) · 섹션 · 세션
tasks/<phase>/태스크 계획 · 실행 요청 · 실행(runs) · 결과(results)
reviews/ · repairs/ · decisions/리뷰 패킷/결과 · 수리 요청 · 사용자 결정 게이트
operations/active-lease.json동시성 락 — 상태 변경 작업이 둘 동시에 못 돌게
비유

건축 현장의 '현장 사무소 캐비닛'을 떠올리세요. 설계 승인서(기획 계약), 구조 도면(아키텍처 계약), 작업 지시서(태스크), 검측 보고서(리뷰), 하자 보수 요청(수리)이 칸칸이 정리돼 있습니다. 담당자가 바뀌어도(에이전트 교체·세션 종료) 새 사람이 캐비닛만 열면 어디까지 됐는지를 압니다. active-lease는 "한 캐비닛을 두 사람이 동시에 못 헤집게" 하는 자물쇠고요.

설계 패턴 ③ — 단계(phase)들은 'route action' 열거형이다

Loom의 단계는 코드 안에 열거형(enum)으로 박혀 있습니다. continue 라우터는 저장 상태를 보고 이 중 하나를 "다음 행동"으로 반환합니다.

// src/core/schemas.ts — 배달 단계 = route action
routeAction = [
  "brainstorm_start", "brainstorm_clarification", "brainstorm_confirmation",
  "technical_baseline_request", "repository_context_request",
  "planning_contract_create", "architecture_artifact_contract",
  "taskplan_generation", "continue_execution", "review",
  "execution_repair", "task_result_repair", "taskplan_repair",
  "architecture_artifact_repair",
  "needs_user_decision", "manual_review",  // ← 사람이 개입하는 두 게이트
  "continue_to_next_phase", "done"
]

배달(delivery)은 여러 단계(phase)의 연속이고, 각 단계가 위 파이프라인을 한 바퀴 돕니다. continue_to_next_phase는 그 단계의 리뷰가 승인된 뒤 다음 단계로 넘깁니다. needs_user_decision·manual_review자동으로 못 넘기는 지점에서 사람을 부르는 두 개의 게이트입니다 — 에이전트가 임의로 결정하지 않도록.

설계 패턴 ④ — 태스크는 '계약', 검증은 'wired 증거'를 요구

Loom은 큰 목표를 바운디드 태스크(bounded task)로 쪼갭니다. 각 태스크는 그냥 할 일이 아니라 계약입니다 — 건드려도 되는/안 되는 경로, 수용 기준, 검증 의도가 명시됩니다.

// src/core/contracts.ts — 태스크 계약(요약)
task = {
  taskId, title, objective,
  scopeRefs, acceptanceRefs,        // 범위·수용 기준
  writeBoundary: {
    forbiddenPaths: [...],        // 이 태스크가 건드리면 안 되는 파일
  },
  verificationIntents: [...],       // 무엇을 어떻게 검증할지
}

여기에 Loom의 가장 까다로운 가드가 붙습니다. workflow-closure는 UI가 실제로 작동(wired)하는지를 증거로 요구합니다 — 정적·목업 화면은 통과 불가.

// src/core/workflow-closure.ts — "버튼이 진짜로 작동하는가"
requiredDataBindingMode: "wired",        // 실제 연결만 인정
staticModePolicy: "not_satisfied",        // 정적/목업은 불통과
requiredEvidence: [
  "user_action",                      // 사용자가 실제로 눌렀다
  "declared_interface_invocation",    // 선언한 API가 실제로 호출됐다
  "state_or_persistence_change",      // 상태/저장이 실제로 바뀌었다
  "success_or_blocking_feedback",     // 성공/실패 피드백이 떴다
]
함정
"데모는 되는데 제품은 안 되는" 격차

AI가 만든 화면은 그럴듯해 보여도 버튼이 아무것도 안 하는 경우가 흔합니다(목업). Loom은 그걸 "완료"로 인정하지 않으려고 위처럼 "사용자 행동 → API 호출 → 상태 변화 → 피드백"의 네 증거를 요구합니다. 또 runtime-delivery-closure는 빌드→기동→프리뷰 체인이 코드 레벨에서 실제로 도는지 최종 확인하는 태스크를 강제합니다. 이게 "데모에서 배달로(From Demo to Delivery)"라는 README 슬로건의 실체입니다.

설계 패턴 ⑤ — 훅으로 '딴짓'을 원천 차단

봉투와 SKILL.md만으로는 에이전트가 규약을 어길 여지가 남습니다. 그래서 Claude Code 어댑터는 (plugins/claude-code/hooks/loom-workflow-guard.js)을 PreToolUse·UserPromptSubmit·Stop 시점에 겁니다. 핵심은 Loom 작업이 활성일 때 Claude Code의 네이티브 Plan Mode(EnterPlanMode/ExitPlanMode)를 막는 것 — 에이전트가 자기 식 기획으로 갈아타 Loom의 순서를 우회하지 못하게 하는 하드 집행 계층입니다.

용어
훅 (hook) · PreToolUse
에이전트가 특정 행동을 하기 직전/직후에 끼어드는 콜백입니다. Claude Code의 PreToolUse 훅은 에이전트가 도구(예: Bash, Plan Mode)를 쓰기 직전에 실행돼, 그 행동을 막거나 바꿀 수 있습니다. Loom은 이를 이용해 "지금은 Loom 루프 안이니 네 마음대로 기획하지 마"를 코드로 강제합니다. 프롬프트로 부탁하는 것과 달리, 훅은 거부권을 가집니다.

5디렉토리 구조 해부

"src/는 보이지 않는 엔진, plugins/는 에이전트가 실제로 보는 얼굴. 둘을 런처가 잇는다."

최상위 한눈에

loom/ ├── src/ ← TypeScript 엔진(사용자에겐 안 보임) │ ├── cli.ts · 진입점 → runCli() │ ├── version.ts · LOOM_VERSION="0.1.0", 지원 스키마 버전 │ ├── commands/ · 40여 개 CLI 하위명령(commander) │ └── core/ · 배달 엔진의 심장 │ ├── schemas.ts · route action·상태·설정 zod 스키마 │ ├── contracts.ts · 태스크·계약 스키마(약 2,000줄) │ ├── validators.ts · 교차 검증, 수리 가능성 분류 │ ├── workflow-closure.ts · "wired 증거" 요구 │ ├── runtime-delivery-closure.ts · 빌드/기동 최종 검증 │ ├── operations/ · continue(라우터)·tasks·brainstorm·review·repair │ ├── knowledge/ · 로컬 문서 색인(PDF/DOCX/zip) │ ├── deployment/ · Dockerfile/Compose 생성·기동·수리 │ └── state/paths.ts · .loom/ 폴더 지도(상태 경로의 단일 정의) ├── plugins/ ← 어댑터(에이전트가 보는 얼굴) │ ├── claude-code/ · commands/loom.md · skills/loom/SKILL.md · hooks/ │ ├── codex/ · @loom 플러그인 │ ├── opencode/ · .opencode/ 플러그인 훅 │ └── shared/ · 공용 참조 문서(delivery·uix·deploy 가이드) ├── scripts/ ← 설치/제거 스크립트 + lib/(런처 설치) ├── benchmarks/agent-run/ ← 11케이스 토큰 벤치(cases·results·run.js·verify.js) ├── docs/ ← use-cases.md(데모 갤러리) ├── tests/ ← ~13개 스위트(protocol·task·review·deploy…) ├── package.json · tsconfig.json └── README.md · README.zh-CN.md · LICENSE(Apache-2.0)
용어
엔진(src/)과 어댑터(plugins/)의 분리
Loom은 한 개의 엔진(src/dist/cli.js)을 만들고, 여러 어댑터(plugins/)가 각 에이전트의 말투(/loom vs @loom)로 그 엔진을 부르게 합니다. 비유하면 엔진은 '발전소', 어댑터는 나라마다 다른 '콘센트 모양'입니다. 새 에이전트를 지원하려면 어댑터 하나만 추가하면 되고, 배달 로직(엔진)은 건드리지 않습니다. 이것이 '에이전트-중립'의 구현 방식입니다.

핵심 파일 — 크기로 본 무게중심

파일줄 수(약)역할
core/operations/tasks.ts4,900태스크 계획 생성 · next-task 라우팅 · 결과 기록 · 완료 장벽
core/operations/brainstorm.ts4,100요구사항 명료화 엔진(질문 블록·후보 생성)
core/operations/contracts.ts4,000기획/아키텍처/베이스라인 계약의 요청·승인 라이프사이클
core/validators.ts2,400교차 검증 → 이슈를 수리 가능/사용자 결정 필요/차단으로 분류
core/operations/continue.ts2,100라우터 — 상태를 보고 다음 route action 결정, command→argv 매핑
core/operations/repository-context.ts2,000압축 레포 컨텍스트 팩 생성(토큰 절감의 실체)

무게중심이 operations/(특히 continue·tasks·brainstorm)에 쏠려 있다는 건, 이 프로젝트가 결국 "상태를 보고 다음 한 수를 정하는 라우팅"과 "요구사항을 계약으로 굳히는 일"에 가장 많은 코드를 쓴다는 뜻입니다.

6학습 포인트 (기술별 — 배울 것 + 실습 아이디어)

"Loom 한 레포 안에 에이전트 하네스 설계·계약 기반 프로그래밍·파일 상태 머신·플러그인/훅이 다 들어 있다."

① 에이전트 하네스 · 지시 봉투 설계

배울 것: "에이전트에게서 판단을 덜어내고, 다음 행동을 데이터로 건넨다"는 발상. 봉투의 finalResponseGuard·completionBarrier·stopOnlyWhen이 어떻게 '조기 완료'와 '딴짓'을 막는지. LLM을 제어 가능한 부품으로 다루는 컨트롤 이론에 가깝습니다.

실습: 작은 CLI를 만들어, 호출할 때마다 { instruction, mustRunImmediately, stopOnlyWhen } 같은 JSON을 돌려주게 하고, 그 JSON을 Claude Code/Codex에 "그대로 따르라"고 물려 보기. 가드 플래그를 켰을 때와 껐을 때 행동 차이를 관찰.

② zod로 계약(contract) 스키마 설계 + 버저닝

배울 것: 에이전트가 만든 JSON을 믿지 않고 검증하는 법. schemaVersion으로 포맷을 진화시키는 법(구버전 산출물 호환). 타입과 런타임 검증을 한 소스로 묶는 zod의 힘.

실습: zod로 "태스크 계약" 스키마(writeBoundary.forbiddenPaths, acceptanceRefs 포함)를 정의하고, 일부러 형식을 어긴 JSON을 넣어 검증이 어떻게 막는지 확인. schemaVersion: 1 → 2 마이그레이션도 흉내 내 보기.

③ commander로 다(多)명령 CLI 설계

배울 것: 40여 개 하위 명령을 --json·--compact·--project-root 같은 공통 플래그로 일관되게 묶는 법. 에이전트가 파싱하기 좋은 compact 출력 vs 사람이 읽는 출력의 분리.

실습: commander로 mytool plan / continue / review 세 명령을 만들고, --json이면 기계용 JSON을, 아니면 사람용 표를 출력하게 분기. LOOM_COMPACT_OUTPUT=1처럼 환경변수로 모드를 바꾸는 패턴도 따라 하기.

④ 파일 기반 상태 머신 · 재개 가능성

배울 것: DB 없이 폴더+JSON으로 상태 머신을 만드는 법. state/paths.ts처럼 "경로를 한 곳에서만 정의"해 흩어지지 않게 하는 규율, active-lease.json 같은 파일 락으로 동시성 다루기.

실습: ./.mini/<id>/state.json에 "현재 단계"를 저장하고, continue를 부를 때마다 다음 단계로 넘어가는 미니 워크플로를 만들기. 프로세스를 강제 종료한 뒤 다시 continue이어지는지 확인(재개 가능성의 핵심).

⑤ Claude Code 플러그인 · 훅 · 스킬

배울 것: commands/*.md(슬래시 명령), skills/*/SKILL.md(행동 규약), hooks/*.js(PreToolUse/Stop 거부권)의 3종 세트. 프롬프트로 "부탁"하는 것과 훅으로 "강제"하는 것의 차이.

실습: 아주 단순한 Claude Code 훅을 작성해 특정 명령(예: 특정 파일 쓰기)을 PreToolUse에서 막아 보기. Loom의 loom-workflow-guard.js가 Plan Mode를 막는 방식이 정답지.

⑥ 멀티 에이전트 어댑터 패턴

배울 것: 한 엔진을 여러 에이전트가 공유하게 하는 런처 + 어댑터 구조. ~/.loom/bin/loom-cli처럼 PATH에 의존하지 않는 안정 실행기를 두는 이유(에이전트마다 셸 환경이 다름).

실습: "엔진 1개 + 어댑터 2개(가짜 에이전트 A/B)" 구조를 만들어, 두 어댑터가 같은 ~/.mytool/bin/cli를 부르게 하기. 어댑터별 메타데이터를 ~/.mytool/adapters/<agent>에 남기는 것까지.

⑦ 검증 클로저 · 컨텍스트 팩(토큰 절감)

배울 것: "데모가 아니라 배달"을 코드로 강제하는 법 — workflow-closurewired 증거 4종. 그리고 레포를 매번 다시 읽지 않게 압축 컨텍스트 팩을 만들어 두는 토큰 경제.

실습: "버튼 클릭 → API 호출 → 상태 변경 → 피드백" 4단계 증거가 모두 있어야만 PASS를 주는 미니 검증기를 작성. 그다음 같은 기능을 (a) 목업 (b) 실제 연결로 만들어 검증기가 (a)를 떨어뜨리는지 확인.

7하드웨어 / 시스템 요구사항

"GPU·클라우드·DB 전부 필요 없다. Node와, 네가 이미 쓰는 에이전트 CLI와, (배포 프리뷰엔) Docker만 있으면 된다."

항목요구사항 / 메모
런타임Node.js ≥ 20 + npm. 엔진은 순수 TypeScript→JS라 별도 런타임 의존성 없음.
에이전트 CLI설치할 어댑터에 맞는 CLI가 있어야 함 — Codex CLI / Claude Code CLI / opencode CLI 중 하나.
Docker (선택)loom deploy(로컬 Docker Compose 프리뷰)에만 필요. 배달의 코어 루프엔 불필요.
외부 서비스없음. 데이터베이스·벡터DB·클라우드 API 불필요. 상태는 전부 .loom/ 로컬 파일.
GPU불필요. 모델 추론은 네가 쓰는 에이전트가 담당하고, Loom은 그 바깥의 하네스일 뿐.
디스크/메모리가벼움. 상태 JSON과 컨텍스트 팩 위주라 부담이 작다.
OS크로스 플랫폼(Node 동작 환경). 런처는 ~/.loom/bin/loom-cli에 설치.
함정
"설치했는데 명령이 안 먹어요"

어댑터를 깐 뒤에는 반드시 새 에이전트 세션을 열어야 갱신된 로컬 플러그인이 로드됩니다. 스모크 체크는 "$HOME/.loom/bin/loom-cli" --versionstatus로 합니다. 아직 Loom을 안 쓴 프로젝트에서 statusSTATE_NOT_INITIALIZED를 내는 건 정상입니다 — "런처는 잘 돌고, 배달이 아직 시작 안 됨"이라는 뜻이지 오류가 아닙니다. 또 보통 loom init을 손으로 칠 필요는 없습니다 — /loom build …가 필요할 때 .loom/을 알아서 초기화합니다.

8직접 해볼 수 있는 실습 과제

"설치해 스모크 → 작은 기능을 굴려 .loom/ 들여다보기 → 봉투 해부 → 미니 하네스 만들기, 단계별로."

과제 1난이도 ★☆☆☆☆ · 입문

설치하고 스모크 체크 통과시키기

git clonenpm installnpm run plugin:install-claude(또는 codex/opencode). 그다음 "$HOME/.loom/bin/loom-cli" --version과 빈 프로젝트에서 status를 돌려 STATE_NOT_INITIALIZED가 나오는지 확인.

목표: 런처·어댑터가 제대로 깔렸는지 감 잡기. STATE_NOT_INITIALIZED가 "정상 스모크 결과"임을 이해하는 게 포인트.

과제 2난이도 ★★☆☆☆ · 초급

작은 기능을 굴리고 .loom/를 해부하기

샘플 프로젝트에서 /loom build "간단한 방명록"을 시작한 뒤, 몇 번 /loom continue를 부르며 .loom/deliveries/<id>/ 아래에 requirements/·brainstorms/·tasks/ 폴더가 어떻게 채워지는지 직접 열어 본다.

목표: 추상적인 "단계"가 실제 파일·폴더로 어떻게 떨어지는지 눈으로 확인. index.jsonnextAction이 바뀌는 걸 추적해 보기.

과제 3난이도 ★★★☆☆ · 중급

'지시 봉투'를 날것으로 읽어 보기

런처로 직접 loom-cli continue --project-root /경로 --json을 호출해, 돌아오는 actionRequired JSON을 통째로 들여다본다. mode·resultFile·submitCommand·finalResponseGuard·stopOnlyWhen이 각각 무엇을 시키는지 주석을 달아 본다.

목표: 에이전트가 "왜 그렇게 행동하는지"의 근원이 이 봉투임을 체득. 같은 상태에서 단계가 바뀌면 봉투가 어떻게 달라지는지 비교.

과제 4난이도 ★★★★☆ · 중상

미니 딜리버리 하네스 직접 만들기

zod로 "태스크 계약" 스키마를 정의하고, continue 라우터(저장된 단계를 보고 다음 명령을 반환)를 흉내 낸 작은 CLI를 작성한다. 상태는 ./.mini/<id>/state.json에 저장하고, 중단 후 재개되는지 확인.

목표: Loom의 뼈대(상태→라우팅→봉투→실행→기록→반복)를 100줄 규모로 재현. "에이전트 없이도 하네스의 골격은 순수 로직"임을 깨닫기.

과제 5난이도 ★★★★★ · 고급

새 에이전트 어댑터 or 'wired 증거' 검증기 만들기

(a) plugins/ 구조를 읽고 가상의 새 에이전트용 어댑터(슬래시 명령 + 런처 연결)를 추가하거나, (b) workflow-closure의 4종 증거(user_action·interface_invocation·state_change·feedback)를 실제로 수집·판정하는 검증기를 구현한다.

목표: 에이전트-중립 설계 또는 "데모→배달" 검증의 본질을 손으로 구현. 둘 다 Loom이 풀려는 핵심 난제다.

9관련 기술 심화 학습 로드맵 (6주 플랜)

"TypeScript CLI에서 출발해 계약 기반 상태 머신·에이전트 하네스·플러그인까지, Loom을 길잡이 삼아."

주차주제핵심 학습 + Loom 연결점
1주TypeScript + commander CLI타입·strict 모드, commander로 하위명령·플래그, --json/--compact 분리 → src/cli.ts·commands/
2주zod 계약 + 파일 상태스키마 선언·런타임 검증·schemaVersion, 폴더+JSON 상태 → core/schemas.ts·contracts.ts·state/paths.ts
3주에이전트 하네스 개념지시 봉투·라우팅·완료 장벽·가드 플래그 → core/operations/continue.ts + commands/types.ts
4주Claude Code 플러그인/훅/스킬슬래시 명령·SKILL.md·PreToolUse 훅의 거부권 → plugins/claude-code/
5주검증 루프 + 토큰 절감구현/검증 분리, wired 증거, 압축 컨텍스트 팩 → workflow-closure.ts·repository-context.ts
6주멀티 에이전트 + 배포 프리뷰런처·어댑터 패턴, Dockerfile/Compose 생성·기동 → scripts/lib·core/deployment/
비유

이 로드맵은 "CLI 기초 → 데이터 계약 → 제어(하네스) → 집행(훅) → 품질(검증) → 확장(어댑터)"을 한 줄로 꿴 코스입니다. 'LLM을 어떻게 프롬프트하나'가 아니라 'LLM을 어떻게 신뢰할 수 있는 시스템의 부품으로 가두나'를 배우는 길이라, 에이전트 시대의 소프트웨어 공학 그 자체를 실전 코드로 복습하는 셈입니다.

10핵심 키워드 사전

"이 문서와 저장소에서 반복되는 용어를 한곳에 모았다."

용어의미
딜리버리 하네스 (delivery harness)모델·에디터를 갈아치우지 않고 그 바깥에 둘러, 출하 과정 전체를 반복·검증·재개 가능하게 만드는 골격. Loom의 정체
동적 워크플로 (dynamic workflows)목표 성격에 따라 거쳐야 할 단계(경로)를 그때그때 고르고, 그 경로를 상태로 굳히는 방식
지시 봉투 (instruction envelope)CLI가 에이전트에게 "다음 한 수"를 건네는 JSON. mode·resultFile·submitCommand + 강제 플래그를 담는다
finalResponseGuard / completionBarrier"절반에서 다 됐다고 선언"을 막는 가드 — 결과 파일 존재 + 제출 성공 전엔 완료 불가
stopOnlyWhen / mustNotReportProgress"여기서만 멈춰라(사용자게이트·차단·완료·실패)" / "진행 중 잡담 금지" 등 행동 강제 플래그
.loom/ (상태 디렉토리)한 배달의 모든 산출물을 담는 프로젝트-로컬 JSON 폴더. 진실의 원천(source of truth)
route action배달의 '단계'를 나타내는 열거형. continue 라우터가 상태를 보고 다음 값을 반환
delivery / phase배달=목표 하나 / phase=그 안의 단계. 한 배달은 여러 phase의 연속, 각 phase가 파이프라인 1회전
brainstorm무엇을 만들지 합의하는 요구사항 명료화 단계(질문→결정→확정)
PGC (Planning Contract)기획 계약 — 무엇을 어떤 범위로 할지 굳힌 문서
AAC (Architecture Artifact Contract)아키텍처 계약 — 구조·인터페이스·화면 흐름을 굳힌 문서
태스크 계약 (task contract)바운디드 태스크. writeBoundary(forbiddenPaths)·acceptanceRefs·verificationIntents 포함
writeBoundary / forbiddenPaths한 태스크가 건드려도 되는/안 되는 파일 경계 — 범위 이탈 방지
workflow-closure (wired 증거)UI가 실제로 작동하는지 4종 증거(행동·API호출·상태변화·피드백)를 요구. 정적/목업 불통과
runtime-delivery-closure빌드→기동→프리뷰 체인이 실제로 도는지 코드 레벨로 최종 검증하는 강제 태스크
needs_user_decision / manual_review자동으로 못 넘기는 지점에서 사람을 부르는 두 게이트
active-lease.json상태 변경 작업이 둘 동시에 못 돌게 하는 파일 기반 동시성 락
에이전트-중립 (agent-neutral)같은 배달 프로토콜을 Claude Code·Codex·opencode에 동일 적용
어댑터 / 런처 (launcher)어댑터=에이전트별 입구(/loom vs @loom) / 런처=PATH에 안 기대는 안정 실행기 ~/.loom/bin/loom-cli
훅 (hook) · PreToolUse에이전트 행동 직전에 끼어들어 막거나 바꾸는 콜백. Loom은 네이티브 Plan Mode를 차단
컨텍스트 팩 (context pack)레포를 매 턴 다시 읽지 않게 미리 만들어 둔 압축 요약 — 토큰 절감의 핵심
compaction (압축)대화가 길어지면 맥락을 줄이는 과정. 이때 정렬이 깨지는 걸 Loom의 상태가 보완
zod / commander스키마+런타임 검증 라이브러리 / Node CLI 프레임워크 — Loom 엔진의 두 기둥

11참고 링크