mcpField
C
cross-linker

cross-linker

github.com/ar9av生产力3.6k3.3k 次安装1 天前更新
代码仓库

关于 cross-linker

cross-linker 是用于为 Obsidian wiki 页面补充交叉链接的技能。它结合名称匹配与评分建议,并为新增链接记录关系类型。

主要功能

  1. 01查找缺失的页面链接
  2. 02匹配名称与别名
  3. 03为链接建议评分
  4. 04添加类型化关系
  5. 05更新杂项页面亲和度

适用场景

  1. 01连接新导入的 wiki 页面
  2. 02查找 vault 中未链接的提及
  3. 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;保留源内容和结构化记录。

  1. 解析配置 — 遵循 llm-wiki/SKILL.md 中的 Config Resolution Protocol(内联 @name 覆盖 → 沿 CWD 向上查找 .env → 全局配置 → 提示设置)。由此获取 OBSIDIAN_VAULT_PATH 和 OBSIDIAN_LINK_FORMAT(默认值:wikilink)。
  2. 阅读 index.md,获取页面完整清单及其单行描述
  3. 浏览 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 步:扫描缺失的链接

对于知识库中的每个页面:

  1. 读取完整内容

  2. 提取现有 wikilink——查找已经存在的所有 [[...]] 引用

  3. 搜索未链接提及——检查页面文本是否包含以下内容,但没有用 [[...]] 包裹:

    • 页面文件名(例如,出现了“MyProject”一词,但缺少 [[projects/my-project/my-project]])
    • frontmatter 中的页面标题
    • frontmatter 中的别名
    • 注册表中的实体名称、项目名称、概念名称
  4. 检查语义关联——检查具有多个相同标签,或位于同一项目目录中但彼此没有链接的页面

匹配规则
  • 名称匹配不区分大小写(例如,“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——合理但有歧义
置信度标签

根据分数为每个候选项标记置信度:

分数标签操作
≥ 6EXTRACTED链接基本确定——名称完全匹配或匹配度很高。直接内联添加。
3–5INFERRED链接是合理推断——基于共享上下文、跨类别或外围页面→枢纽页面。直接内联添加或添加到 Related 部分。
1–2AMBIGUOUS匹配较弱或仅部分匹配。跳过,除非用户特别要求连接孤立页面。

仅处理 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 页面:

  1. 收集外向链接——页面正文中的所有 [[wikilinks]]
  2. 收集内向链接——在知识库中 grep [[misc/<slug>]] 和 [[<slug>]] 引用
  3. 对于每个链接页面(两个方向都包括),检查它是否属于某个项目:
    • 位于 projects/<project-name>/ 下
    • frontmatter 中有与某个项目名称匹配的 project: 字段
  4. 按项目名称分组并求和:outgoing_links + incoming_links
  5. 更新 misc 页面上的 affinity frontmatter 块:
affinity:
  obsidian-wiki: 3
  another-project: 1
  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 + verified
  • QMD refreshed: update only + verified
  • QMD skipped: QMD_WIKI_COLLECTION unset
  • QMD skipped: qmd CLI unavailable
  • QMD failed: <short error summary>

评论

支持 Markdown