content-forge/CLAUDE.md
lizikk 29bcbb89db feat: add claude-md-guardian, thinking commands, and security fixes
- Add claude-md-guardian agent with SessionStart hook for auto CLAUDE.md maintenance
- Add 6 thinking commands: /my-world, /emerge, /challenge, /connect, /today, /close
- Add my-world skill for one-shot vault context loading
- Fix command injection vulnerability in init-vault.sh (use env vars)
- Add error handling and logging to vault-sync.sh
- Update write-article skill with complete frontmatter fields
- Upgrade CLAUDE.md to v1.3.0 with cycle time tracking and exit criteria

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 16:58:43 +08:00

409 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# content-forge / CLAUDE.md
## 1) 项目定位
`content-forge` 是一个「以 Obsidian Vault 为单一内容源」的自媒体内容生产编排项目,目标是把选题、写作、配图、格式化、发布变成可重复执行的流水线。
黄金法则:**Agents Read, Humans Write** — Agent 只读取 Vault永远不写入。Vault 只包含人类的思考Agent 的输出走 CLI 命令或终端,不污染知识源。
核心边界:
- 只新增一个本地 skill`write-article`(文章生成)。
- 其余能力优先复用现有 `baoyu-*`、`image-gen-orchestrator`、`basic-image-gen`、`social-media-pipeline`。
- 所有中间产物必须落到 Vault禁止在多个系统维护平行真相。
成功标准:
- 可以从 `01-topics` 的选题笔记自动产出 `02-drafts` 草稿。
- 可以把草稿格式化并生成配图资产,再发布到微信/X。
- 全链路状态通过 frontmatter 字段可追踪。
### 1.1 Quick Start
```bash
# 1. 初始化 Vault创建目录 + 注册到 Obsidian
bash scripts/init-vault.sh
# 2. 验证环境
command -v obsidian # CLI 可用
obsidian vault # Vault 已注册
obsidian search query="templates" # 模板可搜索
# 3. 创建第一个选题
obsidian create path="01-topics/2026-03-02-my-first-topic.md" content="---
title: 我的第一个选题
slug: my-first-topic
status: topic
content_type: article
---
# 选题内容"
# 4. 用 write-article skill 生成草稿
# 在 Claude Code 中执行:/write-article
```
### 1.2 项目文件结构
```text
content-forge/
├── CLAUDE.md # 项目规范(本文件)
├── my-commands.md # 自定义命令文档
├── .gitignore # 排除 content-forge/ (vault 有独立仓库)
├── scripts/
│ ├── init-vault.sh # Vault 初始化脚本
│ └── vault-sync.sh # Vault 自动同步到 Gitea
├── .claude/
│ ├── commands/ # 自定义 slash 命令
│ │ ├── my-world.md # /my-world — 一键加载 vault 上下文
│ │ ├── emerge.md # /emerge — 发现隐藏模式
│ │ ├── challenge.md # /challenge — 压力测试信念
│ │ └── connect.md # /connect — 跨领域桥接
│ └── skills/
│ ├── write-article/ # 从 Vault 选题生成文章
│ │ ├── SKILL.md # skill 定义与工作流
│ │ └── references/
│ │ └── writing-styles.md # 4 种写作风格规范
│ └── my-world/ # 一键加载 vault 上下文skill 版)
│ └── SKILL.md
└── content-forge/ # Obsidian Vault内容存储
├── 00-inbox/ # 临时灵感、原始素材
├── 01-topics/ # 结构化选题
├── 02-drafts/ # 初稿/改稿
├── 03-review/ # 待审核稿
├── 04-published/ # 已发布归档
├── 05-assets/ # 配图、封面等资产
├── 06-archived/ # 废弃/放弃的内容
└── templates/ # article / tech-blog / social-post
```
---
## 2) 完整依赖关系图
### 2.1 技能依赖图(必读)
```mermaid
graph TD
WA[write-article<br/>新建] --> OBS[obsidian:obsidian-cli]
BAI[baoyu-article-illustrator] --> AUTO[image gen skill auto-discover]
BCI[baoyu-cover-image] --> AUTO
BXI[baoyu-xhs-images] --> AUTO
BINF[baoyu-infographic] --> AUTO
AUTO --> IGO[image-gen-orchestrator]
IGO --> BIG[basic-image-gen<br/>硬依赖]
AUTO --> BIMG[baoyu-image-gen<br/>备选]
PTW[post-to-wechat] --> M2H[baoyu-markdown-to-html<br/>硬依赖]
PTW --> CDP[Chrome CDP 发布链路]
PTW --> WXA[WeChat API 发布链路]
PTX[post-to-x] --> XCDP[Chrome CDP + X 登录态]
UTM[url-to-markdown] --> UCDP[Chrome CDP]
FMD[format-markdown] --> REMARK[remark + remark-cjk-friendly]
SMP[social-media-pipeline] --> NONE[无 skill 运行时依赖]
```
### 2.2 生产链路图(执行顺序)
```text
social-media-pipeline
-> url-to-markdown可选采集外部素材
-> write-article
-> format-markdown
-> baoyu-cover-image / baoyu-article-illustrator / baoyu-xhs-images / baoyu-infographic
-> image-gen-orchestrator -> basic-image-gen
-> post-to-wechat
-> post-to-x
```
---
## 3) 必需插件 / API 清单
### 3.1 插件与本地技能
| 类型 | 名称 | 作用 | 必要性 | 最小验证 |
|---|---|---|---|---|
| 插件 | `obsidian` | 提供 `obsidian-cli`Vault 读写) | 必需 | `obs vault` |
| 插件包 | `ai-generation-skills``content-skills` | 提供 `baoyu-*` 系列技能 | 必需 | 在技能列表可见对应 skill |
| 本地 skill | `basic-image-gen` | 图片生成底层能力 | 必需 | 能被 `image-gen-orchestrator` 调用 |
| 本地 skill | `image-gen-orchestrator` | 批量图片编排 | 必需 | 触发图像任务成功返回 |
| 本地 skill | `social-media-pipeline` | 选题/模板/日历方法论 | 建议启用 | 能输出结构化选题与日历 |
| 本地 skill | `write-article` | 从 Vault 选题生成文章 | 必需(本项目唯一新增) | 生成 `02-drafts/*.md` |
| 本地 skill | `my-world` | 一键加载 vault 上下文 | 建议启用 | `/my-world` 输出 vault 摘要 |
| 社区插件 | `dataview` (v0.5.68) | Vault 当数据库查询 | 建议启用 | Obsidian 设置中已启用 |
| 社区插件 | `templater-obsidian` | 高级模板引擎 | 建议启用 | Obsidian 设置中已启用 |
| 社区插件 | `note-to-mp` | 笔记转微信公众号格式 | 建议启用 | Obsidian 设置中已启用 |
### 3.2 外部依赖与环境变量
| 类别 | 项 | 用途 | 关键配置 |
|---|---|---|---|
| 浏览器 | Google Chrome | CDP 抓取与发布url-to-markdown / post-to-wechat / post-to-x | 本机可启动 Chrome |
| 图像 API | OpenAI / Google / DashScope 任一 | `basic-image-gen` 推理 | `OPENAI_API_KEY``GOOGLE_API_KEY``DASHSCOPE_API_KEY` |
| 微信发布 | WeChat APIAPI 模式) | 公众号发布 | `WECHAT_APP_ID`, `WECHAT_APP_SECRET` |
| 微信/X 发布 | 浏览器登录态CDP 模式) | 无 API 时发布兜底 | 本地已登录对应账号 |
| 配置文档 | `EXTEND.md`(各 skill | 首次配置入口 | 按 skill 文档逐项完成 |
---
## 4) Vault 目录约定与 frontmatter 规范
### 4.1 目录约定(固定)
默认 Vault 路径:`<PROJECT_ROOT>/content-forge/`(通过 `scripts/init-vault.sh` 初始化,可用 `VAULT_PATH` 环境变量覆盖)。
**关键操作约束**Obsidian CLI 的 `vault=` 参数存在已知 bug静默失效**必须先 `cd` 到 vault 目录内再执行 CLI 命令**CLI 会自动检测当前目录所属的 vault
```bash
cd /home/kang/apps/content-forge/content-forge
obsidian vault # 正确识别 content-forge vault
obsidian orphans # 在 vault 目录内执行才有效
```
```text
<VAULT_ROOT>/
├── 00-inbox/ # 临时灵感、原始素材、待分类
├── 01-topics/ # 结构化选题write-article 输入)
├── 02-drafts/ # 初稿/改稿format-markdown 输入)
├── 03-review/ # 待审核稿(人工或规则审校)
├── 04-published/ # 已发布内容归档
├── 05-assets/ # 配图、封面、信息图等资产
├── 06-archived/ # 废弃/放弃的内容
└── templates/ # 模板article / tech-blog / social-post
```
命名规则:
- 文件名:`YYYY-MM-DD-<slug>.md`
- 资产目录:`05-assets/<slug>/...`
- 一个内容单元topic/draft/review/published使用同一个 `slug`,避免多份身份。
### 4.2 frontmatter 统一规范
所有 `01-topics`、`02-drafts`、`03-review`、`04-published` 笔记必须包含以下字段:
```yaml
---
id: "2026-03-01-example-slug"
title: "示例标题"
slug: "example-slug"
status: "topic" # inbox | topic | draft | formatting | review | publishing | published | revision | blocked | archived
content_type: "article" # article | thread | x-post | wechat-post | infographic
channels: ["wechat", "x"]
language: "zh-CN"
source_urls: []
assets: []
cover_image: ""
template: "article"
owner: "content-forge"
created_at: "2026-03-01T00:00:00+08:00"
updated_at: "2026-03-01T00:00:00+08:00"
published_at: null
# 周期时间追踪(可选)
cycle_days: null # 从创建到发布的总天数
stage_days: # 各阶段停留天数
inbox: 0
topic: 0
draft: 0
review: 0
total: 0
---
```
字段约束:
- `id``slug` 一一对应,禁止同 slug 多 id。
- `status` 只能按 `topic -> draft -> review -> published` 前进。
- `assets` 只存 Vault 相对路径(禁止外部临时路径)。
- `cycle_days` 在发布时自动计算:`published_at - created_at`。
- `stage_days``/today``/close` 命令更新。
### 4.3 各阶段退出标准
每个阶段必须满足以下条件才能前进到下一阶段:
| 阶段 | 必填字段 | 退出条件 |
|------|----------|----------|
| **inbox** | `title` | 有标题即可进入 topic |
| **topic** | `slug`, `source_urls` 或明确观点 | 有 slug + 明确写作角度 |
| **draft** | 完整正文 | 正文结构完整,有开头/主体/结尾 |
| **formatting** | `assets`, `cover_image` | 配图已生成,格式化完成 |
| **review** | 审核通过 | 人工审核完成,无事实错误 |
| **publishing** | `channels` | 渠道已确定,准备发布 |
| **published** | `published_at`, `published_url` | 已发布,记录发布时间和链接 |
**特殊情况**
- **revision**:从 review 回退,修复后返回 draft 或 review
- **blocked**:等待外部输入,解除后返回原阶段
- **archived**:废弃内容,不再前进
---
## 5) 内容生产流水线(阶段 -> skill -> obs 命令)
> 说明:以下命令是编排约定,默认在已注册 Vault 环境执行。
| 阶段 | 输入/输出 | Skill | obs 命令(最小可执行) |
|---|---|---|---|
| S0 选题入库 | 输入:灵感/素材;输出:`01-topics/*.md` | `social-media-pipeline`(方法论) | `obsidian create path="01-topics/2026-03-01-<slug>.md"` |
| S1 外链采集(可选) | 输入URL输出Markdown 摘要并入 topic | `url-to-markdown` | `obsidian read path="01-topics/2026-03-01-<slug>.md"` |
| S2 草稿生成 | 输入topic输出`02-drafts/*.md` | `write-article` | `obsidian create path="02-drafts/2026-03-01-<slug>.md"` |
| S3 状态标记 | 输入draft输出frontmatter 完整化 | `write-article` | `obsidian property:set path="02-drafts/2026-03-01-<slug>.md" name="status" value="draft"` |
| S4 格式清洗 | 输入draft输出发布友好 Markdown | `format-markdown` | `obsidian read path="02-drafts/2026-03-01-<slug>.md"` |
| S5 视觉资产生成 | 输入final markdown输出`05-assets/<slug>/...` | `baoyu-cover-image` / `baoyu-article-illustrator` / `baoyu-xhs-images` / `baoyu-infographic` -> `image-gen-orchestrator` -> `basic-image-gen` | `obsidian property:set path="02-drafts/2026-03-01-<slug>.md" name="assets" value='["05-assets/<slug>/cover.png"]'` |
| S6 审核入列 | 输入draft+assets输出`03-review/*.md` | 人工审核 + 必要 skill 回修 | `obsidian move path="02-drafts/2026-03-01-<slug>.md" to="03-review"` |
| S7 发布微信 | 输入review 稿;输出:公众号文章 | `post-to-wechat`(依赖 `baoyu-markdown-to-html` | `obsidian property:set path="03-review/2026-03-01-<slug>.md" name="channels" value='["wechat","x"]'` |
| S8 发布 X | 输入review 稿输出X 帖子 | `post-to-x` | `obsidian property:set path="03-review/2026-03-01-<slug>.md" name="status" value="published"` |
| S9 发布归档 | 输入:发布结果;输出:`04-published/*.md` | 发布后归档流程 | `obsidian move path="03-review/2026-03-01-<slug>.md" to="04-published"` |
### 5.1 常用命令速查
```bash
# 选题
obsidian create path="01-topics/YYYY-MM-DD-<slug>.md" content="<MARKDOWN>"
obsidian read path="01-topics/YYYY-MM-DD-<slug>.md"
# 草稿
obsidian create path="02-drafts/YYYY-MM-DD-<slug>.md" content="<MARKDOWN>"
obsidian property:set path="02-drafts/YYYY-MM-DD-<slug>.md" name="status" value="draft"
# 阶段流转
obsidian move path="02-drafts/YYYY-MM-DD-<slug>.md" to="03-review"
obsidian move path="03-review/YYYY-MM-DD-<slug>.md" to="04-published"
# 查找
obsidian search query="<slug>"
# 资产关联
obsidian property:set path="<path>" name="assets" value='["05-assets/<slug>/cover.png"]'
```
### 5.2 端到端最小验证链路
```bash
obsidian vault
obsidian create path="01-topics/2026-03-01-demo.md" content="# Demo Topic"
obsidian read path="01-topics/2026-03-01-demo.md"
obsidian create path="02-drafts/2026-03-01-demo.md" content="# Demo Draft"
obsidian property:set path="02-drafts/2026-03-01-demo.md" name="status" value="draft"
obsidian search query="2026-03-01-demo"
```
---
## 6) Obsidian CLI 使用规范与故障排查
### 6.1 使用规范(强制)
1. **先 cd 再执行**:所有 CLI 命令必须在 `cd /home/kang/apps/content-forge/content-forge` 之后执行。
2. 所有写入必须使用 Vault 相对路径,禁止绝对路径。
3. 写入前先创建文件,再写 frontmatter 属性,避免属性写入到不存在文件。
4. 每次阶段切换都要更新 `status``updated_at`
5. 资产路径统一写入 `assets` 数组,不在正文硬编码临时 URL。
6. 发布前必须能通过 `obsidian search query="<slug>"` 找到 topic/draft/review/published 至少一个节点。
### 6.1.1 NEVER 规则(踩坑编纂)
- **NEVER** 使用 `vault=` 参数 — 已知 bug静默失效总是 cd 到 vault 目录。
- **NEVER** 用 `find`/`ls`/`cat` 替代 CLI — `obsidian search`/`obsidian read` 效率高 70000 倍。
- **NEVER** 让 Agent 直接写入 Vault 笔记内容 — 黄金法则Agents Read, Humans Write。通过 `obsidian create`/`obsidian property:set` 的结构化命令操作 frontmatter 和流水线状态是允许的。
- **NEVER** 在 Vault 中存放非内容文件脚本、zip、临时文件 — Vault 只放 markdown 笔记和资产。
- **NEVER** 跳过 frontmatter — 每个 01-04 目录的文件必须有完整 frontmatter。
### 6.2 故障排查(按优先级)
| 症状 | 根因 | 诊断命令 | 处理动作 |
|---|---|---|---|
| `obsidian: command not found` | CLI 未安装或 PATH 未注入 | `command -v obsidian` | 按 obsidian-setup skill 安装 |
| `obsidian vault` 无输出或报错 | Vault 未注册 | `obsidian vault` | 运行 `scripts/init-vault.sh` 或手动注册 |
| `obsidian read` 失败 | 路径拼写或文件不存在 | `obsidian search query="<slug>"` | 先 `obsidian create``obsidian read` |
| `obsidian property:set` 不生效 | frontmatter 块损坏或 name 拼写错误 | `obsidian read path="<path>"` | 修复 frontmatter 结构后重试 |
| `obsidian vault` 段错误segfault | `~/.local/bin/obsidian` 是 symlink 而非 wrapper缺少 `DISPLAY` 注入 | `file ~/.local/bin/obsidian` 应显示 shell script | 重新部署 wrapper`obsidian-setup` skill Step 2wrapper 会自动注入 `DISPLAY=:42` |
| 配图 skill 调用失败 | `basic-image-gen` API key 缺失 | 检查环境变量 | 补齐 `OPENAI_API_KEY/GOOGLE_API_KEY/DASHSCOPE_API_KEY` |
| 微信/X 发布失败 | 登录态失效或接口凭证过期 | 检查浏览器登录态/API 凭证 | 重新登录或刷新凭证 |
### 6.3 运行前检查清单
```bash
command -v obsidian
obsidian vault
obsidian search query="templates"
```
通过后再执行流水线,避免中途失败回滚。
---
## 7) Git 仓库与数据同步
项目代码和 Vault 数据使用**独立仓库**管理:
| 仓库 | 地址 | 内容 | 同步方式 |
|---|---|---|---|
| `content-forge` | `http://gitea.towards-agi.cn/zhukang/content-forge.git` | CLAUDE.md、skills、scripts | 手动 commit + push |
| `content-forge-vault` | `http://gitea.towards-agi.cn/zhukang/content-forge-vault.git` | Vault 数据(选题、草稿、资产) | cron 每天凌晨 2 点自动 |
### 7.1 认证方式
- 使用 `git credential store`token 统一存放在 `~/.git-credentials`(权限 600
- Token 更换时只需修改 `~/.git-credentials` 一个文件。
- Remote URL 中不含 token。
### 7.2 自动同步
`scripts/vault-sync.sh` 由 cron 每天执行,逻辑:有变更时 `git add -A && commit && push`,无变更时跳过。
```bash
# 查看 cron 配置
crontab -l | grep vault-sync
# 手动触发同步
bash scripts/vault-sync.sh
# 查看同步日志
tail -20 /tmp/vault-sync.log
```
### 7.3 其他设备 clone
```bash
git clone http://gitea.towards-agi.cn/zhukang/content-forge-vault.git
# 首次 push 时 credential store 会提示输入用户名和 token
```
---
## 8) 已知问题与限制(含 NEVER 规则踩坑记录)
| 问题 | 影响 | 状态 | 降级方案 |
|---|---|---|---|
| ~~`obsidian vault` segfault~~ | ~~无法通过 CLI 操作~~ | **已修复**wrapper 脚本注入 DISPLAY | — |
| `obsidian` CLI 与桌面客户端为独立进程 | 桌面端修改不会自动触发 CLI 事件 | 设计如此 | 以文件系统为准CLI 和桌面端都会读取同一目录 |
| `vault=` 参数静默失效 | CLI 命令作用到错误 vault | **已确认** | 必须 `cd` 到 vault 目录内执行 CLI 命令 |
---
## 9) 自定义命令(`.claude/commands/`
基于 Vin Obsidian Workflows 理念构建的思维工具,详见 `my-commands.md`
| 命令 | 用途 | 使用时机 |
|------|------|----------|
| `/my-world` | 一键加载 vault 全量上下文 | 每次 session 开始 |
| `/emerge` | 从笔记中发现隐藏模式 | 周回顾、新增多篇笔记后 |
| `/challenge` | 用 vault 历史压力测试信念 | 发布前、重大决策前 |
| `/connect` | 跨领域桥接两个不相关主题 | 寻找新内容角度 |
待建:`/today`(晨间仪式)、`/close`(晚间仪式)。
---
## 版本
- **CLAUDE.md 版本**1.3.0
- **最后更新**2026-03-02
- **项目阶段**环境就绪CLI 验证通过,双仓库同步已配置,思维工具命令已部署