wiki-import について
wiki-import は、wiki-export が生成した graph.json または OKF バンドルから、現在の Obsidian Vault に知識を取り込みます。グラフからページのスタブを再構築する方法と、本文を含むページを復元する方法があり、競合時はマージ、スキップ、上書きを選べます。
主な機能
- 01graph.json または OKF バンドルの取り込み
- 02グラフデータからページのスタブと関係を再構築
- 03OKF バンドルから完全なページを復元
- 04マージ、スキップ、上書きモードに対応
- 05Vault のメタデータ更新とページリンクの変換
活用シーン
- 01graph.json で出力した構造を Vault に取り込み
- 02Vault 間で完全な Markdown ページを移行
- 03選択した競合モードでインポートページをマージ
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ ar9av/ obsidian-wiki --skill wiki-importインストール後、Claude Code で/wiki-importを入力して読み込まれたか確認します。
詳細
Wiki インポート — エクスポートからページを再構築する
wiki-export が生成する次の 2 種類のソースのどちらかから、Vault のナレッジを現在の Vault にインポートします。
graph.json— グラフの骨格です。ページのスタブ(フロントマター、型付きリレーションシップ、## Relatedのリンクリスト。本文はありません)を再構築します。情報は失われます。- OKF バンドル(
wiki-export/okf/ディレクトリ) — 実際の Markdown ファイルです。実際の本文を含む完全なページを再構築します。情報は失われません。Vault 間で完全に移行する場合に使用してください。
どちらの場合も、インポートでは正しいフロントマターと Wiki リンクを含むページを書き込み、その後、Vault のすべてのメタデータを更新します。Step 2、Step 3(グラフのみ)、Step 5 は共通です。Step 4 はソースの種類によって分岐します。
開始する前に
執筆プロファイル: 自然言語の Markdown を新規作成または書き直す前に、llm-wiki/SKILL.md の Writing Profile Resolution セクションを読み、適用してください。フレームワークのスキーマ、出典、安全性、および操作固有の要件が優先されます。
インポートしたソースの文章は保持してください。WRITING.md の設定は、新しく生成するメタデータまたはスタブにのみ適用してください。
- 設定を解決する —
llm-wiki/SKILL.mdの Config Resolution Protocol に従います(インラインの@nameによる上書き → CWD から上位ディレクトリへ.envを検索 → グローバル設定 → セットアップのプロンプト)。これによりOBSIDIAN_VAULT_PATHが得られます。 $OBSIDIAN_VAULT_PATH/AGENTS.mdが存在する場合は読み、所有者固有の規約を適用します。
Step 1: ソースを見つけて種類を判定する
インポート元を見つけます:
- ユーザーがパス引数を指定した場合は、そのパスを直接使用します。
- それ以外の場合は、次の順に自動検出します。
./wiki-export/okf/(ディレクトリ)→./wiki-export/graph.json(ファイル)。 - どちらも存在しない場合は、ユーザーにパスを尋ねます。
ソースの種類を判定します:
- パスが
.jsonで終わるファイル → graph.json インポート(以下の検証を行い、Step 3 と Step 4-Graph に進みます)。 - パスが
.mdファイルを含むディレクトリで、そのファイルに OKF フロントマター(type:キー)がある、またはルートにokf_versionを含むindex.mdがある → OKF バンドルインポート(Step 3 をスキップし、Step 4-OKF に進みます)。okf_versionが 0.1 と 0.2 のバンドルはどちらも受け付けます。Step 4-OKF はどちらも読み取ります。 - それ以外 → 問題の内容を報告して終了します。
graph.json ソースを検証します:
- 有効な JSON であること
- トップレベルに
nodes(配列)、links(配列)、graph(オブジェクト)のキーがあること - ノードが 1 つ以上あること
検証に失敗した場合は、問題の内容を報告して終了します。
OKF バンドルソースを検証します:
typeが空でないことを含む、解析可能な YAML フロントマターを持つ、予約済みではない.mdファイル(つまりindex.md/log.md以外)が 1 つ以上あること。- フロントマターがない、または
typeがない.mdファイルは、エラーではなくスキップされます(件数を表示します)。OKF のコンシューマーは寛容です(OKF §11)。
インポート前にプレビューを表示します:
graph.json:
Import preview (graph.json — stubs)
Source: <path> (exported at <graph.exported_at>)
Nodes: N total (concepts: A, entities: B, skills: C, references: D, ...)
Links: M edges (X typed, Y untyped)
Target: $OBSIDIAN_VAULT_PATH
OKF バンドル:
Import preview (OKF bundle — full pages)
Source: <dir> (okf_version <ver if present>)
Pages: N total (concepts: A, entities: B, skills: C, references: D, ...)
Target: $OBSIDIAN_VAULT_PATH
Step 2: 競合解決モードを決める
ユーザーの依頼内容からモードを判定します。デフォルトは merge です。
| モード | 判定する表現 | 動作 |
|---|---|---|
merge | (デフォルト、特別な表現なし) | 既存ページ:フロントマターのタグ/概要/リレーションシップを更新し、不足している Wiki リンクを追加します。新規ページ:スタブを作成します。 |
skip | 「既存のものはスキップ」「上書きしない」「新しいページのみ」 | 既存ページには一切手を加えず、まだ存在しないページのみを作成します。 |
overwrite | 「上書き」「既存のものを置き換え」「強制インポート」 | 既存の内容にかかわらず、一致するすべてのページを新たに再構築したスタブで置き換えます。 |
Step 3: 内部マップを作成する (graph.json のみ — OKF バンドルではスキップ)
書き込みを始める前に、links 配列から 2 つのマップを作成します。
隣接マップ — 各ノード ID について、すべての隣接 ID(いずれかの方向のエッジ)を収集します。
adjacency["concepts/transformers"] = ["entities/vaswani", "concepts/lstm", ...]
型付きエッジマップ — 各ノード ID について、出力方向の型付きエッジ(typed: true)のみを収集します。
typed_edges["concepts/transformers"] = [
{target: "concepts/lstm", relation: "contradicts"},
...
]
Step 4-Graph: graph.json からページを再構築する (graph.json ソースのみ)
記録件数:created = 0、skipped = 0、merged = 0。
nodes の各ノードについて:
page_path = $VAULT/<node.id>.mdを計算します- 親ディレクトリが存在することを確認します(例:
$VAULT/concepts/) - ファイルがすでに存在するか確認します:
- マージモード(デフォルト)+存在する → 既存のファイルを読み込み、マージロジック(下記参照)を適用して、
mergedをインクリメントします - マージモード(デフォルト)+存在しない → スタブの作成に進み、
createdをインクリメントします - スキップモード+存在する →
skippedをインクリメントし、次のノードに進みます - スキップモード+存在しない → スタブの作成に進み、
createdをインクリメントします - 上書きモード+存在する → 新しいスタブの書き込みに進み(上書き)、
mergedをインクリメントします - 上書きモード+存在しない → スタブの作成に進み、
createdをインクリメントします
- マージモード(デフォルト)+存在する → 既存のファイルを読み込み、マージロジック(下記参照)を適用して、
ページテンプレート(新規作成または上書き)
---
title: <node.label>
category: <node.category>
tags: <node.tags as YAML list>
sources:
- "imported from <graph.json path>"
<if node.summary exists>
summary: "<node.summary>"
</if>
<if typed_edges[node.id] is non-empty>
relationships:
<for each {target, relation} in typed_edges[node.id]>
- target: "[[<target>]]"
type: <relation>
</for>
</if>
lifecycle: draft
lifecycle_changed: <today YYYY-MM-DD>
base_confidence: 0.5
tier: supporting
created: <ISO timestamp>
updated: <ISO timestamp>
---
# <node.label>
<node.summary paragraph if available, else omit>
## Related
<for each neighbour in adjacency[node.id], sorted alphabetically>
<if edge is typed>
- [[<neighbour>]] — <relation>
<else>
- [[<neighbour>]]
</if>
</for>
adjacency[node.id] が空の場合は、## Related セクション全体を省略します。
マージロジック(マージモード、既存ページ)
- 既存ページのフロントマターを読み込みます。
- タグ:既存のタグと
node.tagsの和集合(重複を除き、既存の順序を維持して新しいタグを追加します)。 - 概要:既存ページに
summaryフィールドがなく、node.summaryが存在する場合は追加します。 - 関連:既存の
relationships:エントリーとtyped_edges[node.id]の和集合とします。同じ(target, type)の組み合わせがすでに存在するエントリーはスキップします。 - 更新日時:
updatedに現在のISOタイムスタンプを設定します。 - 本文:
## Relatedセクションを検索します。存在する場合は、本文内のどこにもまだリンクされていないadjacency[node.id]のウィキリンクを追加します。## Relatedセクションが存在しない場合は、不足しているリンクを含むセクションを追加します。 - 本文の残りの部分は変更しません。
Step 4-OKF: OKF バンドルからページを再構築する (OKF ソースのみ)
記録件数:created = 0、skipped = 0、merged = 0、unparseable = 0。
バンドルのディレクトリツリーを走査します。予約ファイル(index.md、log.md)以外の各.mdファイルについて:
- YAML フロントマターを解析します。フロントマターがない場合、または空でない
typeがない場合は、unparseableをインクリメントしてファイルをスキップします。 - コンセプト ID を計算します。バンドルのルートからのファイルパスで、
.mdを取り除いたものです(例:concepts/transformers.md→concepts/transformers)。対象ページは$VAULT/<concept-id>.mdです。 - フロントマターを逆マッピングします(
wiki-exportの Step 3.5 にある正規マッピングテーブルの逆変換です)。title←title。category← 保存された拡張キーcategoryがあればその値。なければコンセプト ID のディレクトリプレフィックスを小文字にします(concepts/…→concepts)。それもなければtypeから導出します(Concept→concepts、Entity→entities、Skill→skills、Reference→references、Synthesis→synthesis、Project→projects、Journal→journal)。tags←tags。summary←description。updated← 保存された拡張キーupdatedがあればその値。なければgenerated.at、それもなければレガシー v0.1 のtimestamp、それもなければ現在時刻です。created← 保存された拡張キーcreatedがあればその値、なければ現在時刻です。sources← OKF のsourcesを文字列のリストとして扱います。マッピングである各エントリからはresourceを取得し、通常の文字列はそのまま保持します(古いエクスポート由来の v0.1 バンドルでは、この形式でネイティブリストが格納されていました)。バンドルにsourcesがない場合は、["imported from OKF bundle <bundle path>"]を使用します。トップレベルにresourceURL があり、まだリストに含まれていない場合は追加します。lifecycle← 保存された拡張キーlifecycleがあればその値。なければstatusから設定します。draft→draft、deprecated→archived、stableまたは未指定の場合はlifecycleを設定しません。(OKF にはreviewed/verified/disputedに相当するものがないため、保存されたキーを通じて復元されるのは独自のエクスポートのみです。)- その他の保存された拡張キー(
relationships、lifecycle_changed、tier、base_confidence、…)と、OKF 専用キーのgenerated、verified、stale_after、usage_windowはそのまま引き継ぎます。これにより、後続のエクスポートでも情報を損なわずに往復変換できます。単独のverifiedマッピングは、要素が1つのリストとして扱います(OKF §5.2)。 - ただし、独自のエクスポーターが導出したものは除きます。
generated.byがobsidian-wiki/で始まる場合はgeneratedを削除します(updatedから計算されたためです)。また、byがhuman:vault-ownerのverifiedエントリは削除します(転送されないソース Vault の信頼台帳から計算されたためです)。これらを保持すると、ソースページにはなかったキーが追加されてしまいます。他の生成元によるgeneratedまたはverifiedブロックは保持します。
- 本文のリンクを逆変換します。
.mdパスを指す Markdown リンクを Wiki リンクに変換します(これにより、実際の相互リンクと、wiki-exportの Step 3.5 に従ってエクスポーターが保持した前方参照の両方が復元されます)。[text](../concepts/transformers.md)または[text](/concepts/transformers.md)→ パスを解決し(相対パスはこのファイルのディレクトリを基準にし、/で始まる絶対パスはバンドルルートを基準にします)、コンセプト ID に変換して[[concepts/transformers]]にします。textが対象のタイトルと異なる場合は[[concepts/transformers|text]]にします。対象のタイトルは、バンドル内にページが存在する場合はそのページから取得します。存在しない場合、エクスポーターはリンクテキストに対象の ID を出力しているため、textが完全な ID または最後のパスセグメントと一致する場合はエイリアスなしとして扱います。- Markdown のリンク先はまずファイルパスとして扱います。
.mdパスを現在のファイルからの相対パスとして正規化し、解決済みファイルパスの末尾の.mdを取り除いてページ ID を復元します。完全なファイルパスを解決する前に、ディレクトリ走査セグメントから ID を推測しないでください。これにより、projects/social-twitter.mdとprojects/social-twitter/...のようなフォルダーノート形式でも往復変換を維持できます。この場合、../../social-twitter.mdはprojects/social-twitterに復元されます。 - この処理は、対象ページがバンドル内にない場合にも適用します。まだ書き出されていないページを指すパス形式のリンクも、ぶら下がりリンクの
[[wikilink]]に戻します(Obsidian はこれをサポートしており、OKF §11 でも拒否を禁じています)。Markdown リンクのまま残さないでください。 - 設定で
OBSIDIAN_LINK_FORMAT=markdownが指定されている場合は、Markdown リンクを維持し(パスのみ Vault 相対パスに書き換えます)、Wiki リンクには変換しません。 - 外部の
http(s)://リンクと# Citationsセクションは変更しません。
- Step 2 の競合モードを使用してページを書き込みます。
- merge + exists → フロントマターを逆マッピングして既存ページにマージします(
tagsは和集合にし、summary/sourcesは値がない場合にのみ補完し、relationshipsは和集合にし、updatedは更新します)。本文については、OKF に実際の本文が含まれています。既存ページがスタブ(本文が見出しと## Relatedのみ)の場合に限り、既存の本文をバンドルの本文で置き換えます。それ以外の場合は既存の本文を維持し、バンドル内の# Citationsおよび未掲載の##セクションを追加します。mergedをインクリメントします。 - merge + doesn't exist → ページ全体(フロントマターとバンドルの本文全体)を書き込みます。
createdをインクリメントします。 - skip + exists →
skippedをインクリメントして続行します。 - skip + doesn't exist → ページ全体を書き込みます。
createdをインクリメントします。 - overwrite + exists → 既存ページを置き換えてページ全体を書き込みます。
mergedをインクリメントします(サマリーではReplacedと表示します)。 - overwrite + doesn't exist → ページ全体を書き込みます。
createdをインクリメントします。
- merge + exists → フロントマターを逆マッピングして既存ページにマージします(
- 書き込む前に、親ディレクトリ(
$VAULT/concepts/など)が存在することを確認します。 graph.json のパスとは異なり、## Relatedのスタブセクションは生成しないでください — バンドルの本文にはすでに実際のクロスリンクが含まれています。
ステップ 5: Vault メタデータを更新する
.manifest.json
graph.json ファイルの正規パスをキーとする新しいエントリを追加します:
"<absolute path to source>": {
"ingested_at": "<ISO timestamp>",
"source_type": "wiki-export",
"pages_created": ["list/of/created/pages.md"],
"pages_updated": ["list/of/merged/pages.md"]
}
graph.json インポートの場合は source_type を "wiki-export" に、OKF バンドルインポートの場合は "okf-bundle" に設定します。エントリのキーにはソースの絶対パス(graph.json ファイルまたはバンドルディレクトリ)を使用します。
さらに、以下をインクリメントします:
stats.total_sources_ingestedを 1 増やすstats.total_pagesを実際に作成されたページ数だけ増やす(スキップ/マージされたものは含めない)
.manifest.json が存在しない場合は、標準構造で作成します:
{
"stats": {
"total_sources_ingested": 1,
"total_pages": <created count>
},
"<graph.json path>": { ... }
}
index.md、log.md、hot.md
ロックされた呼び出しを 1 回行います。インデックスは現在ディスク上にあるページから再調整されるため、作成またはマージされたすべてのページが、規定の ( #tag) の間隔でそれぞれのカテゴリの下に配置されます:
obsidian-wiki memory sync IMPORT \
source="<bundle path>" \
pages_created=<N> pages_skipped=<K> pages_merged=<M> \
--takeaways "Imported <bundle>: <what it adds to the picture>"
インポートによって全体像が変わらない場合は --takeaways を省略します。以前の takeaways がそのまま引き継がれます。index.md、log.md、hot.md を手動で編集しないでください — このコマンドは、並行して書き込む他のプロセスがあなたの更新を失わせないようにするロックを取得します。
完全な手順については .skills/llm-wiki/references/MEMORY.md を参照してください。
ステップ 6: サマリーを出力する
Wiki import complete → $OBSIDIAN_VAULT_PATH
Source: <source path> (<graph.json | OKF bundle>)
<graph: exported at <graph.exported_at>, N nodes, M links | okf: N pages, okf_version <ver>>
Created: <X> pages
Merged: <Z> pages (existing pages updated)
Skipped: <Y> pages (only when --skip mode was used)
Skipped の行は、skip モードが明示的に要求された場合にのみ表示します。overwrite モードが使用された場合は、マージされたページを代わりに Replaced としてラベル付けします。OKF インポートの場合、U > 0 のときは Unparseable: <U> files (no frontmatter/type, skipped) も報告します。
注意事項
- スタブと完全なページ: graph.json インポートはスタブを生成します — 構造とウィキリンクはありますが本文はなく、将来の取り込みのための出発点となります。OKF バンドルインポートは実際の本文を伴う完全なページを生成します — これはロスレスでコンテンツを含む経路であり、Vault 間の転送に適した選択肢です。
- 再実行は安全です: デフォルトの
mergeモードは冪等です — 変更されていないエクスポートに対して再実行するとタイムスタンプは更新されますが、コンテンツは破壊されません。overwriteは、ページを完全にスタブにリセットしたい場合にのみ使用してください。 - ディレクトリの作成: ページを書き込む前に、必ず不足しているカテゴリディレクトリを作成してください。
- 壊れたウィキリンク: ページは同じエクスポートから一緒に作成されるため、ほとんどのリンクは解決されます。
linksで参照されているがnodesに存在しないノード(元のエクスポートで壊れているもの)は、依然としてウィキリンクとして表示されます — 対応するページファイルが存在しないだけであり、これは有効です。 - フィルタリングされたエクスポート: ソースの
graph.jsonが可視性フィルタリング付きで生成された場合(graph.metadataに記載)、インポートされるページはフィルタリングされたセットのみを反映します。graph.graphにfilteredキーが含まれている場合は、サマリーにこの点を記載してください。