@m16khb/llm-wiki
v0.1.3
Published
npx wrapper for the llm-wiki Go MCP server and CLI
Readme
llm-wiki
llm-wiki는 Claude Code와 Codex가 같은 Obsidian-backed LLM Wiki vault를 안전하게 공유하도록 하는 Go 기반 MCP 서버/CLI다.
현재 기본 구조는 단일 long-running daemon process + streamable HTTP MCP + SQLite WAL queue + in-memory metadata cache다. Claude Code/Codex는 기본적으로 mcp-autostart stdio shim을 실행하고, shim은 daemon이 없으면 자동으로 띄운 뒤 실제 tool call을 같은 daemon의 HTTP MCP endpoint로 proxy한다. 즉 client마다 짧은 shim process는 생길 수 있지만, vault/DB를 소유하고 write를 직렬화하는 프로세스는 하나의 llm-wiki serve daemon이다.
핵심 원칙
- Single writer:
llm-wiki servedaemon 하나가 write를 직렬화한다. - Lazy start:
llm-wiki mcp-autostart가 MCP client 시작 시 daemon health를 확인하고 없으면 자동 기동한다. - Auto init:
llm-wiki init또는mcp-autostart --init-vault가 누락된 vault 폴더 구조를 non-destructive하게 만든다. - SQLite WAL queue: write job은 durable queue/audit DB에 먼저 기록된다.
- Local-first: Markdown vault가 canonical source다. SQLite는 queue/index/cache/audit state이며 rebuild 가능해야 한다.
- Read-safe:
.obsidian/, hidden/runtime directory, path traversal은 차단한다. - Write-minimal: 기본 write는
wiki_capture의 additive Markdown 생성뿐이다. - Destructive maintenance:
llm-wiki cleanup은 기본 dry-run이며--apply가 있을 때만 archive/rename/rewrite를 수행한다. - Source 보호:
10-sources/body 수정/삭제 도구는 제공하지 않는다.
빠른 시작
# repo root
./scripts/install-local.sh
# read-only CLI smoke
./bin/llm-wiki init --vault ~/workspace/knowledge-base/llm-wiki --json
./bin/llm-wiki info --vault ~/workspace/knowledge-base/llm-wiki --json
./bin/llm-wiki search --vault ~/workspace/knowledge-base/llm-wiki --limit 5 karpathy
./bin/llm-wiki lint --vault ~/workspace/knowledge-base/llm-wiki --jsonMCP client에서는 아래 설정 파일을 복사/병합하면 된다. daemon을 미리 켤 필요는 없다.
- Claude Code:
config/claude-code.mcp.json을 target project의.mcp.json에 복사 - Codex:
config/codex.config.toml내용을~/.codex/config.toml에 병합
수동 운영이나 launchd/systemd가 daemon을 관리하는 환경에서는 직접 daemon을 띄우고 HTTP config를 써도 된다.
./bin/llm-wiki serve --vault ~/workspace/knowledge-base/llm-wiki
curl http://127.0.0.1:39233/healthz
./bin/llm-wiki jobs --limit 20--vault를 생략하면 LLM_WIKI_ROOT, LLM_WIKI_VAULT, ~/workspace/knowledge-base/llm-wiki, ~/Workspace/knowledge-base/llm-wiki 순서로 찾는다.
--db를 생략하면 LLM_WIKI_DB 또는 OS user config directory 아래 llm-wiki/llm-wiki.db를 사용한다.
CLI commands
| Command | Purpose |
|---|---|
| llm-wiki init | 누락된 vault root와 표준 폴더 구조 생성 |
| llm-wiki serve | singleton daemon + streamable HTTP MCP endpoint 시작 |
| llm-wiki mcp-autostart | stdio MCP shim; daemon을 자동 기동/재사용하고 HTTP MCP로 proxy |
| llm-wiki mcp | legacy direct stdio MCP server; daemon 공유가 필요 없는 compatibility path |
| llm-wiki info | vault root/count 요약 |
| llm-wiki search QUERY | Markdown lexical search |
| llm-wiki read PAGE_OR_PATH | slug 또는 vault-relative path로 page 읽기 |
| llm-wiki lint | frontmatter/wikilink/slug 구조 점검 |
| llm-wiki capture | SQLite queue를 통해 allowed folder에 curated note 생성 |
| llm-wiki cleanup | dry-run 기본의 apply-gated vault cleanup; repository-references, duplicate-slugs, LLM-reviewed analyze/apply-plan 지원 |
| llm-wiki session-context | hook/수동 사용을 위한 project-aware wiki context 검색 |
| llm-wiki session-capture | 세션 중 선별한 내용을 30-sessions/에 capture |
| llm-wiki hook | Claude Code/Codex 공용 lifecycle hook entrypoint |
| llm-wiki jobs | SQLite queue 최근 job audit 출력 |
표준 vault 구조는 00-meta/, 00-meta/reports/, 10-sources/, 20-wiki/concepts/, 20-wiki/entities/, 20-wiki/summaries/, 30-sessions/이다. init은 .obsidian/을 만들거나 수정하지 않고 기존 파일을 rewrite하지 않는다.
MCP tools
| Tool | Type | Purpose |
|---|---|---|
| wiki_info | read-only | vault count/root 확인 |
| wiki_search | read-only | keyword search |
| wiki_read | read-only | page content 읽기 |
| wiki_lint | read-only | structural lint |
| wiki_capture | queued additive write | 20-wiki/, 30-sessions/, 00-meta/reports/ 하위에 note 생성 |
Vault cleanup
llm-wiki cleanup은 ai-slop-cleaner식으로 과도하게 파편화된 wiki 내용을 정리하는 CLI-only maintenance command다. MCP tool로 노출하지 않는 이유는 archive/rename/bulk wikilink rewrite가 destructive operation이라서, local shell에서 dry-run 결과를 본 뒤 명시적으로 --apply를 붙이는 흐름이 더 안전하기 때문이다.
현재 지원 scope는 repository-references와 duplicate-slugs다.
# 계획만 출력하고 파일은 변경하지 않음
llm-wiki cleanup --vault ~/workspace/knowledge-base/llm-wiki --json
# repo별 dated fragment를 bundle page로 합치고 원본은 _archive/로 rename
llm-wiki cleanup --vault ~/workspace/knowledge-base/llm-wiki --scope repository-references --apply --json
# duplicate slug warning을 없애기 위해 non-canonical page를 unique slug로 rename
llm-wiki cleanup --vault ~/workspace/knowledge-base/llm-wiki --scope duplicate-slugs --apply --jsonLLM이 “진짜 cleanup 대상인지 / 어떤 전략이 안전한지” 먼저 판단하게 하려면 analyze → plan JSON → apply-plan 흐름을 사용한다. CLI 자체는 외부 LLM을 호출하지 않고, candidate packet과 deterministic plan executor만 제공한다. Codex/Claude 같은 agent가 analysis를 읽고 allowlisted JSON plan을 작성한 뒤, CLI가 다시 dry-run 검증과 --apply gate를 담당한다.
# LLM/agent가 검토할 candidate packet 생성; 파일 변경 없음
llm-wiki cleanup analyze --vault ~/workspace/knowledge-base/llm-wiki --scope repository-references --json
llm-wiki cleanup analyze --vault ~/workspace/knowledge-base/llm-wiki --scope duplicate-slugs --json
# agent가 작성한 JSON plan을 먼저 검증만 수행
llm-wiki cleanup apply-plan --vault ~/workspace/knowledge-base/llm-wiki --plan /tmp/cleanup-plan.json --json
# 검증 결과가 의도와 맞을 때만 적용
llm-wiki cleanup apply-plan --vault ~/workspace/knowledge-base/llm-wiki --plan /tmp/cleanup-plan.json --apply --jsonPlan schema는 versioned JSON이고 현재 allowlisted action은 run_scope와 rename_page뿐이다. run_scope는 기존 guarded cleanup을 통째로 실행하므로 plan 안에서 단독 action이어야 한다.
{
"version": 1,
"scope": "repository-references",
"summary": "LLM-reviewed reason for why these candidates are true cleanup targets.",
"actions": [
{
"type": "run_scope",
"scope": "repository-references",
"reason": "Consolidate dated fragments through the guarded deterministic cleanup scope."
}
]
}Repo-local skill 표면도 제공한다. MCP 설정만으로 skill이 자동 배포되지는 않는다. MCP는 tool 호출 표면이고, skill은 Claude Code/Codex client가 별도로 로드하는 prompt package다. 이 repo에는 같은 workflow를 Codex와 Claude Code 양쪽 skill 폴더에 둔다.
| Skill | Purpose |
|---|---|
| llm-wiki-query | info/search/read/lint/session-context read-only lookup |
| llm-wiki-capture | wiki_capture, capture, session-capture curated additive write |
| llm-wiki-cleanup | LLM-reviewed cleanup analyze → apply-plan workflow |
| llm-wiki-mcp-ops | daemon, mcp-autostart, jobs, npx/MCP smoke |
| llm-wiki-hooks | SessionStart, UserPromptSubmit, Stop hook validation |
Locations:
- Codex/OMX:
.codex/skills/<skill>/SKILL.md($llm-wiki-query,$llm-wiki-capture, ...) - Claude Code:
.claude/skills/<skill>/SKILL.md(client skill picker/skill trigger)
repository-references 적용 시 동작:
20-wiki/concepts/repository-references/<repo>/아래 dated fragment들을<repo>-reference-bundle-YYYY-MM-DD.md로 통합한다.- 원본 fragment는
_archive/repository-reference-fragments-YYYY-MM-DD/<repo>/archived-*.md로 이동해 duplicate slug를 피한다. - active wiki page의 wikilink는 bundle slug로 rewrite한다.
00-meta/index.md,00-meta/log.md,00-meta/reports/repository-reference-cleanup-YYYY-MM-DD*.md를 갱신한다..obsidian/과10-sources/body는 수정하지 않는다.
duplicate-slugs 적용 시 동작:
- 같은 filename slug를 가진 page들 중 canonical page를 하나 고른다.
10-sources/는 보호 대상,00-meta/canonical entry는 root compatibility page보다 우선한다. - non-canonical page를 같은 폴더의 unique slug로 rename한다. 예: root
index.md→root-compatibility-index.md. - renamed page에는 canonical page wikilink와 이전 path notice를 추가한다.
00-meta/log.md와00-meta/reports/duplicate-slug-cleanup-YYYY-MM-DD*.md를 갱신한다..obsidian/과10-sources/body는 수정하지 않는다.
Lazy daemon MCP 설정
권장 설정은 stdio command로 llm-wiki mcp-autostart를 실행하는 방식이다.
MCP client ── stdio ── llm-wiki mcp-autostart shim
│ health/start/proxy
▼
llm-wiki serve daemon ── /mcp ── shared service/queue/vault동시에 여러 client가 시작되어도 같은 --db path의 daemon lock이 중복 daemon을 막는다. 이미 다른 vault/DB를 가진 daemon이 같은 address를 점유 중이면 shim은 proxy하지 않고 에러를 낸다.
Claude Code
config/claude-code.mcp.json을 target project의 .mcp.json에 복사한다.
{
"mcpServers": {
"llm-wiki": {
"command": "npx",
"args": [
"-y",
"--prefix",
"/tmp",
"--package",
"/Users/m16khb/Workspace/llm-wiki",
"--",
"llm-wiki",
"mcp-autostart",
"--init-vault",
"--vault",
"/Users/m16khb/Workspace/knowledge-base/llm-wiki",
"--addr",
"127.0.0.1:39233"
]
}
}
}npm registry package를 쓸 때는 --package 값을 @m16khb/llm-wiki로 바꾼다. config/claude-code.npx.mcp.json은 registry package 예시, config/claude-code.npx-local.mcp.json은 local repo 예시다.
Claude Code는 local stdio뿐 아니라 HTTP MCP server 설정도 지원한다. 공식 문서는 claude mcp add와 .mcp.json scope를 설명한다: https://code.claude.com/docs/en/mcp
Codex
config/codex.config.toml 내용을 ~/.codex/config.toml에 병합한다.
[mcp_servers.llm-wiki]
command = "npx"
args = [
"-y",
"--prefix", "/tmp",
"--package", "/Users/m16khb/Workspace/llm-wiki",
"--",
"llm-wiki",
"mcp-autostart",
"--init-vault",
"--vault", "/Users/m16khb/Workspace/knowledge-base/llm-wiki",
"--addr", "127.0.0.1:39233",
]
startup_timeout_sec = 60
tool_timeout_sec = 60Codex config는 MCP stdio server에 mcp_servers.<id>.command / args를 쓰고, streamable HTTP server에는 mcp_servers.<id>.url을 쓴다: https://developers.openai.com/codex/config-reference
Claude Code / Codex 공용 session hooks
두 client의 hook 설정 문법은 다르지만, llm-wiki는 같은 command를 실행하게 만든다.
SessionStart -> llm-wiki hook -> project/tech terms로 wiki_search 후 additionalContext 주입
UserPromptSubmit -> llm-wiki hook -> prompt keyword + project/tech terms로 wiki_search 후 relevant context 주입
Stop -> llm-wiki hook -> assistant가 명시한 llm-wiki-capture block만 30-sessions/에 저장SessionStart/UserPromptSubmit hook은 suppressOutput: true로 transcript 출력을 숨긴다. 실제 context는
hookSpecificOutput.additionalContext로 주입되지만, Codex/Claude transcript에 긴 hook context: 문자열이 빽빽하게
보이지 않게 하기 위한 UX 안전장치다.
go.mod가 있으면 Go/Golang을 감지하고, MCP SDK·SQLite·Gin·GORM·Redis 같은 dependency 신호, package.json/bin 기반 Node/npm/npx wrapper 신호, swaggo dependency나 swagger.yaml/openapi.yaml 같은 API spec 파일을 tech context로 별도 검색한다. 검색 결과는 현재 project와 맞는 문서를 우선하고, 다른 repository 전용 reference는 hook tech context에서 제외한다.
공용 wrapper는 scripts/hooks/llm-wiki-hook.sh다. LLM_WIKI_BIN이 있으면 그 binary를 쓰고, 없으면 llm-wiki PATH, 마지막으로 이 repo를 npx --package <repo>로 실행한다.
현재 repo에는 project-local hook 설정도 포함되어 있다: .claude/settings.json, .codex/hooks.json. 다른 repo에 붙일 때는 아래 예시를 복사하고 command path/vault path를 조정한다.
예시 파일:
- Claude Code project/user settings 예시:
config/claude-code.hooks.settings.json - Codex project/user hooks 예시:
config/codex.hooks.json
Codex는 ~/.codex/hooks.json 또는 <repo>/.codex/hooks.json, Claude Code는 .claude/settings.json/~/.claude/settings.json에 같은 wrapper command를 등록하면 된다. Codex hooks는 기본 enabled지만 trust review가 필요할 수 있고, Claude Code는 UserPromptSubmit/SessionStart에서 hookSpecificOutput.additionalContext를 context로 넣는다.
세션 중 수동 capture:
llm-wiki session-capture \
--vault ~/workspace/knowledge-base/llm-wiki \
--project "$PWD" \
--phase progress \
--title "MCP hook decision" \
--body "Claude Code와 Codex는 같은 llm-wiki hook command를 호출한다."Stop hook에서 자동 저장하려면 assistant 최종 답변에 아래처럼 명시적으로 선별 블록을 포함한다. 블록이 없으면 Stop hook은 아무것도 저장하지 않는다.
```llm-wiki-capture
title: MCP hook decision
tags: hooks, codex, claude
---
Claude Code와 Codex hook은 같은 `llm-wiki hook` command를 호출한다.
```직접 HTTP daemon 설정
launchd/systemd/manual command로 daemon을 이미 관리한다면 HTTP URL config를 써도 된다.
/Users/m16khb/Workspace/llm-wiki/bin/llm-wiki serve \
--vault /Users/m16khb/Workspace/knowledge-base/llm-wikiClaude Code HTTP 예시는 config/claude-code.http.mcp.json, Codex HTTP 예시는 config/codex.http.config.toml에 있다.
[mcp_servers.llm-wiki]
url = "http://127.0.0.1:39233/mcp"
startup_timeout_sec = 10
tool_timeout_sec = 60Direct stdio compatibility
llm-wiki mcp는 daemon을 거치지 않고 stdio MCP server가 직접 vault/service를 연다. stdio-only 환경의 비상/호환 경로이며, Claude Code와 Codex가 같은 daemon을 공유해야 하는 기본 운영에는 mcp-autostart를 사용한다.
npx wrapper는 기존 bin/llm-wiki가 있고 Go build input보다 최신이면 그대로 실행한다. bundled binary가 stale이거나 없으면 Go toolchain으로 CLI를 cache에 빌드한 뒤 실행한다. LLM_WIKI_NPM_REBUILD=1은 bundled/cache binary를 모두 무시하고 재빌드한다. MCP stdio 안전을 위해 wrapper 자체는 stdout에 진단을 쓰지 않는다. --prefix /tmp는 이 repo처럼 현재 프로젝트의 package.json 이름이 @m16khb/llm-wiki와 같을 때 npx가 local package로 오인하는 것을 피하기 위한 안전장치다.
개발 문서
작업 전 AGENTS.md와 agent_docs/CONSTITUTION.md를 읽는다.
agent_docs/ARCHITECTURE.md— daemon/queue/MCP 구조와 계층 책임agent_docs/CONVENTIONS.md— 구현 컨벤션agent_docs/GO_GUIDE.md— Go 작성 가이드agent_docs/TESTING.md— 검증 기준agent_docs/CAUTIONS.md— 반복 주의사항agent_docs/TECH_STACK.md— 버전/명령/설정agent_docs/ADR.md— 유지할 결정 기록
검증
gofmt -w cmd internal
npm run test:npm
go test ./... -count=1
go build ./...실제 사용자 vault를 대상으로 destructive test를 하지 않는다. capture/write 동작은 temp vault test나 명시적인 test vault에서 검증한다.
