# Wiki Sync 系统搭建完整记录 > 日期:2026-04-16 > 作者:Hermes Agent > 用途:记录 llm-wiki-agent 自动化同步系统的完整搭建过程 --- ## 背景 用户希望将 Obsidian vault 中的 markdown 文件批量摄入到 LLM Wiki(Karpathy's LLM Wiki)中。原有方案是手动逐篇执行,效率低下。本次目标:搭建自动化系统,实现定时自动摄入。 --- ## 系统架构 ``` ┌─────────────────────────────────────────────────────────────────┐ │ Hermes Agent (我) │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │ │ │ Cron Job │ → │ TMUX Session │ → │ Claude Code Agent │ │ │ │ 每15分钟 │ │ wiki-ingest │ │ /wiki-ingest │ │ │ └─────────────┘ └─────────────┘ └─────────────────────┘ │ │ ↓ ↓ │ │ manifest.json ←───────────────────────────────── 实际生成文件 │ │ 更新 wiki/ │ └─────────────────────────────────────────────────────────────────┘ ``` ### 核心组件 | 组件 | 位置 | 职责 | |------|------|------| | **llm-wiki-sync skill** | `~/.hermes/skills/research/llm-wiki-sync/SKILL.md` | 执行模板和工作流定义 | | **sync.py** | `/Users/weishen/Git/llm-wiki-agent/tools/sync.py` | manifest 管理、CLI 工具 | | **manifest.json** | `/Users/weishen/Git/llm-wiki-agent/tools/manifest.json` | 文件状态追踪(181篇) | | **Hermes Cron Job** | 内部调度器 | 每 15 分钟触发一次摄入 | ## 一、初始探索(手动执行阶段) ### 1.1 发现 raw 文件 - 路径:`/Users/weishen/Workspace/nexus/raw/`(Obsidian vault) - 通过 symlink 挂载到:`/Users/weishen/Git/llm-wiki-agent/raw/` - 文件数:182 个 markdown 文件 ### 1.2 创建 manifest.json 手动扫描 raw 目录,生成初始 manifest: ``` # 扫描 raw 目录,提取 frontmatter for md in Path("raw").glob("**/*.md"): # 提取 title, ingested, slug 等字段 manifest.append({...}) ``` ### 1.3 测试 /wiki-ingest Claude Code 的 `/wiki-ingest` 命令执行 9 步流程: 读取 source 文档 读取 wiki/index.md 和 overview.md 生成 wiki/sources/.md 更新 wiki/index.md 更新 wiki/overview.md 创建/更新 Entity 页面 创建/更新 Concept 页面 检测并记录冲突 追加 wiki/log.md ## 二、遇到的问题和解决方案 ### 问题 1:stdin 交互问题 **现象**:`claude --print` 模式在非交互环境下无法正常工作,stdin 被占用导致命令卡住。 **解决方案**:使用 TMUX 交互模式启动 Claude Code: ```bash # 启动 TMUX session tmux new-session -d -s wiki-ingest "cd /Users/weishen/Git/llm-wiki-agent && claude --permission-mode bypassPermissions" # 等待启动完成 sleep 8 && tmux send-keys -t wiki-ingest Enter # 发送任务 tmux send-keys -t wiki-ingest "请执行任务..." ``` ### 问题 2:manifest slug 与实际文件不匹配 **现象**:manifest 中记录的 slug 和 source_path 与 LLM 实际生成的文件名不一致。 **原因**:LLM 根据内容自动生成 slug,而不是简单从文件名转换。 **解决方案**:要求 LLM 在任务完成后输出 `SLUG: xxx`,然后 Hermes 解析并更新 manifest: ```python def parse_slug_from_output(output: str) -> str: """从 LLM 输出中解析实际使用的 slug""" match = re.search(r'SLUG:\s*([^\s]+)', output) return match.group(1) if match else None ``` ### 问题 3:170 条 ingest 错误记录 **现象**:manifest 中有 170 条记录标记为 `ingested=true` 但实际未成功。 **原因**:早期测试时使用 `--print` 模式失败但仍标记为成功。 **解决方案**:使用 `sync.py --reset-failed` 清理错误状态。 --- ## 三、自建组件 ### 3.1 sync.py CLI 工具 **位置**:`/Users/weishen/Git/llm-wiki-agent/tools/sync.py` **功能**: - `--pending`:列出待摄取文件 - `--check`:预览变化 - `--reset-failed`:重置失败记录 - `--bootstrap`:从现有 wiki sources 重建 manifest **核心函数**: ```python def get_pending_files() -> list: """返回所有未摄入的文件""" def mark_ingested(file_path: str, slug: str): """标记文件为已摄入""" def reset_failed(): """重置所有失败状态""" def parse_slug_from_output(output: str) -> str: """从 LLM 输出解析 SLUG""" ``` ### 3.2 llm-wiki-sync skill **位置**:`~/.hermes/skills/research/llm-wiki-sync/SKILL.md` **版本**:1.4.0 **核心内容**: - **角色分工**:Hermes 编排流程 → Claude Code 执行 ingest - **关键设计**:TMUX 交互模式、顺序执行、SLUG 输出要求 - **TMUX 执行流程**:完整的启动、发送任务、监控、清理流程 - **Ingest Workflow 9 步**:标准化执行步骤 - **Cron Job 自动化**:使用 Hermes 原生 cron job ### 3.3 Hermes Cron Job **创建命令**: ```bash cronjob create \ --name wiki-sync-15min \ --skill llm-wiki-sync \ --schedule "*/15 * * * *" \ --repeat 999999 \ --deliver "telegram:5038825565" \ --prompt "使用 llm-wiki-sync 技能执行一次 wiki 文章摄入..." ``` **配置**: - Job ID:`98265b6998c5` - Schedule:`*/15 * * * *`(每 15 分钟) - 交付方式:Telegram(ID: 5038825565) - 技能:llm-wiki-sync --- ## 四、执行流程(自动化阶段) ### 4.1 Cron Job 触发 1. 每 15 分钟(00, 15, 30, 45 分)触发 2. 加载 llm-wiki-sync skill 3. 执行 skill 中的 prompt ### 4.2 实际执行步骤 ``` 1. 加载 llm-wiki-sync 技能 2. 检查 manifest(python tools/sync.py --pending) 3. 启动 TMUX session 4. 启动 Claude Code(bypassPermissions) 5. 发送任务指令(含 SLUG 输出要求) 6. 监控任务完成(tmux capture-pane) 7. 解析 SLUG 并更新 manifest.json 8. 清理 TMUX session 9. 输出结果(自动发往 Telegram) ``` ### 4.3 示例输出 ``` ## Wiki Sync 完成 | 项目 | 结果 | |------|------| | 摄入文件 | raw/Home Office/用Docker中安装Navidrome.md | | Slug | 用docker中安装navidrome | | 状态 | ✅ 已完成 | 新增页面: - wiki/sources/用docker中安装navidrome.md - wiki/entities/Navidrome.md - wiki/concepts/Docker-Compose.md manifest 已更新:ingested: true 剩余待摄入:165 篇 ``` --- ## 五、当前状态 | 指标 | 值 | |------|-----| | 总文件数 | 181 篇 | | 已摄入 | 16 篇 | | 待摄入 | 165 篇 | | Cron Job 状态 | 运行中 | | 下次运行 | 18:15:00 | --- ## 六、关键命令速查 ```bash # 检查待摄取文件 cd /Users/weishen/Git/llm-wiki-agent && python tools/sync.py --pending # 预览变化 python tools/sync.py --check # 重置失败记录 python tools/sync.py --reset-failed # 查看 cron job 状态 cronjob --list # 手动触发 cron job cronjob --run ``` --- ## 七、注意事项 1. **必须使用 TMUX**:不能用 subprocess 或 --print 模式 2. **必须顺序执行**:并发会触发 529 rate limit 3. **必须解析 SLUG**:LLM 输出的实际 slug 用于更新 manifest 4. **交付方式**:使用 `telegram:5038825565` 发给用户 5. **保留 orphan**:不删除任何原始数据 --- ## 八、扩展方向 - [ ] 添加错误重试机制(529 时等待后重试) - [ ] 支持批量摄入(改为每次 3-5 篇) - [ ] 添加 webhook 通知(不只是 Telegram) - [ ] 统计摄入速率和成功率 --- *End of Note*