从 Obsidian 到 GitHub Pages:一套 Codex 协作的个人知识管理与发布工作流

8月 7, 2026
Tools, Skills, AI, DevOps, ByAI

AI 参与说明(Agent:Codex;模型:gpt-5.6-terra;reasoning effort:ultra):本文基于作者正在使用的实际工作流,由 Codex 协助梳理、资料校验和撰写。它是一套个人实践,不代表 Obsidian、GitHub、Hugo、Pagefind 或 OpenAI 的官方推荐方案。示例已脱敏,不包含仓库标识、令牌、私有提交信息或本机路径;产品行为与配置请以文末原始资料为准。

先给结论#

我把“记笔记、写文章、部署博客”当作同一个知识系统,而不是三件孤立的事:

  • Markdown 与 Git 是事实源:内容可迁移、可审阅、可追溯。
  • Obsidian 是作者端:负责捕捉、链接、浏览、周刊与本地编辑;它不是托管平台,也不是 CI。
  • Codex / AI 是受约束的协作作者和工程助手:协助调研、结构化、生成初稿、检查示例与构建,不跳过事实、公开性与发布条件的核验。
  • 私有内容仓库与公开站点仓库分离:前者保存 Markdown,后者保存 Hugo 主题、站点配置与部署工作流。
  • GitHub Actions、Hugo、Pagefind 与 GitHub Pages 负责确定性发布:内容变动生成静态站点和搜索索引,再通过 artifact 部署到自定义域名。

这套机制追求的不是“让 AI 无条件自动发文”,而是把低摩擦记录、可验证写作和可回溯发布连成一条链。本文记录的是 2026-08-07 的架构快照;工具和版本会变化,但职责边界与验收方法可以复用。

架构:四层系统,加一个发布核验环#

flowchart LR
    author["作者"] --> obsidian["Obsidian Vault<br/>Markdown、链接、模板"]
    codex["Codex / AI<br/>调研、起草、校验、测试"] -. 协作并按规则核验 .-> author
    codex -. 读取规则与项目上下文 .-> rules["Agents.md / Skills"]

    obsidian --> git["Git<br/>私有内容仓库"]
    git -->|push main| notify["私有通知工作流<br/>仅发送不透明更新信号"]

    notify --> site["公开站点仓库<br/>Hugo 主题、配置、工作流"]
    site --> ci["公开构建工作流<br/>只读检出私有内容"]
    ci --> build["Hugo + Pagefind<br/>静态 artifact"]
    build --> pages["GitHub Pages<br/>自定义域名"]

    r2["可选:R2 / CDN 媒体"] --> pages
    pages --> giscus["可选:Giscus 讨论"]

图中的实线是当前发布链;虚线是辅助工作。最重要的原则是:内容完成规定的事实、链接、代码与排版核验,并通过公开性检查后,即可用 draft: false 进入发布边界;由 Agent 一次性完成的内容也按相同标准处理。

层次当前职责不是它的职责
Obsidian编辑 Markdown、知识链接、模板与本地浏览CI、静态站点托管、事实裁决
Git / 私有内容仓库内容历史、核验与发布边界、发布信号的起点自动保证内容适合公开
Codex / AI调研、写作、代码与链接校验、构建排查跳过事实与公开性核验的发布、替作者承担事实责任
公开站点仓库Hugo 主题、模板、配置与 Pages workflow保存私有内容的 Git 历史
GitHub Actions检出、构建、校验、部署 artifact替代内容核验
Hugo + Pagefind生成静态页面与站内搜索动态 CMS 或实时协作服务

Obsidian 官方将 vault 定义为本地文件系统中的文件夹,笔记是 Markdown 纯文本,因此同一组文件可以被编辑器、Git 和 Hugo 共同使用。Obsidian 的数据存储说明

1. 知识从哪里来:把内容类型和生命周期分开#

内容仓库不是只有“文章”一种对象。当前约定按照生命周期组织:

