关于 cross-linker
cross-linker 是用于为 Obsidian wiki 页面补充交叉链接的技能。它结合名称匹配与评分建议,并为新增链接记录关系类型。
主要功能
- 01查找缺失的页面链接
- 02匹配名称与别名
- 03为链接建议评分
- 04添加类型化关系
- 05更新杂项页面亲和度
适用场景
- 01连接新导入的 wiki 页面
- 02查找 vault 中未链接的提及
- 03识别可晋升的杂项页面
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ ar9av/ obsidian-wiki --skill cross-linker安装后在 Claude Code 中输入/cross-linker确认已加载。
详细介绍
Cross-Linker — 自动 Wiki 交叉引用
通过找出并插入缺失的 [[wikilinks]],让 wiki 的知识图谱联系得更紧密:这些页面本应相互引用,但目前却没有。
遵循 llm-wiki/SKILL.md 中的检索原语表。 在第 1 步中,仅通过 grep 检索 frontmatter(不要检索完整页面)来构建注册表。完整的 Read 操作仅用于检测未链接提及;即便如此,也只能读取摘要或标题表明可能是链接目标的页面。盲目读取整个知识库正是这个框架要避免的做法。
开始之前
写作风格: 在起草或改写自然语言 Markdown 之前,先阅读并遵循 llm-wiki/SKILL.md 中的 Writing Profile Resolution 部分。框架架构、出处、安全及具体操作要求优先。
WRITING.md 中的偏好仅适用于新起草或改写的自然语言 Markdown;保留源内容和结构化记录。
- 解析配置 — 遵循
llm-wiki/SKILL.md中的 Config Resolution Protocol(内联@name覆盖 → 沿 CWD 向上查找.env→ 全局配置 → 提示设置)。由此获取OBSIDIAN_VAULT_PATH和OBSIDIAN_LINK_FORMAT(默认值:wikilink)。 - 阅读
index.md,获取页面完整清单及其单行描述 - 浏览
log.md,了解最近导入的内容(将链接工作重点放在新页面上)
在第 4 步插入链接时,根据 llm-wiki/SKILL.md(Link Format 部分)中的链接格式,并使用 OBSIDIAN_LINK_FORMAT 的值。当 OBSIDIAN_LINK_FORMAT=markdown 时,计算从正在编辑的文件到目标页面的相对 .md 路径。
第 1 步:构建页面注册表
遍历知识库中所有 .md 文件(排除 _archives/、_readouts/、.obsidian/)。对每个页面提取:
- 文件名(不含
.md)——这是 wikilink 目标 - frontmatter 中的标题
- frontmatter 中的别名(如有)
- frontmatter 中的标签
- frontmatter 中的类别或根据目录推断的类别
- 单行摘要——第一句话或
title字段
构建查找表:
page_name → { path, title, aliases, tags, summary }
这是你的“词汇表”——表中的每一项都是有效的 wikilink 目标。
第 2 步:扫描缺失的链接
对于知识库中的每个页面:
-
读取完整内容
-
提取现有 wikilink——查找已经存在的所有
[[...]]引用 -
搜索未链接提及——检查页面文本是否包含以下内容,但没有用
[[...]]包裹:- 页面文件名(例如,出现了“MyProject”一词,但缺少
[[projects/my-project/my-project]]) - frontmatter 中的页面标题
- frontmatter 中的别名
- 注册表中的实体名称、项目名称、概念名称
- 页面文件名(例如,出现了“MyProject”一词,但缺少
-
检查语义关联——检查具有多个相同标签,或位于同一项目目录中但彼此没有链接的页面
匹配规则
- 名称匹配不区分大小写(例如,“my-project”匹配页面
MyProject) - 匹配时忽略变音符号——比较前,使用 Unicode NFKD 规范化页面名称和正文文本(将带重音的字符分解为基本字符和组合标记,并移除组合标记)。这样正文中的 “Muller” 就能匹配页面
[[entities/müller]],反之亦然。 - 跳过自引用——页面不应链接到自身
- 跳过常见词——不要链接 “the”、“and” 等通用词。只匹配有辨识度的名称
- 优先使用最短且无歧义的 wikilink 路径——如果名称在整个知识库中唯一,使用
[[page-name]],而非[[full/path/to/page-name]] - 不要在代码块或 frontmatter 中添加链接
- 不要重复链接——如果页面上已出现
[[foo]],就不要再添加
第 3 步:为建议评分并排序
并非每个可能的链接都值得添加。使用综合信号为每个候选链接评分,然后标注置信度标签。
评分
| 信号 | 分数 | 示例 |
|---|---|---|
| 文本中名称完全匹配 | +4 | 正文中出现“MyProject” → 链接到 my-project.md |
| 共享标签(2 个以上) | +2 | 两者都带有 #ai #agent 标签,但彼此没有链接 |
| 同一项目,但没有链接 | +2 | 两者都位于 projects/my-project/ 下,但互相没有引用 |
| 提及的实体/概念 | +2 | 页面提及“知识图谱” → 链接到 [[concepts/knowledge-graphs]] |
| 跨类别关联 | +2 | 源页面位于 concepts/,目标页面位于 entities/(或 skills/ ↔ synthesis/)——不同的知识层让这类链接在架构上更有价值 |
| 外围页面→枢纽页面的连接 | +2 | 源页面总链接数 ≤ 2(外围页面),但目标页面有 ≥ 8 个链接(枢纽页面)——将孤立页面连接到承载重要内容的概念 |
| 名称部分匹配 | +1 | 出现“graph”,但页面名称为 knowledge-graphs——合理但有歧义 |
置信度标签
根据分数为每个候选项标记置信度:
| 分数 | 标签 | 操作 |
|---|---|---|
| ≥ 6 | EXTRACTED | 链接基本确定——名称完全匹配或匹配度很高。直接内联添加。 |
| 3–5 | INFERRED | 链接是合理推断——基于共享上下文、跨类别或外围页面→枢纽页面。直接内联添加或添加到 Related 部分。 |
| 1–2 | AMBIGUOUS | 匹配较弱或仅部分匹配。跳过,除非用户特别要求连接孤立页面。 |
仅处理 EXTRACTED 和 INFERRED 候选项。在 Cross-Link Report 中注明置信度标签,以便用户在信任 INFERRED 链接前进行审查。
第 4 步:应用链接
写入前快照——首次写入文件之前,检查知识库本身是否为 Git 仓库的根目录。仅仅是较大仓库中的子目录并不符合条件:在那里运行 git add -A 可能会捕获无关文件。如果知识库不是独立的 Git 仓库,请静默跳过此步骤——不要催促,也不要建议运行 git init。
VAULT_REAL_PATH=$(cd "$OBSIDIAN_VAULT_PATH" && pwd -P)
VAULT_GIT_ROOT=$(git -C "$OBSIDIAN_VAULT_PATH" rev-parse --show-toplevel 2>/dev/null || true)
SNAPSHOT_SHA=""
if [ -n "$VAULT_GIT_ROOT" ] && [ "$VAULT_GIT_ROOT" = "$VAULT_REAL_PATH" ]; then
if git -C "$OBSIDIAN_VAULT_PATH" diff --quiet \
&& git -C "$OBSIDIAN_VAULT_PATH" diff --cached --quiet \
&& [ -z "$(git -C "$OBSIDIAN_VAULT_PATH" ls-files --others --exclude-standard)" ]; then
SNAPSHOT_SHA=$(git -C "$OBSIDIAN_VAULT_PATH" rev-parse HEAD)
else
if ! git -C "$OBSIDIAN_VAULT_PATH" add -A; then
echo "Pre-write snapshot failed; abort the skill without writing any vault files." >&2
exit 1
fi
if ! git -C "$OBSIDIAN_VAULT_PATH" commit -m "pre-cross-linker snapshot" --quiet; then
echo "Pre-write snapshot failed; abort the skill without writing any vault files." >&2
exit 1
fi
SNAPSHOT_SHA=$(git -C "$OBSIDIAN_VAULT_PATH" rev-parse HEAD)
fi
fi
干净仓库分支会刻意避免调用 git commit,因此“没有要提交的内容”不会被视为错误。如果 git add 或 git commit 失败,请在编辑知识库前停止;绝不要在没有预期快照的情况下继续。
如果 SNAPSHOT_SHA 非空且该技能写入了文件,请在最终报告中注明 SHA。若要丢弃整次运行的更改,在确认没有后续更改需要保留后,用户可以运行:
git -C "$OBSIDIAN_VAULT_PATH" reset --hard "$SNAPSHOT_SHA"
git -C "$OBSIDIAN_VAULT_PATH" clean -fd
对于每个缺少链接的页面:
4a:内联链接(首选)
在正文中找到该术语首次自然出现的位置,并将其括在 wikilink 中:
之前:
This project uses knowledge graphs to connect entities.
之后:
This project uses [[concepts/knowledge-graphs|knowledge graphs]] to connect entities.
当 wikilink 路径与显示文本不同时,使用 [[path|display text]] 格式。
4b:Related 部分(备用)
如果正文中没有自然提及该术语,但页面在语义上相关(共享标签、同一项目),请在页面底部添加 ## Related 部分:
## Related
- [[projects/my-project/my-project]] — Also uses AI agents for research automation
- [[concepts/knowledge-graphs]] — Core technique used in this project
如果已存在 ## Related 部分,则追加条目。不要重复添加已有条目。
4c:推断并写入关系类型
对于每个新增的已提取或推断出的链接(行内链接或相关章节链接),根据上下文句子推断语义关系类型,并将其写入页面的 relationships: frontmatter 块。跳过含义不明确的链接。
类型推断规则——扫描包含该提及内容的句子(对于相关章节链接,则查看页面标题和共享标签上下文):
| 句式模式 | 推断类型 |
|---|---|
| “X 扩展 / 构建于 / 泛化了 Y” | extends |
| “X 实现了 / 是 Y 的一个实现” | implements |
| “X 与 Y 矛盾 / 对立 / 相悖 / 不一致” | contradicts |
| “X 源自 / 基于 / 改编自 Y” | derived_from |
| “X 使用 / 依赖于 / 取决于 / 需要 Y” | uses |
| “X 替代 / 取代 / 弃用 Y” | replaces |
| 共享标签或跨类别推断,且没有方向性线索 | related_to |
如果上下文含义不明确,或链接来自共享标签匹配(正文中没有提及),默认使用 related_to。
编写此块:
读取页面的 YAML frontmatter。如果已存在 relationships: 块,则追加新条目,不要重复已有目标。如果不存在,则将其添加在 aliases: 之后(如果没有 aliases:,则添加在 tags: 之后)。
relationships:
- target: "[[concepts/knowledge-graphs]]"
type: uses
relationships: YAML 块中的 target 值始终使用维基链接格式([[path/to/page]]),无论 OBSIDIAN_LINK_FORMAT 如何设置。OBSIDIAN_LINK_FORMAT 设置控制正文内容;frontmatter 属性始终使用维基链接语法,以便 wiki-export 能可靠地解析它们。
只为本次 cross-linker 运行中新增的链接添加条目——不要修改原本就存在的带类型条目。
第 5 步:评估 Misc 页面亲和度
完成主要链接处理后,更新 misc/ 中所有页面的亲和度分数(frontmatter 中含有 promotion_status: misc 的页面,或位于 misc/ 目录下的页面)。
对于每个 misc 页面:
- 收集外向链接——页面正文中的所有
[[wikilinks]] - 收集内向链接——在知识库中 grep
[[misc/<slug>]]和[[<slug>]]引用 - 对于每个链接页面(两个方向都包括),检查它是否属于某个项目:
- 位于
projects/<project-name>/下 - frontmatter 中有与某个项目名称匹配的
project:字段
- 位于
- 按项目名称分组并求和:
outgoing_links + incoming_links - 更新 misc 页面上的
affinityfrontmatter 块:
affinity:
obsidian-wiki: 3
another-project: 1
- 如果任一项目的分数 ≥ 3:将此页面标记为晋升候选项,并记录下来以便写入报告
**效率提示:**只需读取 misc 页面的完整正文;对于其他页面,只需 grep frontmatter 来确定其所属项目。
第 6 步:报告
汇总如下:
## Cross-Link Report
### Links Added: 23 across 12 pages
| Page | Links Added | Confidence | Placement | Relationship Types |
|---|---|---|---|---|
| `projects/my-project/my-project.md` | 3 | EXTRACTED | 2 inline, 1 related | uses ×2, related_to ×1 |
| `entities/jane-doe.md` | 5 | INFERRED | 3 inline, 2 related | extends ×1, uses ×3, related_to ×1 |
| ... | | | | |
### Orphan Pages Remaining: 2
- `references/foo.md` — no incoming or outgoing links found
- `concepts/bar.md` — could not find related pages
### Misc Promotion Candidates: N
Pages in misc/ that have ≥ 3 connections to a single project — ready to be promoted:
| Page | Top Project | Score |
|---|---|---|
| `misc/web-martinfowler-articles-microservices.md` | `obsidian-wiki` | 4 |
To promote: move the page to `projects/<project-name>/references/` and update all backlinks.
### Pages Skipped: 3
- `index.md`, `log.md` — special files
- `_archives/*` — archived content
- `_readouts/*` — derived readouts (wiki-narrate output)
第 7 步:更新日志和热缓存
一次加锁调用即可更新日志和热缓存(索引不受影响——没有创建任何页面):
obsidian-wiki memory sync CROSS_LINK \
pages_scanned=<N> links_added=<M> typed_relations_written=<T> \
pages_modified=<P> orphans_remaining=<Q> \
misc_affinity_updated=<R> promotion_candidates=<S> \
--takeaways "Cross-linked 23 mentions across 12 pages; 2 orphans remain."
切勿手动编辑 index.md、log.md 或 hot.md——此命令会获取锁,防止并行写入者丢弃你的更新。
完整流程请参阅 .skills/llm-wiki/references/MEMORY.md。
提示
- 每次摄取后都运行。 新页面几乎总是缺少足够的关联。运行此流程即可修复。
- 谨慎添加行内链接。 只链接首次自然出现的位置,不要链接每次出现。
- 不要修改
_archives/或_readouts/中的页面。 归档是冻结快照;readout 是wiki-narrate生成的派生输出,不是知识页面。 - 尊重现有结构。 如果页面在
## Key Concepts章节中精心整理了链接,请将内容添加到该章节,而不是新建一个单独的## Related。 - 实体页面是链接焦点。
jane-doe这样的实体应从几乎所有项目页面链接。优先处理这些页面。
Vault 写入后的 QMD 刷新
QMD 是搜索索引,不是真实信息源。如果 $QMD_WIKI_COLLECTION 为空或未设置,请跳过此步骤。仅在此技能写入或重写 vault Markdown 后运行。如果 QMD 刷新失败,不要回滚 vault 更改;请单独报告 QMD 状态。
如果已设置 $QMD_CLI,请使用它;否则使用 qmd。
${QMD_CLI:-qmd} update
如果输出提示需要向量或嵌入可能已过期,请运行:
${QMD_CLI:-qmd} embed
使用以下任一方式验证集合:
${QMD_CLI:-qmd} ls "$QMD_WIKI_COLLECTION"
或者,在已知特定页面路径时:
${QMD_CLI:-qmd} get "qmd://$QMD_WIKI_COLLECTION/<page>.md" -l 5
记录以下其中一项:
QMD refreshed: update + embed + verifiedQMD refreshed: update only + verifiedQMD skipped: QMD_WIKI_COLLECTION unsetQMD skipped: qmd CLI unavailableQMD failed: <short error summary>