TRENDSHIFT DAILY #2 · 2026-07-01

dao-code(道) 딥다이브
— 비싼 모델 대신 '캐시 경제학'으로 승부하는 터미널 코딩 에이전트

터미널에서 코드를 읽고·쓰고·명령을 실행하며 버그를 고치는 AI 코딩 에이전트다. Claude Code에서 영감을 받았지만 길이 다르다 — 비싼 모델로 '경험'을 사는 대신, 값싼 DeepSeek V4를 프롬프트 캐시로 극한까지 아껴 쓴다. 프리픽스를 바이트 단위로 고정하고, 반성·기억을 '캐시를 재활용하는 분신'에서 돌려, 세션을 넘나드는 기억과 자가 교정 기능을 거의 공짜로 얹었다. 명령어는 dao. (저장소: tigicion/dao-code · TypeScript · ★732 · TrendShift Daily 2위 · MIT)
목차
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트 (기술별)
  7. 시스템 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

이 레포가 무엇을 하는 물건인가.

핵심 메시지

"비싼 물감을 계속 사는 화가가 아니라,
쓰던 붓과 팔레트를 악착같이 아껴 쓰는 화가."

Claude Code 같은 도구가 '똑똑하지만 비싼 모델'을 사서 좋은 경험을 낸다면, dao-code는 '값싼 모델(DeepSeek V4) + 캐시 규율'로 같은 경험을 훨씬 싸게 낸다. 핵심 무기는 성능이 아니라 돈을 아끼는 엔지니어링이다.

dao-code(명령어 dao)는 터미널 안에서 사는 AI 코딩 비서다. 코드를 읽고, 코드를 쓰고, 셸 명령을 실행하고, 버그를 고친다 — 그 과정에서 자기 추론(reasoning)과 도구 호출을 실시간으로 흘려보여 주되, 쓰기·실행처럼 위험한 동작은 승인 게이트(approval gate) 뒤에서만 한다. 대상 모델은 DeepSeek V4이고, 1M(백만) 토큰 컨텍스트를 쓴다. 중국어 우선(Chinese-first)으로 설계됐고, 영감의 원천은 Claude Code다.

여기서 계속 나올 핵심 단어부터 이름표를 붙여 두자. 프롬프트 캐시는 "모델이 방금 읽은 앞부분을 기억해 두었다가 다음에 싸게 재활용하는 장치"이고, dao-code의 모든 비용 마법이 여기서 나온다.

용어
prompt cache / prefix cache (프롬프트 캐시 · 프리픽스 캐시)
LLM에 매번 같은 앞부분(시스템 지시·도구 목록 등)을 보내면, 모델 서버가 그 앞부분의 계산 결과를 저장해 두고 다음 요청에서 재사용한다. 그 부분은 다시 계산할 필요가 없어 값이 확 싸진다. 카페에서 "늘 먹던 걸로"라고 하면 주문을 처음부터 설명할 필요가 없는 것과 같다. DeepSeek는 이 '캐시 적중(hit)' 가격이 '실패(miss)' 가격의 약 1/120이라, 앞부분을 얼마나 안 바꾸고 유지하느냐가 곧 요금이 된다.

2왜 주목받는가

트렌딩 이유 · 경쟁(특히 Claude Code) 대비 장점.

dao-code는 자신을 세 축 — 가용성(Availability) · 비용(Cost) · 경험(Experience) — 으로 설명한다. 이 셋이 곧 주목 이유다.

① 가용성 — 에이전트는 "실제로 돌릴 수 있어야" 쓸모가 있다. Claude Code는 Anthropic 계정과 해외 네트워크가 필요해 중국 본토에선 문턱이 높고, 일부 국산 코딩 플랜은 쿼터(사용량 할당)가 부족하다. dao-code는 완전 오픈소스(MIT)이고, 기반 모델 DeepSeek가 가입 즉시·쓴 만큼 결제·본토에서 바로 접속이라 그 문턱이 없다.

