Skill3.5k repo starsupdated today
wiki-export
Wiki Export extracts a vault's wikilink graph into structured formats (JSON, CSV, GraphML) for use in external visualization and analysis tools like Gephi or Neo4j. Use it when you need to analyze page relationships, apply optional filters by project or visibility tags, and generate data suitable for graph databases or custom downstream processing.
Install in Claude Code
Copygit clone --depth 1 https://github.com/Ar9av/obsidian-wiki /tmp/wiki-export && cp -r /tmp/wiki-export/.skills/wiki-export ~/.claude/skills/wiki-exportThen start a new Claude Code session; the skill loads automatically.
Definition
SKILL.md
# Wiki Export — Knowledge Graph Export
You are exporting the wiki's wikilink graph to structured formats so it can be used in external tools (Gephi, Neo4j, custom scripts, browser visualization).
## Before You Start
1. **Resolve config** — follow the Config Resolution Protocol in `llm-wiki/SKILL.md` (inline `@name` override → walk up CWD for `.env` → global config → prompt setup). This gives `OBSIDIAN_VAULT_PATH`
2. Confirm the vault has pages to export — if fewer than 5 pages exist, warn the user and stop
## Project Filter (optional)
If the user's invocation includes a project name — e.g. `/wiki-export prismor`, `"export the prismor project"`, `"export project:security"` — activate **project filter mode**:
1. **Extract the project name** from the argument or phrase. Normalise: lowercase, strip the word "project".
2. Keep only pages where **either** condition holds:
- The page `id` starts with `projects/<name>/` (path-based match)
- The page's `tags` array contains `<name>` (tag-based match)
3. Drop any edge where either endpoint was excluded.
4. Note the filter in the summary: `(filtered: project:<name> — X of Y pages)`
5. Set `graph.graph.filter = "project:<name>"` in the JSON output.
If both a project filter and a visibility filter are active, apply both (project filter first, then visibility filter on the remaining set).
## Visibility Filter (optional)
By default, **all pages are exported** regardless of visibility tags. This preserves existing behavior.
If the user requests a filtered export — phrases like **"public export"**, **"user-facing export"**, **"exclude internal"**, **"no internal pages"** — activate **visibility filtered mode**:
- Build a **blocked tag set**: `{visibility/internal, visibility/pii}`
- Skip any page whose frontmatter tags contain a blocked tag when building the node list
- Skip any edge where either endpoint was excluded
- Note the filter in the summary: `(filtered: visibility/internal, visibility/pii excluded)`
Pages with no `visibility/` tag, or tagged `visibility/public`, are always included.
## Step 1: Build the Node and Edge Lists
Glob all `.md` files in the vault (excluding `_archives/`, `_raw/`, `_readouts/`, `.obsidian/`, `index.md`, `log.md`, `_insights.md`). Apply any active filters (project and/or visibility) after collecting the full file list.
For each page, extract from frontmatter:
- `id` — relative path from vault root, without `.md` extension (e.g. `concepts/transformers`)
- `label` — `title` field from frontmatter, or filename if missing
- `category` — directory prefix (`concepts`, `entities`, `skills`, `references`, `synthesis`, `projects`, or `journal`)
- `tags` — array from frontmatter tags field
- `summary` — frontmatter `summary` field if present
This is your **node list**.
For each page, Grep the body for `\[\[.*?\]\]` to extract all wikilinks:
- Parse each `[[target]]` or `[[target|display]]` — use the target part only
- Resolve the target to a node id (normalize: lowercase, spaces→hyphens, strip `.md`)
- Skip links that point outside the node list (broken links)
- Each resolved link becomes an edge: `{source: page_id, target: linked_id, relation: "wikilink", confidence: "EXTRACTED"}`
- If the linking sentence ends with `^[inferred]` or `^[ambiguous]`, override `confidence` accordingly
**Typed edge enrichment:** After building the wikilink edge list, read each page's `relationships:` frontmatter block. For each `{target, type}` entry:
- The `target` YAML value is a quoted wikilink string such as `"[[concepts/lstm]]"`. Strip the surrounding `[[` and `]]` characters, then apply the same normalization (lowercase, spaces→hyphens, strip `.md`) to get the node id.
- Skip entries whose resolved target is not in the node list (broken link)
- If an edge for this `(source, target)` pair already exists, override its `relation` field with the typed value (e.g., `"contradicts"`) and set `typed: true`
- If no edge exists yet for this pair, add one: `{source: page_id, target: target_id, relation: <type>, confidence: "EXTRACTED", typed: true}`
This means `relation: "wikilink"` is the default for plain untyped links; a `relationships:` entry promotes it to a named semantic type. Edges that originated from both a body wikilink and a `relationships:` entry keep a single record — the typed version wins.
This is your **edge list**.
## Step 2: Assign Community IDs
Group pages into communities by tag clustering:
- Pages sharing the same dominant tag belong to the same community
- Dominant tag = the first tag in the page's frontmatter tags array
- Pages with no tags get community id `null`
- Number communities starting from 0, ordered by size descending (largest community = 0)
This enables community-based coloring in the HTML visualization and tools like Gephi.
## Step 3: Write the Output Files
Create `wiki-export/` at the vault root if it doesn't exist. Write all five files:
---
### 3a. `graph.json`
NetworkX node_link format — standard for graph tools and scripts:
```json
{
"directed": false,
"multigraph": false,
"graph": {
"exported_at": "<ISO timestamp>",
"vault": "<OBSIDIAN_VAULT_PATH>",
"total_nodes": N,
"total_edges": M
},
"nodes": [
{
"id": "concepts/transformers",
"label": "Transformer Architecture",
"category": "concepts",
"tags": ["ml", "architecture"],
"summary": "The attention-based architecture introduced in Attention Is All You Need.",
"community": 0
}
],
"links": [
{
"source": "concepts/transformers",
"target": "entities/vaswani",
"relation": "wikilink",
"confidence": "EXTRACTED"
},
{
"source": "concepts/transformers",
"target": "concepts/lstm",
"relation": "contradicts",
"confidence": "EXTRACTED",
"typed": true
}
]
}
```
---
### 3b. `graph.graphml`
GraphML XML format — loadable in Gephi, yEd, and Cytoscape:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<grap