note-to-blog

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Note to Blog

笔记转博客

从 Obsidian Note 仓库中筛选适合发布的笔记,评估适配性,批量选题,双通道处理(快速转换 / 深度研究),并行 Agent 派发。
从 Obsidian Note 仓库中筛选适合发布的笔记,评估适配性,批量选题,双通道处理(快速转换 / 深度研究),并行 Agent 派发。

Prerequisites

前置条件

ToolTypeRequiredInstall
Python 3cliYesPre-installed on macOS
PyYAMLpipYes
pip install pyyaml
writing-proofreadingskillNoIncluded in
npx skills add niracler/skill
Do NOT proactively verify these tools on skill load. If a command fails due to a missing tool, directly guide the user through installation and configuration step by step.
工具类型是否必需安装方式
Python 3climacOS系统预装
PyYAMLpip
pip install pyyaml
writing-proofreadingskill包含在
npx skills add niracler/skill
命令中
请勿在技能加载时主动验证这些工具。如果因工具缺失导致命令执行失败,请直接逐步引导用户完成安装和配置。

Script Location

脚本位置

All deterministic operations are handled by the Python script:
text
scripts/note-to-blog.py  (collect / convert / state subcommands)
Path configuration is in user-config.md.
所有确定性操作均由Python脚本处理:
text
scripts/note-to-blog.py  (包含 collect / convert / state 子命令)
路径配置在user-config.md中。

Workflow Overview

工作流概述

text
Phase 1          Phase 2         Phase 3            Phase 4              Phase 5
 Collect   ──▶   Evaluate  ──▶   Interact    ──▶   Execute        ──▶   Summary
 (script)        (LLM)          (user)             (Agent Teams)         (report)
                                 ├─ select          ├─ Fast track
                                 ├─ skip            └─ Deep track
                                 └─ assign track
text
阶段1          阶段2         阶段3            阶段4              阶段5
 收集   ──▶   评估  ──▶   交互    ──▶   执行        ──▶   总结
 (脚本)        (LLM)          (用户)             (Agent团队)         (报告)
                                 ├─ 选择          ├─ 快速轨道
                                 ├─ 跳过            └─ 深度轨道
                                 └─ 分配轨道

Phase 1: Collect

阶段1:收集

Run the
collect
script to gather all data in one call:
bash
python3 scripts/note-to-blog.py collect \
  --note-repo "~/Library/Mobile Documents/iCloud~md~obsidian/Documents/Note/" \
  --blog-content "repos/bokushi/src/content/" \
  --project-paths \
    "~/.claude/projects/-Users-sueharakyoko-code-nini-dev" \
    "~/.claude/projects/-Users-sueharakyoko-code-nini-dev-repos-bokushi" \
  --history-file "~/.claude/history.jsonl"
The script outputs a single JSON object to stdout containing:
  • candidates
    : all eligible notes with title, summary, char_count, outgoing_links
  • clusters
    : wikilink hub nodes (3+ inbound links) with related notes
  • published_posts
    : existing blog posts with title, tags, collection
  • session_keywords
    : recent Claude Code session activity signals
  • stats
    : total_scanned, filtered_out, candidates_count
Read the JSON output and proceed to Phase 2.
运行
collect
脚本一次性收集所有数据:
bash
python3 scripts/note-to-blog.py collect \
  --note-repo "~/Library/Mobile Documents/iCloud~md~obsidian/Documents/Note/" \
  --blog-content "repos/bokushi/src/content/" \
  --project-paths \
    "~/.claude/projects/-Users-sueharakyoko-code-nini-dev" \
    "~/.claude/projects/-Users-sueharakyoko-code-nini-dev-repos-bokushi" \
  --history-file "~/.claude/history.jsonl"
脚本会向标准输出输出一个JSON对象,包含以下内容:
  • candidates
    : 所有符合条件的笔记,包含标题、摘要、字符数、外链
  • clusters
    : 维基链接枢纽节点(入站链接≥3个)及其关联笔记
  • published_posts
    : 已发布的博客文章,包含标题、标签、分类
  • session_keywords
    : 近期Claude Code会话的活动信号
  • stats
    : 扫描总数、过滤数量、候选笔记数量
