Skill: kelcey2023/zeelin-writing-v2 (version 0.1.0)

--- name: zeelin-writing description: 自媒体写作助手，提供完整的10步创作流程：需求分析→知识搜索→选题讨论→风格学习→创作初稿→三遍审校(降AI味)→封面配图→HTML排版→发布草稿箱→归档。当用户说"写一篇文章"、"帮我创作"、"改一下这篇文章"、"审校"、"降AI味"、"降重"、"选题讨论"、"我想写"时触发。支持公众号、小红书、视频逐字稿多平台，自动生成封面图并发布到公众号草稿箱。支持微信公众号顶级排版规范和小红书一键自动发布。 --- # 自媒体写作助手 **用户**：AI自媒体博主 **领域**：AIGC、AI视频/漫剧、AI工具、AI应用 **风格**：洞察口语化、干货感强、爆款结构化写作 --- ## 快速导航 - [首次配置](#首次配置api-keys) - [触发场景](#触发场景) - [任务类型判断](#任务类型判断) - [完整工作流程](#完整工作流程10步) - [降AI味速查表](#降ai味速查表) - [写作技巧](#写作技巧知识库) --- ## 首次配置：API Keys 首次使用前需配置 API Keys（一次配置，永久生效）： **配置方式**：在 skill 目录创建配置文件： ```bash # 设置 SKILL_DIR（根据实际安装位置） SKILL_DIR="$HOME/.agents/skills/zeelin-writing" # 或 SKILL_DIR="$HOME/.claude/skills/zeelin-writing" # 创建配置文件 mkdir -p "$SKILL_DIR/.wechat" ``` 然后在 `$SKILL_DIR/.wechat/.env` 中填入： ```env # 封面图生成（必需） GOOGLE_API_KEY=your_key_here # 公众号发布（可选，不发布公众号可不填） WECHAT_APP_ID=your_app_id WECHAT_APP_SECRET=your_app_secret ``` **获取方式**： - `GOOGLE_API_KEY` → https://aistudio.google.com/app/apikey - `WECHAT_APP_ID/SECRET` → mp.weixin.qq.com → 开发 → 基本配置 **配置保存流程**（用户提供 Key 后 Claude 执行）： 1. **确定 SKILL_DIR**： ```bash SKILL_DIR=$([ -f "$HOME/.agents/skills/zeelin-writing/.wechat/.env" ] && echo "$HOME/.agents/skills/zeelin-writing" || echo "$HOME/.claude/skills/zeelin-writing") ``` 2. **创建目录**（如不存在）： ```bash mkdir -p "$SKILL_DIR/.wechat" ``` 3. **写入配置**：使用 Write 工具创建 `$SKILL_DIR/.wechat/.env` 文件，内容格式如下： ```env GOOGLE_API_KEY=用户提供的key WECHAT_APP_ID=用户提供的appid WECHAT_APP_SECRET=用户提供的secret ``` 4. **继续执行流程** **自动检测**：Key 未配置时，Claude 会在对应步骤暂停并引导配置，无需提前手动检查。 --- ## 触发场景 当用户提到以下关键词时，加载此 Skill： | 触发词类别 | 关键词示例 | |-----------|-----------| | 创作类 | "写一篇..."、"帮我创作..."、"我想写..."、"生成 brief" | | 修改类 | "改一下这篇文章"、"修改"、"润色" | | 审校类 | "审校一下"、"降AI味"、"降重"、"去AI味" | | 讨论类 | "选题讨论"、"给我几个选题"、"有什么选题" | | 咨询类 | "怎么写..."、"如何..."（直接回答，不保存） | --- ## 任务类型判断 收到用户请求后，首先判断任务类型，然后执行对应流程： | 类型 | 判断条件 | 执行流程 | |------|---------|---------| | **A. 新写作（有 brief）** | 用户提供了 brief 文件或完整需求信息 | 执行[完整10步流程](#step-1-理解需求--保存-brief-) | | **B. 新写作（无 brief）** | 用户只说"写一篇..."，没有具体信息 | 先执行 Step 1 生成 brief，再继续 | | **C. 修改已有文章** | 用户提供了原文文件路径或粘贴了原文 | 执行[修改文章流程](#c-修改已有文章) | | **D. 审校/降AI味** | 用户明确说"审校"、"降AI味"、"降重" | 执行[三遍审校流程](#d-审校降ai味) | | **E. 快速咨询** | 用户问"怎么写"、"如何"等简单问题 | 直接回答，不保存文件 | --- ## 完整工作流程（10步） > **执行规则：Step 1 信息足够时直接进入 Step 2，无需等待；Step 2 到 Step 10 全部自动连续执行，步骤之间不停顿、不询问、不等待用户确认。** ### Step 1: 理解需求 & 保存 Brief ⭐ #### 路径规范（固定不变） **目录结构要求**： ``` 你的项目目录/ ├── _briefs/ ← Brief 文件 ├── _协作文档/ ← 协作文档 ├── images/ ← 配图 └── YYYY.MM.DD 文章标题.md ← 最终文章 ``` #### 需求确认（按需询问） 从用户消息中提取以下信息，有则直接使用，缺则询问： - **平台**：公众号 / 视频号逐字稿 / 小红书 / 其他 - **主题方向**：具体想写什么 - **目标受众**：谁会看 - **核心价值**：读者能获得什么 - **特殊要求**：字数、风格、截止时间等（可选） 信息足够时，无需逐项确认，直接保存 Brief 并进入 Step 2。 #### Brief 文件保存规则 **文件位置**：`./_briefs/` **命名格式**：`YYYY.MM.DD 项目名-brief.md` **Brief 内容模板**：参考 [references/brief-template.md](references/brief-template.md) > **重要**：如果有 shell 脚本 `scripts/创建项目结构.sh`，优先使用它初始化项目结构。 --- ### Step 2: 信息搜索与知识管理 ⭐ #### 2.0 加载本地资料（自动，不询问） 按以下优先级自动加载，无需询问用户： 1. **用户初始消息中的 @文件**：直接读取并加载 2. **当前目录下的默认路径**（存在则自动读取，不存在则跳过）： - `./知识资料/` — 提取信息、观点、数据 - `./历史文章/` — 学习风格、语气、结构 加载完成后，将路径写入 brief 文件的「资料来源」章节，然后立即继续。 **两路并行搜索，结果合并**： #### 路线 A：本地资料 | 来源 | 用途 | 原则 | |------|------|------| | **历史文章** | 学习风格、语气、结构 | ❌ 不复用内容，只提取框架 | | **知识资料** | 提取信息、观点、数据 | ❌ 不直接引用，提炼后重新组织 | #### 路线 B：网络搜索 优先检测 `agent-reach` 是否可用： ```bash which xreach 2>/dev/null && echo "agent-reach 可用" || echo "使用内置搜索" ``` **有 `agent-reach`（推荐）**：直接调用 agent-reach skill，支持微博、小红书、微信文章等中文平台。 **无 `agent-reach`（内置方式）**：使用以下工具完成搜索： - `WebSearch` 搜索关键词，获取相关 URL - `curl https://r.jina.ai/{URL}` 读取页面全文（Jina Reader 自动转换为干净文本） - 覆盖：官方信息、媒体报道、社区讨论、用户反馈 #### 合并输出 两路搜索完成后，整理成以下结构： ```markdown ## 资料收集结果 ### 本地资料 - 历史文章风格要素：[开头方式、句式特点、金句模板] - 知识资料关键信息：[提炼后的信息和观点] ### 网络资料 - 官方信息：[...] - 媒体报道：[...] - 用户反馈：[...] - 技术细节：[...] ### 信息缺口 - [ ] 待补充信息1 - [ ] 待补充信息2 ``` **⭐ 核心原则：历史文章学风格不学内容；知识资料提炼观点不直接复用** --- ### Step 3: 选题讨论 ⭐⭐ 必做 **⚠️ 重点警告：永远不要跳过这一步！不要直接写文章！** #### 自动化流程（方案 B） 1. **生成 3-4 个选题方向**（每个包含详细大纲） 2. **自动评分并选择最优选题** 3. **保存所有选题到备选文件**：`_协作文档/YYYY.MM.DD-选题备选.md` 4. **直接进入 Step 4**（用户可随时查看备选选题） #### 选题生成格式 提供 **3-4 个**选题方向，每个必须包含： ``` ## 选题 [序号]：[标题] **核心角度**：[一句话说明文章切入点] **优势**：[为什么这个角度好写/有价值] **劣势**：[可能遇到的困难] **去模板化检查**： - □ 这个角度在本地资料中出现过吗？ - □ 如果出现过，如何做出差异化？ - [具体差异化方法] **工作量**：⭐/⭐⭐/⭐⭐⭐ (评估难度) **是否需要真实测试**：□ 是 / □ 否 **详细大纲**： 1. [大标题1] (预计 XXX 字) - 子要点 2. [大标题2] (预计 XXX 字) - 子要点 3. [大标题3] (预计 XXX 字) - 子要点 **预计总字数**：XXX 字 **自动评分**：[总分]/100 - 信息完整度：[分数]/30（搜索到的资料是否充足） - 差异化程度：[分数]/30（与历史文章的重复度，越低越好） - 可行性：[分数]/20（工作量、是否需要测试） - 爆款潜力：[分数]/20（话题热度、争议性、吸引力） ``` #### 自动选择逻辑 **评分标准**（总分 100）： 1. **信息完整度**（30 分） - 搜索到的资料是否充足（官方信息、用户反馈、技术细节） - 是否有足够的数据支撑 - 是否有真实案例 2. **差异化程度**（30 分） - 与历史文章的重复度（越低越好） - 切入角度的独特性 - 观点的原创性 3. **可行性**（20 分） - 工作量评估（⭐ = 20分，⭐⭐ = 15分，⭐⭐⭐ = 10分） - 是否需要真实测试（不需要 = 20分，需要 = 10分） 4. **爆款潜力**（20 分） - 话题热度和时效性 - 争议性和讨论价值 - 对目标受众的吸引力 **选择规则**： - 自动选择总分最高的选题 - 如果分数相同，优先选择工作量低的 - 如果仍相同，优先选择不需要测试的 #### 备选文件保存格式 保存到 `_协作文档/YYYY.MM.DD-选题备选.md`： ```markdown # 选题备选方案 生成时间：YYYY-MM-DD HH:mm:ss ## ✅ 已选择：选题 [序号] [完整选题内容] --- ## 备选方案 ### 选题 [序号]：[标题] [完整选题内容] ### 选题 [序号]：[标题] [完整选题内容] ``` --- ### Step 4: 学习博主风格 ⭐ #### 阅读材料 优先级顺序： 1. `references/style.md` - 核心风格指南（四种开头方式、论证四要素、金句模板） 2. `references/wechat-style.md` / `references/xiaohongshu-patterns.m ## ClawHub Public Edition This public package keeps the core workflow concise so ClawHub indexing can complete. The local OpenClaw workspace version may contain longer references, templates, generated outputs, or private environment configuration that are intentionally excluded from publishing.

