Agent Skills: Linkify Entity

Automatically add [[wikilinks]] to all mentions of existing entities within a file or entire world. Scans for entity names, aliases, and partial matches, then wraps them in wikilink syntax. Use when user wants to "linkify", "auto-link", "add links to existing entities", or "wikilink this file".

UncategorizedID: hopeoverture/worldbuilding-system/linkify

Install this agent skill to your local

pnpm dlx add-skill https://github.com/hopeoverture/Worldbuilding-System/tree/HEAD/.claude/skills/linkify

Skill Files

Browse the full folder contents for linkify.

Download Skill

Loading file tree…

.claude/skills/linkify/SKILL.md

Skill Metadata

Name
linkify
Description
Automatically add [[wikilinks]] to all mentions of existing entities within a file or entire world. Scans for entity names, aliases, and partial matches, then wraps them in wikilink syntax. Use when user wants to "linkify", "auto-link", "add links to existing entities", or "wikilink this file".

Linkify Entity

Linkify: $ARGUMENTS

Overview

This skill scans an entity file and automatically wraps any mentions of existing entities in [[wikilink]] syntax. It's a focused tool that only adds links to entities that already exist—it does NOT create new entities.

Quick Start

# Linkify a specific entity
/linkify "Aldersgate"

# Preview changes without modifying
/linkify "Aldersgate" --dry-run

# Linkify by file path
/linkify Worlds/Eldermyr/Settlements/Aldersgate.md

# BULK: Linkify all entities in a world
/linkify --world Eldermyr

# BULK: Linkify only Characters in a world
/linkify --world Eldermyr --category Characters

# BULK: Preview bulk changes
/linkify --world Eldermyr --dry-run

Instructions

Step 1: Parse Arguments

Required:

  • Entity path or name

Optional Flags: | Flag | Purpose | Default | |------|---------|---------| | --dry-run | Show what would be linked without making changes | false | | --all-worlds | Search all worlds for entities, not just the source entity's world | false | | --case-sensitive | Require exact case matching | false | | --world [name] | BULK MODE: Process all entities in the specified world | - | | --category [type] | With --world: only process entities in this category (Characters, Settlements, etc.) | all |

Step 2: Locate Entity & Determine World

  1. If path provided (contains / or .md):

    • Read the file directly
    • Extract world name from path: Worlds/[World Name]/...
  2. If name provided:

    • Search Worlds/ directories for matching entity
    • Try exact filename match first
    • Then fuzzy match on filename and YAML name: field
    • If multiple matches, list them and ask user to clarify
  3. If not found:

    • List similar entities and ask for clarification

Step 3: Build Entity Index

Create a complete index of existing entities:

  1. Scan all files in Worlds/[World Name]/ recursively (or all worlds if --all-worlds)
  2. For each entity file, extract:
    • Filename (without .md extension) → primary name
    • YAML name: field → canonical name
    • YAML aliases: array → alternative names
  3. Build lookup dictionary (case-insensitive by default):
{
  "Lord Varic Valdren": { path: "Characters/Lord Varic Valdren.md", canonical: "Lord Varic Valdren" },
  "Varic": { path: "Characters/Lord Varic Valdren.md", canonical: "Lord Varic Valdren" },
  "The Merchant Lord": { path: "Characters/Lord Varic Valdren.md", canonical: "Lord Varic Valdren" },
  ...
}

Important: Sort the lookup dictionary by name length (longest first) to ensure longer matches are found before shorter partial matches.

Step 4: Identify Content to Scan

Read the source entity file and identify sections to scan:

INCLUDE these sections:

  • Overview
  • Geography
  • History
  • Demographics
  • Government & Politics
  • Economy
  • Defense & Military
  • Notable Locations
  • Key Figures
  • Secrets
  • Plot Hooks
  • Description
  • Any custom content sections

