zettel-link

TotalClaw 作者 totalclaw

此技能维护 Zettelkasten 的注释嵌入,以搜索注释、检索注释并发现注释之间的联系。

安装 / 下载方式

TotalClaw CLI推荐
totalclaw skills install shop:totalclaw:totalclaw~hxy9243-zettel-link
cURL直接下载,无需登录
curl -fsSL https://skills.taituai.com/api/skills/totalclaw%3Atotalclaw~hxy9243-zettel-link/file -o hxy9243-zettel-link.md
# Zettel Link Skill

This skill provides a suite of idempotent Python scripts to embed, search, and link notes in an Obsidian vault using semantic similarity. All scripts live in `scripts/` and support multiple embedding providers.

The skill should be triggered when the user wants to search notes, retrieve notes, or discover connections between notes.

If the search directory is indexed with embeddings, the skill should prompt the user if they want to create new embeddings.

## Dependencies

- uv 0.10.0+
- Python 3.10+
- One of the following embedding providers:
  - [Ollama](https://ollama.com) with `mxbai-embed-large` (local, default)
  - [OpenAI API](https://platform.openai.com/) with `text-embedding-3-small`
  - [Google Gemini API](https://ai.google.dev/) with `text-embedding-004`

## Overview of Commands

- `uv run scripts/config.py`: Configure the embedding model and other settings.
- `uv run scripts/embed.py`: Embed notes and cache to `.embeddings/embeddings.json`
- `uv run scripts/search.py`: Semantic search over embedded notes
- `uv run scripts/link.py`: Discover semantic connections, output to `.embeddings/links.json`

## Workflow

### Step 0 — Setup and Config

If the `config/config.json` file does not exist, create it:

```bash
uv run scripts/config.py
```

This creates `config/config.json` with defaults:

```json
{
    "model": "mxbai-embed-large",
    "provider": {
        "name": "ollama",
        "url": "http://localhost:11434"
    },
    "max_input_length": 8192,
    "cache_dir": ".embeddings",
    "default_threshold": 0.65,
    "top_k": 5,
    "skip_dirs": [".obsidian", ".trash", ".embeddings", "Spaces", "templates"],
    "skip_files": ["CLAUDE.md", "Vault.md", "Dashboard.md", "templates.md"]
}
```

To use a remote provider:

```bash
# OpenAI
uv run scripts/config.py --provider openai

# Gemini
uv run scripts/config.py --provider gemini

# Custom model
uv run scripts/config.py --provider openai --model text-embedding-3-large
```

To adjust tuning parameters:

```bash
uv run scripts/config.py --top-k 10 --threshold 0.7 --max-input-length 4096
```

### Step 1 — Create Embeddings

```bash
uv run scripts/embed.py --input <directory>
```

This creates `<directory>/.embeddings/embeddings.json` with the embedding cache.

- **Incremental updates**: Only re-embeds files that have been modified since the last run (based on file modification time).
- **Text truncation**: Automatically truncates text to `max_input_length` before embedding.
- **Stale pruning**: Removes entries for files that no longer exist.
- **Force re-embed**: Use `--force` to re-embed everything.

### Step 2 — Semantic Search

```bash
uv run scripts/search.py --input <directory> --query "<query>"
```

This embeds the query using the configured provider and compares it with all cached embeddings, returning the `top_k` most similar notes.

Results are saved to `<directory>/.embeddings/search_results.json`.

### Step 3 — Semantic Connection Discovery

```bash
uv run scripts/link.py --input <directory>
```

This computes cosine similarity for all note pairs and outputs connections above the `default_threshold` to `<directory>/.embeddings/links.json`.

The output includes:
- A flat list of all link pairs with scores
- A per-note grouping for easy lookup

**Tuning**: Adjust `--threshold` to widen or narrow the connection discovery.

## Cache

- **Format**: JSON with metadata envelope (`metadata` + `data`)
- **Location**: `<directory>/.embeddings/embeddings.json`
- **Metadata**: Tracks generation timestamp, model, provider, embedding size
- **Invalidation**: Based on file modification time (`mtime`)
- **Force rebuild**: Delete the cache file or use `--force` flag

## Agent Instructions

When using this skill:

1. Always run `config.py` first if `config/config.json` does not exist.
2. Run `embed.py` before `search.py` or `link.py` — the cache must exist.
3. For remote providers (openai, gemini), ensure the API key environment variable is set (or provide a local `.env` file in the skill directory).
4. All scripts are idempotent and safe to re-run.

---

## 中文说明

# Zettel Link 技能

此技能提供了一套幂等的 Python 脚本,使用语义相似度对 Obsidian 知识库中的笔记进行嵌入、搜索和关联。所有脚本都位于 `scripts/` 中,并支持多种嵌入服务提供方。

当用户希望搜索笔记、检索笔记或发现笔记之间的联系时,应触发此技能。

如果搜索目录已建立了嵌入索引,技能应提示用户是否要创建新的嵌入。

## 依赖

- uv 0.10.0+
- Python 3.10+
- 以下嵌入服务提供方之一:
  - [Ollama](https://ollama.com),使用 `mxbai-embed-large`(本地,默认)
  - [OpenAI API](https://platform.openai.com/),使用 `text-embedding-3-small`
  - [Google Gemini API](https://ai.google.dev/),使用 `text-embedding-004`

## 命令概览

- `uv run scripts/config.py`:配置嵌入模型及其他设置。
- `uv run scripts/embed.py`:嵌入笔记并缓存到 `.embeddings/embeddings.json`
- `uv run scripts/search.py`:在已嵌入的笔记上进行语义搜索
- `uv run scripts/link.py`:发现语义联系,输出到 `.embeddings/links.json`

## 工作流程

### 第 0 步 — 安装与配置

如果 `config/config.json` 文件不存在,则创建它:

```bash
uv run scripts/config.py
```

这会使用以下默认值创建 `config/config.json`:

```json
{
    "model": "mxbai-embed-large",
    "provider": {
        "name": "ollama",
        "url": "http://localhost:11434"
    },
    "max_input_length": 8192,
    "cache_dir": ".embeddings",
    "default_threshold": 0.65,
    "top_k": 5,
    "skip_dirs": [".obsidian", ".trash", ".embeddings", "Spaces", "templates"],
    "skip_files": ["CLAUDE.md", "Vault.md", "Dashboard.md", "templates.md"]
}
```

使用远程服务提供方:

```bash
# OpenAI
uv run scripts/config.py --provider openai

# Gemini
uv run scripts/config.py --provider gemini

# Custom model
uv run scripts/config.py --provider openai --model text-embedding-3-large
```

调整调优参数:

```bash
uv run scripts/config.py --top-k 10 --threshold 0.7 --max-input-length 4096
```

### 第 1 步 — 创建嵌入

```bash
uv run scripts/embed.py --input <directory>
```

这会创建 `<directory>/.embeddings/embeddings.json` 作为嵌入缓存。

- **增量更新**:仅重新嵌入自上次运行以来被修改过的文件(基于文件修改时间)。
- **文本截断**:在嵌入前自动将文本截断到 `max_input_length`。
- **过期清理**:移除已不再存在的文件所对应的条目。
- **强制重新嵌入**:使用 `--force` 重新嵌入全部内容。

### 第 2 步 — 语义搜索

```bash
uv run scripts/search.py --input <directory> --query "<query>"
```

这会使用配置的服务提供方对查询进行嵌入,并将其与所有缓存的嵌入进行比较,返回 `top_k` 个最相似的笔记。

结果将保存到 `<directory>/.embeddings/search_results.json`。

### 第 3 步 — 语义联系发现

```bash
uv run scripts/link.py --input <directory>
```

这会计算所有笔记对之间的余弦相似度,并将高于 `default_threshold` 的联系输出到 `<directory>/.embeddings/links.json`。

输出包括:
- 一份带分数的所有链接对的扁平列表
- 一份按笔记分组的结构,便于查找

**调优**:调整 `--threshold` 以扩大或缩小联系发现的范围。

## 缓存

- **格式**:带元数据外壳的 JSON(`metadata` + `data`)
- **位置**:`<directory>/.embeddings/embeddings.json`
- **元数据**:记录生成时间戳、模型、服务提供方、嵌入维度
- **失效判定**:基于文件修改时间(`mtime`)
- **强制重建**:删除缓存文件或使用 `--force` 标志

## Agent 指令

使用此技能时:

1. 如果 `config/config.json` 不存在,始终先运行 `config.py`。
2. 在运行 `search.py` 或 `link.py` 之前先运行 `embed.py` —— 缓存必须存在。
3. 对于远程服务提供方(openai、gemini),确保已设置 API 密钥环境变量(或在技能目录中提供本地 `.env` 文件)。
4. 所有脚本都是幂等的,可安全重复运行。