| name | wiki-tags-refresh |
| description | Scan the vault (or a target directory) for tags used in page frontmatter and page bodies, diff against the vault's tag-index.md, prompt the user to approve new tags and clean stale ones, then update tag-index.md in place. Run after heavy ingest or other large content changes when new concepts may have introduced new tags. Triggers on: wiki-tags-refresh, refresh tags, update tag index, wiki tags, sync tags.
|
| allowed-tools | Read Write Edit Glob Grep Bash |
wiki-tags-refresh
Read skills/wiki-schema/SKILL.md fully before proceeding.
Invoke with: /wiki-tags-refresh [directory]
If no directory argument is given, scan the entire vault (excludes .obsidian/).
Step 1 — Resolve VAULT_PATH and scan scope
Vault path: ~/obsidian_vault by default; set VAULT_PATH to override. WSL users with a Windows-side vault must set VAULT_PATH explicitly (e.g. /mnt/c/Users/<name>/obsidian_vault).
Scan scope: the vault root (default) or the given directory argument.
Step 2 — Read the current tag index
Read .obsidian/copilot/tag-index.md fully. Extract every documented tag (lines matching
`#tagname`).
Step 3 — Collect tags from scanned pages
Scan every .md file under the scan scope for frontmatter tags: entries only.
A broad grep would also match related: wikilinks — use the awk approach below
to stay strictly within the tags: block:
find "<scope>" -name "*.md" -not -path "*/.obsidian/*" -print0 | xargs -0 awk '
FNR==1{front=0; intags=0}
/^---/{if(front==0) front=1; else front=0; next}
!front{next}
/^tags:/{intags=1; next}
/^[a-zA-Z]/{intags=0; next}
intags && /^ - /{gsub(/^ - /, ""); print}
' | sort -u
Note: tags must use the YAML multi-line block form (tags: followed by - tagname lines); inline arrays (tags: [a, b]) are silently skipped by this script. -print0/xargs -0 is required — vault filenames routinely contain spaces (e.g. Daily/2026-07-13 Standup.md), which would otherwise be word-split into separate, unopenable arguments.
Also collect inline tags from page bodies across the same scope:
grep -roh --exclude-dir=".obsidian" "#[a-zA-Z][a-zA-Z0-9/_-]*" "<scope>" | sort -u
Exclude false positives: markdown headings at line start (^#), code blocks, URLs.
Deduplicate the full collected set.
Step 4 — Diff against tag-index.md
- New tags: found in scanned pages (default: entire vault) but NOT documented in
tag-index.md
- Stale candidates: documented in
tag-index.md but found in ZERO scanned pages
(flag only — never auto-remove; they may be used in other vault files)
Step 5 — Report findings
wiki-tags-refresh results
─────────────────────────
New (undocumented in tag-index.md): #newtag #anothertag
Stale (0 uses found): #oldtag #unusedtag
Already in sync: N tags
Step 6 — Process new tags
For each new tag, ask the user:
- "What does
#newtag mean?"
- "Which section of tag-index.md should it go in?"
Present the existing section list as choices + "Other / new section…"
- If the user skips a tag, leave it undocumented.
Step 7 — Process stale candidates
Present the stale list and ask:
"Remove all stale tags from index" — removes only confirmed zero-use tags
"Review one by one" — step through each with keep/remove choice
"Keep all (ignore)" — leave index unchanged for these
Always confirm zero vault-wide use before suggesting removal — the Step 3 scan may have
been narrower than the full vault. Exclude only tag-index.md itself (not all of
.obsidian/): every documented tag appears in tag-index.md by definition, so excluding
the whole .obsidian/ directory would also hide genuine uses in other .obsidian/ files
(e.g. Copilot custom prompts), silently dropping their removal protection.
grep -roh --include="*.md" --exclude="tag-index.md" "#[a-zA-Z][a-zA-Z0-9/_-]*" "<VAULT_PATH>" \
| grep -xF "#tagname" | wc -l
The exact-match filter (-xF) avoids #tagname false-matching a longer tag like
#tagname-extended or #tagname/nested.
If vault-wide count > 0, flag as "used elsewhere in the vault — keep?" rather than suggesting removal.
Step 8 — Update tag-index.md
For approved new tags:
For confirmed removals:
- Remove the entry from its section.
- Do NOT remove from
## Recently Approved Tags (history record).
Do not touch any section not affected by the diff.
Step 9 — Append to _log.md
## [YYYY-MM-DD] tags-refresh | N new tags proposed, M approved, L removed
- New: #tag1, #tag2 (if any approved)
- Removed: #oldtag (if any removed)
Finish
wiki-tags-refresh complete.
Tags added: N Tags removed: M Unchanged: K
tag-index.md updated.