EXCLUDE these sections:

  • YAML frontmatter (between --- markers)
  • Image Prompts section and everything after it
  • Connections section (already has wikilinks)
  • Code blocks (between ``` markers)
  • Existing wikilinks [[...]]
  • Block quotes used for image prompts (lines starting with > after **Prompt:**)

Step 5: Find Matches

For each entity name/alias in the index (longest first):

  1. Skip if entity is the source file itself (don't self-link)

  2. Search for the name in content:

    • Use word-boundary matching to avoid partial matches within words
    • Match: "Lord Varic Valdren" in "talked to Lord Varic Valdren about"
    • Skip: "Lord Varic Valdren" in "[[Lord Varic Valdren]]" (already linked)
    • Skip: "Stone" in "Aldric Stone" if "Aldric Stone" is a separate entity
  3. Record each match:

    • Line number
    • Exact text matched
    • Canonical entity name (for the wikilink)
    • Surrounding context (5 words before/after)
  4. Handle partial name matches:

    • If "Lord Varic Valdren" exists but text says "Lord Varic", offer to link as [[Lord Varic Valdren|Lord Varic]]
    • If "House Valdren" exists but text says "the Valdren house", consider display text

Step 6: Present Findings

=== LINKIFY ANALYSIS: [Entity Name] ===

World: [World Name]
Source: [path/to/entity.md]
Entities Indexed: X

---

MATCHES FOUND: Y

| # | Text Found | Line | Links To | Context |
|---|------------|------|----------|---------|
| 1 | Lady Serana Valdren | 121 | [[Lady Serana Valdren]] | "...wife, manages court..." |
| 2 | High Confessor Maren | 136 | [[High Confessor Maren]] | "...supporters, seeking..." |
| 3 | Sister Elspeth | 204 | [[Sister Elspeth]] | "...Abbess of the..." |
| 4 | Lord Varic | 117 | [[Lord Varic Valdren|Lord Varic]] | "...ensuring Varic holds..." |

---

PARTIAL MATCHES (display text needed):

| # | Text Found | Line | Suggested Link |
|---|------------|------|----------------|
| 1 | "the Owl" | 123 | [[The Owl|the Owl]] |
| 2 | "young Edric" | 117, 177 | [[Edric Valdren|young Edric]] |

---

AMBIGUOUS (multiple possible matches):

| # | Text Found | Line | Could Match |
|---|------------|------|-------------|
| 1 | "Edric" | 177 | [[Edric Valdren]] or [[Prince Edric the Liberator]] |

---

SUMMARY:
- Exact matches: X
- Partial matches: X
- Ambiguous: X
- Total changes: X

Options:
1. Apply all exact matches
2. Apply exact + partial matches
3. Review each individually
4. Dry run complete (--dry-run flag)

If --dry-run flag is set, show report and stop.

Step 7: Apply Changes

For each approved match:

  1. Build replacement text:

    • Exact match: EntityName[[EntityName]]
    • Partial match: PartialName[[FullEntityName|PartialName]]
  2. Apply using Edit tool:

    • Process from bottom of file to top (so line numbers don't shift)
    • Use precise string replacement with surrounding context for uniqueness
    • Verify each replacement succeeded
  3. Handle duplicates:

    • If the same entity is mentioned multiple times, link ALL occurrences
    • Exception: Don't link the same name twice in the same sentence

Step 8: Validation

After applying changes:

  1. Re-read the file
  2. Verify all intended wikilinks are present
  3. Check no content was accidentally corrupted
  4. Verify wikilinks point to existing files

Step 9: Summary Report

=== LINKIFY COMPLETE: [Entity Name] ===

Changes Applied: X

Links Added:
- [[Lady Serana Valdren]] (line 121)
- [[High Confessor Maren]] (line 136)
- [[Sister Elspeth]] (lines 204, 252)
- [[Lord Varic Valdren|Lord Varic]] (line 117)

Skipped (ambiguous):
- "Edric" (line 177) - multiple matches possible

---

File Updated: [path/to/entity.md]

Suggested Next Steps:
- Review ambiguous matches manually
- Run /audit-world to check bidirectional links
- Use /link-entities to add reciprocal connections

Matching Rules

Word Boundary Matching

Only match complete words/phrases:

| Text | Entity | Match? | Reason | |------|--------|--------|--------| | "spoke to Lord Varic Valdren about" | Lord Varic Valdren | Yes | Complete phrase | | "the Valdren family" | House Valdren | No | "Valdren" alone, different entity | | "visited Aldersgate" | Aldersgate | Yes | Complete word | | "Aldersgates" | Aldersgate | No | Different word | | "[[Lord Varic Valdren]]" | Lord Varic Valdren | No | Already linked |

Partial Name Handling

When text contains a shorter form of an entity name:

| Text | Entity | Link Format | |------|--------|-------------| | "Lord Varic said" | Lord Varic Valdren | [[Lord Varic Valdren|Lord Varic]] | | "the Owl knows" | The Owl | [[The Owl|the Owl]] | | "young Edric" | Edric Valdren | [[Edric Valdren|young Edric]] |

Case Handling

By default (case-insensitive):

  • "lord varic valdren" matches "Lord Varic Valdren"
  • Original case is preserved in display text

With --case-sensitive:

  • Only exact case matches

Exclusion Patterns

Never link:

  • Text inside existing [[wikilinks]]
  • Text in YAML frontmatter
  • Text in code blocks
  • Text in Image Prompts section
  • The entity's own name (no self-linking)
  • Text that's part of a markdown header (# Name)
  • Text in the Connections section (manage links there separately)

Bulk Processing Mode

When --world flag is provided, the skill processes multiple entities:

Bulk Mode Workflow

  1. Scan world directory:

    • List all .md files in Worlds/[World Name]/
    • If --category specified, only scan that folder (e.g., Characters/)
    • Exclude World Overview.md by default (use --include-overview to include)
  2. Build combined entity index:

    • Same process as single-entity mode
    • Index is built once and reused for all files
  3. Process each entity:

    • For each file, run Steps 4-7 (Find Matches → Apply Changes)
    • Track cumulative statistics
  4. Batch report:

    === BULK LINKIFY COMPLETE: [World Name] ===
    
    Files Processed: X
    Files Modified: Y
    Files Unchanged: Z
    
    Total Links Added: N
    
    By Category:
    - Characters: X files, Y links
    - Settlements: X files, Y links
    - Organizations: X files, Y links
    ...
    
    Skipped (ambiguous): N references across M files
    
    Performance: X.X seconds total
    

Bulk Mode Options

# Process entire world
/linkify --world Eldermyr

# Process only one category
/linkify --world Eldermyr --category Settlements

# Dry run to preview bulk changes
/linkify --world Eldermyr --dry-run

# Process multiple categories
/linkify --world Eldermyr --category Characters --category Organizations

Performance Notes

For large worlds (100+ entities), bulk mode:

  • Builds the entity index once (faster than per-file)
  • Processes files in parallel where possible
  • Reports progress every 10 files
  • For very large worlds (300+), consider using scripts/linkify_world.py instead

Examples

# Basic linkify
/linkify "Aldersgate"

# Preview what would be linked
/linkify "Aldersgate" --dry-run

# Linkify checking all worlds for entities
/linkify "Aldersgate" --all-worlds

# Linkify by path
/linkify Worlds/Eldermyr/Settlements/Aldersgate.md

# Case-sensitive matching
/linkify "Lord Varic Valdren" --case-sensitive

Integration with Other Skills

After /create-entity

Run /linkify on newly created entities to link any mentioned existing entities.

Before /audit-world

Run /linkify on key entities to add missing links before the audit.

With /link-entities

  • /linkify adds wikilinks within entity content
  • /link-entities manages the Connections section relationships
  • Use together for comprehensive linking

With /populate-entity

  • /linkify only links to EXISTING entities
  • /populate-entity --links-only does the same thing
  • /populate-entity (full) also CREATES missing entities
  • Use /linkify when you just want to add links without creating anything

Error Handling

File not found:

Error: Could not find entity "[name]"
Similar entities in Worlds/:
- [similar1]
- [similar2]
Please specify the full path or exact name.

No matches found:

=== LINKIFY: [Entity Name] ===

No unlinked entity references found.

This file either:
- Already has all entities properly linked
- Contains no references to other known entities
- References entities that don't exist yet (use /populate-entity to create them)

Write permission error:

Error: Could not write to [path]
The dry-run showed X matches. Please check file permissions.