The PKM loop'smaintenance·support phase: it does not produce new knowledge content; it only ensures that the vault, as infrastructure, is itself clean, trustworthy, and traceable — links don't break, tags don't drift, the map doesn't go stale, and there's a record of what the AI changed.
Client-readable description
What this skill can do
Obsidian vault maintenance skill (support type) — three workflows: ① Weekly maintenance (lint four-category health check + weekly brief) ② Full-vault map regeneration ③ AI session log ingestion (Claude Code / Codex dual platform). The underlying mechanical scripts are pure Python stdlib / bash, parameterized to support any vault path, with no hardcoded specific vault
| The client wants | The skill will do | The client can see |
|---|---|---|
| Complete the work covered by this skill | Read the user request, necessary context, and this skill's body workflow, and execute the minimal reliable steps | The client will see Obsidian/vault file changes, terminal logs, generated artifact paths, and the final receipt. |
| Missing dependencies, permissions, configuration, or keys | Stop actions that require external state, and clearly point out what is missing | Install commands, application addresses, configuration paths, or questions that need client confirmation |
| Execution completed | Summarize successes, skips, failures, file changes, and verification results | A completion receipt that can be copied into a ticket/log |
How the client uses it
- State the goal in natural language and provide the necessary inputs: files, URLs, repo, workspace, proposal, vault, or platform account status.
- The Agent first determines whether this skill is triggered, then checks dependencies, configuration, permissions, and risky actions.
- For actions that can be dry-run or previewed, provide a preview first; when deletion, overwriting, sending, publishing, or writing remote state is involved, ask the client for confirmation first.
- After execution, verify the real output; do not substitute "looks successful" for evidence.
- The final reply must give the client a visible summary: what was done, log summary, file changes, issues, and next steps.
Dependencies and installation
Install this skill (single skill):
npx skills add soia-team/soia-open-pkm-vault-skills -g -a '*' -s soia-pkm-maintain -y
Configuration conventions:
~/.config/soia-skills/soia-pkm-maintain/config.yml
SOIA_PKM_MAINTAIN_CONFIG_FILE=<custom-config-path>
- If this skill does not need private configuration, you may skip creating
config.yml。 - If an API key, cookie, session, provider home, or local path is needed, it can only go into a private
config.yml, the process environment, or the provider's own login state; it must not be written into the repo, vault body, or logs. - Strong dependencies, optional dependencies, and third-party skill relationships must be based on this
SKILL.md's subsequent "dependencies / prerequisites / resources / boundaries" description; if it is not clearly stated, first supplement the description or ask the client, and do not guess. - Third-party skills may only declare dependencies and installation methods; do not directly modify third-party skill files.
Logs and completion receipt
Every execution must let the client see the process and results. Minimum receipt format:
完成:<一句话说明本次完成了什么>。
日志摘要:
- started: <检查到的输入/配置/依赖,不打印秘密值>
- processed: <数量或范围>
- created/updated: <数量或路径>
- skipped/failed: <数量和原因>
文件变化:
- <绝对路径或“未改动文件”>
验证:
- <运行过的检查、命令或人工核对点>
问题与下一步:
- <缺 key / 缺依赖 / 需要客户确认 / 建议下一条命令;没有则写“无”>
Positioning
Over time, a vault accumulates three types of "infrastructure debt":
- Content rot: Dead links, duplicate file names, tag drift, and time-sensitive articles that are overdue for review — they don't affect whether a single note can be read, but they drag down the credibility of retrieval and MOC aggregation.
- Outdated map: The overall vault structure has changed,
OB知识库地图.mdyet this kind of overview snapshot remains in its old state. - No trace of AI changes: Multiple AIs (Claude Code / Codex) are all modifying the vault, but what was changed and when has no unified record.
This skill addresses these with three workflows respectively: ① health check + weekly brief, ② regenerate the map, ③ session log ingestion. All aremechanical-layer scripts + AI judgmentcombinations — scripts handle deterministic scanning/generation, AI handles reading reports, writing briefs, and aligning configuration changes with the user.
Prerequisites
- Obsidian vault (any directory structure; scripts do not assume fixed section naming)
- Python 3, pure stdlib (
lint_vault.py/gen_vault_map.pyno third-party dependencies) - bash(
session_end_log.sh/codex_notify_wrapper.sh) --vault <path>, or privateconfig.ymlin theenv.OBSIDIAN_VAULT(choose one,--vaulttakes priority)- Soft dependency
soia-pkm-organize-article-moc: MOC rebuilding and topic categorization are its responsibility; this skill only references it, does not reimplement it— if the "duplicate file name" in the lint report is a case that requires MOC merging, hand it off tosoia-pkm-organize-article-mocfor handling
Trigger words
| User says | invoke |
|---|---|
| "vault weekly maintenance" "run weekly maintenance" | Workflow ①: lint four-category health check + weekly brief |
| "rebuild vault-wide map" "update knowledge base map" | Workflow ②: regenerate OB知识库地图.md |
| "ingest session log" "configure session log" | Workflow ③: Claude Code / Codex session log ingestion |
Workflow ① Weekly maintenance (lint + weekly brief)
-
Run the health check script:
python3 scripts/lint_vault.py --vault <path>Get four categories of findings: dead link wikilinks / duplicate file names / primary tag drift / expired articles.
-
AI summarizes and writes the weekly brief, output path:
<vault>/<周报目录>/<YYYY>-W<ISO周数>-vault周报.mdExample:
2026-W28-vault周报.md(ISO week number taken from the current day'sdate.isocalendar()week number, zero-padded to two digits).frontmatter:
--- tags: [周报] created: <YYYY-MM-DD> ---Body skeleton (all four sections must be written; for anything with no findings, always write "none"; do not omit an entire section):
- Statistics on articles newly added in the past 7 days(AI uses
git logor scans by file name date for newly added.md) - Four categories of lint findings(dead links / duplicate file names / primary tag drift / expired articles; write "none" if empty)
- Safe fixes already performed(those already directly changed by AI in this round; see step 4)
- List of items recommended for manual handling(items that are uncertain and require user judgment)
- Statistics on articles newly added in the past 7 days(AI uses
-
MOC merging declares a dependency on
soia-pkm-organize-article-moc: if behind the discovered duplicate file names/tag drift is "needs re-categorization/merging of MOCs," this skill does not make that judgment; it only flags it in the brief and recommends connecting tosoia-pkm-organize-article-moc, without overstepping to reimplement its topic categorization logic. -
Onlyitems that can be determined to be safe fixesOnly directly modify items that are certain (for example, a broken link is clearly a typo in capitalization/an extra space, and can be matched one-to-one to a unique file with the same name); whenever there is ambiguity (for example, there is more than one candidate file with the same name, or tag drift may be an intentional new category), only write it into the brief and do not modify content on your own.
Workflow ② Full-vault map regeneration
python3 scripts/gen_vault_map.py --vault <path> # 覆盖 <vault>/20_资料库/OB知识库地图.md
python3 scripts/gen_vault_map.py --vault <path> --output /tmp/x.md # 干跑预览,不碰 vault
Traverse the entire vault directory tree,.md render them as clickable wikilinks, non- .md list only file names; directories with more than 40 files are displayed compressed (first 2 + last 1 + count). The header's "file count/directory count/GB" statistics and dates are all calculated dynamically at runtime, not hardcoded historical snapshots.
Workflow ③ AI session log integration
Follow references/session-log-setup.md to execute the complete steps (Claude Code's hooks.SessionEnd snippet example, Codex's notify + wrapper integration steps, differences between the two platforms, and uninstall method are all included).
⚠️ Prominent reminder: before writing Claude Code's
.claude/settings.json(hooks) or modifying Codex'sconfig.toml(notify),you must first explain to the user what will be changed and why, and obtain explicit consent; never silently change the configuration. When hooks already exist, "merge and append", not overwrite entirely.
Underlying scripts:scripts/session_end_log.sh(shared by both platforms, relying on --agent to distinguish subdirectories and throttle state files) + scripts/codex_notify_wrapper.sh(Codex-specific wrapper layer, because notify can only attach one command).
Command-line reference
# 工作流① lint 体检
python3 scripts/lint_vault.py --vault <path>
python3 scripts/lint_vault.py --vault <path> --json
python3 scripts/lint_vault.py --vault <path> --exclude "20_资料库/OB知识库地图.md,某目录/某文件.md"
python3 scripts/lint_vault.py --vault <path> --tags "书库,童书,日记,调研,文章摘抄,阅读记录,阅读计划,重读,周报"
# 工作流② 地图重生成
python3 scripts/gen_vault_map.py --vault <path>
python3 scripts/gen_vault_map.py --vault <path> --output /tmp/preview.md
# 工作流③ 会话日志(一般由 hooks/notify 自动调用,不需要手动跑)
bash scripts/session_end_log.sh --vault <path> --agent Claude-Code
bash scripts/session_end_log.sh --vault <path> --agent Codex
All scripts share the same set of parameterization conventions:--vault <path> or private config.yml 's env.OBSIDIAN_VAULT(choose one,--vault takes precedence), and do not hardcode any specific vault path. The session log directory can be overridden with --log-dir <vault内相对目录> or the private configuration's SOIA_SESSION_LOG_DIR ; the default is 30_日志与思考/20_Agent工作日志. Private configuration precedence:$SOIA_PKM_MAINTAIN_CONFIG_FILE(or compatible alias $SOIA_PKM_MAINTAIN_ENV_FILE)> ~/.config/soia-skills/soia-pkm-maintain/config.yml。
Boundaries and exceptions
| Scenario | Handling |
|---|---|
If --vault is not specified and the private config.yml has no OBSIDIAN_VAULT |
error exit (exit 1), prompting to choose one of the two |
| All four types of lint findings are empty | Write "none" in the weekly brief; do not omit that section |
| Duplicate file names/tag drift in the lint report involve topic categorization decisions | Hand off to soia-pkm-organize-article-moc; this skill does not make categorization decisions |
| WeChat Reading sync requirement | Hand off to soia-pkm-library-weread-sync; this skill does not touch the library data pipeline |
| Library supplemental record / overview generation requirement | Hand off to soia-pkm-library-book-catalog; this skill does not touch the library data pipeline |
Session log integration requires changing settings.json / config.toml |
You must first ask the user and obtain consent before writing; never silently change the configuration; existing configuration should be merged, not overwritten |
Codex notify has already been connected to another use (such as a computer-use client) |
Use codex_notify_wrapper.sh wrapper, do not overwrite the original command, see the references document |
lint_vault.py encounters attachment-type wikilinks (images/PDF/office documents, etc.) |
Treat as attachment references and skip dead-link checking (the script only maintains the .md index) |
| Want to dry-run preview the map without overwriting the original vault files | gen_vault_map.py supports --output <临时路径> |
Completion receipt
After executionmustoutput to the user (do not do it silently):
- What was done — a one-sentence summary of the completed work.
- File changes — list newly created / modified / moved files (full paths); if no files were changed, state "no files changed".
- Next steps — optional follow-up suggestions (e.g., connect to
soia-pkm-organize-article-mocto handle MOC merging).