openwiki/ 폴더에 문서(위키)를 써 주는 도구다.
한 번 만들고 끝이 아니라, GitHub Action이 매일 코드 변경분을 감지해 문서 업데이트 PR을 자동으로 열어 "문서가 코드보다 항상 낡는" 고질병을 정면으로 겨냥한다.
핵심 엔진은 LangChain의 DeepAgents + LangGraph이고, 모델은 OpenRouter·OpenAI·Anthropic·Baseten·Fireworks 중 골라 쓴다(BYO-Key).
(저장소: langchain-ai/openwiki · TypeScript/Node · MIT · v0.0.1 · TrendShift 오늘 1위, 모멘텀 1079)
이 저장소가 대체 무엇인가.
OpenWiki의 정체는 새 LLM도, 새 프레임워크도 아니다. LangChain의 deepagents 라이브러리로 만든 "문서 작성 전용 에이전트"를, ink(터미널 UI)로 감싼 명령줄 프로그램이다. openwiki --init을 실행하면 이 에이전트가 저장소를 스스로 훑어 openwiki/quickstart.md를 필두로 한 문서 세트를 만들고, openwiki --update는 그 이후 바뀐 코드만 골라 문서를 "외과 수술하듯" 최소한만 고친다.
비유하면: 회사에 갓 들어온 성실한 개발자가 레포를 처음부터 끝까지 읽고 위키를 정리해 두고, 이후 매일 아침 git 커밋 로그를 확인해 "어제 바뀐 부분"만 문서에 반영하는 것과 같다. 다른 점은, 이 신입이 사람이 아니라 GLM·Claude·GPT 같은 모델이고, 하루 몇 센트로 24시간 일한다는 것뿐이다.
README의 자기소개는 딱 한 줄이다: "OpenWiki is a CLI that writes and maintains documentation for your codebase, built specifically for agents." — 여기서 놓치면 안 되는 표현이 "built specifically for agents(에이전트를 위해 특별히 설계된)"이다. 이 문서는 사람만 읽으라고 만드는 게 아니라, 다음에 이 저장소에서 작업할 또 다른 코딩 에이전트(Claude Code, Cursor 등)가 소스를 덜 뒤지고도 정확한 수정을 하도록 만드는 "에이전트용 지도"이기도 하다.
그래서 OpenWiki는 문서를 다 쓰고 나면 저장소 최상위의 AGENTS.md / CLAUDE.md 파일에 "이 레포엔 /openwiki 문서가 있으니 먼저 읽어라"는 안내 문단을 자동으로 심는다. 파일이 없으면 만들어 준다. 즉 "에이전트가 쓴 문서를, 다음 에이전트가 자동으로 찾아 읽게" 하는 순환 고리를 설계에 못 박아 둔 것이 이 프로젝트의 정체성이다.
openwiki/ 폴더에 마크다운(.md) 파일로 쌓이는 서로 링크된 문서 묶음을 뜻한다. quickstart.md(입구) → architecture/·workflows/·domain/ 같은 섹션 페이지로 뻗어 나간다. "에이전트 문서"는 사람의 가독성뿐 아니라, LLM이 컨텍스트로 삼아 코드 수정 품질을 높이도록 구조·링크·근거(source reference)를 갖춘 문서를 말한다."문서는 항상 낡는다"는 오래된 통증 + LangChain이라는 신뢰 + 로컬·오픈소스라는 차별점.
2026년 코딩 에이전트 시대의 역설은 코드는 그 어느 때보다 빨리 바뀌는데, 문서는 그만큼 빨리 낡는다는 것이다. 사람이 문서를 갱신하려면 시간과 규율이 필요하고, 대부분의 팀은 그걸 지키지 못한다. OpenWiki는 이 문제를 "문서 작성·유지보수 자체를 에이전트에게 위임한다"는 정공법으로 푼다. 이것이 폭발적 트렌딩의 1차 동력이다.
| 비교 축 | DeepWiki 등 SaaS형 문서 생성 | 수작업 위키 / README | OpenWiki |
|---|---|---|---|
| 실행 위치 | 외부 클라우드 서비스 | 사람이 직접 | 내 머신·내 CI에서 로컬 실행 (코드가 밖으로 안 나감) |
| 모델 선택 | 공급자 고정 | 해당 없음 | OpenRouter/OpenAI/Anthropic/Baseten/Fireworks, 내 API 키(BYO) |
| 유지보수 | 재생성 필요 | 수동, 자주 방치됨 | --update + GitHub Action으로 매일 자동 PR |
| 대상 독자 | 사람 위주 | 사람 | 사람 + 다음 코딩 에이전트 (AGENTS.md 연동) |
| 비용 통제 | 구독료 | 인건비 | GLM 5.2 같은 저가 모델로 하루 몇 센트 가능 |
둘째 동력은 출신이다. 이 저장소의 owner는 langchain-ai — LangChain·LangGraph·LangSmith를 만든 팀이다. 즉 OpenWiki는 자사의 에이전트 스택(deepagents, langgraph, langsmith 추적)을 "우리 도구로 실제 쓸 만한 걸 만들 수 있다"고 보여주는 레퍼런스 구현이기도 하다. 그래서 코드 품질과 에이전트 설계 규율(뒤에서 볼 프롬프트의 "discipline" 섹션들)이 데모 수준을 훨씬 넘는다.
셋째, "에이전트를 위한 문서"라는 프레이밍이 시의적절하다. Cursor·Claude Code가 AGENTS.md·CLAUDE.md를 표준처럼 읽기 시작한 상황에서, OpenWiki는 그 파일에 위키 안내를 자동 주입해 "에이전트 → 문서 → 다음 에이전트"로 이어지는 흐름의 빠진 고리를 채운다.
package.json의 버전은 0.0.1이다. 문서 품질은 결국 선택한 모델의 실력과 저장소 크기에 좌우되고, LLM이 근거 없이 지어내는(hallucination) 위험은 프롬프트의 "Do not invent files/APIs/behavior" 규율로 억제하려 하지만 완전히 사라지진 않는다. 자동 생성 문서는 사람의 리뷰를 거친 PR로 병합하는 전제로 쓰는 게 안전하다(그래서 Action도 직접 push가 아니라 PR을 연다).
package.json · tsconfig.json · src/를 직접 뜯어 확인한 구성.
| 항목 | 선택 | 설명 |
|---|---|---|
| 언어 | TypeScript 5.7 | type: module (순수 ESM). tsc로 dist/에 컴파일, bin.openwiki → ./dist/cli.js |
| 런타임 | Node ≥ 20 | engines에 명시. 개발은 tsx로 src/cli.tsx 직접 실행(pnpm dev) |
| 패키지 매니저 | pnpm 10 | packageManager 고정. better-sqlite3·esbuild만 빌드 허용(onlyBuiltDependencies) |
| 배포 형태 | npm 전역 CLI | npm install -g openwiki → openwiki 명령 등록. files엔 dist만 포함 |
| 품질 도구 | ESLint 10 · Prettier 3 | typescript-eslint 포함. lint/format 스크립트 제공 |
| 패키지 | 역할 |
|---|---|
deepagents ^1.10 | 이 프로젝트의 심장. createDeepAgent()로 파일시스템 도구(ls/read/write/edit/glob/grep)·셸·서브에이전트(task)를 갖춘 에이전트를 생성 |
langchain / @langchain/core ^1 | 메시지·툴·스트리밍 등 에이전트 기반 추상화 (LangChain v1 라인) |
@langchain/langgraph-checkpoint-sqlite | SqliteSaver — 대화(스레드) 상태를 ~/.openwiki/openwiki.sqlite에 체크포인트로 저장해, 세션을 이어서 진행 가능하게 함 |
@langchain/openrouter · @langchain/openai · @langchain/anthropic | 모델 공급자 어댑터. OpenRouter는 fallback 라우팅까지 지원 |
| 패키지 | 역할 |
|---|---|
ink ^5 + react ^18 | 터미널을 React 컴포넌트로 그리는 라이브러리. src/cli.tsx(무려 79KB)가 인터랙티브 채팅 UI·스트리밍 출력·툴 호출 표시를 담당 |
marked ^18 | 마크다운을 터미널에 보기 좋게 렌더링(에이전트가 뱉는 응답의 서식 처리) |
deepagents = 두뇌·손발(코드를 읽고 파일을 쓰는 에이전트), langgraph SqliteSaver = 기억(중단해도 이어서), ink/react = 얼굴(터미널 화면), 공급자 어댑터 = 입(어떤 LLM으로 말할지). OpenWiki는 이 네 조각을 --init/--update라는 목적에 맞게 프롬프트로 조립한 것이다.
openwiki/에 문서를 쓰는" 전용 에이전트로 특수화했다. 즉 tools: []로 빈 도구를 넘겨도, DeepAgents가 제공하는 파일·셸 도구가 기본 탑재된다.src/agent/index.ts의 runOpenWikiAgent()를 따라가며 본 실제 실행 흐름.
에이전트에게 파일 쓰기 권한을 주는 건 위험하다. OpenWiki는 LocalShellBackend를 virtualMode: true, rootDir: cwd로 설정해, 에이전트가 보는 /가 실제로는 저장소 폴더가 되도록 못 박는다. 시스템 프롬프트도 반복해서 "호스트 절대경로(/Users/...)를 쓰지 말고 가상경로(/README.md)를 써라", "부모 디렉토리나 다른 저장소를 뒤지지 마라"고 지시한다. 출력은 maxOutputBytes: 100_000, 명령은 timeout: 120초로 제한한다.
각 실행은 createThreadId()로 저장소 경로를 SHA-256 해시한 값 + 랜덤 run id를 스레드 ID로 삼는다. 대화 상태는 SqliteSaver가 ~/.openwiki/openwiki.sqlite에 저장하므로, 인터랙티브 모드에서 후속 메시지를 보내면 이전 맥락을 이어서 처리한다. 민감 파일은 chmod 0600/0700으로 권한을 조인다.
기본 공급자 OpenRouter에서는 route: "fallback"과 함께 [선택 모델, gpt-5.4-mini, claude-sonnet-5] 순의 모델 배열을 넘긴다. 한 모델이 5xx(서버 오류)를 내면 shouldRetryOpenRouterServerError()가 다음 모델로 재시도한다. 게다가 globalThis.fetch를 감싸는 디버그 후킹을 심어 실패한 OpenRouter 요청의 상태·본문 미리보기를 캡처하되, 정규식으로 api-key·token·password 같은 값은 [REDACTED]로 가린다. 데모라기엔 상당히 방어적인 엔지니어링이다.
agent.stream(..., { streamMode: ["messages","tools"], subgraphs: true })로 받은 청크는 모델·공급자마다 모양이 제각각이다. index.ts의 절반 이상이 parseStreamEvent·extractMessageText·parseToolStreamEvent 같은 "어떤 형태의 스트림 청크든 텍스트/툴 이벤트로 뽑아내는" 정규화 코드다. 서브그래프(서브에이전트)에서 온 출력인지도 구분(isSubgraphStreamChunk)해 UI에 다르게 표시한다.
messages는 모델이 생성 중인 텍스트를, tools는 도구 호출 시작/종료 이벤트를 실시간으로 준다. subgraphs:true는 서브에이전트 내부 이벤트까지 함께 스트리밍한다.루트와 src/의 주요 파일이 각각 무슨 일을 하는가.
구조의 핵심은 "관심사 분리가 명확하다"는 점이다. UI(cli.tsx, credentials.tsx), 에이전트 실행(agent/index.ts), 에이전트의 행동 규범(agent/prompt.ts), 설정·상수(constants.ts, env.ts)가 파일 단위로 갈라져 있다. 특히 프로젝트의 "지능"은 코드가 아니라 prompt.ts에 텍스트로 들어 있다 — 여기가 진짜 읽을 가치가 있는 파일이다.
① README.md로 사용법 감 잡기 → ② src/agent/prompt.ts로 "에이전트에게 무엇을·어떻게 시키는가"의 프롬프트 엔지니어링 읽기 → ③ src/agent/index.ts의 runOpenWikiAgent로 DeepAgents·체크포인터·스트리밍 조립 보기 → ④ examples/openwiki-update.yml로 자동화 얼개 확인. 이 넷만 읽어도 프로젝트의 90%를 이해한다.
이 레포에서 실제로 배워 갈 수 있는 것들.
prompt.ts는 에이전트 프롬프트 설계의 교과서다. 단순히 "문서 만들어"가 아니라, Run/Subagent/Planning/Git/Security 등 영역별 "discipline(규율)"로 나눠 지시한다. 예: "glob **/*를 루트에서 부르지 마라(비용 폭발)", "서브에이전트는 읽기·요약만, 파일 쓰기 금지", "완료 전 임시 _plan.md를 지워라", ".env·비밀값은 읽지도 문서화하지도 마라". 이렇게 "하지 말 것"을 구체적으로 못 박는 것이 실전 에이전트 신뢰성의 핵심이라는 걸 이 파일 하나로 배울 수 있다.
여러분의 취미 프로젝트에 OpenWiki를 돌려 보고, 생성된 openwiki/quickstart.md가 실제 코드와 어긋난 부분(hallucination)을 찾아 목록화해 보라. 그 오차가 프롬프트의 어느 규율이 부족해서 생겼는지 역추적하면 프롬프트 감각이 는다.
createDeepAgent({ model, tools, checkpointer, backend, systemPrompt }) 한 번의 호출로 파일·셸·서브에이전트를 갖춘 에이전트가 생긴다는 것, 그리고 agent.stream()으로 진행 상황을 실시간 스트리밍한다는 것이 핵심 배움이다. 도구를 직접 짜지 않고도(tools:[]) 백엔드가 파일 도구를 제공하는 구조는 새 에이전트를 빠르게 프로토타이핑할 때 매우 유용하다.
deepagents로 "폴더 안 README들을 읽고 한 줄 요약 목록을 만드는" 미니 에이전트를 만들어 보라. 모델은 OpenRouter의 무료 티어 모델로.
cli.tsx는 React 컴포넌트로 터미널 UI를 그리는 ink의 대형 실전 예제다. 스트리밍 텍스트, 툴 호출 상태 표시, 온보딩 폼(credentials.tsx)까지 — "CLI도 컴포넌트로 만들 수 있다"는 감각을 배울 수 있다.
examples/openwiki-update.yml은 cron 스케줄 → npm 전역 설치 → openwiki --update --print → peter-evans/create-pull-request로 PR 생성이라는 표준 "매일 자동 작업 + PR" 패턴을 그대로 보여준다. 문서뿐 아니라 의존성 업데이트·리포트 생성 등 온갖 자동화에 재활용 가능한 뼈대다.
~/.openwiki/.env에 저장한다. 덕분에 비용·모델을 사용자가 통제하고, 코드가 특정 벤더에 묶이지 않는다.무엇이 있어야 돌릴 수 있는가.
| 구분 | 요구사항 |
|---|---|
| Node.js | 버전 20 이상 (engines.node >=20) |
| 설치 | npm install -g openwiki (또는 소스 클론 후 pnpm install → pnpm build) |
| API 키 | OpenRouter / OpenAI / Anthropic / Baseten / Fireworks 중 하나의 키 (필수). 없으면 실행 시 오류 |
| 디스크 | 거의 무관 — 생성물은 텍스트 .md. 상태 DB(~/.openwiki/openwiki.sqlite)도 소형 |
| 선택 | LangSmith 키(실행 추적, 프로젝트명 "openwiki"), Git(변경 감지·--update 품질에 크게 기여) |
| CI | 매일 자동 PR을 쓰려면 GitHub Actions + 레포 시크릿(예: OPENROUTER_API_KEY)과 contents: write 권한 |
하드웨어 부담은 거의 없다. 진짜 비용은 "토큰"이다. 저장소가 클수록 에이전트가 읽는 파일이 많아져 API 호출 비용이 오른다. 그래서 프롬프트가 "모든 파일을 다 읽지 마라, 엔트리포인트·설정·대표 파일만 표적 탐색하라"고 강하게 제한하고, 저가 모델(GLM 5.2 등)을 기본 후보로 둔다.
난이도별로. 위에서 아래로 갈수록 어렵다.
OpenRouter 무료/저가 키를 발급받고, 파일 10개 이하의 작은 프로젝트에서 openwiki --init을 실행하라. 생성된 openwiki/quickstart.md를 열어, 프롬프트가 요구한 "입구 + 최소 섹션" 구조가 실제로 지켜졌는지 확인한다.
--update 돌려 보기소스 파일 하나를 의미 있게 수정·커밋한 뒤 openwiki --update를 실행하라. 프롬프트의 "surgical / diff budget(변경 파일이 5개 미만이면 위키 1~2쪽만 손봐라)" 규율대로, 정말 관련된 페이지만 바뀌는지 git diff openwiki/로 검증한다.
examples/openwiki-update.yml을 .github/workflows/에 복사하고 레포 시크릿에 API 키를 넣어라. workflow_dispatch로 수동 트리거해 첫 문서 업데이트 PR이 열리는지 확인한다.
src/agent/index.ts의 parseStreamEvent → normalizeStreamEvent → extractMessageText 경로를 따라가며, "왜 이렇게까지 다양한 청크 모양을 방어적으로 처리하는가"를 정리하라. 공급자마다 스트림 포맷이 다르다는 현실을 체감할 수 있다.
createDeepAgent + LocalShellBackend(virtualMode)로, 특정 폴더를 읽어 SUMMARY.md 한 장을 쓰는 최소 에이전트를 구현하라. OpenWiki의 시스템 프롬프트를 축약해 재사용해 보면 "규율의 유무"가 결과 품질을 어떻게 바꾸는지 비교할 수 있다.
이 레포를 완전히 소화하기 위한 4주 코스.
| 주차 | 주제 | 할 일 |
|---|---|---|
| 1주차 | TypeScript ESM + Node CLI | type:module 프로젝트 구조, bin 등록, tsx로 개발 실행. 간단한 인터랙티브 CLI 하나 만들기 |
| 2주차 | LangChain v1 + LLM 어댑터 | ChatOpenAI/ChatAnthropic로 메시지 주고받기, 스트리밍 받기, 공급자 교체 추상화 이해 |
| 3주차 | DeepAgents + LangGraph | createDeepAgent, 파일/셸 백엔드, 체크포인터(SqliteSaver), stream 모드, 서브에이전트(task) 위임 |
| 4주차 | ink/React + CI 자동화 | ink로 터미널 UI, GitHub Actions cron + create-pull-request로 "자동 유지보수 봇" 패턴 완성 |
이 순서의 논리는 "바깥 껍질(CLI) → 말하는 법(LLM) → 일하는 법(에이전트) → 자동화(CI)"다. OpenWiki가 바로 이 네 층을 쌓아 만든 결과물이므로, 4주 뒤에는 이 저장소의 모든 파일을 근거를 대며 설명할 수 있게 된다.
본문에 나온 용어를 한 곳에.
| 용어 | 뜻 |
|---|---|
| OpenWiki | 에이전트가 코드베이스를 읽어 openwiki/ 폴더에 문서를 생성·유지보수하는 CLI. LangChain 팀 제작, MIT. |
| DeepAgents | LangChain의 장기·다단계 작업용 에이전트 라이브러리. 파일·셸·서브에이전트 도구를 기본 제공. |
| LangGraph | 에이전트/워크플로를 그래프로 실행·스트리밍하는 런타임. 체크포인터로 상태 저장. |
| Checkpointer (SqliteSaver) | 대화 상태를 SQLite에 저장해 중단·재개를 가능하게 하는 장치. 여기선 ~/.openwiki/openwiki.sqlite. |
| LocalShellBackend | 에이전트의 파일·셸 작업을 실제 디스크에 연결하는 백엔드. virtualMode로 저장소 폴더를 가상 루트 /로 격리. |
| Virtual Root (가상 루트) | 에이전트가 보는 /를 저장소 폴더로 고정해, 시스템의 다른 경로 접근을 막는 샌드박스 기법. |
| Fallback Routing | OpenRouter에서 여러 모델을 순서대로 두고, 앞 모델이 실패(5xx)하면 다음 모델로 자동 전환하는 라우팅. |
| Stream Mode | 실행 중간 산출을 어떤 형태로 흘려줄지 정하는 옵션. messages=생성 텍스트, tools=도구 이벤트. |
| AGENTS.md / CLAUDE.md | 코딩 에이전트가 저장소 규칙·안내를 읽는 표준 파일. OpenWiki가 위키 안내 문단을 자동 주입. |
| ink | React 컴포넌트로 터미널 UI를 그리는 라이브러리. cli.tsx가 이걸로 채팅 화면을 렌더링. |
| Surgical Update | 변경된 소스에 직접 연관된 문서 페이지만 최소 수정하는 업데이트 규율(diff budget). |
| BYO Key | 사용자가 자기 API 키·모델을 넣어 쓰는 방식. 벤더 종속 없이 비용을 통제. |