A vault for AI and users read-only query layer. It finds evidence, ranks and cites; it does not organize directories, maintain indexes, or change state; hidden config directories and all file/directory symlinks are skipped to avoid reading private content outside the vault. If query results involve ingestion status, they must distinguish captured、organized from the complete receipt of the five-part contract; a search hit itself is not proof of completed organization.
Customer-readable description
What this skill can do
- Search Markdown, Bases, requirements and common UTF-8 code files by filename, body text, frontmatter fields or tags.
- For PDF, DOC/DOCX, PPT/PPTX, XLS/XLSX, images and audio/video, search by filename, path, extension and inbound links; attachment body text is preferably retrieved via verified Omnisearch/Text Extractor or
obsidian-mcp-serverretrieval, and only when connection is impossible does it go through an explicit OCR/conversion process. - Look up the wikilink inbound links of a note.
- Count partitions and file types, helping the AI narrow the scope before reading body text.
- Using
10 当前 → 20 精选长期知识 → 30 证据 → 40/50/60 专项 → 20 历史导入 → 90 历史as the default ordering, and clearly marking the source layer; in area 20, only10_主题知识/、20_规范与手册/、30_学习指南/is marked asstable,90_历史导入/is marked asimported, and it does not automatically gain credibility from its path. 90_系统归档/60_整理与迁移记录/is further subdivided intohistory/evidence: first read that area's navigation to identify the canonical version andsuperseded_by, and old reports, machine inventories and old paths are used only to explain the process at that time.
How customers use it
Provide the vault path and the question/keywords. When only an answer is requested, the Agent does not modify any files. First read the root and hit-area rules, then narrow candidates according to the search manual below, and finally open only the files sufficient to answer the question.
Dependencies and installation
The local deterministic backend only needs Python 3; it does not build a persistent index. The attachment full-text backend recommends Obsidian's Omnisearch + Text Extractor; AI integration optionally obsidian-mcp-server. Semantic recall optionally uses QMD, but it cannot replace exact search.
Install the entire domain (Claude Code and Codex share the same domain plugin):
claude plugin marketplace add soia-team/soia-open-skills
claude plugin install soia-pkm-vault@soia
Install only this one skill:
npx skills add soia-team/soia-open-pkm-vault-skills -g -a '*' -s soia-pkm-query-vault -y
WorkBuddy 's loading unit is role-based experts rather than plugins,npx skills add -a '*' cannot cover it, so it needs separate installation, see docs/install/workbuddy.md。
Private information and intermediate data
By default skip all hidden directories,.git、.obsidian, credential/config directories and binary body text. For attachment body text, report external backend hits first; if the backend is unavailable, explicitly fall back to filename/path hits, then extract on demand in a temporary run directory while preserving the source and hash. Normal results output short snippets of matching lines; for historical imports, accounts, security or other sensitive corpora, first add --no-snippets, returning only paths and match metadata. Scripts do not write persistent caches.
Logs and completion receipt
Results must include query time, mode, number of files checked, number of matches, truncation and unreadable counts. The final answer is organized as "current status / stable knowledge / historical evidence", and gives vault-relative paths or wikilinks.
Query commands
# 综合搜索(文件名 + 正文 + frontmatter)
python3 scripts/query_vault.py --vault <vault-path> --query '<keyword>' --json
# 文档地址/文件名:先用 filename,避免被正文重复命中淹没
python3 scripts/query_vault.py --vault <vault-path> --mode filename --query '<document-name>' --json
# 标签或字段
python3 scripts/query_vault.py --vault <vault-path> --mode tag --query '<tag>' --json
python3 scripts/query_vault.py --vault <vault-path> --mode frontmatter \
--field status --query active --json
# 入链与清单
python3 scripts/query_vault.py --vault <vault-path> --mode backlinks --query '<note-name-or-path>' --json
python3 scripts/query_vault.py --vault <vault-path> --mode inventory --json
# 只查精选知识并避免输出正文片段
python3 scripts/query_vault.py --vault <vault-path> --query '<keyword>' \
--path-prefix '20_资料库' --exclude-prefix '20_资料库/90_历史导入' \
--no-snippets --json
# 需求:先查精选区,排除历史导入;需要时再进入 90_历史导入
python3 scripts/query_vault.py --vault <vault-path> --mode content --query '<需求关键词>' \
--path-prefix '20_资料库' --exclude-prefix '20_资料库/90_历史导入' --json
# 代码:默认支持常见 UTF-8 代码/配置扩展;罕见扩展用 --include-ext 加入
python3 scripts/query_vault.py --vault <vault-path> --mode content --query '<class-or-symbol>' \
--path-prefix '60_开源项目' --include-ext .feature --json
# PDF / Word / 图片:优先走 Omnisearch/MCP;不可用时再提取/OCR
python3 scripts/query_vault.py --vault <vault-path> --mode filename --query '<file-or-topic>' --json
python3 scripts/query_vault.py --vault <vault-path> --mode content --query '<extracted-keyword>' \
--path-prefix '20_资料库' --exclude-prefix '20_资料库/90_历史导入' --json
--path-prefix and --exclude-prefix Reusable, and only accepts vault-relative paths;--limit Controls the output limit, and when exceeded truncated=true. When querying strongly time-sensitive facts, the vault only provides leads; you must still verify the latest external sources as required by the task.
Search Manual (must be followed before answering)
1. First determine the question type
| Question | Preferred mode | Preferred scope | Description |
|---|---|---|---|
| "Where is the document/file" | filename |
10 → 20 curated → 90 | Give the path first, then read the navigation or main text |
| "Specification/how to do it" | all / content |
20 curated | Prefer stable knowledge, and return the source and applicable boundaries |
| "Current progress/next step" | all |
10 workspace | Based on the latest updated control plane |
| "This execution/audit conclusion" | all |
30 logs and thinking | Treat only dated evidence as frozen fact |
| "Requirements/acceptance/interface" | content + frontmatter |
20 curated → 10 project | Identify status, scope, acceptance criteria, and source |
| "Code/class/config/SQL" | filename → content |
60 / specified project | Search by symbol or file name first, then read the minimal context |
| "Who references it" | backlinks |
Whole library or specified scope | When paths have duplicate names, the full path must be used |
| "Is this sentence in the PDF/Word/image" | Omnisearch/MCP → temporary extraction/OCR → content |
Specified attachment directory | First distinguish file name hits, plugin body hits, extracted body hits, and OCR hits; if no backend is connected, you cannot claim a body hit |
2. Then sort by hierarchy, not by number of hits
10 当前状态 → 20 精选长期知识 → 30 冻结证据 → 40/50/60 专项 → 20 历史导入 → 90 归档。20_资料库/90_历史导入 By default it is only an imported lead, and it cannot be upgraded to a stable conclusion just because it has many hits; 90-area organization records must also be sorted by canonical/historical version chain.
3. Specific steps for requirements and code
- Use proper nouns, interface names, class names, or error codes from the requirements to do
filename/contentexact search. - If there are no hits, split into 2–3 short keywords and query them separately; do not treat an entire natural-language sentence as a file name.
- For code, first search for definition symbols, then search for call symbols, config keys, and test names; restrict to a project by path to avoid misjudging same-named items across projects.
- For
.java、.py、.ts、.yaml、.jsonand other common UTF-8 files, search the body by default; for rare extensions use--include-ext <.ext>。 - Finally, open only the minimal set of files that can support the answer, and mark the version, source, and whether verification is needed.
For questions like "find the document address of a component and briefly introduce its usage", always execute in the following order:
filenameSearch for the component name, Chinese aliases, and使用手册, first locking down the 20-area navigation and the actual attachment path.- Open the stable navigation in area 20 and confirm the link target; for file names with decimal points, match by the full file name first, and do not treat the version number as an extension.
- For attachments such as PDF/DOCX, report
filename_hit; only if Omnisearch/Text Extractor, MCP, or temporary extraction succeeds, appendcontent_hit, and record the page number/extractor/hash. - Return "document address + usage summary + source tier + match type"; if only the filename matches, explicitly state "the body has not yet been parsed," and do not pass off RAG or semantic candidates as facts.
3.1 Attachment Search Support Matrix
| Type | Filename/Path | Body | Default Handling |
|---|---|---|---|
| Supported | Omnisearch/Text Extractor or explicit PDF extraction/OCR | Scanned PDFs must be marked with OCR and location | |
| DOCX | Supported | Omnisearch/Text Extractor or Word extractor | Preserve the original DOCX and source hash |
| DOC (legacy format) | Supported | Requires an external converter; the current query skill does not parse it directly | If conversion fails, only report a filename match |
| PPT/PPTX、XLS/XLSX | Supported | Requires the corresponding converter or extraction pipeline | Do not read table/slide binaries as UTF-8 |
| Images such as PNG/JPG/GIF/WebP | Supported | Omnisearch/Text Extractor or explicit OCR | OCR results must be marked ocr and allow manual verification |
| Audio/Video | Supported | Requires a transcription skill to generate text | The query skill only searches filenames or transcripts |
soia-pkm-query-vault itself does not upload files, does not maintain plugin caches, and does not overwrite OCR/extraction results back onto the original attachments. When no Omnisearch/MCP/extractor is available, the receipt must explicitly state "filename/path match only."
For multimedia selection, sidecar fields, plugin inspiration, and phased rollout, see references/multimedia-search-options.md。
4. Result Interpretation and Security Boundaries
layer=current/stable/evidence/specialized/imported/historyis a source tier, not automatic proof of factual truth.needs_review、deprecated、superseded_by, old dates, or historical paths must be explicitly flagged in the answer.- When
90_系统归档/60_整理与迁移记录is matched, the result must includeevidence_class(migration/reorganization/resource reference/verification cleanup/handover/historical version) and a "represents only the state at that time" note; when v1/v2/v3 all match, give the canonical version first, then list the superseded versions. - When historical imports, security, accounts, or private corpora are involved, use
--no-snippets, and initially return only paths and metadata. - This skill's deterministic backend defaults to keyword/structural retrieval; it does not upload content and does not enable RAG. Only when the user explicitly enables local semantic retrieval should independent index layers such as QMD/Smart Connections be added, and vector results be downgraded to candidate recall.
- Search is always read-only: do not move, delete, modify frontmatter, update maps, or create to-dos.
- When querying "whether it has been organized/archived," read the five-part receipt generated by the management skill; if it lacks
MOC/导航、maporBaseevidence, it can only be reported as partially complete or unknown, and completion must not be inferred. - Directory numbering or legacy path migration is handled by
soia-pkm-manage-vault-lifecycle; do not rename directories yourself during a query.
AI Reading Flow
- Read root
AGENTS.md, and confirm the partition semantics of the client vault. - First search narrowly by filename/tag, then read the body; do not load large files across the entire library at the outset.
- For the current task, look first at section 10; for methods and specifications, prioritize the curated directory in section 20; when temporal evidence is needed, supplement with section 30; for specialized reading/writing/project research, go to sections 40/50/60;
20_资料库/90_历史导入and 90 are only read during traceability. - When multiple files with the same name are hit, use the path, not fuzzy short-link guessing.
- Compare
updated, date,superseded_by, archive tags, and body correction notes; search ranking is not equal to factual priority. - In the answer, cite the files that truly support the conclusion, and clearly mark old materials, drafts, pending confirmation, or conflicts.
Boundaries
- Do not modify Markdown, frontmatter, Bases, maps, or git status.
- Do not save the index to the vault or the user directory.
- Do not mix health risk judgments into ordinary queries; dead-link/tag audits go to the health skill.
- Do not automatically create to-dos or archives because of search hits; lifecycle actions go to the lifecycle skill.
- When the user requests complete documents, still comply with permission, privacy, and copyright boundaries.
Acceptance
- The content hashes of the vault file tree are consistent before and after the run.
- The JSON includes
checked_at、matches、truncated、unreadable、scanned_files、searchable_extensions, path scope, and snippet status. - Chinese, path filtering, inline/multiline tags, frontmatter, and backlinks fixtures can all be hit.
- The requirements/code fixture can hit body text such as
.java、.yaml, and rare extensions can be added via--include-ext. - Attachment acceptance must distinguish filename hits from body hits; body hits for PDF/DOCX/OCR require evidence of the extraction process, and when the backend is missing, stably return "unparseable/filename only".
--no-snippetsThe results of do not include hit body text or frontmatter values.- The final answer can distinguish current, stable, and historical sources, and does not treat old status in the 90 area as the current state.