读取JSON输出后进入阶段2。

Phase 2: Evaluate

阶段2:评估

Make a single LLM evaluation using the prompt template from scoring-criteria.md.
使用scoring-criteria.md中的提示模板,调用LLM进行一次评估。

Input

输入

Construct the evaluation prompt with the
collect
JSON data:
  • candidates
    : title + summary + char_count for each
  • clusters
    : hub_title + related count + link_count for each
  • published_posts
    : title + tags for deduplication
  • session_keywords
    : for timeliness scoring
结合
collect
脚本输出的JSON数据构建评估提示:
  • candidates
    : 每条笔记的标题 + 摘要 + 字符数
  • clusters
    : 枢纽标题 + 关联笔记数 + 链接数
  • published_posts
    : 标题 + 标签(用于查重)
  • session_keywords
    : 用于时效性评分

Output

输出

The LLM SHALL return a JSON array of 5~8 recommendations, mixing individual notes and topic clusters:
json
[
  {
    "type": "single",
    "path": "Areas/大模型(LLM)/关于后LLM时代的代码Review.md",
    "title": "关于后 LLM 时代的代码 Review 的看法",
    "score": 92,
    "collection": "blog",
    "effort": "小",
    "session_activity": "★★★",
    "duplicate_risk": "none",
    "reason": "结构完整、有真实案例、观点独特"
  },
  {
    "type": "cluster",
    "hub_title": "优雅的哲学",
    "hub_path": "Areas/生活(Life)/优雅的哲学-v2.0.md",
    "related_count": 9,
    "score": 88,
    "collection": "blog",
    "effort": "大",
    "theme_summary": "关于如何优雅地生活的哲学思考,散落在多篇笔记中",
    "reason": "主题深度足够,需要整合多篇笔记"
  }
]
If the LLM response is not valid JSON, retry once with explicit format instructions.
LLM需返回一个包含5~8条推荐的JSON数组,混合单篇笔记和主题簇:
json
[
  {
    "type": "single",
    "path": "Areas/大模型(LLM)/关于后LLM时代的代码Review.md",
    "title": "关于后 LLM 时代的代码 Review 的看法",
    "score": 92,
    "collection": "blog",
    "effort": "小",
    "session_activity": "★★★",
    "duplicate_risk": "none",
    "reason": "结构完整、有真实案例、观点独特"
  },
  {
    "type": "cluster",
    "hub_title": "优雅的哲学",
    "hub_path": "Areas/生活(Life)/优雅的哲学-v2.0.md",
    "related_count": 9,
    "score": 88,
    "collection": "blog",
    "effort": "大",
    "theme_summary": "关于如何优雅地生活的哲学思考,散落在多篇笔记中",
    "reason": "主题深度足够,需要整合多篇笔记"
  }
]
如果LLM返回的不是有效JSON,需使用明确的格式说明重试一次。

Phase 3: Interact

阶段3:交互

Step 3.1: Present recommendations

步骤3.1:展示推荐结果

Display the recommendation list as a mixed table:
text
undefined
以混合表格形式展示推荐列表:
text
undefined

类型 标题 适配分 目标 工作量 活跃 重复风险

类型 标题 适配分 目标 工作量 活跃 重复风险

1 单篇 后LLM时代代码Review 92 blog 小 ★★★ 无 2 主题簇 优雅的哲学 (9篇关联) 88 blog 大 ★ 无 3 单篇 SSH私钥加密 85 til 小 ─ 无 4 单篇 Feed内容阅读姿势 82 blog 小 ★ 无 ...

For cluster entries, show the hub title and related note count.
1 单篇 后LLM时代代码Review 92 blog 小 ★★★ 无 2 主题簇 优雅的哲学 (9篇关联) 88 blog 大 ★ 无 3 单篇 SSH私钥加密 85 til 小 ─ 无 4 单篇 Feed内容阅读姿势 82 blog 小 ★ 无 ...

对于主题簇条目,需显示枢纽标题和关联笔记数量。

Step 3.2: User actions

步骤3.2:用户操作

