PKM closed loop'smaintenance · support stage: produces no new knowledge content, only ensures that the vault infrastructure itself is clean, trustworthy, and traceable — links don't break, tags don't drift, maps don't go stale, and what AI changed is traceable.
Customer-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
| Customer wants | Skill will do | Customer can see |
|---|---|---|
| Complete the work covered by this skill | Read the user request, necessary context, and this skill's main workflow, and execute the minimal reliable steps | The customer will see Obsidian/vault file changes, terminal logs, generated artifact paths, and the final receipt. |
| Missing dependencies, permissions, configuration, or key | Stop actions that require external state, and clearly state what is missing | Install commands, application URLs, configuration paths, or questions requiring customer confirmation |
| Execution complete | Summarize successes, skips, failures, file changes, and verification results | A completion receipt that can be copied into a ticket/log |
How the customer uses it
- State the goal in natural language and provide the necessary inputs: files, URL, repo, workspace, proposal, vault, or platform account status.
- The Agent first determines whether this skill applies, then checks dependencies, configuration, permissions, and risky actions.
- For actions that can be dry-run or previewed, provide a preview first; for actions involving deletion, overwriting, sending, publishing, or writing remote state, ask the customer for confirmation first.
- After execution, verify the real output; do not substitute "looks successful" for evidence.
- The final reply must give the customer 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-skills -g -a '*' -s soia-pkm-maintain -y
Configuration conventions:
~/.config/soia-skills/soia-open-skills/soia-pkm/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 private
config.yml, the process environment, or the provider's own login state; it must not be written into the repository, vault body, or logs. - Strong dependencies, optional dependencies, and third-party skill relationships must be based on this
SKILL.mdand the subsequent "dependencies / prerequisites / resources / boundaries" description; if it is not clearly written, first supplement the description or ask the customer, 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 customer 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 decay: Dead links, duplicate filenames, tag drift, and time-sensitive articles that are overdue for review — these don't affect whether a single note can be read, but they drag down the credibility of retrieval and MOC aggregation.
- Outdated map: The structure of the whole vault has changed, but
OB知识库地图.mdoverview snapshots like this remain stuck in the old state. - AI changes leave no trace: Multiple AIs (Claude Code / Codex) are all modifying the vault, but there is no unified record of what was changed or when.
This skill uses three workflows to address these respectively: ① health check + weekly brief, ② regenerate the map, ③ ingest session logs. All aremechanical-layer scripts + AI judgmentcombinations — the scripts handle deterministic scanning/generation, and the AI handles reading reports, writing briefs, and aligning configuration changes with the user.
Prerequisites
- Obsidian vault (any directory structure; the 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 a privateconfig.ymlinenv.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 filenames" in the lint report are a case that requires MOC merging, hand it off tosoia-pkm-organize-article-mocfor handling
Trigger words
| The user says | invoke |
|---|---|
| "vault weekly maintenance" "run weekly maintenance" | Workflow ①: lint four-category health check + weekly brief |
| "rebuild the whole-vault map" "update the knowledge base map" | Workflow ②: regenerate OB知识库地图.md |
| "ingest session logs" "configure session logs" | 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 wikilinks / duplicate filenames / primary tag drift / expired articles.
-
The AI summarizes and writes the weekly brief, output path:
<vault>/<周报目录>/<YYYY>-W<ISO周数>-vault周报.mdExample:
2026-W28-vault周报.md(the ISO week number is taken from the week number of the current daydate.isocalendar(), zero-padded to two digits).frontmatter:
--- tags: [周报] created: <YYYY-MM-DD> ---Body skeleton (all four sections must be written; for anything with no findings, write "none" — do not omit entire sections):
- Statistics on articles newly added in the past 7 days(the AI uses
git logor scans by filename date for newly added.md) - Four categories of lint findings(dead links / duplicate filenames / primary tag drift / expired articles; write "none" if empty)
- Safe fixes already performed(those the AI has already directly changed in this round; see step 4)
- List recommended for manual handling(items that are uncertain and require user judgment)
- Statistics on articles newly added in the past 7 days(the AI uses
-
MOC merge declarations depend on
soia-pkm-organize-article-moc: if behind the discovered duplicate filenames/tag drift is a need to "recategorize/merge 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. -
Onlycan be certain it is a safe fixOnly make direct changes to items that are unambiguous (for example, a dead 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); if there is any 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 briefing and do not modify the content without authorization.
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 as clickable wikilinks, not .md only list filenames; directories with more than 40 files are displayed compressed (first 2 + last 1 + count). The header's "file count/directory count/GB" statistics and date are all calculated dynamically at runtime, not hard-coded historical snapshots.
Workflow ③ AI session log integration
Follow references/session-log-setup.md to execute the complete steps (Claude Code's hooks.SessionEnd snippet examples, Codex's notify + wrapper integration steps, differences between the two platforms, and uninstall methods 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 modify the configuration. When hooks already exist, it is "merge and append", not a full overwrite.
Underlying scripts:scripts/session_end_log.sh(shared by both platforms, relying on --agent to distinguish subdirectories and throttling 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 of the two,--vault takes precedence), without hard-coding any specific vault path. The session log directory can be overridden with --log-dir <vault内相对目录> or the privately configured 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-open-skills/soia-pkm/soia-pkm-maintain/config.yml。
Boundaries and exceptions
| Scenario | Handling |
|---|---|
No --vault specified and no private config.yml in OBSIDIAN_VAULT |
Error exit (exit 1), prompting to choose one of the two |
| All four lint finding categories are empty | Write "none" in the weekly briefing, do not omit the section |
| Duplicate filenames/tag drift in the lint report involve topic categorization judgment | 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 book library data line |
| Book library supplemental record / overview generation requirement | Hand off to soia-pkm-library-book-catalog; this skill does not touch the book library data line |
Session log integration requires modifying settings.json / config.toml |
You must first ask the user and obtain consent before writing, never silently modify the configuration; existing configuration should be merged, not overwritten |
Codex notify already has another use (such as a computer-use client) |
Use codex_notify_wrapper.sh wrapper, do not overwrite the original command, see references documentation |
lint_vault.py encounters attachment-type wikilinks (images/PDF/office documents, etc.) |
Treat as attachment references, skip dead link checks (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 quietly finish):
- 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., proceed to
soia-pkm-organize-article-mocto handle MOC merging).