path: _meta.json
content: slug: zeelin-writing
version: 2.1.0
updatedAt: 2026-03-30
changelog: 新增微信公众号顶级排版规范（Step 8 强制执行）、小红书自动发布 SOP（Step 9 扩展）、双平台一键发布流程

path: package.json
content: {
  "name": "zeelin-writing",
  "version": "1.0.0",
  "description": "自媒体写作助手 - 本地脚本依赖",
  "private": true,
  "dependencies": {
    "juice": "^10.0.1",
    "marked": "^12.0.0"
  }
}


path: references/README.md
content: # 参考文档索引

zeelin-writing skill 参考文档使用指南。

---

## 📚 文档分类

### 核心风格指南
| 文档 | 行数 | 用途 | 何时查阅 |
|------|------|------|---------|
| **style.md** | 770 | 智灵动力写作风格完整参考 | Step 4 学习风格、Step 5 创作初稿 |
| **降AI味指南.md** | 143 | AI 套话检测和改写方法 | Step 6 第二遍审校（降 AI 味） |
| **反模板化指南.md** | 273 | 避免复制历史文章的方法 | Step 3 选题、Step 5 创作 |

### 平台特定指南
| 文档 | 行数 | 用途 | 何时查阅 |
|------|------|------|---------|
| **wechat-style.md** | 116 | 公众号写作模式和结构 | 创作公众号文章 |
| **xiaohongshu-patterns.md** | 139 | 小红书爆款笔记模式 | 创作小红书笔记 |
| **video-rhythm.md** | 101 | 视频脚本节奏和时长规划 | 创作视频逐字稿 |