② 비용 — DeepSeek는 주요 모델 중 최저가 축이고, 여기에 캐시가 얹힌다. 적중 가격이 실패의 약 1/120(두 자릿수 배 차이)이라, 시스템 프리픽스·도구 목록·기억을 바이트 단위로 고정해 적중률을 끌어올린다. 실제 오픈소스 버그 수정 7건(valibot·date-fns·es-toolkit·sqlglot·hono)을 돌린 측정치가 README에 통째로 공개돼 있다.

측정 항목의미
총 입력 토큰3,886,0377개 실제 버그수정 작업 합계
캐시 적중률95.8%과제별 85.4%~97.7%
총 비용¥1.07기능 1개당 평균 ¥0.15 (읽기+수정+테스트+자가검토)
vs Claude Opus 4.8약 30배 저렴같은 토큰 트레이스를 각 공식 요금으로 환산
vs Claude Sonnet 4.6약 18배 저렴동일 비교(캐시 이점은 상대에게도 유리하게 적용)

③ 경험 — 단순히 싼 게 아니라, 비싼 모델이 주던 '똑똑한 경험'을 캐시로 흉내 낸다. 세션을 넘나드는 기억, 막혔을 때 스스로 의심하는 반성 레이어, 긴 작업이 삼천포로 빠지지 않게 하는 재초점(refocus) — 이 셋을 모두 '메인 캐시를 재활용하는 분신(fork)'에서 돌려 추가 비용을 거의 안 들인다. 그리고 이 모든 수치를 /cost 명령으로 언제든 재생·검증할 수 있게 열어 둔 '검증 가능성'이 신뢰를 준다.

기존 방식의 한계
"경험을 돈으로 산다"

세션 간 기억·자가 교정 같은 고급 경험을 얻으려면 보통 매 요청에 많은 문맥을 다시 넣어야 하고, 비싼 모델일수록 그 비용이 눈덩이처럼 커진다. 장시간 자율 작업은 특히 토큰을 태운다.

dao-code의 해결
"경험을 캐시로 만든다"

앞부분(프리픽스)을 절대 흔들지 않고 고정해 캐시 적중률을 극대화하고, 반성·기억은 그 캐시를 그대로 물려받은 분신에서 돌린다. 그래서 '고급 경험'의 추가 요금이 거의 0에 수렴한다. 같은 결과를 30배 싸게.

3기술 스택 전체 지도

터미널 UI부터 모델·빌드까지 한눈에.

놀라운 점부터: 런타임 의존성이 딱 6개다. HTTP 라이브러리(axios)도, 인자 파서(commander)도, 벤더 SDK(openai)도 없다 — 대부분 직접 구현했다. 그만큼 "군더더기 없이 캐시·프리픽스를 손수 통제"하겠다는 설계 의지가 읽힌다.

레이어기술 / 버전역할
언어TypeScript 5.6 (ESM, 85.4%)전체 코드베이스. 타입 안전.
터미널 UIInk 7 + React 19React 문법으로 터미널 화면을 그림(TUI).
코드 색칠cli-highlightdiff·코드 블록 구문 강조.
모델DeepSeek V4 (pro / flash)추론 엔진. 자체 streamChat로 스트리밍 호출.
스키마/검증Zod + zod-to-json-schema도구 입력 검증 + 도구 정의를 모델용 JSON Schema로 변환.
확장 프로토콜@modelcontextprotocol/sdk 1.29MCP 서버 연결(외부 도구 붙이기).
런타임Node.js ≥20실행 환경.
빌드tsc → dist · bun build --compile라이브러리 빌드 + 의존성 없는 단일 실행 바이너리 생성.
테스트Vitest 2 + ink-testing-library단위 테스트 + TUI 컴포넌트 테스트.
용어
Ink · TUI (Text-based User Interface, 텍스트 기반 사용자 인터페이스)
Ink는 "터미널을 브라우저처럼, React로 그리게 해 주는 라이브러리"다. 우리가 웹에서 <div>를 쓰듯, Ink에선 <Box>·<Text>로 터미널 화면을 컴포넌트로 조립한다. 그래서 dao-code의 화려한 화면(태극 스플래시, 실시간 스트리밍, 할 일 체크리스트)이 React 코드로 만들어진다. TUI는 그렇게 만든 '글자로 된 UI'를 부르는 말.
용어
Zod (조드) · JSON Schema
Zod는 "이 데이터는 이런 모양이어야 해"를 코드로 적어 검사하는 TypeScript 검증 도구다. dao-code는 각 도구(read_file 등)의 입력 규격을 Zod로 정의한 뒤, zod-to-json-schema모델이 이해하는 JSON Schema 형식으로 바꿔 "너는 이런 도구들을 이런 인자로 부를 수 있어"라고 알려 준다. 규격 한 곳(Zod)만 고치면 검증과 모델 노출이 동시에 맞춰진다.

