- Skill ID
- ar9av/obsidian-wiki/wiki-import
- Publisher
- ar9av
- Repository
- obsidian-wiki
- Installs
- 0
- Files
- 1
- Synced
- Sep 23, 2026
Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.
ar9av/obsidian-wiki/wiki-importInstalls these files- SKILL.md
What this skill tells the agent
Wiki Import — Reconstruct Pages from an Export
You are importing a vault's knowledge into the current vault from one of two sources produced by wiki-export:
- `graph.json` — the graph skeleton. Reconstructs page stubs (frontmatter, typed relationships, a
## Relatedlink list — no body). Lossy. - OKF bundle (a
wiki-export/okf/directory) — the actual markdown files. Reconstructs full pages with their real bodies. Lossless. Use this for true vault-to-vault transfer.
Either way, the import writes pages with correct frontmatter and wikilinks, then updates all vault metadata. Step 2, Step 3 (graph only), and Step 5 are shared; Step 4 forks by source type.
Before You Start
Writing profile: Before drafting or rewriting natural-language Markdown, read and apply the Writing Profile Resolution section in llm-wiki/SKILL.md. Framework schema, provenance, safety, and operation-specific requirements take precedence. Preserve imported source prose; apply WRITING.md preferences only to newly generated metadata or stubs.
- Resolve config — follow the Config Resolution Protocol in
llm-wiki/SKILL.md(inline@nameoverride → walk up CWD for.env→ global config → prompt setup). This givesOBSIDIAN_VAULT_PATH. - Read
$OBSIDIAN_VAULT_PATH/AGENTS.mdif it exists — apply any owner-specific conventions.
Step 1: Locate and Detect Source Type
Find the import source:
- If the user provided a path argument, use it directly.
- Otherwise auto-detect, in order:
./wiki-export/okf/(a directory) →./wiki-export/graph.json(a file). - If neither exists, ask the user for the path.
Detect the source type:
- The path is a file ending in `.json` → graph.json import (validate below, then Step 3 + Step 4-Graph).
- The path is a directory containing
.mdfiles with OKF frontmatter (atype:key), and/or a rootindex.mdwithokf_version→ OKF bundle import (skip Step 3; go to Step 4-OKF). - Anything else → report what's wrong and stop.
Validate a graph.json source:
- Must be valid JSON
- Must have top-level keys:
nodes(array),links(array),graph(object) - Must have at least 1 node
If validation fails, report what's wrong and stop.
Validate an OKF bundle source:
- Must contain at least 1 non-reserved
.mdfile (i.e. notindex.md/log.md) with parseable YAML frontmatter containing a non-emptytype. - A
.mdwith no frontmatter or notypeis skipped (with a count), not fatal — OKF consumers are permissive (OKF §9).
Show a preview before importing:
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_PATHOKF bundle:
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_PATHStep 2: Determine Conflict Resolution Mode
Read the user's phrasing to determine mode. Default is merge.
| Mode | Trigger phrases | Behaviour |
|---|---|---|
merge | (default, no special phrasing) | Existing pages: update frontmatter tags/summary/relationships and add missing wikilinks; new pages: create stub. |
skip | "skip existing", "don't overwrite", "only new pages" | Leave existing pages completely untouched; only create pages that don't exist yet. |
overwrite | "overwrite", "replace existing", "force import" | Replace all matched pages with freshly reconstructed stubs regardless of existing content. |
Step 3: Build Internal Maps (graph.json only — skip for OKF bundles)
Before writing anything, build two maps from the links array:
Adjacency map — for each node id, collect all neighbour ids (edges in either direction):
adjacency["concepts/transformers"] = ["entities/vaswani", "concepts/lstm", ...]Typed edge map — for each node id, collect outgoing typed edges only (typed: true):
typed_edges["concepts/transformers"] = [
{target: "concepts/lstm", relation: "contradicts"},
...
]Step 4-Graph: Reconstruct Pages from graph.json (graph.json source only)
Record counts: created = 0, skipped = 0, merged = 0.
For each node in nodes:
- Compute
page_path = $VAULT/<node.id>.md - Ensure the parent directory exists (e.g.
$VAULT/concepts/) - Check if the file already exists:
- merge mode (default) + exists → read existing file, apply merge logic (see below), increment
merged - merge mode (default) + doesn't exist → proceed to create stub, increment
created - skip mode + exists → increment
skipped, continue to next node - skip mode + doesn't exist → proceed to create stub, increment
created - overwrite mode + exists → proceed to write fresh stub (overwrite), increment
merged - overwrite mode + doesn't exist → proceed to create stub, increment
created
Page template (new or overwrite)
---
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>If adjacency[node.id] is empty, omit the ## Related section entirely.
Merge logic (merge mode, existing page)
- Read the existing page's frontmatter.
- Tags: union of existing tags and
node.tags(deduplicated, keep existing order, append new ones). - Summary: if the existing page has no
summaryfield andnode.summaryexists, add it. - Relationships: union of existing
relationships:entries andtyped_edges[node.id]— skip entries where the same(target, type)pair already exists. - Updated: set
updatedto the current ISO timestamp. - Body: scan for a
## Relatedsection. If it exists, append any missing wikilinks fromadjacency[node.id]that aren't already linked anywhere in the body. If no## Relatedsection exists, append one with the missing links. - Leave the rest of the body untouched.
Step 4-OKF: Reconstruct Pages from an OKF bundle (OKF source only)
Record counts: created = 0, skipped = 0, merged = 0, unparseable = 0.
Walk the bundle directory tree. For each .md file that is not a reserved file (index.md, log.md):
- Parse the YAML frontmatter. If it has no frontmatter or no non-empty
type, incrementunparseableand skip the file. - Compute the concept id = the file's path relative to the bundle root, with
.mdstripped (e.g.concepts/transformers.md→concepts/transformers). The target page is$VAULT/<concept-id>.md. - Reverse-map frontmatter (the inverse of the canonical mapping table in
wiki-exportStep 3.5):
title←title.category← the preservedcategoryextension key if present; else lower-case the directory prefix of the concept id (concepts/…→concepts); else derive fromtype(Concept→concepts,Entity→entities,Skill→skills,Reference→references,Synthesis→synthesis,Project→projects,Journal→journal).tags←tags.summary←description.updated←timestamp(or now if absent).created← the preservedcreatedextension key if present, else now.
More from ar9av
Use this skill in a project
Open any RiverX project, search the Skills panel for ar9av/obsidian-wiki/wiki-import, and install it in one click.