### 写作技巧
| 文档 | 行数 | 用途 | 何时查阅 |
|------|------|------|---------|
| **写作技巧-金字塔原理.md** | 198 | 结构化写作方法（SCQA） | 任何文章创作 |

### 模板和配置
| 文档 | 行数 | 用途 | 何时查阅 |
|------|------|------|---------|
| **brief-template.md** | 80 | Brief 模板 | Step 1 创建 Brief |
| **用户人设.md** | 21 | 智灵动力品牌调性和目标受众 | 了解公司定位 |

---

## 🎯 快速查找

### 我想知道...

#### "如何开头？"
→ 查看 `style.md` 第 21-100 行：四种开头方式

#### "如何降 AI 味？"
→ 查看 `降AI味指南.md`：
- 第 3-27 行：必须删除的 AI 套话
- 第 29-56 行：必须改写的 AI 句式
- 第 136-143 行：紧急降 AI 味 3 步法

#### "如何避免重复历史文章？"
→ 查看 `反模板化指南.md`：
- 第 19-76 行：历史文章的正确使用方式
- 第 78-120 行：知识资料的提炼方法
- 第 237-265 行：审校时的检查清单

#### "公众号怎么写？"
→ 查看 `wechat-style.md`：
- 第 3-19 行：标题设计原则
- 第 21-33 行：开篇导语模板
- 第 35-47 行：正文段落结构

#### "小红书怎么写？"
→ 查看 `xiaohongshu-patterns.md`：
- 第 3-24 行：爆款标题模式
- 第 26-50 行：内容结构模板