4아키텍처 심화 분석

먼저 전체 그림, 그다음 요청 한 줄기를 끝까지 따라가기.

dao-code의 심장은 에이전트 루프(agent loop) 하나다. "모델에게 물어본다 → 모델이 도구를 쓰겠다고 하면 승인 받고 실행한다 → 결과를 다시 모델에게 준다 → 모델이 더 이상 도구를 안 쓸 때까지 반복"이 전부다. 먼저 숲을 보자.

┌──────────────────────────────────────────────────────────────┐ │ dao-code │ │ │ │ 사용자 ──▶ Ink TUI ──▶ agent loop ──▶ DeepSeek V4 │ │ (src/agent/loop.ts) │ │ │ │ │ ┌────────────────────┼───────────────────────┐ │ │ ▼ ▼ ▼ │ │ streamChat 모델이 도구 호출 요청 승인 게이트 │ │ (추론+답 스트림) (read/edit/exec ...) write·exec만 │ │ │ │ │ │ │ └────────── 도구 실행 → 결과를 모델에 되먹임 ◀─┘ │ │ │ │ │ (도구 요청이 멈출 때까지 loop) │ └──────────────────────────────────────────────────────────────┘

이제 대표 흐름 딱 한 줄기를 손으로 따라가 보자. 사용자가 이렇게 쳤다고 하자: dao "src/utils.ts의 formatDate를 타임존 인식하게 고쳐줘". 핵심 5% 경로(해피 패스)만 본다.

① Ink TUI가 입력을 받아 agent loop에 넘긴다 ② loop가 streamChat() 호출 → DeepSeek가 추론을 스트리밍 ③ 모델: "먼저 read_file(src/utils.ts) 할게" ← 도구 호출 요청 ④ 승인 게이트: 읽기는 안전 → auto 모드면 자동 통과 ⑤ 파일 내용을 결과로 모델에 되먹임 ⑥ 모델: "edit_file로 이 부분을 이렇게 바꿔" ← 쓰기 도구 요청 ⑦ 승인 게이트: 쓰기 = 위험 → [y]한번 / [a]기억 / [n]거부 물어봄 ⑧ 승인되면 수정 적용 → 결과 되먹임 → ⑨ 완료까지 ②~⑧ 반복

여기서 이 프로젝트 특유의 '정상 모양새'를 하나 짚자. 위 루프가 도는 내내 모델에게 보내는 맨 앞부분(시스템 지시 + 도구 목록 + 기억)은 한 글자도 바뀌지 않게 고정돼 있다. 이게 byte-stable prefix(바이트 고정 프리픽스)이고, 캐시 적중률의 근원이다. 반성·기억 같은 곁가지 작업은 이 고정 프리픽스를 그대로 물려받은 분신(fork)에서 돌려, 캐시를 깨지 않으면서 별도 일을 처리한다.

[ 고정 프리픽스 (캐시 적중 ↑) ]───┬──▶ 메인 대화 (코드 작업) 시스템 지시 · 도구표 · 기억 │ ※ 한 글자도 안 바꿈 ├──▶ fork ① 반성(challenger) — 캐시 재활용 ├──▶ fork ② 재초점(refocuser) — 캐시 재활용 └──▶ fork ③ 기억 distill — 값싼 flash 모델
설계 패턴
Constitution priority (헌법식 우선순위)
여러 지시가 충돌할 때 무엇을 먼저 따를지 정한 서열이다. dao-code는 안전·진실 > 사용자의 현재 지시 > dao-code 핵심 정책(모델/캐시 규율) > 스킬·기억 순으로 고정한다. 그래서 외부에서 설치한 스킬이 '일하는 방식'은 바꿀 수 있어도, 안전선과 캐시 하한선은 절대 못 넘는다. 나라의 헌법이 일반 법률보다 위에 있는 것과 같은 원리.