目录适合放什么发布与维护特征
docs/可长期维护的知识条目、概览和实践手册主题稳定,持续修订
posts/<year>/有明确发布时间的文章、经验总结保留当时的上下文与日期
weekly/<year>/周刊、工作记录和收集固定周期、低摩擦积累
timeline/<year>.md仅包含链接的轻量记录不把一个链接强行扩写成文章
links/portfolio/独立导航或展示内容按页面类型渲染

这种划分解决的是一个常见问题:所有笔记都放在一个平铺目录时,“长期知识”“临时灵感”和“已发布文章”会很快混在一起。这里的规则是,先判断内容未来是否值得维护,再决定它是 docs 还是 posts;单个链接先进入 Timeline,只有明确需要独立说明时才成为页面。

图片等公开媒体是另一条可选支路:Markdown 只引用公开 URL,上传凭据留在本地环境变量中,上传前执行检查、dry run 和 CDN 验证。这样媒体传输不必混进内容发布 token,也不会让二进制文件污染正文的 Git 历史。

2. Obsidian:知识工作台,而不是“自动发布器”#

Obsidian 在这套系统中的价值,不在于把笔记锁进某个专有数据库,而在于它直接操作 Markdown vault。作者可以用模板快速创建周刊或文章,用反向链接和图谱发现关联,并在本地预览 Hugo 页面时从页面跳回对应的笔记。

当前作者机还启用了 Obsidian Git 的本地自动备份:配置会在文件变更后及每 60 分钟创建 backup,且 push 没有被禁用。这能显著降低“忘记保存到远端”的概率,但它带来一个非常关键的工程结论:

main 的推送会触发部署时,main 不是普通备份分支,而是发布许可边界。

因此,自动备份并不等于内容已经满足发布条件。对于希望保留自动 Git 备份的个人工作流,draft 应当反映内容状态:

  1. 完成事实、链接、代码与排版核验,且通过公开性检查的内容,直接使用 draft: false;由 Agent 一次性完成的内容也一样,无需额外等待确认。
  2. 内容尚未完成、仍有待核实事实、未通过公开性检查,或作者明确要求暂不发布时,使用 draft: true
  3. 需要多人审批或严格审稿的其他团队,可额外使用工作分支和 PR;本 Blog 知识库固定在 main 分支工作,不以分支作为日常发布机制。

为体现“完成即发布”的默认边界,template/new-post.mddraft: false 创建新文章;若创建时内容尚未满足上述条件,应立即改为 true 并在核验完成前保持草稿。本文已按完成内容设置为 draft: false,并在发布前复核 front matter、事实来源和生成结果。Obsidian 的插件配置属于作者机器的 .obsidian/ 目录,不应假定其他人 clone 仓库后会获得完全相同的自动化行为。

3. Codex / AI:把“会写”变成可审计的协作#

AI 最容易被误用成无来源、无验证的自动写作器。我的做法是把它纳入项目规则,而不是把规则留在一次对话里。

仓库根部的 Agents.md 是一份持久化的协作约定。它可以要求代理:

# 以下为写作规则的简化示意,不是可直接替换的完整文件
- 易变的产品事实优先引用官方一手资料,并标注适用版本或整理日期。
- 技术文章说明前置条件、边界与失败场景,提供可复现的代码或命令。
- 发布前检查链接、配置键、构建结果和生成 HTML。
- 不把隐私、令牌、私有路径、原始聊天记录或未经验证的猜测发布出去。
- 内容完成上述核验且通过公开性检查后,直接使用 <code>draft: false</code>;由 Agent 一次性完成的内容也适用。

Codex 的官方说明也建议通过仓库中的指令文件(如 AGENTS.md)提供代码库导航、测试命令和项目标准;本仓库使用的文件名为 Agents.md。其输出应结合日志与测试结果完成相应核验后再集成。OpenAI:Codex 与 AGENTS.md

在具体执行上,Codex / AI 的职责可以拆成四类:

  1. 选题与结构化:把一次问答或零散笔记改写成面向读者的独立文档,先给结论,再补背景、例子、限制和验证方法。
  2. 资料校验:对于 API、版本、定价、配额、兼容性等易变信息,优先寻找官方文档;无法验证时明确写成推断或待确认项。
  3. 工程校验:检查 Markdown front matter、内部链接、Mermaid、代码示例;运行 Hugo 构建,必要时检查生成 HTML。
  4. 变更卫生:只改任务涉及的文件,保留用户已有的工作区改动;在提交、推送、修改 Secrets 等外部动作前请求明确授权。