#### "视频脚本怎么写？"
→ 查看 `video-rhythm.md`：
- 第 3-9 行：时长规划
- 第 11-42 行：情绪曲线设计
- 第 44-50 行：开场钩子模板

#### "如何用金字塔原理？"
→ 查看 `写作技巧-金字塔原理.md`：
- 第 3-42 行：核心原则（结论先行、纵向关系、横向关系）
- 第 44-100 行：SCQA 故事框架

---

## 📖 阅读建议

### 首次使用（必读）
1. `用户人设.md` - 了解智灵动力是谁
2. `style.md` 前 200 行 - 掌握核心风格
3. `降AI味指南.md` - 学会识别 AI 套话
4. `QUICK_REFERENCE.md` - 记住常用命令

### 创作前（快速查阅）
1. 根据平台类型，查阅对应指南（wechat/xiaohongshu/video）
2. 查看 `反模板化指南.md` - 避免重复
3. 查看 `style.md` 中的开头模板

### 审校时（重点检查）
1. `降AI味指南.md` - 逐项检查套话
2. `style.md` 中的论证四要素 - 检查论证质量
3. `反模板化指南.md` 审校清单 - 检查原创性

---

## 🔗 文档关系图

```
SKILL.md (主流程)
    ↓
Step 1 → brief-template.md
Step 2 → SEARCH_TOOLS_GUIDE.md
Step 3 → 反模板化指南.md (避免重复)
Step 4 → style.md + 用户人设.md
Step 5 → style.md + wechat-style.md / xiaohongshu-patterns.md / video-rhythm.md
Step 6 → 降AI味指南.md + 反模板化指南.md
Step 7 → scripts/README-生成封面图.md
Step 8 → scripts/保存文章.sh
```

---

## 💾 文档维护

### 更新频率
- **style.md**：每月更新（基于新的优秀案例）
- **降AI味指南.md**：发现新的 AI 套话时更新
- **平台指南**：平台规则变化时更新
- **用户人设.md**：公司定位调整时更新

### 贡献新案例
发现好的写作案例时，添加到对应文档：
1. 提取核心技巧
2. 写清楚"为什么好"
3. 提供改写对照

---

**最后更新**：2026-03-17
**文档总数**：9 个参考文档
**总行数**：2041 行


path: references/brief-template.md
content: # 项目 Brief

**创建日期**：YYYY.MM.DD
**项目名称**：
**目标平台**：□ 公众号 □ 视频逐字稿 □ 小红书 □ 其他

## 一、基本信息

### 创作目标
（你想达成什么效果？）

### 核心主题
（这篇文章/视频的核心是什么？）

### 目标受众
（谁会看这篇文章/视频？）

### 核心价值
（读者/观众能获得什么？）

## 二、内容要求

### 关键信息点
（必须包含的信息）

### 风格要求
- □ 洞察口语化
- □ 干货感强
- □ 爆款结构化
- □ 其他：________

### 特殊要求
（有什么特别需要注意的？）

## 三、参考资料

### 资料来源
（Step 2 自动写入，勿手动修改）
- 历史文章：
- 知识资料：

### 相关链接
（可以参考的文章、视频、产品文档等）

### 背景资料
（需要搜索的主题、关键词）

### 竞品参考
（类似主题的优秀案例）

## 四、交付标准

### 字数/时长要求
- 公众号：____ 字
- 视频逐字稿：____ 分钟
- 小红书：____ 字

### 配图需求
- □ 不需要
- □ 封面图（16:9）
- □ 核心概念图
- □ 案例/截图

### 交付时间
- 初稿：____
- 定稿：____

## 五、协作事项

### 需要测试的产品/工具
- □ 无
- ▏有：_______________

### 需要配图的内容
- □ 无
- ▏有：_______________

### 其他协作需求
_______________
_______________
_______________

## 六、备注

（其他需要说明的事项）


path: references/用户人设.md
content: # 智灵动力基本信息-用户人设
## 公司业务
1.  AI漫剧/视频承制（B端）
- 为企业提供AI驱动的视频内容生产服务
2. AI相关培训（C端）
- 面向个人和团队的AI应用培训
- 写文章的主要目的：吸引C端用户，建立专业影响力

3. AI智能体开发（B端）
- 为企业定制AI智能体解决方案

## 目标受众
1. 主要受众：对AI感兴趣的个人学习者、企业决策者、技术从业者
2. 次要受众：行业观察者、潜在合作伙伴

## 品牌调性
1. 专业但不装：有技术深度，但不炫技
2. 有趣但不油：用比喻和案例，但不刻意搞笑
3. 团队视角：用"我们"而非"我"，体现团队专业性
4. 行动导向：文章结尾引导读者行动（报名培训/咨询合作）



path: scripts/markdown-to-html.ts
content: #!/usr/bin/env node

