"문서가 거의 없는 어려운 주제를 골라 말하면, AI가 그 자리에서 '직접 손으로 따라 짜는' 실습 튜토리얼을 써주고, 그걸 내 컴퓨터에 저장해 브라우저로 읽으며, 진짜 코드가 돌아가는지까지 검증해주는 도구"입니다. "Go로 데이터베이스 밑바닥부터 만들기", "Zig로 디지털 신디사이저 만들기"처럼 검색해도 좋은 자료가 안 나오는 영역을 타깃으로 합니다.
구조는 두 겹입니다. Claude Code 스킬(/lathe)이 마크다운 튜토리얼을 생성하고, Go로 짠 lathe CLI가 그것을 ~/.lathe/tutorials/에 저장하고 localhost:4242에 서빙합니다. 그리고 원할 때 또 다른 Claude 세션이 튜토리얼을 한 단계씩 실제로 따라 해보며 컴파일·실행을 검증합니다.
유튜브 강의는 영상을 '보기만' 합니다. 반대로 Lathe는 이름처럼 선반(lathe) 위에 재료를 올려놓고 내 손으로 깎게 만듭니다. AI는 "이 단계에서 이 코드를 여기 끼워넣어라, 그다음 이 명령으로 결과를 확인하라"는 식의 체크포인트가 박힌 작업 지시서를 써주고, 실제 타이핑·실행은 학습자가 합니다.
게다가 그 지시서가 거짓말(환각)을 하지 않았는지, 별도의 AI 견습공이 똑같이 처음부터 따라 만들어보고 "여기 3번 단계에서 컴파일 안 됨"이라고 빨간 딱지를 붙여줍니다. '보는 학습'이 아니라 '만드는 학습', 그리고 '검증된 교재'가 Lathe의 두 기둥입니다.
SKILL.md). 사용자가 /lathe ...처럼 슬래시 명령으로 불러냅니다. Lathe는 스킬 6개(lathe, lathe-verify, lathe-extend, lathe-ask, lathe-tag, lathe-voice)로 이뤄집니다.lathe serve처럼 명령어를 쳐서 쓰는 프로그램. Lathe의 CLI는 Go로 짠 단일 실행파일 하나이며, 튜토리얼 파일·메타데이터·웹서버 같은 "오래 남아야 하는 것" 전부를 책임집니다.일반 튜토리얼 사이트나 LLM은 React·Python처럼 자료가 넘치는 주제에 강합니다. 그런데 정작 배우기 어려운 건 "Go로 DB 엔진을 밑바닥부터", "Zig로 신디사이저를"처럼 자료가 희박한 영역이죠. Lathe는 바로 이 지점을 노립니다. 그리고 자료가 적은 주제일수록 LLM이 없는 사실을 지어낼 위험(환각)이 가장 큰데, Lathe의 스킬은 "쓰기 전에 웹에서 3~8개 1차 출처를 실제로 열어 읽어라"를 강제합니다.
Lathe 튜토리얼에는 교육학이 설계로 박혀 있습니다. 예측(PREDICT)·회상(RECALL)·점점 줄어드는 발판(faded scaffolding) 같은 인지과학 기법을 의무화합니다. 마지막 코드 블록은 일부러 완성본을 안 주고 "방금 본 패턴으로 다음 한 줄을 직접 써라"라고 시킵니다. 단순 복붙으로 끝나는 강의와 결이 다릅니다.
AI가 쓴 코드 튜토리얼의 최대 약점은 "그대로 따라 했는데 안 돌아감"입니다. Lathe는 /lathe-verify로 별도 Claude 서브프로세스가 임시 폴더에서 튜토리얼을 처음부터 끝까지 실제로 실행하고, 결과를 ✅검증됨 / ❌실패 / ⚠️건너뜀 배지로 박아줍니다. "여기 컴파일러가 없어서 못 돌렸다(skipped)"와 "튜토리얼이 진짜 틀렸다(failed)"를 구분하는 디테일까지 있습니다.
인기 요인의 절반은 코드 자체의 모범성입니다. Go 표준 라이브러리만으로 웹서버·임베딩·라우팅을 처리하고, embed.FS로 HTML·CSS·폰트·스킬까지 바이너리 하나에 다 넣어 100% 오프라인 동작합니다. "AI 도구지만 정작 Go 바이너리는 절대 모델을 호출하지 않는다"는 경계 설계가 특히 회자됩니다.
| Lathe | 일반 블로그/문서 | LLM에 직접 질문 | 유튜브 강의 | |
|---|---|---|---|---|
| 희소 주제 대응 | 강함(즉석 생성) | 약함(없으면 끝) | 중간(환각 위험) | 약함 |
| 학습 방식 | 직접 타이핑·실습 | 읽기 | 대화 | 시청 |
| 정확성 검증 | AI가 실제 실행 | 없음 | 없음 | 없음 |
| 출처 추적 | 소스 링크 기록 | 들쭉날쭉 | 거의 없음 | 거의 없음 |
| 오프라인 | 완전 가능 | 불가 | 불가 | 불가 |
Lathe는 코드를 대신 짜주는 도구가 아니라, 내가 직접 손으로 짜도록 안내하는 교재 생성기입니다. 핵심 가치는 "학습"이지 "자동화"가 아닙니다. 또한 검증은 --dangerously-skip-permissions로 도는 소프트 격리(임시 디렉터리 + 지침)일 뿐, 보안 샌드박스가 아니라고 README가 명시합니다.
Lathe의 스택은 놀랄 만큼 단출합니다. 언어는 Go 1.25 하나, 외부 의존성은 단 4개뿐(+간접 의존성 몇 개). AI 부분은 라이브러리가 아니라 "사용자의 Claude Code 세션"이라는 외부 런타임에 위임합니다.
| 구성요소 | 역할 |
|---|---|
| Go 1.25 | 전체 CLI·웹서버·임베딩. 표준 라이브러리 net/http만으로 서버 구현 |
| spf13/cobra | 서브커맨드 구조(lathe serve, list, store …). 파일 하나당 커맨드 하나 |
| yuin/goldmark | 마크다운 → HTML 렌더링 엔진 |
| goldmark-highlighting + alecthomas/chroma | 코드 블록 구문 강조(라이트=tango / 다크=gruvbox 테마) |
| embed.FS (표준) | HTML 템플릿·CSS·폰트·mermaid.js·스킬을 바이너리에 내장 → 오프라인 |
| 구성요소 | 역할 |
|---|---|
| Go html/template | layout.html·list.html·components.html를 서버에서 렌더링 |
| styles.css (단일 디자인 시스템) | 라이트/다크 토큰, @font-face, 모든 컴포넌트 스타일. 인라인 주입(FOUC 없음) |
| 바닐라 JS (인라인) | 목록 페이지의 검색·필터·정렬·테마 토글. 프레임워크 0 |
| mermaid.min.js (내장) | 튜토리얼 내 다이어그램 렌더링 |
| latin-subset woff2 폰트 | Fraunces·Newsreader·JetBrains Mono를 내장 → 외부 요청 0 |
| 구성요소 | 역할 |
|---|---|
| Claude Code (claude CLI) | 스킬을 실행하는 대화형 세션. 생성·검증·확장·질의응답 모두 여기서 |
| SKILL.md × 6 | lathe(생성)·verify(검증)·extend(확장)·ask(질문)·tag(태그)·voice(말투). 마크다운 지침 |
| voice 프리셋 | plainspoken(기본)·companion(따뜻한 말투). 톤만 바꾸고 정확성은 못 건드림 |
| 구성요소 | 역할 |
|---|---|
| magefile.go (Mage) | 표준 라이브러리만 쓰는 빌드 태스크. mage check = CI와 동일 게이트 |
| golangci-lint + go test -race | 린트·레이스 검출 테스트. PR마다 mage check 통과 필수 |
| GoReleaser | darwin/linux × amd64/arm64 바이너리, Homebrew cask 자동 배포 |
| install.sh | curl | sh 설치 경로(체크섬 검증 포함) |
주방(Go CLI)과 셰프(Claude 스킬)의 분업. 셰프는 그날그날 요리(튜토리얼)를 창작하지만, 식자재 창고·냉장고·서빙(영속 상태)은 전부 주방 시스템이 관리합니다. 셰프는 절대 창고 열쇠를 직접 만지지 않고, "이거 저장해줘(lathe store)"라고 주방에 요청만 합니다. 덕분에 셰프가 바뀌어도 창고는 일관됩니다.
사용자가 /lathe ...로 시작해서 브라우저로 읽기까지의 전 과정입니다. 화살표를 따라 "누가 무엇을 만들고, 누가 그것을 소유하는가"를 보세요.
이 프로젝트를 관통하는 단 하나의 원칙입니다. 모델 작업(생성·검증·확장·답변)은 전부 사용자의 대화형 Claude 세션에서 돌고, Go 바이너리는 절대 claude를 직접 실행하지 않습니다.
claude -p 호출은 과금되지만, 사용자가 직접 켠 대화형 세션은 과금되지 않습니다. 그래서 Lathe는 "Go가 모델을 부르는" 대신, CLI가 붙여넣을 명령어 문자열만 돌려주고(handoff) 실제 실행은 사용자 세션에 맡깁니다. 비용 + 권한 + 단순함을 한 번에 잡은 결정입니다.그 결과 스킬은 ~/.lathe/에 직접 쓰지 못하고, 항상 CLI 명령(lathe store, lathe verify-result, lathe extend-commit)을 통해서만 상태를 바꿉니다. "durable state의 단일 작성자는 오직 Go 바이너리" — 이 한 문장이 코드 전반의 규칙입니다.
웹 UI의 "Verify this tutorial" 버튼을 눌러도 서버가 검증을 돌리지 않습니다. 대신 {"command": "/lathe-verify <slug>"} 같은 붙여넣을 명령어를 돌려주고, 사용자가 그걸 자기 Claude 세션에 붙여넣어 실행합니다. 상태(verifying→verified)는 스킬만 설정합니다. 덕분에 "버튼만 누르고 실행 안 한" 경우에도 배지가 verifying에 멈추는 사고가 원천 차단됩니다.
HTML 템플릿·CSS·폰트·mermaid.js, 심지어 스킬 마크다운까지 //go:embed로 바이너리에 박습니다. 외부 CDN·네트워크 요청이 0이라 완전 오프라인으로 돕니다.
go:embed는 점(.)으로 시작하는 경로를 무시한다스킬 원본은 .claude/skills/에 있는데, go:embed는 .으로 시작하는 디렉터리를 못 넣습니다. 그래서 mage skills가 internal/skills/data/에 내장 가능한 복제본을 만들고, mage skillsCheck가 둘이 어긋나면 CI를 실패시킵니다. internal/skills/data/는 절대 손으로 고치지 말 것 — 원본을 고치고 mage skills를 돌려야 합니다.
검증은 Go 바이너리가 서브프로세스를 스폰하는 것이 아니라, 사용자의 대화형 에이전트 세션에서 /lathe-verify 스킬이 직접 실행한다. 스킬은 mktemp -d로 만든 임시 디렉터리에서 작업하며, 격리는 OS 샌드박스(sandbox-exec·Docker)가 아닌 지침 수준(soft isolation)이다. README는 이를 "보안 경계가 아니라 소프트 격리"라고 명시한다.
1) CLAUDE.md — 설계 철학과 "하지 말 것"이 다 적혀 있어 최고의 입문서. 2) .claude/skills/lathe/SKILL.md — 튜토리얼 품질 기준(교육학·출처·말투)의 본체. 3) internal/serve/server.go — Go 1.22+ 메서드·패턴 라우팅과 경로 traversal 방어(safeTutorialPath). 4) internal/store/metadata.go — 상태 enum과 데이터 모델.
cmd/ vs internal/ 분리cmd/는 cobra(CLI 프레임워크)에 의존하는 "껍데기", internal/은 cobra를 모르는 순수 로직이라 테스트에서 직접 불러 쓸 수 있습니다. internal/이라는 이름은 Go가 특별 취급해, 외부 모듈이 import하지 못하게 막아줍니다.배울 것: 외부 웹 프레임워크 없이 net/http의 1.22+ 패턴 라우팅(mux.HandleFunc("GET /{slug}/", …))으로 라우터를 짭니다. embed.FS로 정적 자산을 바이너리에 넣어 배포를 단일 파일로 만듭니다. safeTutorialPath의 경로 traversal 방어(조인 결과가 루트 밑에 있는지 확인)는 파일을 다루는 모든 웹앱이 꼭 배워야 할 패턴입니다.
localhost에 띄워주는 50줄짜리 Go 뷰어를 net/http + goldmark만으로 직접 짜보기.배울 것: "파일 하나당 서브커맨드 하나 + init()에서 rootCmd.AddCommand"라는 확장 가능한 패턴. 에러는 RunE로 위로 흘려보내고 루트 Execute()가 종료 코드를 정합니다. write-only 커맨드(verify-result)와 read 커맨드(voice show)를 의도적으로 분리한 설계도 음미할 만합니다.
배울 것: 요즘 AI 도구의 흔한 함정은 "코드 안에서 LLM을 막 호출"하는 것입니다. Lathe는 정반대로 결정론적 로직은 Go, 창의적 작업은 사용자 세션으로 칼같이 나눕니다. 비용·테스트 용이성·예측 가능성을 모두 얻는 이 경계 설계는 에이전트 시스템을 짤 때 그대로 베껴 쓸 만합니다.
배울 것: lathe/SKILL.md는 그 자체로 한 편의 글쓰기·교육학 교본입니다. "금지된 첫 문장", "용어를 정의하고 곧바로 업계 은어를 알려줘라", "틀린 버전을 먼저 보여주고 고쳐라", "load-bearing 주장은 출처 링크 아니면 [!UNVERIFIED]" — 막연한 'AI에게 잘 시키기'가 아니라 검증 가능한 규칙으로 분해한 사례입니다.
배울 것: 예측(PREDICT)·간격 회상(RECALL)·점점 줄어드는 발판(faded scaffolding)·자기설명(closing reflection). 강의 자료를 만드는 사람이라면 이 스킬의 "Before/After" 예시만 읽어도 콘텐츠 품질이 달라집니다.
| 항목 | 요구사항 |
|---|---|
| 설치(빌드) | Go 1.25+ — go install github.com/devenjarvis/lathe@latest |
| 설치(바이너리) | macOS는 Homebrew cask, Linux는 install.sh(curl | sh) |
| 생성·검증·확장 | claude CLI가 $PATH에 있어야 함 (Claude Code 구독/인증) |
| 웹 리더 | 브라우저만 있으면 됨. 기본 포트 4242(--port로 변경), 완전 오프라인 |
| 검증 실행 | 해당 튜토리얼의 툴체인이 로컬에 설치돼 있어야(예: zig). 없으면 ⚠️ skipped |
| 저장 위치 | ~/.lathe/tutorials/<slug>/ — 전역, 슬러그당 폴더 하나 |
slug, title, status(unverified/verifying/verified/failed/skipped/extending), parts[], 그리고 repo·tools(버전 칩)·sources·voice·model. 검증 실패 시 옆에 verify-result.json(실패 파트·단계·에러)이 함께 생깁니다.go install github.com/devenjarvis/lathe@latest 후 Claude Code에서 /lathe build a tiny JSON parser in Go를 실행하세요. lathe serve로 브라우저를 열어 체크포인트·예측 프롬프트가 실제로 어떻게 렌더링되는지 관찰합니다.
같은 튜토리얼을 /lathe-verify로 검증해 ✅를 보고, 일부러 툴체인이 없는 주제(예: Zig)로 하나 더 만들어 ⚠️skipped를 재현하세요. "건너뜀 ≠ 실패"의 의미를 체감합니다.
/lathe-voice로 나만의 말투(예: "아주 간결하고 군더더기 없는")를 만들고, 같은 주제를 기본 plainspoken과 새 voice로 각각 생성해 결과를 나란히 비교하세요. "voice는 톤만 바꾸고 정확성·구조는 못 건드린다"는 불변식이 실제로 지켜지는지 확인합니다.
cmd/에 lathe stats(저장된 튜토리얼 수·상태별 집계 출력)를 추가해보세요. "파일 하나당 커맨드 하나 + init() 등록" 관례를 따르고, internal/store의 메타데이터 읽기 함수를 재사용합니다. cobra 구조를 손으로 익히는 과제입니다.
예컨대 archived 상태를 추가한다면, README/CLAUDE.md가 알려주는 4곳을 모두 동기화해야 합니다: store.Status enum → cmd/list.go의 statusBadge → components.html의 {{define "badge"}} → styles.css의 --badge-* 토큰. "한 곳만 고치면 다른 곳이 깨지는" 결합 지점을 추적하는 좋은 연습입니다.
net/http 1.22+ 라우팅, html/template, embed.FS를 익힙니다. 목표: 마크다운 폴더를 서빙하는 미니 뷰어를 직접 완성. server.go·renderer.go를 읽으며 비교하세요.
서브커맨드·플래그·RunE 에러 전파를 익히고, cmd/를 모방해 자신만의 작은 CLI 도구를 만듭니다. write/read 커맨드 분리, internal/ 분리로 테스트 가능하게 짜는 법까지.
"모델을 코드 밖에 두는" 핸드오프 패턴을 이해하고, lathe/SKILL.md를 정독하며 좋은 스킬/프롬프트가 어떻게 검증 가능한 규칙으로 분해되는지 분석합니다. 내 도메인용 SKILL.md를 한 편 써보세요.
Mage 빌드 태스크, golangci-lint, go test -race, GoReleaser, ldflags 버전 주입을 익힙니다. 목표: 내 Go 프로젝트에 mage check 게이트와 크로스플랫폼 릴리스를 붙이기.
digital-synth-zig. 폴더 이름·URL 경로·메타데이터 키로 쓰입니다./lathe-verify <slug>)만 돌려주는 방식. "Go는 모델을 부르지 않는다" 원칙을 지키는 핵심 메커니즘.plainspoken(비의인화), companion(따뜻한 말투). 고정 preamble로 감싸여 정확성·검증·출처 규칙은 절대 못 건드리게 막혀 있습니다.mage check 하나가 gofmt·vet·lint·go test -race·build를 모두 돌리며, CI와 똑같은 명령이라 로컬과 CI가 어긋날 수 없습니다.-ldflags "-X ...Version=v1.2.3"로 소스 변수에 값을 박는 기법. 코드를 안 고치고도 바이너리에 버전·커밋·날짜를 새깁니다. internal/buildinfo가 이를 담당합니다.unverified. 사용자가 명시적으로 요청해야만 검증이 돕니다. "저장이 자동 검증을 유발하지 않는다"는 의도된 안전 설계입니다.| 링크 | 설명 |
|---|---|
| GitHub 저장소 | 소스 전체. CLAUDE.md·.claude/skills/lathe/SKILL.md가 최고의 읽을거리 |
| TrendShift 페이지 | 트렌딩 추이(일간 24위, 2026-06-08) |
| net/http (1.22+ 라우팅) | 메서드·패턴 라우팅 mux.HandleFunc("GET /{slug}/", …) |
| embed 패키지 | 정적 자산을 바이너리에 내장하는 표준 기능 |
| spf13/cobra | Go CLI 프레임워크. 서브커맨드 구조의 사실상 표준 |
| yuin/goldmark | 마크다운 렌더링 엔진 |
| alecthomas/chroma | 코드 구문 강조 라이브러리 |
| Mage | Go로 짜는 빌드 자동화 도구 |
| GoReleaser | Go 프로젝트 크로스플랫폼 릴리스 자동화 |
| Claude Code 스킬 문서 | SKILL.md 작성·동작 원리 공식 문서 |