llm-wiki について
llm-wiki は、ローカル HTTP API 経由で LLM Wiki を利用するスキルです。ユーザーのナレッジベースを扱うエージェント向けに、プロジェクト選択、検索、ページ閲覧、グラフ照会、ソース再スキャンを案内し、プロジェクト境界とトークンの扱いにも触れます。
主な機能
- 01ローカル HTTP API でアクセス
- 02Wiki ページの検索と閲覧
- 03Wikilinks グラフの照会
- 04ソースファイルの再スキャン
- 05複数プロジェクトの解決
活用シーン
- 01Wiki 内のトピックを検索
- 02ページを読みパスを引用
- 03Wiki グラフの構造を確認
- 04追加ソースを再スキャン
MCP 対応
入力には MCP との関係が記載されていません。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ nashsu/ llm_wiki_skill --skill llm-wikiインストール後、Claude Code で/llm-wikiを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
README.mdexamples.mdapi-reference.md詳細
LLM Wiki ローカル API スキル
組み込み HTTP API を使って、ユーザーがローカルで実行している LLM Wiki アプリとやり取りします。これは標準的な JSON APIです。環境にすでにある HTTP ツール(curl、fetch、requests、http ミドルウェアなど)から直接呼び出してください。インストールが必要なクライアントライブラリも、習得が必要な SDK もありません。
この Wiki は、ユーザーがキュレーションしてきたプライベートで構造化されたナレッジベースとして扱います。ページは wiki/**.md にあり、未加工のドキュメントは raw/sources/ に保存され、Wiki リンクがグラフを形成しています。
呼び出すタイミング
ユーザーがアプリ名、「wiki」という文脈、または「知識庫」という文脈で、明確に LLM Wiki を指している場合にのみ呼び出してください。具体的には、次のような場合です。
- 「自分のwiki/ナレッジベース/我的知識庫/LLM Wikiには X について何と書かれていますか」のように尋ねる
- 「X について自分の wiki/LLM Wikiプロジェクト/我的知識庫を検索して」と依頼する
- wiki ページをファイル名のベース名/タイトルで指定し、内容の確認や相互リンクを求める
- wiki グラフ/知識グラフ/wiki の概要/wiki の構造について尋ねる
- LLM Wiki のソースフォルダー内のファイルを追加または編集した直後に、再取り込み/再インデックスを求める
- 「文脈として自分の wikiを使って」/「回答の根拠を自分の wikiにして」/「自分の LLM Wikiを確認して」と言う
- wiki プロジェクトを(ID、絶対パス、または
currentで)指定する
次のような場合は呼び出さないでください。
- 追加の説明なしに「自分のノートを検索して」と言う場合。Obsidian/Apple Notes/Notion/Logseq/Bear などを指している可能性があります
- 「自分のノートブックで探して」と言う場合。Jupyter/OneNote/Notability を指している可能性があります
- 「自分の Obsidian/Notion/Roam/Logseq の保管庫を確認して」と言う場合。別のツールを明示的に指しています
- 「自分の Anki/Readwise/Pocketを調べて」と言う場合。別のツールです
- 「自分のファイル/Documents フォルダーを検索して」と言う場合。一般的なファイルシステムを指しており、Wiki ではありません
- 一般的な知識、時事問題、またはユーザーが明らかにオープンウェブからの情報を求めている場合
ユーザーがどのナレッジツールを指しているか不明な場合は、「LLM Wiki のことですか。それとも別のツールですか?」と尋ねてください。Obsidian の保管庫かもしれないのに、黙って LLM Wiki API を呼び出してはいけません。
クイックスタート
API はすべてプレーンな HTTP + JSON です。最短の手順は次のとおりです。
BASE=http://127.0.0.1:19828
TOKEN="${LLM_WIKI_API_TOKEN:-<paste-from-Settings>}"
# 1. probe state — no auth needed
curl -s $BASE/api/v1/health
# 2. list projects
curl -s -H "Authorization: Bearer $TOKEN" $BASE/api/v1/projects
# 3. search
curl -s -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{"query":"rope embedding","topK":5}' \
$BASE/api/v1/projects/current/search
# 4. read a page
curl -s -H "Authorization: Bearer $TOKEN" \
"$BASE/api/v1/projects/current/files/content?path=wiki/concepts/rope.md"
TypeScript/JavaScript を書く場合:
const res = await fetch("http://127.0.0.1:19828/api/v1/projects/current/search", {
method: "POST",
headers: { "Authorization": `Bearer ${process.env.LLM_WIKI_API_TOKEN}`, "Content-Type": "application/json" },
body: JSON.stringify({ query: "rope embedding", topK: 5 }),
})
const { results } = await res.json()
Python も同じ形式です。urllib.request、requests、httpx など、すでに使っているものを利用できます。新しいものはインストールしないでください。
認証モデル
API はローカルホストからのみ利用できます。トークンは次のいずれかです。
LLM_WIKI_API_TOKEN環境変数(設定されている場合、UI の設定より優先されます)- Settings → API Server で保存されたユーザーの
apiConfig.token allowUnauthenticated: trueモード(トークン不要。まれなケースで、ユーザーが明示的に選んだ場合に限ります)
必ず最初に /api/v1/health を確認してください。ここでは { enabled, authConfigured, allowUnauthenticated, tokenSource } が返されます。authConfigured: false && allowUnauthenticated: false の場合は、ユーザーに Settings → API Server → Generate new token を開くよう依頼してください。認証を設定せずに先へ進んではいけません。
トークンを送信する方法は、同等のものが 3 通りあります。
Authorization: Bearer <token> # preferred
X-LLM-Wiki-Token: <token> # alternative header
?token=<urlencoded-token> # query param — last resort, leaks into logs
トークンをログに記録したり、応答に含めたりしてはいけません。ユーザーに見える出力内の URL にも決して含めないでください(Referer、シェル履歴、ログなどから漏えいする可能性があります)。
標準的なワークフロー
ユーザーから「自分の wiki で調べて」と頼まれた場合:
- プロジェクトを解決します(下記のプロジェクトの解決を参照)。
- 検索します。
POST /api/v1/projects/{id}/searchに{ query, topK: 5..10 }を指定すると、ランキングされたヒット(path、title、snippet、score、titleMatch、任意のvectorScore、images)が返されます。ハイブリッド検索が使われたかどうかを確認するため、response.modeを調べてください。 - 上位のヒットを読み込みます。有望なヒットごとに、
GET /api/v1/projects/{id}/files/content?path=...を呼び出して Markdown 全文を取得します。または、検索へのラウンドトリップを省略するため、検索リクエストにincludeContent: trueを渡します。 - 出典を示して回答します。読み込んだページに基づいて回答をまとめます。ユーザーが確認してアプリ内で該当ページを開けるよう、使用した各ページの
pathを引用してください。
スコアの読み方
score フィールドの尺度は mode によって異なります。
mode: "keyword"— キーワードの加算スコアです。ファイル名が完全一致する場合は約200、タイトル内のフレーズ一致は約50以上、トークンの集合による一致は1桁台になります。最上位の結果の約5%未満のスコアは、信頼度が低いものとして扱ってください。mode: "hybrid"または"vector"— RRF(Reciprocal Rank Fusion)スコアで、通常は 0.015~0.035 の範囲です。絶対値は小さいため、重要なのは相対的な順位です。「埋め込みがどの程度強く一致したか」を確認する必要がある場合は、結果ごとのvectorScore(生のコサイン類似度、0~1)を使ってください。
モードをまたいで固定のスコアしきい値を適用しないでください。score の降順で並べ、相対的な差に基づいて判断してください。
プロジェクトの解決
プロジェクトを指定する各エンドポイントの {id} は、次の4つの形式を受け付けます。
| 形式 | 使用する場合 | 例 |
|---|---|---|
current(文字列そのまま) | 「自分の wiki/自分のナレッジベース/このプロジェクト/この wiki」のデフォルトです。ユーザーはデスクトップ UI で開いているプロジェクトを指しています。 | /api/v1/projects/current/search |
| UUID | ユーザーがプロジェクト ID を貼り付けた場合、または名前を ID に解決済みで再利用する場合です。 | /api/v1/projects/a0e90b29-fcf3-4364-9502-8bd1272de820/files |
| 絶対ファイルシステムパス(URL エンコード済み) | ユーザーがパス(例:~/notes/research)を指定した場合です。名前が似ている複数のプロジェクトがユーザーにある場合に便利です。 | /api/v1/projects/%2FUsers%2Fme%2Fwiki%2Fresearch/files |
| プロジェクト名 | 直接はサポートされていません。 まず GET /api/v1/projects を実行し、name で一致するプロジェクトを見つけてから、そのプロジェクトの id を使う必要があります。 |
ユーザーの発言に応じた判断フロー:
"my wiki" / "my 知识库" / "this wiki" / "this project" / unspecified
→ use `current`
"my Research project" / "in Reading"
→ GET /api/v1/projects
→ name-match (case-insensitive substring on `name`)
→ use the resulting `id`
→ if 0 matches: tell the user, list available names, fall back to `current` only if they confirm
→ if 2+ matches: ask the user to disambiguate, quoting both names + paths
"the project at /Users/me/foo"
→ URL-encode the path, use directly
→ if the API returns 404, the project isn't registered — list and let user pick
"project a0e90b29-…"
→ use the UUID literally
解決した id は会話の残りの間キャッシュしてください。呼び出しごとに /projects を再度 GET する必要はありません。ただし、ユーザーが会話の途中でコンテキストを切り替えた場合(「次は Reading プロジェクトを見て」など)は、再度解決してください。
ユーザーがプロジェクトを指定しない場合は、デフォルトで current を使い、その旨を一度伝えてください。「アクティブなプロジェクト(Research Notes)を検索しています……」。これにより、意図しない別プロジェクトの参照を防げます。
グラフや相互参照に関する質問の場合:
GET /api/v1/projects/{id}/graph?limit=200→{ nodes: [{id, label, nodeType, path, linkCount}], edges: [{source, target, weight}] }?q=term(id/label の部分一致、大文字と小文字は区別しません)および?nodeType=entity|concept|...でフィルターします。
「新しいドキュメントを追加した」という依頼の場合:
POST /api/v1/projects/{id}/sources/rescan→{ queue: { tasks }, changedTasks: [...] }を返します。変更されたファイル数をユーザーに伝えてください。実際の取り込みはデスクトップキューを通じて非同期で実行されます。
エンドポイントの仕様(v1)
| メソッド | パス | 説明 |
|---|---|---|
| GET | /api/v1/health | 認証不要。{ ok, status, version, enabled, authRequired, authConfigured, allowUnauthenticated, tokenSource } を返します。 |
| GET | /api/v1/projects | プロジェクトの一覧です。各項目は { id, name, path, current } です。 |
| GET | /api/v1/projects/{id}/files?root=wiki|sources|all&recursive=true&maxFiles=2000 | { name, path, isDir, size, children } のツリーです。ノード数は10000件に制限されます(413)。 |
| GET | /api/v1/projects/{id}/files/content?path=wiki/foo.md | テキストファイルのみ(md/mdx/txt/json/yaml/yml/csv/html/htm/xml/rtf/log)。最大2 MB。バイナリファイルは415、サイズ超過は413、対象範囲外のパスは403を返します。 |
| POST | /api/v1/projects/{id}/search | 本文:{ "query": "...", "topK": 10, "includeContent": false }。ユーザーが Settings で埋め込みを設定している場合は ハイブリッド(キーワード+ベクトル) で検索し、それ以外の場合はキーワードのみの検索にフォールバックします。レスポンスには mode: "keyword" | "vector" | "hybrid"、tokenHits/vectorHits、および結果ごとの vectorScore が含まれます。空のクエリは400を返します。 |
| GET | /api/v1/projects/{id}/graph?q=&nodeType=&limit=200 | wiki/*.md の Wikilinks グラフです。上限は1000に制限されます。 |
| POST | /api/v1/projects/{id}/sources/rescan | ユーザーの Source Watch 設定を使って、バックエンドの再スキャンを開始します。再スキャン後のキューと、実際に変更されたタスクを返します。 |
| POST | /api/v1/projects/{id}/chat | 501 — v1 では実装されていません。呼び出さないでください。 |
{id} は UUID、絶対ファイルシステムパス(URL エンコード済み)、または文字列そのままの current を受け付けます。
エラー処理
ステータスコードを常に契約として扱ってください。
| ステータス | 意味 | 対応 |
|---|---|---|
| 200 | OK | 念のため body.ok === true を確認してください。ペイロードは同じオブジェクト内にあります。 |
| 400 | 不正なリクエスト | body.error を表示してください。よくある原因:空の query、無効な ?root=、リクエスト本文のサイズ超過。 |
| 401 | 認証されていません | トークンがないか、正しくありません。Settings → API Server でトークンを設定するか、再生成するようユーザーに伝えてください。 |
| 403 | 禁止されています | パストラバーサル、または許可範囲外です(例:../app-state.json)。同じパスで再試行しないでください。 |
| 404 | 見つかりません | 不明なプロジェクト ID、または不明なルートです。プロジェクトが不明な場合は、復旧のため最初にプロジェクト一覧を取得してください。 |
| 405 | 許可されていないメソッド | HTTP メソッドが誤っています。 |
| 413 | ペイロードが大きすぎます | ファイルが 2 MB を超えている、ファイルツリーが maxFiles を超えている、またはリクエスト本文が 1 MB を超えています。対象範囲を絞るよう提案してください。 |
| 415 | サポートされていないメディア形式 | バイナリ、または UTF-8 以外のファイル内容です。API はテキストのみを扱います。 |
| 429 | リクエストが多すぎます | レート制限(全体で 120 リクエスト/秒)です。1 秒以上待ってから再試行してください。 |
| 500 | 内部エラー | ログに記録して報告してください。繰り返し処理しないでください。 |
| 501 | 未実装 | /chat のスタブです。再試行しないでください。 |
| 503 | サービスを利用できません | 2 つの原因があります:API が無効になっている(error に "disabled" が含まれる)、または処理中リクエスト数の上限(64)に達している("busy")。2 秒以上待ってから再試行してください。 |
HTTP 呼び出し自体が失敗した場合(connection refused/ENOTFOUND)、デスクトップアプリは起動していません。ユーザーに「LLM Wiki を起動してから、もう一度お試しください」と伝えてください。
エチケット
- パスを明記してください。 Wiki の内容を使って回答するときは、ページ名を記載してください:(
wiki/concepts/rope.mdから)。ユーザーはこれを使って内容を確認し、アプリ内でページを開きます。 - デフォルトでは読み取り専用で対応してください。 状態を変更するのは
sources/rescanだけです。それ以外はすべて読み取りです。書き込み用エンドポイントを作り出さないでください。v1 には存在しません。 - 求められない限り、ページ全体を出力しないでください。 通常はスニペットとパスがあれば十分です。推論に本当に必要な場合に限り、全内容を取得してください。
- プロジェクトの境界を尊重してください。 現在のプロジェクトはユーザーがアクティブに使用しているコンテキストです。黙ってプロジェクトを切り替えないでください。
- レート制限を守ってください。 120 リクエスト/秒あれば順次処理には十分ですが、ページの読み取りを並列で行うと上限に近づくことがあります。API で可能な場合はまとめて処理してください(検索時に
includeContent: trueを指定すると、N+1 回の読み取りを避けられます)。 - トークンを決して漏らさないでください。 ヘッダーは安全ですが、クエリパラメーターと自身の出力テキストは安全ではありません。
関連項目
api-reference.md— リクエスト/レスポンスの例を含む、すべてのエンドポイントの形式examples.md— 一般的な会話パターンと、それに対応する直接的なcurl/fetchの実行例README.md— 人間向けのセットアップ手順(トークン生成、ポート競合、トラブルシューティング)