/**
 * Markdown to WeChat-compatible HTML converter
 *
 * Usage:
 *   npx -y tsx scripts/markdown-to-html.ts --input "article.md"
 *   npx -y tsx scripts/markdown-to-html.ts --input "article.md" --output "article.html"
 *   npx -y tsx scripts/markdown-to-html.ts --input "article.md" --css "templates/wechat-theme.css"
 *
 * Output: writes .html file, prints JSON manifest to stdout
 *   { htmlPath, title, contentImages: [{ placeholder, localPath, originalSrc }] }
 *
 * Dependencies: marked, juice (npm install)
 */

import { readFile, writeFile } from 'fs/promises';
import { existsSync } from 'fs';
import path from 'path';
import { execSync } from 'child_process';

// ── Arg parsing ──────────────────────────────────────────────────────────────

function parseArgs() {
  const args = process.argv.slice(2);
  const opts: Record<string, string> = {
    css: path.resolve(__dirname, '../templates/wechat-theme.css'),
  };
  for (let i = 0; i < args.length; i++) {
    const key = args[i].replace(/^--/, '');
    if (args[i].startsWith('--') && args[i + 1] && !args[i + 1].startsWith('--')) {
      opts[key] = args[++i];
    }
  }
  return opts;
}

// ── Frontmatter parser ───────────────────────────────────────────────────────

function parseFrontmatter(content: string): { meta: Record<string, string>; body: string } {
  const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
  if (!match) return { meta: {}, body: content };
  const meta: Record<string, string> = {};
  for (const line of match[1].split('\n')) {
    const [k, ...v] = line.split(':');
    if (k && v.length) meta[k.trim()] = v.join(':').trim();
  }
  return { meta, body: match[2] };
}

// ── Image placeholder extraction ─────────────────────────────────────────────

interface ContentImage {
  placeholder: string;
  localPath: string;
  originalSrc: string;
}

function extractImages(
  html: string,
  baseDir: string
): { html: string; images: ContentImage[] } {
  const images: ContentImage[] = [];
  let idx = 0;

  // Replace <img src="..."> with data-local-path for local files
  const result = html.replace(/<img([^>]*?)src="([^"]*)"([^>]*?)>/g, (match, pre, src, post) => {
    // Skip remote URLs — leave as-is
    if (src.startsWith('http://') || src.startsWith('https://') || src.startsWith('data:')) {
      return match;
    }
    idx++;
    const placeholder = `MDTOHTMLIMGPH_${idx}`;
    const localPath = path.resolve(baseDir, src);
    images.push({ placeholder, localPath, originalSrc: src });
    // Keep src, add data-local-path so post-to-wechat.ts can find the file
    return `<img${pre}src="${src}" data-local-path="${localPath}"${post}>`;
  });

  return { html: result, images };
}

// ── HTML wrapper ─────────────────────────────────────────────────────────────

function wrapHtml(title: string, bodyHtml: string, css: string): string {
  return `<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>${escapeHtml(title)}</title>
<style>
${css}
</style>
</head>
<body>
<div id="output">
${bodyHtml}
</div>
</body>
</html>`;
}

function escapeHtml(str: string): string {
  return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
}

// ── Main ─────────────────────────────────────────────────────────────────────

async function main() {
  const opts = parseArgs();

  if (!opts.input) {
    console.error('Usage: npx -y tsx scripts/markdown-to-html.ts --input "article.md"');
    process.exit(1);
  }

  const inputPath = path.resolve(opts.input);
  if (!existsSync(inputPath)) {
    console.error(`File not found: ${inputPath}`);
    process.exit(1);
  }

  const baseDir = path.dirname(inputPath);
  const rawContent = await readFile(inputPath, 'utf-8');
  const { meta, body } = parseFrontmatter(rawContent);
  const title = meta.title || path.basename(inputPath, '.md');

  // Dynamic import — auto-install if missing
  let marked: any, juice: any;
  try {
    ({ marked } = await import('marked'));
    juice = (await import('juice')).default;
  } catch {
    console.error('依赖未安装，正在自动安装 marked + juice...');
    const pkgDir = path.resolve(__dirname, '..');
    execSync('npm install', { cwd: pkgDir, stdio: 'inherit' });
    ({ marked } = await import('marked'));
    juice = (await import('juice')).default;
  }

  // Configure marked
  marked.setOptions({ gfm: true, breaks: false });

  // Convert markdown → HTML
  const rawHtml = await marked.parse(body);

  // Load CSS
  const cssPath = path.resolve(opts.css);
  const css = existsSync(cssPath) ? await readFile(cssPath, 'utf-8') : '';

  // Extract local images and add data-local-path attributes
  const { html: htmlWithAttrs, images } = extractImages(rawHtml, baseDir);

  // Wrap in full HTML doc
  const fullHtml = wrapHtml(title, htmlWithAttrs, css);

  // Inline CSS (WeChat strips <style> tags, all CSS must be in style="")
  const inlinedHtml = juice(fullHtml);

  // Write output
  const outputPath = opts.output
    ? path.resolve(opts.output)
    : path.join(baseDir, path.basename(inputPath, '.md') + '.html');

  await writeFile(outputPath, inlinedHtml, 'utf-8');

  // Print JSON manifest to stdout
  const manifest = {
    title,
    author: meta.author || '',
    summary: meta.description || meta.summary || '',
    htmlPath: outputPath,
    contentImages: images,
  };
  console.log(JSON.stringify(manifest, null, 2));
}