这并不构成内容质量保证。人仍然负责:选题取舍、来源可信度的最终判断、涉及个人或公司信息的公开性审查,以及是否合并或推送。

4. 为什么使用双仓库#

这套实现把“内容”与“站点工程”分成两个不同权限域:

仓库可见性保存内容为什么这样拆
<private-content-repo>私有Markdown、写作规则、模板、本地工具不公开内容历史和作者端配置
<public-site-repo>公开Hugo 主题、配置、构建与 Pages workflow让站点工程可审阅、可复用、可独立演进

公开仓库忽略运行时检出的 content/ 目录。构建发生时,公开 workflow 使用只读凭据在临时工作目录检出私有内容;内容不会作为 Git 提交复制到公开站点仓库。

不过,这不是“私有内容永远不会泄露”的承诺:Hugo 会把被选中的 Markdown 渲染为公开页面。因此私有内容仓库应理解为作者源仓库,而不是存放任意机密的保险箱;任何会被检出参与生产构建的内容都必须先通过公开性审查。

双仓库也有成本:需要维护两个工作流、两个最小权限凭据和跨仓库排障路径。若站点很小、内容全部公开且不需要隔离历史,单仓库会更简单。若需要严格审稿流程,则应再加一个工作分支或 PR 阶段。

5. 从一次内容变更到线上页面#

5.1 私有仓库只发送一个不透明信号#

私有仓库在 main 推送后,不把提交 SHA、提交信息或文件列表带到公开仓库,而是发送一个仅含事件类型的 repository_dispatch。GitHub 说明该事件可通过 API 触发,workflow 可用 types 只接收约定的 event_type;如果发送 client_payload,它会暴露给目标 workflow 的事件上下文。GitHub Actions:repository_dispatch

下面是可运行的最小发送端示例。前提是:在私有仓库设置了 SITE_DISPATCH_TOKEN Secret,并在变量 SITE_REPOSITORY 中配置目标公开仓库的 owner/repo;令牌仅被授予向该目标仓库发送 dispatch 所需的最小权限。

name: Notify public site

on:
  push:
    branches: [main]
  workflow_dispatch:

permissions: {}

jobs:
  dispatch:
    runs-on: ubuntu-latest
    steps:
      - name: Send an opaque content-update signal
        env:
          DISPATCH_TOKEN: ${{ secrets.SITE_DISPATCH_TOKEN }}
          SITE_REPOSITORY: ${{ vars.SITE_REPOSITORY }}
        run: |
          set -euo pipefail
          test -n "$DISPATCH_TOKEN"
          test -n "$SITE_REPOSITORY"

          curl --fail --silent --show-error \\
            --request POST \\
            --header 'Accept: application/vnd.github+json' \\
            --header 'Content-Type: application/json' \\
            --header "Authorization: Bearer $DISPATCH_TOKEN" \\
            --header 'X-GitHub-Api-Version: 2026-03-10' \\
            "https://api.github.com/repos/$SITE_REPOSITORY/dispatches" \\
            --data '{"event_type":"content-updated"}'

目标公开仓库的 workflow 同时接受三种触发方式:

  • 公开站点仓库默认分支的 push:用于主题、模板、配置或 workflow 的变更;
  • repository_dispatch: types: [content-updated]:用于内容仓库的更新;
  • workflow_dispatch:用于人工重试与排障。

GitHub 对 repository_dispatch 的运行上下文使用目标仓库默认分支的最新提交。因此如果短时间内连续推送多次,目标构建应被设计为“最终收敛到启动时的最新内容”,而不是承诺“一次内容提交严格对应一次部署”。这是一种有意的吞吐量取舍。

5.2 公开工作流构建什么#

