| name | generate-links |
| description | 分析指定文件夹内的 Obsidian 笔记,基于共享 tags 和内容相似度自动识别相关笔记对,生成 [[双链]] 互链。触发时机:用户要求建立笔记关联、生成文件夹内链接、连接相关内容时。 |
Skill: generate-links(相关笔记链接生成)
触发时机
用户希望为某个文件夹内的笔记自动建立 [[双链]] 关联时。
输入
- 目标文件夹路径(用户指定,或询问后确认)
- 相关性阈值(默认 3,用户可调整)
执行步骤
Step 1: 确认目标文件夹
- 用户已指定路径 → 直接使用
- 未指定 → 询问:"要为哪个文件夹生成链接?"
- 确认目录存在(
ls 检查)
- 确认目录下有 ≥2 个
.md 文件(否则无配对可能,提前终止)
Step 2: 扫描文件
用 find 或 ls 获取目录下所有 .md 文件,排除:
- 隐藏目录/文件(
. 开头)
MOC.md 或 _index.md 文件
对每个文件提取以下元数据:
- 文件名(不含
.md):作为 wikilink 目标和显示名
- frontmatter
tags:读取 YAML frontmatter 中的 tags 字段,处理 [tag1, tag2] 和 - tag1\n- tag2 两种格式
- H1 标题:读取第一个
# 开头的行,作为笔记标题
- 已有 wikilinks:提取文件中所有
[[...]] 的目标(不含别名、锚点),去重得到已有链接集合
- 关键术语:从所有
## 和 ### 标题中提取名词短语(中英文均可),过滤停用词(如"概述""总结""前言""参考"等无实质内容的标题)
Step 3: 计算相关性
对所有文件两两配对(N 个文件产生 N×(N-1)/2 个配对)。
Pass A: Tag 重叠得分
- 文件 A 和文件 B 每个共享 tag → +3 分
- 例:A 的 tags:
[react, hooks, frontend],B 的 tags: [react, typescript]
共享 react → +3 分
Pass B: 内容相似度得分
- 文件 A 和文件 B 每个共享的关键术语(大小写不敏感)→ +1 分
- 关键术语集合来自 Step 2 提取的标题词
- 术语必须在两个文件中都是独立出现的(不只是文件名或一句话中)
总分 = Pass A + Pass B
相关性判定: 总分 ≥ 阈值(默认 3 分)的配对为"相关"
Step 4: 生成链接方案
对每个相关配对:
链接插入位置:
Step 5: 呈现方案 + 用户确认
以表格呈现所有配对:
## 链接方案
文件夹:`path/to/folder/`
文件数:N,配对总数:P,相关配对:R
| # | 文件 A | 文件 B | 得分 | 理由 |
|---|--------|--------|------|------|
| 1 | React Hooks | useEffect 详解 | 7 | 共享 #react, #hooks; 共有 useEffect |
| 2 | 组件设计 | React Hooks | 4 | 共享 #react; 共有组件 |
| ... | ... | ... | ... | ... |
询问用户:
- "Apply all? (全部应用)"
- "Select specific pairs? (选择特定配对,输入编号如 1,3,5)"
- "Adjust threshold? (调整阈值,当前 {threshold})"
- "Preview a specific pair? (预览某个配对的详细 diff)"
Step 6: 写入链接
对每个批准的配对:
- 使用
Read 确认文件当前内容(避免 stale context)
- 使用
Edit 工具精确插入链接行
- 每个文件只打开一次,批量添加所有指向该文件的新链接
最小 diff 原则: 只插入新行,不修改文件其他任何部分。
Step 7: 报告结果
## 链接生成完成
- 分析文件:N 个
- 发现相关配对:R 个
- 实际添加链接:M 个(跳过已存在的 S 个)
- 涉及文件:K 个
产出
- 目标文件被更新(仅在
## 相关笔记 小节追加 [[wikilinks]])
禁止行为
- 不要修改文件除添加
## 相关笔记 小节外的任何内容
- 不要重复添加已存在的双向链接
- 不要编造不存在的 tags 或术语作为理由
- 不要移动或重命名任何文件
- 不要对只有 1 个文件的目录执行(无配对可能)
- 不要未经用户确认直接写入链接