main().catch((err) => {
  console.error('Error:', err.message);
  process.exit(1);
});


path: scripts/保存文章.sh
content: #!/bin/bash
set -e  # 遇错退出
set -u  # 未定义变量报错
set -o pipefail  # 管道命令失败检测

# 自媒体写作助手 - 保存文章脚本
# 用途：将写好的文章保存到当前项目目录

echo "📝 自媒体写作助手 - 保存文章"
echo "======================================"
echo ""

# 检查参数
if [ -z "$1" ]; then
    echo "❌ 请提供文章标题"
    echo "用法: ./保存文章.sh \"文章标题\""
    echo ""
    echo "示例:"
    echo "  ./保存文章.sh \"Claude Code 使用体验\""
    exit 1
fi

ARTICLE_TITLE="$1"
DATE=$(date +%Y.%m.%d)
FILENAME="$DATE $ARTICLE_TITLE.md"
FILEPATH="./$FILENAME"

# 验证文件名（避免特殊字符）
if [[ "$ARTICLE_TITLE" =~ [/\\:\*\?\"\<\>\|] ]]; then
    echo "❌ 文件名包含非法字符: / \\ : * ? \" < > |"
    echo "请使用合法的文件名"
    exit 1
fi

# 检查文件是否已存在
if [ -f "$FILEPATH" ]; then
    echo "⚠️  文件已存在：$FILEPATH"
    echo ""
    read -p "是否覆盖？(y/n) " -n 1 -r
    echo ""
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        echo "❌ 已取消"
        exit 1
    fi
fi

# 从标准输入读取文章内容
echo "📝 请粘贴文章内容（按 Ctrl+D 结束输入）："
echo ""

cat > "$FILEPATH"

echo ""
echo "✅ 文章已保存：$FILEPATH"
echo ""
echo "📊 文章信息："
WORD_COUNT=$(cat "$FILEPATH" | wc -m | xargs)
LINE_COUNT=$(cat "$FILEPATH" | wc -l | xargs)
echo "   - 文件大小：$WORD_COUNT 字符"
echo "   - 行数：$LINE_COUNT"
echo "   - 保存时间：$(date '+%Y-%m-%d %H:%M:%S')"
echo ""
echo "💡 下一步："
echo "   - 如果需要修改，请手动编辑该文件"
echo "   - 发布后将文件移动到 \`../历史存档/\` 目录"


path: scripts/创建项目结构.sh
content: #!/bin/bash
set -e  # 遇错退出
set -u  # 未定义变量报错
set -o pipefail  # 管道命令失败检测

# 自媒体写作助手 - 项目结构初始化脚本
# 用途：自动创建新项目的标准目录结构

echo "📝 自媒体写作助手 - 项目结构初始化"
echo "======================================"
echo ""

# 检查项目名称参数
if [ -z "$1" ]; then
    echo "❌ 请提供项目名称"
    echo "用法: ./创建项目结构.sh \"项目名称\""
    echo ""
    echo "示例:"
    echo "  ./创建项目结构.sh \"Claude Code 评测\""
    exit 1
fi

PROJECT_NAME="$1"

# 验证项目名称（避免特殊字符）
if [[ "$PROJECT_NAME" =~ [/\\:\*\?\"\<\>\|] ]]; then
    echo "❌ 项目名称包含非法字符: / \\ : * ? \" < > |"
    echo "请使用合法的项目名称"
    exit 1
fi

DATE=$(date +%Y.%m.%d)
PROJECT_DIR="$DATE $PROJECT_NAME"

echo "项目名称：$PROJECT_NAME"
echo "创建日期：$DATE"
echo ""

# 检查是否已存在
if [ -d "$PROJECT_DIR" ]; then
    echo "⚠️  项目目录已存在：$PROJECT_DIR"
    echo ""
    read -p "是否继续？（将在现有目录中创建子文件夹）(y/n) " -n 1 -r
    echo ""
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        echo "❌ 已取消"
        exit 1
    fi
fi

# 创建项目主目录
mkdir -p "$PROJECT_DIR"
echo "✅ 创建项目目录：$PROJECT_DIR"

# 创建子目录
mkdir -p "$PROJECT_DIR/_briefs"
mkdir -p "$PROJECT_DIR/_协作文档"
mkdir -p "$PROJECT_DIR/images"
echo "✅ 创建子目录：_briefs, _协作文档, images"

# 复制 brief 模板
BRIEF_FILE="$PROJECT_DIR/_briefs/$DATE $PROJECT_NAME-brief.md"

if [ -f "references/brief-template.md" ]; then
    cp "references/brief-template.md" "$BRIEF_FILE"
    echo "✅ 创建 brief 文件：$BRIEF_FILE"
else
    # 如果模板不存在，创建一个空文件
    cat > "$BRIEF_FILE" << EOF
# 项目 Brief

**创建日期**：$DATE
**项目名称**：$PROJECT_NAME
**目标平台**：□ 公众号 □ 视频逐字稿 □ 小红书 □ 其他

## 一、基本信息

### 创作目标
（你想达成什么效果？）

### 核心主题
（这篇文章/视频的核心是什么？）

### 目标受众
（谁会看这篇文章/视频？）

### 核心价值
（读者/观众能获得什么？）

## 二、内容要求

### 关键信息点
（必须包含的信息）

### 风格要求
- □ 洞察口语化
- □ 干货感强
- □ 爆款结构化
- □ 其他：________

### 特殊要求
（有什么特别需要注意的？）

## 三、参考资料

### 相关链接
（可以参考的文章、视频、产品文档等）

### 背景资料
（需要搜索的主题、关键词）

### 竞品参考
（类似主题的优秀案例）

## 四、交付标准

### 字数/时长要求
- 公众号：____ 字
- 视频逐字稿：____ 分钟
- 小红书：____ 字

### 配图需求
- □ 不需要
- □ 封面图（16:9）
- □ 核心概念图
- □ 案例/截图

### 交付时间
- 初稿：____
- 定稿：____

## 五、协作事项

### 需要测试的产品/工具
- □ 无
- □ 有：_______________

### 需要配图的内容
- □ 无
- □ 有：_______________

### 其他协作需求
___________________
___________________
___________________

## 六、备注

（其他需要说明的事项）
EOF
    echo "✅ 创建 brief 文件：$BRIEF_FILE"
fi

# 创建项目说明文件
cat > "$PROJECT_DIR/项目说明.md" << EOF
# $PROJECT_NAME

**创建日期**：$DATE
**状态**：进行中

## 项目信息

- **Brief 文件**：\`./_briefs/$DATE $PROJECT_NAME-brief.md\`
- **知识库**：\`./_knowledge_base/\`
- **协作文档**：\`./_协作文档/\`
- **配图**：\`./images/\`

## 进度跟踪

- [ ] Brief 确认
- [ ] 信息搜索
- [ ] 选题讨论
- [ ] 风格学习
- [ ] 创作初稿
- [ ] 第一遍审校（内容）
- [ ] 第二遍审校（降AI味）
- [ ] 第三遍审校（细节）
- [ ] 配图建议
- [ ] 定稿发布

## 备注
EOF

echo "✅ 创建项目说明文件"
echo ""
echo "🎉 项目结构创建完成！"
echo ""
echo "📂 项目目录：$PROJECT_DIR"
echo "📄 Brief 文件：$BRIEF_FILE"
echo ""
echo "💡 下一步："
echo "   1. cd \"$PROJECT_DIR\""

path: scripts/初始化.sh
content: #!/bin/bash
set -e
set -u
set -o pipefail

# 一键初始化脚本
# 用途：检查依赖、创建目录、设置环境、运行测试

echo "🚀 alex-writing Skill 初始化"
echo "======================================"
echo ""

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# 检查函数
check_command() {
    if command -v "$1" &> /dev/null; then
        echo -e "${GREEN}✅ $1 已安装${NC}"
        return 0
    else
        echo -e "${RED}❌ $1 未安装${NC}"
        return 1
    fi
}

# 步骤 1：检查依赖
echo "📦 步骤 1/5: 检查依赖"
echo "--------------------------------------"

MISSING_DEPS=0

# 检查 Node.js
if check_command node; then
    NODE_VERSION=$(node --version)
    echo "   版本: $NODE_VERSION"
else
    echo -e "${YELLOW}   请安装 Node.js: https://nodejs.org/${NC}"
    MISSING_DEPS=1
fi

echo ""

# 检查 Git（可选）
if check_command git; then
    GIT_VERSION=$(git --version)
    echo "   版本: $GIT_VERSION"
else
    echo -e "${YELLOW}   Git 未安装（可选）${NC}"
fi

echo ""

# 检查 agent-reach（可选）
if check_command mcporter; then
    echo -e "${GREEN}✅ agent-reach 已安装${NC}"
    echo "   可使用多平台搜索功能"
else
    echo -e "${YELLOW}⚠️ agent-reach 未安装（可选）${NC}"
    echo "   将使用基础搜索工具"
fi

echo ""

if [ $MISSING_DEPS -eq 1 ]; then
    echo -e "${RED}❌ 缺少必需依赖，请先安装${NC}"
    exit 1
fi

# 步骤 2：创建目录结构
echo "📁 步骤 2/5: 创建目录结构"
echo "--------------------------------------"

DIRS=("_briefs" "_协作文档" "知识资料" "历史文章" "images")

for dir in "${DIRS[@]}"; do
    if [ -d "$dir" ]; then
        echo -e "${YELLOW}⚠️ $dir 已存在${NC}"
    else
        mkdir -p "$dir"
        echo -e "${GREEN}✅ 创建 $dir${NC}"
    fi
done

echo ""

# 步骤 3：检查环境变量
echo "🔑 步骤 3/5: 检查环境变量"
echo "--------------------------------------"

if [ -n "${GOOGLE_API_KEY:-}" ]; then
    echo -e "${GREEN}✅ GOOGLE_API_KEY 已设置${NC}"
    echo "   可使用封面图生成功能"
else
    echo -e "${YELLOW}⚠️ GOOGLE_API_KEY 未设置${NC}"
    echo ""
    read -p "是否现在设置 GOOGLE_API_KEY? (y/n) " -n 1 -r
    echo ""
    if [[ $REPLY =~ ^[Yy]$ ]]; then
        read -p "请输入 GOOGLE_API_KEY: " API_KEY
        if [ -n "$API_KEY" ]; then
            # 添加到 ~/.zshrc 或 ~/.bashrc
            if [ -f "$HOME/.zshrc" ]; then
                echo "export GOOGLE_API_KEY=\"$API_KEY\"" >> "$HOME/.zshrc"
                echo -e "${GREEN}✅ 已添加到 ~/.zshrc${NC}"
                echo "   请运行: source ~/.zshrc"
            elif [ -f "$HOME/.bashrc" ]; then
                echo "export GOOGLE_API_KEY=\"$API_KEY\"" >> "$HOME/.bashrc"
                echo -e "${GREEN}✅ 已添加到 ~/.bashrc${NC}"
                echo "   请运行: source ~/.bashrc"
            fi
            export GOOGLE_API_KEY="$API_KEY"
        fi
    fi
fi

echo ""

# 步骤 4：运行测试
echo "🧪 步骤 4/5: 运行测试"
echo "--------------------------------------"

# 测试脚本语法
echo "检查脚本语法..."
if bash -n scripts/保存文章.sh && bash -n scripts/创建项目结构.sh && bash -n scripts/生成封面图-批量.sh; then
    echo -e "${GREEN}✅ Shell 脚本语法正确${NC}"
else
    echo -e "${RED}❌ Shell 脚本语法错误${NC}"
fi

echo ""

# 测试 Node.js 脚本
echo "检查 Node.js 脚本..."
if node scripts/检查文章质量.js 2>&1 | grep -q "请提供文章文件路径"; then
    echo -e "${GREEN}✅ 检查文章质量.js 可用${NC}"
else
    echo -e "${RED}❌ 检查文章质量.js 不可用${NC}"
fi

if node scripts/检查选题重复.js 2>&1 | grep -q "请提供选题标题"; then
    echo -e "${GREEN}✅ 检查选题重复.js 可用${NC}"
else
    echo -e "${RED}❌ 检查选题重复.js 不可用${NC}"
fi

echo ""

# 步骤 5：显示快速开始指南
echo "📚 步骤 5/5: 快速开始指南"
echo "--------------------------------------"
echo ""
echo "🎉 初始化完成！"
echo ""
echo "📖 快速开始:"
echo ""
echo "1. 查看快速参考手册:"
echo "   cat QUICK_REFERENCE.md"
echo ""
echo "2. 创建新项目:"
echo "   ./scripts/创建项目结构.sh \"项目名称\""
echo ""
echo "3. 生成封面图:"
echo "   ./scripts/生成封面图-批量.sh prompts/cover.md"
echo ""
echo "4. 检查文章质量:"
echo "   node scripts/检查文章质量.js \"文章.md\""
echo ""
echo "5. 检查选题重复:"
echo "   node scripts/检查选题重复.js \"选题标题\""
echo ""
echo "📚 文档导航:"
echo "   - 主流程: SKILL.md"
echo "   - 快速参考: QUICK_REFERENCE.md"
echo "   - 故障排查: TROUBLESHOOTING.md"
echo "   - 工作流程: workflows/README.md"
echo "   - 参考文档: references/README.md"
echo ""
echo "💡 遇到问题？查看故障排查指南:"
echo "   cat TROUBLESHOOTING.md"
echo ""


Security scan verdicts — ClawScan: suspicious | static analysis: suspicious | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)