公开 workflow 的实际步骤如下:

  1. 检出公开站点的 Hugo 主题和配置。
  2. 使用只读 token 解析私有内容仓库 main 的 revision,并以 detached checkout 方式检出到临时 content/
  3. 删除内容 checkout 的 remote 和临时认证文件;将 Markdown 文件的修改时间归一化为各自最后一次 Git 提交时间,避免 CI checkout 时间影响“最近更新”。
  4. 使用公开站点配置和私有 content/ 运行 Hugo。
  5. 在生成的静态 HTML 上运行 Pagefind,写入 public/pagefind 搜索索引。
  6. 验证首页与搜索索引存在、产物没有符号链接,并检查本次选定的私有 revision 没有出现在静态产物中。
  7. public/ 上传为 GitHub Pages artifact,再由独立部署 job 发布。

GitHub Pages 的自定义 workflow 要求部署 job 使用 pages: writeid-token: write 等权限,且 Pages artifact 不能包含符号链接。GitHub Pages:自定义 workflow

Hugo 也建议由 GitHub Actions 持续部署,而不是把构建出的 publishDir 提交进仓库。Hugo:Host on GitHub Pages

5.3 为什么 Pagefind 必须在 Hugo 之后运行#

Pagefind 索引的是已经生成的静态 HTML,并把搜索 bundle 写回站点输出目录;它没有独立的服务端组件。因此顺序必须是 Hugo → Pagefind → 上传 artifact,而不能只运行 hugo server 后期待搜索索引出现。Pagefind:Getting Started

以下命令是本地构建的最小验证方式。前提是本机已安装与站点兼容的 Hugo 和 Node.js,且当前目录是公开 Hugo 站点仓库;<private-content-repo> 是相邻或可访问的 Markdown 目录。

cd <public-site-repo>

hugo \\
  --contentDir "../<private-content-repo>" \\
  --minify \\
  --ignoreCache \\
  --cleanDestinationDir \\
  --gc

npx --yes pagefind@1.5.2 --site public

test -f public/index.html
test -d public/pagefind

示例中的 Pagefind 1.5.2 是本文所述实现的固定版本快照,不是对未来版本的建议。生产 workflow 应显式固定并记录 Hugo、Node.js、Pagefind 和 GitHub Actions 的版本;升级时先在本地和 CI 中验收。

6. 两条日常发布路径#

内容与站点工程分离后,日常操作变得很清楚:

你修改了什么在哪个仓库提交触发什么
Markdown、周刊、文章、长期文档私有内容仓库私有通知 → 公开构建工作流
Hugo 模板、样式、配置、Pages workflow公开站点仓库公开仓库自身的构建工作流

一个内容发布的最小操作如下。文章完成事实、链接、代码与排版核验并通过公开性检查后,即可设为 draft: false 并推送本 Blog 的 main 分支;由 Agent 一次性完成的内容同样按此标准执行,无需额外等待确认。

cd <private-content-repo>

git add posts/2026/<article>.md
git commit -m "docs: publish knowledge workflow article"
git push origin main

首个端到端验收不应只看“页面看起来还在”。应选一处无敏感的微小内容改动,依次确认:

  1. 私有仓库的通知 workflow 成功;
  2. 公开仓库确实出现由 repository_dispatch 触发的 build;
  3. 新内容出现在目标页面,且 draft: true 的内容没有出现;
  4. Pagefind 能搜到新内容;
  5. 文章内链接、Mermaid、代码块、评论入口和移动端布局正常;
  6. workflow 失败时,线上仍保留上一次成功部署。

写作本文时,跨仓库的 dispatch 链路已经配置完成;任何团队在把它视为生产机制前,都应至少完成一次上述真实验收,而不是只验证公开仓库的 push 构建。

7. 安全和可靠性:把权限、产物和审阅拆开#

这套机制的安全重点不是“使用很多 token”,而是让每个 token 只拥有一个方向的最小能力:

凭据放在哪里用途不应拥有的能力
内容只读凭据公开站点仓库的 Secret临时检出私有 Markdown写公开站点、管理 Pages
站点 dispatch 凭据私有内容仓库的 Secret向指定公开仓库发送更新信号读取私有内容