5디렉토리 구조 해부

어떤 폴더가 무슨 일을 하나.

먼저 저장소 전체 레이아웃. 핵심은 src/ 한 채이고, 그 안이 '기능별로 방을 나눈' 구조다.

dao-code/ ├── .dao/ 런타임 상태 — dao가 자기 자신에게 쓰는 설정(도그푸딩) ├── .github/ CI 워크플로 (workflows/ci.yml) ├── docs/ 문서 + assets(데모 gif) ├── evals/ SWE-bench식 평가 하니스 (run.mjs · runs/ · README) ├── scripts/ 빌드·검증 스크립트 (sync-version.mjs · accept-cache.sh …) ├── src/ 핵심 소스 ★ │ ├── agent/ loop.ts(루프) · tasks.ts(서브에이전트) · stuck.ts(막힘감지) │ ├── memory/ 기억 distill · verify · load │ ├── session/ log.ts(세션 로그) · checkpoint.ts(섀도 git) │ ├── permissions/ rules · identity · settings · engine · gate │ ├── tools/ 24개 도구 구현 │ └── index.ts 도구 레지스트리 + 진입점(bin: dao) ├── DAO.md /init로 생성되는 프로젝트 규약 예시 ├── install.sh 원라인 설치 스크립트 ├── package.json · tsconfig*.json · vitest.config.ts └── README.md / README.zh-CN.md

실행하면 작업 폴더에 .dao/가 생겨 '이번 작업의 모든 상태'가 여기 쌓인다. 이 폴더 구조를 알면 crash 복구·되돌리기가 어떻게 가능한지 감이 온다.

경로역할
.dao/settings.json권한 규칙(allow/ask/deny). 프로젝트용은 커밋, .local.json은 커밋 제외.
.dao/sessions/<id>/events.jsonl(매 턴 이벤트) + state.json(스냅샷). dao -c가 여기서 재개.
.dao/shadow.git내 진짜 .git완전히 분리된 작업트리 스냅샷. /restore·/rewind의 근거.
.dao/spill/도구 출력이 너무 크면 여기로 '흘려' 저장하고, 문맥엔 포인터만 남김.
.dao/agents/ · commands/ · skills/사용자 정의 서브에이전트·슬래시 명령·스킬(각각 .md 파일).
.dao/hooks.json · mcp.json수명주기 훅 · MCP 서버 연결 설정.
src/agent/loop.ts에이전트 루프의 본체. 여길 읽으면 전체 동작이 보인다.

6학습 포인트 (기술별)

이 레포에서 훔쳐 배울 만한 것 + 어느 파일을 보면 되는지.

포인트 1

Ink로 '터미널을 React처럼' 그리기

화려한 CLI를 만들고 싶다면 이만한 교보재가 없다. 태극 스플래시, 실시간 스트리밍, diff 하이라이트, 할 일 체크리스트가 전부 React 컴포넌트다. src/의 렌더링 코드를 읽으면 "상태(state)가 바뀌면 화면이 다시 그려진다"는 React 모델이 터미널에서 어떻게 도는지 보인다.

포인트 2

Zod 스키마 → 모델 함수호출(tool call)로 노출

LLM에게 "너는 이런 도구를 쓸 수 있어"를 알려 주는 표준 방법을 실전 코드로 볼 수 있다. 규격을 Zod로 한 번 적고 zod-to-json-schema로 변환하는 이 패턴은 어떤 에이전트를 만들든 재사용된다. 레지스트리는 src/index.ts, 구현은 src/tools/.

포인트 3 ★

'성능'이 아니라 '비용'을 엔지니어링하기

