mcpField
Q
qmd

qmd

github.com/breferrari生産性5.5k82 回インストール2 週間前に更新
リポジトリ

qmd について

qmdは、ファイル全体を開く前に関連箇所を検索する、ナレッジベース運用向けのセマンティック検索スキルです。MCPとコマンドラインに対応し、名前付きインデックスで各ナレッジベースを分離します。

主な機能

  1. 01ハイブリッド・キーワード・セマンティック検索
  2. 02パスまたはドキュメントIDで取得
  3. 03globパターンによる一括取得
  4. 04名前付きインデックスでデータを分離

活用シーン

  1. 01過去の決定やプロジェクトの背景を検索
  2. 02ノート作成前に既存の内容を確認
  3. 03レビュー資料をまとめて読み込む

MCP 対応

qmd MCPサーバーは検索、ドキュメント取得、状態確認を提供します。インデックス更新と埋め込み管理はコマンドラインのみです。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/breferrari/obsidian-mind --skill qmd

インストール後、Claude Code で/qmdを入力して読み込まれたか確認します。

詳細

QMD — Vault のセマンティック検索

Vault のファイルを直接読む前に、まず QMD で検索してください。ファイル全体を読んでコンテキストを消費することなく、関連する抜粋を取得できます。

ツールの利用方法 — 優先順位

利用可能な中で最も優先度の高い方法を選び、それ以外は使わないでください。3つとも同じ SQLite ストアを読み取るため(名前付きインデックスを参照)、返される結果は同じです。選択の違いは、インターフェースの使いやすさとコンテキストの消費量です。

  1. MCP ツール(登録済みの場合は推奨) — mcp__qmd__query、mcp__qmd__get、mcp__qmd__multi_get、mcp__qmd__status。これらがツールメニューに表示されている場合、MCP サーバーは稼働中で、この Vault 用に事前設定されています。直接呼び出してください。--index 引数は不要で、シェルも介さず、引数は型指定されています。セッション中はこの方法を使ってください。
  2. CLI の代替手段 — qmd --index <name> query|search|vsearch|get|multi-get。MCP サーバーが登録されていない場合(古い Vault のクローン、Windows のインストール状態のずれ、.mcp.json で無効化されている場合)、またはセッション外で単発のシェルチェックを行う場合に使用します。必ず --index <name> を指定してください。
  3. Grep / Glob / Read — 最後の手段です。QMD がまったくインストールされていない場合に限り使用してください。ファイル全体を読み取るためコンテキストを消費し、関連度による順位付けも行いません。

理由なく別の方法に切り替えないでください。MCP が登録済みなら、Bash ツールで CLI を呼び出すのは、同じ結果を得るためのより遅い方法にすぎません。

名前付きインデックス(この Vault)

この Vault では名前付き QMD インデックスを使用し、クエリ、更新、コンテキスト文字列がこの Vault の範囲に限定されます。同じマシン上の別の Vault と混在することはありません。このドキュメント内の QMD コマンドには、すべて --index <name> が指定されています。

名前の解決方法は、3つの方法(CLI、MCP、SessionStart フック)すべてで同じです。そのため、常に同じ SQLite ストアを参照します。

  1. 設定されている場合は、vault-manifest.json の qmd_index を使用します。明示的に固定された値です。
  2. それ以外の場合は、Vault フォルダー名をスラッグ化した値を使用します。テンプレートでは qmd_index が空になっているため、質問に答えなくても、インストールごとに個別のストアが作成されます。

Vault フォルダーの名前を変更しても維持される名前を使いたい場合や、すでに作成したストアを使い続けたい場合は、このフィールドに値を設定してください。

どちらの方法で解決されるかを推測するのではなく、コマンドを実行する前に解決後の名前を読み取ってください。