除此以外,还应贯彻以下实践:

  • 事件不透明:通知只表达“内容更新了”,不包含私有 SHA、提交消息、文件清单或正文。
  • 构建与部署分离:构建 job 不需要 Pages 写入权限;部署 job 只消费已经验证的 artifact。
  • 产物可检查:上传前检查入口文件、搜索索引和符号链接;针对已知敏感标识做静态扫描。
  • 依赖可复现:固定 Hugo、Node.js、Pagefind 和 GitHub Actions 的版本或提交。
  • 内容先于技术:私有内容被检出用于生产构建,就应视为可能公开;draft 是渲染控制,不是机密分级。
  • AI 透明标识:对 AI 辅助整理的内容保留清楚的说明和标签,并允许读者复核来源。

评论和媒体也要遵循同样的边界。Giscus 只挂在真实内容页,并使用稳定 pathname 映射;改 URL 前要考虑讨论会不会被分裂。R2/CDN 适合承载公开媒体,但不应成为保存写作凭据或私有原始素材的替代方案。

8. 已知限制,以及我会如何演进它#

这不是“一劳永逸”的架构。几个重要限制需要提前承认:

  1. 不保证逐提交一一部署:不透明 dispatch 不携带内容 revision;连续更新时,构建读取启动时最新的 main。如果业务需要“每次发布都可精确追溯到一个内容 SHA”,应把 revision 以受控方式传递、记录,并处理队列与重试。
  2. 自动备份不会替代发布条件核验:本项目的新文章模板以 draft: false 表示完成即发布;正在编写、待核实或未通过公开性检查的内容必须主动设为 draft: true。需要严格审稿的其他团队可使用工作分支与 PR;本 Blog 知识库则固定在 main 分支工作。
  3. 双仓库增加运维面:Secrets、默认分支、workflow 文件和错误定位都要维护。个人小站可以从单仓库开始,等有隔离需求再拆分。
  4. 静态站不适合所有产品:实时协作、复杂权限、服务端个性化或强审核流,应使用 CMS、应用后端或额外的审核系统。
  5. 运行手册会漂移:workflow、脚本和文档必须一起更新;以可执行 workflow 和构建验收为准,定期校对文字说明。

对我而言,下一步优先级是:完成一次真实的跨仓库 dispatch 验收、把发布规则从“约定”进一步变成模板和分支保护、并继续把可复用的运行手册写成长期维护的 docs/ 文档。

9. 给读者的最小复刻清单#

如果你想用自己的工具复刻这套思路,不必一次性实现所有组件。可以按以下顺序:

  1. 创建一个私有 Markdown 内容仓库和一个公开 Hugo 站点仓库。
  2. 让 Hugo 在本地读取私有仓库作为 contentDir,先通过本地构建。
  3. 将公开站点部署到 GitHub Pages,确认 artifact workflow 和自定义域名正常。
  4. 增加 Pagefind,并确认每次静态构建后都生成搜索索引。
  5. 增加私有 → 公开的 repository_dispatch,使用两枚相互分离的最小权限凭据。
  6. 对一次无敏感的内容改动完成端到端验收。
  7. 最后再接入 Obsidian Git 自动备份、R2/CDN、Giscus 或 AI 辅助写作;每加一层,都保留内容核验与回退路径。

如果你只需要一个轻量博客,单仓库 + Hugo + GitHub Pages 已经足够。如果你希望把私人知识工作台与公开站点工程隔离,并让 AI 参与但不越权,双仓库、明确的发布边界和可验证 CI 会更合适。

参考资料#

整理日期:2026-08-07。本文中的工具版本、权限模型和部署行为均可能随上游产品更新而变化;发布或复刻前请重新核对官方文档。

本文共 6751 字,上次修改于 Aug 7, 2026,以 CC 署名-非商业性使用-禁止演绎 4.0 国际 协议进行许可。

相关文章

» 豆包“让这台设备保持唤醒状态”导致 macOS 无法自动息屏:排查与关闭方法(2.21.10)

» Agently Mail CLI:安装、授权与邮件工作流实践

» GitHub 组织删除后能恢复吗?

» Railway Docker 服务单实例并发不足时,官方建议如何扩容?

» Prometheus 和 ServiceMonitor 介绍