qmd 사용 가이드 (CMDS)
Key Insight
qmd는 Tobias Lütke(Shopify CEO)가 만든 로컬 마크다운 검색 엔진으로, Karpathy가 LLM Wiki 패턴의 공식 권장 도구로 지목한 바 있다. BM25 + 벡터 + LLM 재순위화를 완전 온디바이스로 제공하며, Ollama 없이 GGUF 모델을 자체 임베드한다.
1. 개요
1.1 qmd란?
- 저장소:
github.com/tobi/qmd(npm:@tobilu/qmd, 현재 설치 버전2.1.0) - 용도: 로컬 마크다운 파일에 대한 하이브리드 검색 (키워드 + 시맨틱 + 리랭킹)
- 런타임: Node.js ≥ 22 또는 Bun ≥ 1.0
- 임베딩 백엔드:
node-llama-cpp+ GGUF 모델 (Ollama 불사용) - 저자: Tobias Lütke (Shopify CEO,
tobi)
1.2 왜 qmd인가 — Karpathy 연결
Karpathy의 LLM Wiki 패턴 원문에서 직접 권장:
"qmd is a good option: it's a local search engine for markdown files with hybrid BM25/vector search and LLM re-ranking, all on-device. It has both a CLI (so the LLM can shell out to it) and an MCP server (so the LLM can use it as a native tool)."
LLM Wiki가 ~100 sources, ~수백 pages 규모로 성장할 때 index.md 한 파일만으로는 탐색이 어려워진다. qmd가 그 scale-up 경로를 제공한다.
1.3 CMDS 환경에서의 역할
- 대상 볼트:
CMDS_LLM_Wiki(satellite, Karpathy 3-Layer Architecture 구현체) - 인덱스 범위: Wiki(합성) + Raw Sources(원본) + Queries(합성 결과) — 총 3 collection
- 접근 방식: Claude Code가 MCP 네이티브 툴로, 사용자는 CLI로 (hybrid usage)
2. 아키텍처
2.1 임베딩 스택 (Ollama와의 차이)
qmd는 Ollama를 지원하지 않는다. 대신 node-llama-cpp를 통해 GGUF 모델을 프로세스 내부에서 직접 로드한다.
| 계층 | 구현 |
|---|---|
| 임베딩 모델 | embeddinggemma-300M-Q8_0 (Google Gemma 3 기반, 140+ 언어) ※ [[qmd 임베딩 모델 업그레이드 검토|상세 결정 로그]] |
| 리랭커 | Qwen3-Reranker-0.6B (CJK 지원) |
| 쿼리 확장 | qmd-query-expansion-1.7B (HyDE 스타일) |
| 벡터 DB | SQLite + vec0 확장 |
| GPU 가속 | Apple Metal (M5 Max 기준 VRAM 107GB 활용) |
qmd 2.1.0 CLI 버그 유의
QMD_EMBED_MODEL 환경변수 지정해도 qmd embed CLI는 하드코딩된 default(embeddinggemma-300M)를 사용한다. DB content_vectors.model 컬럼 조회로 실제 사용 모델 확인 가능. 실 운영상 Gemma-300M이 baseline이며, Qwen3로 전환하려면 upstream 수정 대기 또는 로컬 패치 필요.
장점 (Ollama 대비):
- 별도 데몬 관리 불필요
- Metal/CUDA 자동 감지
- 프로세스 내부 호출 → 오버헤드 최소
- 모델 파일
~/.cache/qmd/models/에 자동 관리
단점:
- 모델 공유 불가 (다른 도구가 Ollama를 쓰면 모델 중복 다운로드)
- 한 시점에 하나의 임베딩 모델만 활성 (swap 시 재임베드 필요)
2.2 데이터 위치
| 경로 | 용도 |
|---|---|
~/.config/qmd/index.yml | 사용자 전역 collection 설정 |
~/.cache/qmd/index.sqlite | 인덱스 DB (BM25 + 벡터) |
~/.cache/qmd/models/ | GGUF 모델 파일 (자동 다운로드) |
/tmp/qmd-reindex-cmds-llm-wiki.log | 자동 재인덱싱 로그 |
3. 설치 (이미 완료됨)
이 섹션은 참고용 기록. 이미 설치된 환경을 재구성할 때 사용.
3.1 사전 요구사항
# Node.js 22+ (이미 설치, v22.22.1)
node --version
# Bun 1.0+ (이미 설치, 1.3.11)
bun --version
# Homebrew SQLite (이미 설치, 3.51.3)
brew install sqlite3.2 qmd 설치
bun install -g @tobilu/qmdPostinstall 블록 경고
Bun이 node-llama-cpp postinstall을 자동 차단한다. 일반적으로 문제없지만, 네이티브 백엔드 문제 발생 시:
cd ~/.bun/install/global/node_modules/node-llama-cpp
node ./dist/cli/cli.js postinstall3.3 저장소 clone (참고용)
cd /Users/yohankoo/DEV && git clone https://github.com/tobi/qmd~/DEV/qmd/ — 소스 참조. 실제 실행은 ~/.bun/bin/qmd.
4. 한국어 임베딩 모델 설정
4.1 선택한 모델: Qwen3-Embedding-0.6B
- HuggingFace URI:
hf:Qwen/Qwen3-Embedding-0.6B-GGUF/Qwen3-Embedding-0.6B-Q8_0.gguf - 크기: 639 MB (Q8_0 양자화)
- 임베딩 차원: 1024
- 언어 지원: 119개 언어, 명시적 CJK (Chinese-Japanese-Korean) 최적화
- 선택 이유:
- qmd 작성자가 공식 권장하는 multilingual 옵션
- CJK 토크나이저가 한국어 어간 분리 처리
- 영어 쿼리 ↔ 한국어 문서 cross-lingual 검색 지원
- Q8_0 정확도 손실 ≤ 1%로 FP16 대비 절반 크기
4.2 환경변수 설정 (이미 완료됨)
~/.zshrc 끝에 추가:
# === CMDS LLM Wiki — qmd (Karpathy Pattern) ===
export QMD_EMBED_MODEL="hf:Qwen/Qwen3-Embedding-0.6B-GGUF/Qwen3-Embedding-0.6B-Q8_0.gguf"4.3 다른 모델로 교체할 때
모델 교체 시 전체 재임베드 필요:
# 1. 환경변수 변경 후
export QMD_EMBED_MODEL="hf:<different-model>"
# 2. 강제 재임베드 (벡터 차원이 다를 경우 필수)
qmd embed -f한국어 특화 대안 모델 (아직 GGUF 없음, 필요 시 직접 변환 필요):
nlpai-lab/KURE-v1— Korean Universal Retrieval Embeddingdragonkue/bge-m3-ko— BGE-M3 Korean fine-tunesnunlp/KR-SBERT-V40K-klueNLI-augSTS— KLUE-NLI 기반
GGUF 변환: llama.cpp/convert_hf_to_gguf.py 참조.
5. Config 파일 (~/.config/qmd/index.yml)
5.1 현재 설정
global_context: |
CMDS LLM Wiki — Karpathy 3-Layer Architecture.
- Raw Sources (immutable, ingested originals)
- Wiki (LLM-maintained pages: Concepts, Entities, Guides, MOCs)
- Queries (synthesized answers filed back as compounding knowledge).
collections:
wiki:
path: /Users/yohankoo/Local Obsidian_MBP/CMDS_LLM_Wiki/20. Wiki
pattern: "**/*.md"
context:
"/21. Concepts": "Abstract concepts, patterns, methodologies"
"/22. Entities": "People, organizations, products"
"/23. Guides": "How-to and practical implementation guides"
"/24. Maps": "Map of Content (MOC) — topic-based indexes"
raw_sources:
path: /Users/yohankoo/Local Obsidian_MBP/CMDS_LLM_Wiki/10. Raw Sources
pattern: "**/*.md"
context:
"/": "Immutable source documents — Wiki references via `source:` frontmatter"
"/11. Articles": "Web articles, blog posts, gists"
"/12. Papers": "Academic papers and technical reports"
queries:
path: /Users/yohankoo/Local Obsidian_MBP/CMDS_LLM_Wiki/30. Queries
pattern: "**/*.md"5.2 Context 어노테이션의 효과
context 필드는 LLM 재순위 단계에서 힌트로 사용된다. 예: "이 파일은 21. Concepts 아래 있음" → LLM이 "추상 개념 페이지"로 인지하고 관련성 판정에 반영.
5.3 볼트 내 백업본
CMDS_LLM_Wiki/90. Settings/qmd-config-template.yml — git-tracked 템플릿. 재설치 시:
cp "90. Settings/qmd-config-template.yml" ~/.config/qmd/index.yml
qmd update && qmd embed6. CLI 명령어 Cheat Sheet
6.1 기본 검색
# Hybrid 검색 (BM25 + 벡터 + LLM 재순위, 권장)
qmd query "LLM Wiki 패턴의 핵심은?"
# 키워드만 (BM25, LLM 미사용)
qmd search "Karpathy"
# 벡터만 (시맨틱, 의미 검색)
qmd vsearch "지식 관리의 유지보수 문제"
# 결과 개수 제한
qmd query "Memex" -n 5
# 특정 collection만
qmd query "Memex" -c wiki
qmd vsearch "보안 취약점" -c raw_sources6.2 출력 형식
qmd query "..." --json # JSON
qmd query "..." --md # Markdown
qmd query "..." --files # 파일 경로만
qmd query "..." --full # 전체 내용
qmd query "..." --explain # 스코어 상세
qmd query "..." --min-score 0.56.3 파일 조회
# 단일 문서
qmd get "wiki/21-concepts/llm-wiki-pattern.md"
# 특정 라인 범위
qmd get "wiki/21-concepts/llm-wiki-pattern.md:30 -l 20"
# 일괄 조회 (glob 또는 docid 목록)
qmd multi-get "wiki/22-entities/*.md"6.4 인덱스 관리
qmd status # 전체 상태
qmd collection list # collection 목록
qmd ls wiki # 특정 collection 파일 목록
qmd ls wiki/24-maps # 하위 경로만
qmd update # 변경 파일 재인덱싱 (BM25)
qmd update --pull # git pull 후 재인덱싱
qmd embed # 벡터 임베딩 갱신
qmd embed -f # 강제 전체 재임베드 (모델 교체 후)
qmd cleanup # 캐시 정리, DB vacuum6.5 Context 메타데이터 (수동 어노테이션)
특정 파일에 검색 힌트 추가:
qmd context add "qmd://wiki/21-concepts/llm-wiki-pattern.md" "Core pattern — start here for Karpathy pattern questions"
qmd context list7. MCP 서버 — Claude Code 네이티브 통합
7.1 등록 상태 (이미 완료)
claude mcp list | grep qmd
# qmd: qmd-mcp-wiki - ✓ Connected7.2 등록 방식
환경변수를 stdio MCP에 전달하기 위해 래퍼 스크립트 사용:
파일: ~/.bun/bin/qmd-mcp-wiki
#!/usr/bin/env bash
export QMD_EMBED_MODEL="hf:Qwen/Qwen3-Embedding-0.6B-GGUF/Qwen3-Embedding-0.6B-Q8_0.gguf"
exec qmd mcp "$@"Claude Code 등록 (user scope, 모든 프로젝트에서 접근 가능):
claude mcp add -s user qmd qmd-mcp-wiki7.3 LLM이 MCP로 할 수 있는 것
Claude Code 세션에서 다음 도구들이 자동 노출됨:
qmd__query— hybrid searchqmd__search— BM25 onlyqmd__vsearch— vector onlyqmd__get— 파일 내용 조회qmd__multi_get— 일괄 조회qmd__status— 인덱스 상태qmd__ls— collection 탐색
즉, LLM이 Bash 없이도 네이티브로 위키 검색 가능.
7.4 재설정이 필요한 경우
claude mcp remove qmd
claude mcp add -s user qmd qmd-mcp-wiki8. 자동 재인덱싱 Hook
8.1 작동 방식
- 트리거: PostToolUse (Write / Edit / MultiEdit)
- 스코프:
CMDS_LLM_Wiki내부의*.md파일만 - 제외:
00. Inbox/(ingest 전 staging) - 디바운스: 8초 (burst 쓰기를 하나의 재인덱싱으로 병합)
- 실행: 백그라운드, 메인 세션 논블로킹
8.2 Hook 파일
등록: CMDS_LLM_Wiki/.claude/settings.json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit|MultiEdit",
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/qmd-reindex.sh",
"timeout": 5
}
]
}
]
}
}스크립트: CMDS_LLM_Wiki/.claude/hooks/qmd-reindex.sh (디바운스 + 백그라운드 실행)
8.3 수동 실행이 필요한 경우
- Obsidian에서 직접 편집 (Claude Code 외부, hook 미발화)
- 외부 도구로 대량 파일 변경
- 임베딩 모델 교체 후
- Hook 오류 발생 시
# 수동 재인덱싱
qmd update && qmd embed
# 또는 Claude Code 세션 내에서
/reindex8.4 로그 확인
tail -f /tmp/qmd-reindex-cmds-llm-wiki.log9. Workflow — 일상 사용
9.1 Ingest 후 자동 반영
새 자료 ingest → Claude Code가 Write 도구로 Wiki 페이지 생성 → PostToolUse hook 발화 → 8초 debounce 후 qmd update && qmd embed → 새 페이지 즉시 검색 가능.
사용자가 신경 쓸 것 없음.
9.2 Query 시 의사결정 트리
질문이 있다
├── 자연어 + 모호 → qmd query "..." (권장, 재순위 포함)
├── 정확한 키워드 매치 → qmd search "..." (빠름)
├── 시맨틱만, 속도 우선 → qmd vsearch "..."
└── 특정 파일 참조 → qmd get "path"9.3 Obsidian 직접 편집 후
/reindex # 또는 터미널에서 qmd update && qmd embed9.4 Lint 워크플로우와의 통합
/lint가 모순 · orphan · stale 검사 시 qmd를 활용 가능:
# 모순 검사 예시
qmd search "contradiction" -c wiki
qmd query "이 페이지와 같은 주제를 다루는 다른 페이지는?"
# orphan 검사 (backlink 0인 페이지)
qmd ls wiki | while read page; do
backlinks=$(qmd query "[[$page]]" --files | wc -l)
[ "$backlinks" -eq 0 ] && echo "ORPHAN: $page"
done10. 통합 구조 요약
┌─────────────────────────────────────────────────────────────┐
│ CMDS_LLM_Wiki (Obsidian Vault, Karpathy 3-Layer) │
│ │
│ 10. Raw Sources/ ← immutable originals │
│ 20. Wiki/ ← LLM-synthesized pages │
│ 30. Queries/ ← filed-back query results │
│ │ │
│ │ Write/Edit │
│ ▼ │
│ .claude/hooks/qmd-reindex.sh (PostToolUse, debounce 8s) │
│ │ │
│ ▼ │
│ qmd update && qmd embed ← background, Metal GPU │
│ │ │
│ ▼ │
│ ~/.cache/qmd/index.sqlite │
│ ▲ │
│ │ │
│ ┌──────┴──────────────────────────────────────────┐ │
│ │ Query access: │ │
│ │ • Terminal: qmd query "..." │ │
│ │ • Claude Code: qmd__query MCP tool (native) │ │
│ │ • /reindex (manual fallback) │ │
│ └──────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘11. Troubleshooting
11.1 Dimension mismatch: Expected 1024 dimensions but received 768
원인: 인덱스 생성 시 모델과 쿼리 실행 시 모델의 임베딩 차원이 다름.
해결: env var이 새 셸에 상속되지 않았을 가능성. 다음 중 하나:
# 현재 셸에 export
export QMD_EMBED_MODEL="hf:Qwen/Qwen3-Embedding-0.6B-GGUF/Qwen3-Embedding-0.6B-Q8_0.gguf"
# 또는 .zshrc 재로드
source ~/.zshrc
# 새 터미널 열기11.2 ggml_metal_library_init_from_source: error compiling source
원인: Metal shader 런타임 컴파일 경고. 일반적으로 fallback으로 CPU/일부 기능 비활성화.
실제 영향: 대부분 무해. qmd status에서 "GPU: metal (offloading: yes)" 확인되면 Metal 활성.
11.3 첫 query 시 지연
원인: 쿼리 확장 모델 (1.28GB) 첫 다운로드.
해결: 기다리거나, vsearch(확장 불필요)로 우회:
qmd vsearch "쿼리" -n 311.4 Hook이 발화하지 않음
점검:
# Hook 실행 권한
ls -la "/Users/yohankoo/Local Obsidian_MBP/CMDS_LLM_Wiki/.claude/hooks/qmd-reindex.sh"
# settings.json 로드 확인
cat "/Users/yohankoo/Local Obsidian_MBP/CMDS_LLM_Wiki/.claude/settings.json"
# 수동 실행 테스트
echo '{"tool_input":{"file_path":"/Users/yohankoo/Local Obsidian_MBP/CMDS_LLM_Wiki/20. Wiki/test.md"}}' | \
"/Users/yohankoo/Local Obsidian_MBP/CMDS_LLM_Wiki/.claude/hooks/qmd-reindex.sh"11.5 MCP 연결 실패
# 래퍼 직접 실행 테스트 (Ctrl+C로 종료)
qmd-mcp-wiki
# 재등록
claude mcp remove qmd
claude mcp add -s user qmd qmd-mcp-wiki
claude mcp list | grep qmd12. Quick Reference
12.1 설치된 구성 파일
| 파일 | 용도 |
|---|---|
~/.config/qmd/index.yml | Collection 설정 (3 collections) |
~/.zshrc (line: QMD_EMBED_MODEL) | Korean embedding env var |
~/.bun/bin/qmd | qmd CLI 바이너리 |
~/.bun/bin/qmd-mcp-wiki | MCP 래퍼 스크립트 |
~/.claude.json (user scope) | MCP 서버 등록 |
CMDS_LLM_Wiki/.claude/settings.json | PostToolUse hook 등록 |
CMDS_LLM_Wiki/.claude/hooks/qmd-reindex.sh | 자동 재인덱싱 스크립트 |
CMDS_LLM_Wiki/.claude/commands/reindex.md | /reindex 수동 명령 |
CMDS_LLM_Wiki/90. Settings/qmd-config-template.yml | Config 백업/템플릿 |
/Users/yohankoo/DEV/qmd/ | qmd 저장소 clone (참고용) |
12.2 자주 쓰는 명령
# 기본 검색
qmd query "<자연어 질문>"
# 상태
qmd status
# 재인덱싱
qmd update && qmd embed
# Claude Code 세션 내
/reindex12.3 관련 CMDS 가이드
- [[Obsidian CLI 사용 가이드 (CMDS)]] — 자매 도구 (Obsidian 앱 제어)
12.4 외부 레퍼런스
- qmd GitHub: https://github.com/tobi/qmd
- Karpathy LLM Wiki Gist: https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f
- Qwen3-Embedding HF: https://huggingface.co/Qwen/Qwen3-Embedding-0.6B-GGUF
- Cross-reference: → CMDSPACE
00. Inbox/03. AI Agent/03-1. Claude Code (MBP)/2026-04-06-llm-wiki-karpathy.md
Setup 완료일
2026-04-14 — CMDS_LLM_Wiki 기준 32 문서 (28 Wiki + 3 Raw Sources + 1 Query), 69 chunks, Qwen3-Embedding-0.6B (1024 dim) 벡터화 완료. Metal GPU 활용, embed 소요 15초.