The user can perform batch operations:
ActionExampleEffect
Select + assign track"1 和 3 快速转换,2 走深度"Queue items with track assignment
Override collection"1 放 til"Change target collection
Batch skip"4~6 跳过,reason: private"Mark as skipped via
state skip
See more"还有别的吗"Request additional recommendations (exclude previously shown items)
Check status"状态"Run
state status
to show drafted/published/skipped counts
On skip: run the state script immediately for each skipped item:
bash
python3 scripts/note-to-blog.py state skip "<path>" --reason "<reason>" \
  --note-repo "~/Library/Mobile Documents/iCloud~md~obsidian/Documents/Note/"
用户可执行批量操作:
操作示例效果
选择并分配轨道"1 和 3 快速转换,2 走深度"将条目加入队列并分配处理轨道
覆盖目标分类"1 放 til"修改目标分类
批量跳过"4~6 跳过,原因:私密内容"通过
state skip
标记为已跳过
查看更多"还有别的吗"请求更多推荐(排除已展示的条目)
查看状态"状态"运行
state status
查看草稿/已发布/已跳过的数量
跳过操作:立即为每个跳过的条目运行状态脚本:
bash
python3 scripts/note-to-blog.py state skip "<path>" --reason "<reason>" \
  --note-repo "~/Library/Mobile Documents/iCloud~md~obsidian/Documents/Note/"

Step 3.3: Track assignment

步骤3.3:处理轨道分配

Each selected item must be assigned a track:
TrackWhen to useWhat happens
Fast (快速)Independent, mostly complete notesScript converts → Agent reviews → draft
Deep (深度)Topic clusters or rough notes needing researchAgent reads all related notes → research report
Default suggestions:
  • type: "single"
    with
    effort: "小"
    → suggest fast track
  • type: "cluster"
    or
    effort: "大"
    → suggest deep track
  • User always makes the final decision
每个选中的条目必须分配一个处理轨道:
轨道使用场景处理流程
快速轨道独立完整的笔记脚本转换 → Agent审核 → 生成草稿
深度轨道主题簇或需要补充研究的粗糙笔记Agent读取所有关联笔记 → 生成研究报告
默认建议:
  • type: "single"
    effort: "小"
    → 建议使用快速轨道
  • type: "cluster"
    effort: "大"
    → 建议使用深度轨道
  • 最终决定权在用户手中

Step 3.4: Confirm selections

步骤3.4:确认选择

Before proceeding, display a summary:
text
确认选择:
  Fast track:
    1. 后LLM时代代码Review → blog/
    3. SSH私钥加密 → til/
  Deep track:
    2. 优雅的哲学 (9篇关联) → blog/

开始处理?
Wait for user confirmation.
在执行前展示选择摘要:
text
确认选择:
  快速轨道:
    1. 后LLM时代代码Review → blog/
    3. SSH私钥加密 → til/
  深度轨道:
    2. 优雅的哲学 (9篇关联) → blog/

开始处理?
等待用户确认。

Phase 4: Execute (Agent Teams)

阶段4:执行(Agent团队)

Dispatch N parallel Agents using the Task tool, one per selected item. Each Agent operates independently.
使用Task工具调度N个并行Agent,每个选中的条目对应一个Agent,各Agent独立运行。

Parallel dispatch

并行调度

text
总编 (Main Agent)
├── Task Agent 1: 文章 A (fast track)
├── Task Agent 2: 文章 B (fast track)
└── Task Agent 3: 主题簇 C (deep track)
Use the Task tool to launch all Agents in a single message (parallel execution). Each Agent should be a
general-purpose
subagent with a detailed prompt containing all the information it needs (note path, script path, target collection, etc.).
text
总编 (主Agent)
├── 任务Agent 1: 文章A(快速轨道)
├── 任务Agent 2: 文章B(快速轨道)
└── 任务Agent 3: 主题簇C(深度轨道)
在一条消息中使用Task工具启动所有Agent(并行执行)。每个Agent应为
general-purpose
子Agent,提示信息中需包含其所需的全部信息(笔记路径、脚本路径、目标分类等)。

Fast Track Agent Instructions

快速轨道Agent说明