INDEX=$(node -e '
  const ok = (s) => typeof s === "string" && /^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(s);
  const m = JSON.parse(require("fs").readFileSync("vault-manifest.json", "utf8"));
  if (m.qmd_index && !ok(m.qmd_index)) {
    process.stderr.write("qmd_index is set to an invalid name: " + JSON.stringify(m.qmd_index) + "\n");
    process.exit(1);
  }
  const slug = require("path").basename(process.cwd()).normalize("NFKD").toLowerCase()
    .replace(/[^a-z0-9._-]+/g, "-").replace(/-{2,}/g, "-").replace(/^[^a-z0-9]+|[-._]+$/g, "");
  const name = [m.qmd_index, slug, m.template].find(ok);
  if (!name) { process.stderr.write("no usable qmd index name — set qmd_index in vault-manifest.json\n"); process.exit(1); }
  process.stdout.write(name);
') || exit 1
qmd --index "$INDEX" query "..."

この値は CLI 引数とファイルシステムのパス(~/.cache/qmd/<name>.sqlite)の両方に使われるため、無効な固定値は後続処理に渡すのではなく、ここで失敗させる必要があります。そのため、m.qmd_index || slug ではなく明示的なチェックを行っています。

セッション中は、解決された値をコマンドにそのまま指定してください。フォルダー名を変更しない限り、Vault の存続期間中は変わりません。

コマンド

各操作では、まず MCP の呼び出し方法を示し、次に同等の CLI コマンドを示しています。利用可能な場合は MCP を優先してください。

検索(クエリごとに1つ選択)
  • ハイブリッド(最高品質) — searches=[{type:"lex", query:"..."}, {type:"vec", query:"..."}] と intent 引数を指定して mcp__qmd__query を呼び出します。CLI:qmd --index <name> query "..." --json -n 10。複雑なクエリや概念的なクエリに使用します。
  • キーワード(高速 BM25) — searches=[{type:"lex", query:"..."}] を指定して mcp__qmd__query を呼び出します。CLI:qmd --index <name> search "..." --json -n 10。正確な用語、名前、チケット番号、日付に使用します。
  • セマンティック検索のみ — searches=[{type:"vec", query:"..."}] を指定して mcp__qmd__query を呼び出します。正確な語句がわからない場合の探索的なクエリに使用します。
取得
  • パスで指定 — path 引数を指定して mcp__qmd__get を呼び出します。CLI:qmd --index <name> get "path/to/file.md"。
  • docid で指定 — #abc123 形式で mcp__qmd__get を呼び出します。CLI:qmd --index <name> get "#docid"。
  • glob パターンで一括取得 — pattern 引数を指定して mcp__qmd__multi_get を呼び出します。CLI:qmd --index <name> multi-get "org/people/*.md" --json -l 40。
インデックス管理(CLI のみ — MCP で公開されるのは読み取り操作のみ)
  • qmd --index <name> update — ファイルを変更した後に再インデックスします(高速で、差分更新は約1〜2秒)。SessionStart フックと PostToolUse のデバウンス付き更新の両方がこれを自動で実行するため、手動での実行はほとんど必要ありません。
  • qmd --index <name> embed — ベクトル埋め込みを再生成します(時間がかかります。一括変更の後に実行してください)。

ブートストラップ(新規クローン)

QMD の SQLite ストアはリポジトリの外部(~/.cache/qmd/<index>.sqlite)にあるため、新規クローンではインデックスがありません。ブートストラップを一度実行してください。

node --experimental-strip-types .scripts/qmd-bootstrap.ts

インデックス名(固定の qmd_index、またはボルトフォルダーのスラッグ)を解決し、vault-manifest.json から qmd_context を読み込み、コレクションを登録してボルトのコンテキストを関連付け、ボルト内を走査し、埋め込みを生成します。冪等性があるため、再実行しても安全です。

検索するタイミング

各項目には、優先して使用する MCP 呼び出しを記載しています。MCP が登録されていない場合は、同等の CLI にフォールバックしてください。

  • ユーザーが過去の決定、インシデント、人物、プロジェクトについて言及した場合 → mcp__qmd__query(ハイブリッド)。
  • ユーザーが「X について何を決めましたか」と尋ねた場合 → mcp__qmd__query(決定のコンテキストを説明する intent を指定したハイブリッド検索)。
  • ユーザーが人物の名前を挙げた場合 → searches=[{type:"lex", query:"<name>"}] を指定して mcp__qmd__query を使用します。
  • 新しいノートを作成する前 → 既存の内容を確認するため、searches=[{type:"vec", query:"<topic>"}] を指定して mcp__qmd__query を使用します。
  • ノートを作成した後 → リンクすべきノートを見つけるため、searches=[{type:"vec", query:"<note title>"}] を指定して mcp__qmd__query を使用します。
  • レビュー準備のコンテキストを読み込む場合 → pattern="perf/evidence/*.md" を指定して mcp__qmd__multi_get を使用します。
  • 1 対 1 のコンテキストを読み込む場合 → searches=[{type:"lex", query:"<person name> 1-1"}] を指定して mcp__qmd__query を使用します。

一括変更後

シェルで qmd --index <name> update && qmd --index <name> embed を実行してください。SessionStart フックと PostToolUse のデバウンス更新によって update は自動的に実行されますが、多数のノートを作成したセッションの後には、embed を明示的に実行してください。

コメント