대부분의 에이전트가 더 똑똑한 모델을 좇을 때, dao-code는 프리픽스를 안 흔드는 것만으로 요금을 두 자릿수 배 줄인다. "왜 시스템 프롬프트를 매번 똑같이 유지해야 하나"를 이 레포로 체득하면, LLM 앱의 청구서를 보는 눈이 완전히 달라진다. /audit cache가 '무엇이 캐시를 깼는지'를 4차원 지문으로 짚어 준다.

포인트 4

섀도 git 체크포인트 — 남의 저장소를 안 건드리고 되돌리기

에이전트가 파일을 마구 고쳐도 안심인 이유. 별도 .dao/shadow.git에 스냅샷을 떠 두고, /restore로 직전 턴을 한 번에 되돌린다. 내 진짜 .git 히스토리는 절대 건드리지 않는다. 구현은 src/session/checkpoint.ts. '위험한 자동화에 안전벨트를 다는 법'의 좋은 예.

포인트 5

3단계 권한 엔진(allow / ask / deny)

"AI에게 어디까지 허용할까"를 규칙으로 통제하는 실전 설계다. 우선순위는 deny > ask > allow > 모드 기본값. 특히 cd /tmp && rm -rf x 같은 복합 명령을 조각조각(per-segment) 검사해 한 조각이라도 deny면 전체를 막는 부분이 백미다. 코드는 src/permissions/.

권한 규칙 문법은 도구(대상) 꼴이다. 복사만 하면 되니 겁먹지 말자:

# .dao/settings.json — "이건 허용, 저건 금지" 규칙 예시
Bash(npm run test:*)          # npm run test 로 시작하는 명령만 허용
Edit(src/**)                  # src 아래 파일 수정 허용(gitignore식 glob)
WebFetch(domain:example.com)  # 이 도메인만 웹 접근 허용
mcp__<server>__<tool>          # 특정 MCP 서버의 특정 도구
# 우선순위: deny(하드 차단) > ask(물어봄) > allow(자동) — deny는 YOLO에서도 안 뚫림

7시스템 요구사항

순수 소프트웨어 도구라 GPU도 특수 하드웨어도 필요 없다.

항목요구사항
런타임Node.js ≥20 (npm 설치 시). 단일 바이너리로 받으면 Node 불필요.
모델 접근DeepSeek API 키 1개. 발급 즉시·쓴 만큼 결제(가입 후 바로).
OSmacOS(arm64/x64) · Linux(arm64/x64) · Windows(x64). 릴리스에 각 바이너리 제공.
터미널일반 터미널이면 충분. TTY가 아니면 자동으로 순수 텍스트 REPL로 폴백.
비용(체감)실측상 기능 1개 완수 ≈ ¥0.07~0.21. 사실상 '커피 한 잔에 수백 작업' 수준.

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

읽기만 하지 말고 손에 익히는 단계. 난이도순.

실습 1

설치 없이 띄워 보고 비용 대시보드 보기 난이도 ★☆☆ 입문

npx dao-code로 실행 → DeepSeek 키를 붙여 넣고 아무 질문. 그다음 /cost로 토큰·캐시 적중률을, /help로 명령 목록을 관찰한다. "캐시 적중률이 대화가 길어질수록 오르는가"를 눈으로 확인하는 게 목표.

실습 2

프로젝트 규약 파일 만들기 난이도 ★★☆ 중급

아무 작은 저장소에서 /init을 실행해 DAO.md(프로젝트 개요·컨벤션)를 자동 생성해 본다. 이 파일이 다음 세션부터 자동 로드되는 걸 확인하고, 한 줄 규칙을 손으로 추가해 동작이 바뀌는지 본다.

실습 3

권한 규칙 직접 짜 보기 난이도 ★★☆ 중급

.dao/settings.jsonBash(npm run test:*)는 allow, Edit(//etc/**)는 deny로 넣어 본다. 그다음 에이전트에게 테스트 실행과 시스템 파일 수정을 각각 시켜, 하나는 자동 통과·하나는 차단되는지 확인. 복합 명령도 시험해 보자.

실습 4

나만의 서브에이전트 만들어 병렬 실행 난이도 ★★★ 고급

.dao/agents/<name>.md에 이름·설명·허용 도구·모델을 frontmatter로 적고 본문에 역할 프롬프트를 쓴다. 그런 뒤 tasks[]로 여러 개를 병렬 실행하거나 background:true로 뒤에서 돌려, 완료 알림이 <task-notification>으로 되돌아오는 흐름을 관찰한다.

실습 5

SWE-bench식 평가 한 번 돌리기 난이도 ★★★ 고급

EVAL_RUNS=1 node evals/run.mjs로 스모크 테스트를 돌려, 실제 오픈소스 버그가 fail→pass로 뒤집히는지 본다. 테스트 파일을 에이전트에게 숨겼다가 나중에 주입하는 reward-hacking 방지 설계가 왜 필요한지 체감하는 게 핵심.

9관련 기술 심화 학습 로드맵

한 주씩, 이 레포를 '해부 교보재'로 삼아 따라가는 계획.

주차주제학습 자료 / 볼 곳
1주차코딩 에이전트 큰 그림 + 로컬 실행README 정독 · dao 실행 · /help·/cost 관찰
2주차에이전트 루프의 뼈대src/agent/loop.ts · "도구 요청→승인→되먹임" 흐름 추적
3주차프롬프트 캐시 경제학DeepSeek 캐시 요금 문서 · byte-stable prefix 개념 · /audit cache
4주차도구·권한 시스템src/tools/ · src/permissions/ · Zod→JSON Schema 패턴
5주차기억 · 반성 레이어src/memory/ · challenger/refocuser 설계 읽기
6주차확장(스킬·MCP·훅) + 내 앱에 이식MCP SDK 문서 · Claude Code 호환 포맷 비교

10핵심 키워드 사전

본문에 나온 용어 빠른 참조.

용어의미
prefix cache모델에 보낸 앞부분(프리픽스)의 계산 결과를 서버가 저장해 재사용 → 그 부분 요금이 급감. dao-code 비용 마법의 근원.
byte-stable prefix그 앞부분을 한 바이트도 바꾸지 않고 유지하는 규율. 조금만 달라져도 캐시가 '실패' 처리돼 요금이 튄다.
cache-reusing fork메인 대화의 캐시된 프리픽스를 그대로 물려받은 '분신'. 반성·기억을 여기서 돌려 추가 비용 ≈ 0.
agent loop"모델에 질문 → 도구 요청 실행 → 결과 되먹임 → 반복"의 핵심 순환. src/agent/loop.ts.
approval gate쓰기·실행 같은 위험 동작을 실제 수행 전에 사람 승인으로 거르는 관문.
permission mode승인 강도 설정: default(그때그때) / acceptEdits(수정 자동) / auto(AI가 안전분류) / plan(읽기전용) / YOLO(전부 자동, deny만 예외).
Ink / TUIReact로 터미널 화면을 그리는 라이브러리 / 그렇게 만든 글자 기반 UI.
MCPModel Context Protocol. 에이전트에 외부 도구·데이터를 표준 방식으로 붙이는 규약.
Zod데이터 모양을 코드로 검증하는 TS 라이브러리. 도구 규격의 단일 출처.
shadow git사용자 .git과 분리된 별도 스냅샷 저장소. 되돌리기(/restore)의 안전벨트.
compaction1M 문맥 한계 근처에서 오래된 대화를 요약으로 압축해 자리를 비우는 것.
reflection layer막힘/드리프트 자가 교정. challenger(전제 의심) · refocuser(목표 재확인) · reply-challenger(같은 문제 재질문 감지).
DoD (Definition of Done)"완료의 정의". /dod로 설정한 명령이 성공(exit 0)해야만 작업을 끝난 것으로 인정.
fail2pass / pass2pass평가 이중 검증: 수정 후 대상 테스트가 실패→통과로 뒤집히고(fail2pass), 기존 기능 테스트는 여전히 통과(pass2pass).
steering모델이 답하는 도중에 사용자가 미리 타이핑해 두면 큐에 쌓였다가 현재 턴이 끝나면 자동 처리되는 기능.
DeepSeek V4 (pro / flash)기반 모델. pro는 주력 추론, flash는 값싼 보조(기억 distill 등)에 쓰는 경량판.

11참고 링크