Each fast track Agent receives these instructions:
Step 1 — Run the convert script (use the absolute path to the script in the Agent prompt):
bash
python3 "<absolute-path-to-skill>/scripts/note-to-blog.py" convert "<full-path-to-note>"
Step 2 — Review the converted output (the script automatically handles):
  • Obsidian fields stripped (aliases, date, modified, etc.)
  • Frontmatter set to: title, pubDate (today), tags (merged from frontmatter + inline #tags), hidden: true
  • Wikilinks → plain text, image embeds → standard markdown, callouts → bold, highlights → bold, comments → removed
  • Verify no conversion artifacts or TODO comments from unrecognized syntax
Step 3 — Generate a description: Write a one-sentence description for the blog post frontmatter (in the same language as the article content).
Step 4 — Write the draft: Add the
description
field to the converted frontmatter, then write to
repos/bokushi/src/content/<collection>/<slug>.md
where
<slug>
is a kebab-case version of the title.
Step 5 — Return a result object:
json
{
  "status": "done",
  "note_path": "<relative note path>",
  "draft_path": "<collection>/<slug>.md",
  "description": "<generated description>",
  "issues": ["<any issues found>"],
  "suggestions": ["<improvement suggestions>"]
}
每个快速轨道Agent需执行以下步骤:
步骤1 — 运行转换脚本(在Agent提示中使用脚本的绝对路径):
bash
python3 "<技能的绝对路径>/scripts/note-to-blog.py" convert "<笔记的完整路径>"
步骤2 — 审核转换输出(脚本自动处理以下内容):
  • 移除Obsidian字段(别名、日期、修改时间等)
  • 设置前置元数据:标题、发布日期(今日)、标签(合并前置元数据标签和行内#标签)、hidden: true
  • 维基链接转为纯文本,图片嵌入转为标准Markdown格式,提示框转为粗体,高亮内容转为粗体,注释移除
  • 检查是否存在转换残留或无法识别语法导致的TODO注释
步骤3 — 生成描述:为博客文章的前置元数据写一句描述(语言与文章内容一致)。
步骤4 — 生成草稿:将
description
字段添加到转换后的前置元数据中,然后写入
repos/bokushi/src/content/<collection>/<slug>.md
,其中
<slug>
是标题的短横线分隔形式。
步骤5 — 返回结果对象
json
{
  "status": "done",
  "note_path": "<笔记相对路径>",
  "draft_path": "<collection>/<slug>.md",
  "description": "<生成的描述>",
  "issues": ["<发现的问题>"],
  "suggestions": ["<改进建议>"]
}

Deep Track Agent Instructions

深度轨道Agent说明

Each deep track Agent receives these instructions:
Step 1 — Read all related notes: Read the hub note and all related notes listed in the cluster.
Step 2 — Produce a structured research report:
markdown
undefined
每个深度轨道Agent需执行以下步骤:
步骤1 — 读取所有关联笔记:读取枢纽笔记和主题簇中的所有关联笔记。
步骤2 — 生成结构化研究报告
markdown
undefined

主题报告:<hub_title>

主题报告:<hub_title>

涉及笔记 (N 篇)

涉及笔记(N篇)

  • <title> (hub, <char_count>字)
  • <title> (<char_count>字)
  • ...
  • <标题>(枢纽,<字符数>字)
  • <标题>(<字符数>字)
  • ...

主题地图

主题地图

  • 核心论点:...
  • 子话题 A:...(涉及 N 篇)
  • 子话题 B:...(涉及 N 篇)
  • 核心论点:...
  • 子话题A:...(涉及N篇笔记)
  • 子话题B:...(涉及N篇笔记)

重叠与矛盾

重叠与矛盾

  • <specific overlaps or contradictions found>
  • <发现的具体重叠或矛盾点>

缺口

内容缺口

  • <missing arguments, incomplete sections>
  • <缺失的论点、不完整的章节>

建议大纲

建议大纲

  1. 引言:...
  2. 第一部分:...(来源:笔记 A、B)
  3. 第二部分:...(来源:笔记 C、需要补充)
  4. 结论:...

**Step 3 — Return a result object**:

```json
{
  "status": "done",
  "note_path": "<hub note path>",
  "related_paths": ["<related note paths>"],
  "report": "<full research report markdown>",
  "suggested_collection": "<blog/til/monthly>"
}
  1. 引言:...
  2. 第一部分:...(来源:笔记A、B)
  3. 第二部分:...(来源:笔记C、需补充内容)
  4. 结论:...

**步骤3 — 返回结果对象**:

```json
{
  "status": "done",
  "note_path": "<枢纽笔记路径>",
  "related_paths": ["<关联笔记路径>"],
  "report": "<完整的研究报告Markdown>",
  "suggested_collection": "<blog/til/monthly>"
}

Important: State updates

注意:状态更新

Individual Agents do NOT update
.note-to-blog.json
directly. After all Agents complete, the main agent collects results and runs state updates sequentially:
For each fast track result:
bash
python3 scripts/note-to-blog.py state draft "<note_path>" \
  --target "<collection>/<slug>.md" \
  --note-repo "~/Library/Mobile Documents/iCloud~md~obsidian/Documents/Note/"
Deep track items are NOT marked as drafted (they need further user decision).
单个Agent不得直接更新
.note-to-blog.json
。所有Agent完成后,主Agent收集结果并依次运行状态更新:
对于每个快速轨道结果:
bash
python3 scripts/note-to-blog.py state draft "<note_path>" \
  --target "<collection>/<slug>.md" \
  --note-repo "~/Library/Mobile Documents/iCloud~md~obsidian/Documents/Note/"
深度轨道条目不会标记为草稿(需要用户进一步决策)。

Phase 5: Summary

阶段5:总结

After all Agents complete, present a unified summary:
所有Agent完成后,展示统一总结:

Fast track results

快速轨道结果

text
Fast Track 完成:
  ✓ 后LLM时代代码Review → repos/bokushi/src/content/blog/llm-code-review.md
    - 转换正常,无问题
    - 建议:可补充最新的 AI code review 工具对比
  ✓ SSH私钥加密 → repos/bokushi/src/content/til/ssh-key-encryption.md
    - 发现 1 个 TODO 标记需要手动处理
text
快速轨道完成:
  ✓ 后LLM时代代码Review → repos/bokushi/src/content/blog/llm-code-review.md
    - 转换正常,无问题
    - 建议:可补充最新的AI代码审核工具对比
  ✓ SSH私钥加密 → repos/bokushi/src/content/til/ssh-key-encryption.md
    - 发现1个TODO标记需要手动处理

Deep track results

深度轨道结果

text
Deep Track 完成:
  📋 优雅的哲学 (9篇关联)
    - 研究报告已生成
    - 建议大纲:4 部分,来源涵盖 7 篇笔记
    - 下一步?
      a) 按大纲写作(调用 Agent 生成初稿)
      b) 修改大纲
      c) 暂不处理
text
深度轨道完成:
  📋 优雅的哲学 (9篇关联)
    - 研究报告已生成
    - 建议大纲:4部分,来源涵盖7篇笔记
    - 下一步?
      a) 按大纲写作(调用Agent生成初稿)
      b) 修改大纲
      c) 暂不处理

State update confirmation

状态更新确认

text
状态更新:
  drafted: 2 篇
  下次 collect 时这些笔记将不再出现在候选列表中。

草稿均为 hidden: true,需要手动 review 后改为 false 发布。
建议使用 /writing-proofreading 进行审校。

发布后运行 state publish 更新状态:
  python3 scripts/note-to-blog.py state publish "<note_path>" --note-repo "..."
text
状态更新:
  草稿:2篇
  下次执行collect时这些笔记将不再出现在候选列表中。

所有草稿均设置为hidden: true,需要手动审核后改为false才能发布。
建议使用/writing-proofreading进行审校。

发布后运行state publish更新状态:
  python3 scripts/note-to-blog.py state publish "<note_path>" --note-repo "..."

Detailed References

详细参考文档

  • Path configuration: user-config.md
  • LLM evaluation prompt and scoring: scoring-criteria.md
  • 路径配置:user-config.md
  • LLM评估提示与评分标准:scoring-criteria.md