QMD는 OpenClaw와 함께 동작하는 local-first 검색 사이드카입니다. 하나의 바이너리에서 BM25, 벡터 검색, reranking을 결합하며, 워크스페이스 memory 파일을 넘어선 콘텐츠도 인덱싱할 수 있습니다.
builtin 대비 추가 기능
- Reranking과 query expansion -- 더 나은 recall 제공.
- 추가 디렉토리 인덱싱 -- 프로젝트 문서, 팀 노트 등 디스크상의 무엇이든.
- 세션 전사본 인덱싱 -- 이전 대화를 recall.
- 완전 로컬 -- Bun + node-llama-cpp로 실행, GGUF 모델 자동 다운로드.
- 자동 fallback -- QMD를 사용할 수 없으면 OpenClaw가 자연스럽게 builtin 엔진으로 fallback합니다.
시작하기
사전 요건
- QMD 설치:
npm install -g @tobilu/qmd또는bun install -g @tobilu/qmd - extension을 허용하는 SQLite 빌드(macOS에서는
brew install sqlite). - QMD가 gateway의
PATH에 있어야 합니다. - macOS와 Linux는 바로 동작합니다. Windows는 WSL2를 통해 가장 잘 지원됩니다.
활성화
{
memory: {
backend: "qmd",
},
}OpenClaw는 ~/.openclaw/agents/<agentId>/qmd/ 아래에 자체 포함된 QMD 홈을 생성하고 사이드카 라이프사이클을 자동 관리합니다 -- 컬렉션, 업데이트, embedding 실행이 알아서 처리됩니다. 최신 QMD 컬렉션 및 MCP 쿼리 형태를 선호하지만, 필요 시 레거시 --mask 컬렉션 플래그와 구버전 MCP 도구 이름으로도 fallback합니다. 부팅 시 reconciliation은 이름이 같은 구버전 QMD 컬렉션이 남아있을 때, stale한 관리 컬렉션을 canonical 패턴으로 재생성합니다.
사이드카 동작 방식
- OpenClaw는 워크스페이스 memory 파일과
memory.qmd.paths에 설정된 경로로부터 컬렉션을 생성한 뒤, 부팅 시 그리고 주기적으로(기본 5분마다)qmd update+qmd embed를 실행합니다. - 기본 워크스페이스 컬렉션은
MEMORY.md와memory/트리를 추적합니다. 소문자memory.md는 루트 memory 파일로 인덱싱되지 않습니다. - 부팅 갱신은 백그라운드에서 실행되어 채팅 시작을 지연시키지 않습니다.
- 검색은 설정된
searchMode(기본값:search,vsearch와query도 지원)를 사용합니다. 모드 실패 시 OpenClaw는qmd query로 재시도합니다. - QMD가 완전히 실패하면 OpenClaw는 builtin SQLite 엔진으로 fallback합니다.
INFO
첫 검색은 느릴 수 있습니다 -- QMD가 첫 qmd query 실행 시 reranking과 query expansion용 GGUF 모델(약 2 GB)을 자동 다운로드하기 때문입니다.
모델 오버라이드
QMD 모델 환경 변수는 gateway 프로세스에서 그대로 전달되므로, 새로운 OpenClaw 설정을 추가하지 않고도 QMD를 전역으로 튜닝할 수 있습니다.
export QMD_EMBED_MODEL="hf:Qwen/Qwen3-Embedding-0.6B-GGUF/Qwen3-Embedding-0.6B-Q8_0.gguf"
export QMD_RERANK_MODEL="/absolute/path/to/reranker.gguf"
export QMD_GENERATE_MODEL="/absolute/path/to/generator.gguf"embedding 모델을 변경한 뒤에는 인덱스가 새 벡터 공간과 일치하도록 embedding을 다시 실행하세요.
추가 경로 인덱싱
QMD를 추가 디렉토리로 향하게 하여 검색 가능하게 만들 수 있습니다.
{
memory: {
backend: "qmd",
qmd: {
paths: [{ name: "docs", path: "~/notes", pattern: "**/*.md" }],
},
},
}추가 경로에서 나온 snippet은 검색 결과에 qmd/<collection>/<relative-path> 형태로 나타납니다. memory_get은 이 접두어를 이해하고 올바른 컬렉션 루트에서 읽어들입니다.
세션 전사본 인덱싱
이전 대화를 recall하려면 세션 인덱싱을 활성화하세요.
{
memory: {
backend: "qmd",
qmd: {
sessions: { enabled: true },
},
},
}전사본은 정제된 User/Assistant 턴으로 ~/.openclaw/agents/<id>/qmd/sessions/ 아래의 전용 QMD 컬렉션으로 내보내집니다.
검색 범위(scope)
기본적으로 QMD 검색 결과는 direct 및 channel 세션에서만 노출됩니다(group은 제외). 이를 변경하려면 memory.qmd.scope를 설정하세요.
{
memory: {
qmd: {
scope: {
default: "deny",
rules: [{ action: "allow", match: { chatType: "direct" } }],
},
},
},
}scope가 검색을 거부하면, OpenClaw는 유도된 channel과 chat type을 로그로 남겨 빈 결과를 디버깅하기 쉽게 만듭니다.
Citation
memory.citations가 auto 또는 on이면, 검색 snippet에 Source: <path#line> footer가 포함됩니다. memory.citations = "off"로 설정하면 footer는 생략되지만 경로는 여전히 에이전트에 내부적으로 전달됩니다.
사용 시점
다음이 필요할 때 QMD를 선택하세요.
- 더 고품질의 결과를 위한 reranking.
- 워크스페이스 바깥 프로젝트 문서나 노트를 검색.
- 과거 세션 대화 recall.
- API 키 없이 완전 로컬 검색.
더 단순한 설정으로 충분하다면, builtin 엔진이 추가 의존성 없이 잘 동작합니다.
문제 해결
QMD를 찾을 수 없나요? 바이너리가 gateway의 PATH에 있는지 확인하세요. OpenClaw가 서비스로 실행된다면 심링크를 만드세요: sudo ln -s ~/.bun/bin/qmd /usr/local/bin/qmd.
첫 검색이 매우 느린가요? QMD는 첫 사용 시 GGUF 모델을 다운로드합니다. OpenClaw가 사용하는 것과 동일한 XDG 디렉토리로 qmd query "test"를 실행해 미리 준비하세요.
검색이 타임아웃되나요? memory.qmd.limits.timeoutMs(기본값: 4000ms)를 늘리세요. 느린 하드웨어에서는 120000으로 설정하세요.
group chat에서 결과가 비어 있나요? memory.qmd.scope를 확인하세요 -- 기본값은 direct와 channel 세션만 허용합니다.
루트 memory 검색이 갑자기 너무 넓어졌나요? gateway를 재시작하거나 다음 시작 시 reconciliation을 기다리세요. OpenClaw는 이름이 같은 충돌이 감지되면 stale한 관리 컬렉션을 canonical MEMORY.md와 memory/ 패턴으로 재생성합니다.
워크스페이스에 노출된 임시 저장소 때문에 ENAMETOOLONG이 나거나 인덱싱이 깨지나요? QMD traversal은 현재 OpenClaw의 builtin 심링크 규칙이 아닌 QMD scanner 동작을 따릅니다. QMD가 cycle-safe traversal이나 명시적 제외 제어를 노출하기 전까지는 임시 monorepo 체크아웃을 .tmp/ 같은 숨김 디렉토리 아래나 인덱싱된 QMD 루트 바깥에 두세요.
설정
전체 설정 면(memory.qmd.*), 검색 모드, 업데이트 주기, scope 규칙을 비롯한 모든 옵션은 Memory 설정 레퍼런스를 참고하세요.