From zkfy
Search the Obsidian Zettelkasten vault for notes matching a natural language query. Uses a tiered retrieval system: fast index lookup (Tier 0) → synthesis dedup (Tier 0.5) → grep-based fallback (Tiers 1-3). Works from any working directory. Use when you need to find related notes, check what exists on a topic, or gather context before creating new notes.
npx claudepluginhub jasonsie/zkfy --plugin zkfyThis skill uses the workspace's default tool permissions.
Search the ZK vault for notes matching a natural language query. Returns ranked results with paths, matched metadata, and abstract excerpts.
Mandates invoking relevant skills via tools before any response in coding sessions. Covers access, priorities, and adaptations for Claude Code, Copilot CLI, Gemini CLI.
Share bugs, ideas, or general feedback.
Search the ZK vault for notes matching a natural language query. Returns ranked results with paths, matched metadata, and abstract excerpts.
$ARGUMENTS — <query> [--limit N] [--vault PATH]
"front-end career developing suggestion", "XSS 攻擊防禦", "React performance optimization". — current working directory, i.e., run from inside your vault)Analyze the query and produce a flat list of search terms to drive all tiers:
"front-end career developing suggestion" → frontend, career, developmentfrontend / front-end / web前端, 職涯, 學習路徑)XSS, CORS, DP, DSA)interview-prep, career, learning-strategyinterview-prep, career, learning-strategy, performance, security,
testing, debugging, design-pattern, architecture, api-design,
concurrency, state-management, type-system, beginner, advanced,
reference, cheatsheet, stubProduce a deduplicated flat list of all search terms. Track which terms come from the original query vs. generated synonyms.
Before running grep-based tiers, check if .claude/index.md exists in the vault root.
If index.md does NOT exist:
⚠ No index found. Run /vault-index --full to build it.If index.md exists, run two phases:
.claude/index.md## Keyword Index section- <term>: (case-insensitive)[[NoteNames]] from matching linesIf Phase A yielded < limit results, scan enriched entry lines:
- [[)[[ and ]])— and |)cats:, sub:, tags:, aka: field valuesEarly exit: If Phase A + Phase B yields ≥ limit results → skip all grep tiers, jump to Tier 0.5. If some results but < limit → proceed to Tier 1 but merge with Tier 0 results.
After Tier 0 (and before grep tiers), check the current result set for prior synthesis notes:
Type: permanent in the note (read first 10 lines if needed)[SYNTHESIS]Synthesis notes are created by /query-to-note — finding one means this question may have already been answered and filed.
Only reached if Tier 0 yielded < limit results or index.md is missing.
1a. Search Aliases — for each primary keyword and synonym:
Grep pattern: ^Aliases:.*{term}
Path: {vault_root}
Glob: **/*.md
Case-insensitive: true
1b. Search Filenames — for each primary keyword:
Glob pattern: **/*{term}*.md
Path: {vault_root}
Exclude from all searches:
y.template/, row/, row/assets/, x.temp/, docs/,
.obsidian/, .claude/, .agents/, .prompts/, .github/, .instructions/
Merge Tier 1 results. Score: 25 pts per note, +5 per additional matched term.
If Tier 0 + Tier 1 yields ≥ limit → skip Tier 2 and Tier 3.
Catches topical matches not covered by exact aliases.
For each remaining search term:
Grep pattern: ^(Categories|Sub-Categories|tags):.*{term}
Path: {vault_root}
Glob: **/*.md
Case-insensitive: true
Add new matches (not already found). Score: 20 pts per note, +5 per additional matched term.
If Tier 0 + Tier 1 + Tier 2 ≥ limit → skip Tier 3.
For queries with few results after Tier 2, search note bodies:
Grep pattern: {term}
Path: {vault_root}
Glob: **/*.md
Case-insensitive: true
Restrict to primary keywords only (not all synonyms) to avoid noise. Add new matches. Score: 10 pts per note, +5 per additional term.
For each result note (up to limit), use the Read tool to extract the first 25 lines and parse:
Type, Categories, Sub-Categories, Aliases, tags### Abstract or ## Abstract until next heading or 10 lines## Vault Search: "{original query}"
Found {N} notes ({X} index matches, {Y} grep matches):
### 1. {Note-Filename.md} {[SYNTHESIS] if applicable}
- **Path**: {relative path from vault root}
- **Match**: {tier}: {matched term}
- **Categories**: {categories} **Tags**: {tags}
- **Aliases**: {aliases}
- **Abstract**:
> {abstract excerpt, max 5 lines}
### 2. ...
---
Vault: {vault_root} | Index: {used/missing} | Terms searched: {terms list}
No results found:
000.Index/ MOC files for topic discoveryRun /vault-index --full to enable fast searchChinese-only query:
Aliases field and Keyword Index both contain CJK — these are the primary Chinese match surfacesSingle-word or ambiguous query:
--vault override:
Synthesis note found (Tier 0.5):
[SYNTHESIS] label/query-to-note) can use this to offer dedup optionsThe vault uses this frontmatter schema:
Type: literature # or: permanent (synthesis from /query-to-note)
Categories: [Web, Security] # Title Case domain + secondary
Sub-Categories: [xss, injection] # lowercase-kebab topics
Aliases: [XSS, Cross-Site Scripting, 跨站腳本攻擊] # 3-5 search terms incl. CJK
tags: [security, interview-prep] # cross-cutting controlled vocab
Tags vocabulary (18): interview-prep, career, learning-strategy, performance, security, testing, debugging, design-pattern, architecture, api-design, concurrency, state-management, type-system, beginner, advanced, reference, cheatsheet, stub
When qmd is installed, vault-search gains a Tier -1 that supersedes all other tiers:
which qmd — if not found, skip to Tier 0qmd search "<query>" --path <vault_root> --limit <limit># macOS via Homebrew
brew install tobi/tap/qmd
# or from source
go install github.com/tobi/qmd@latest
qmd also provides an MCP server. If configured in .mcp.json, use the mcp__qmd__search tool instead of shelling out — no CLI install needed.
Use qmd when the vault exceeds ~5000 notes and the index-based Tier 0 becomes the bottleneck.