fastdeai — Markdown 去「AI 味儿」
跨项目 Markdown 清洗工具。去掉 AI 生成时爱追加、但人类不会写的格式装饰(装饰 emoji、引用框、分隔线、斜体 / 删除线、行内代码、加粗、图片、HTML、脚注),只保留有信息量的纯文本结构(标题、表格、列表、段落)。强调(加粗 / 斜体)由作者后续手动重新施加。
实战提炼,持续维护。
载体:~/.claude/skills/fastdeai/fastdeai.exe —— self-contained 单文件(.NET 9,所有 DLL 折叠进 exe,目标机无需安装 .NET 运行时)。为何用 exe 而非像 fastsearch 那样内嵌 C#:fastdeai 重度依赖 System.Text.Rune(.NET Core 3.0+ 才有,PS5.1 的 .NET Framework 没有该类型)且用了 C#8/9 语法,无法内嵌进 PS5.1 的 CodeDom/C#5 即时编译。故以 exe 为权威载体,语义 100% 由源码决定。另有 fastdeai.ps1 薄包装提供 exe 缺的批量目录能力,单文件透传语义不变。
何时用
- ★ 清洗 AI 生成的 Markdown(首要触发):文档里满是装饰 emoji、
> 引用框、--- 分隔线、**加粗**、`行内代码`、~~删除线~~、、HTML 标签等"AI 味儿",想要干净纯文本底稿时 → 优先本 skill(比手写正则/逐个 Edit 可靠全面得多)。
- 批量去味儿:一个目录下几十份 AI 生成的
.md,统一清洗成底稿。
- 大模型输出落地:粘进来的 ChatGPT/Claude 输出太花,先去味儿再人工精修/重排版。
- 强调由作者重施加:工具故意把加粗/斜体一起去掉(见维护笔记),让你按自己的强调意图重新标。
不适用:只需要读/改特定行 → 用 Read/Edit;只需要在某文件里定位内容 → 用 fastsearch/Grep;要保留全部 Markdown 格式 → 别用本工具(它会剥格式)。
0. 心法(一句话)
代码围栏块是绝对原文保护区 → 正文行紧跟 --- 会被当 setext 标题(不是删分隔线)→ 去味儿后强调自己重新加。
1. 前置:定位入口 + 调用约定
入口是 skill 自带的 self-contained exe(优先,固定位置);另有 ps1 薄包装提供批量能力。
# exe 直接可调(无需 powershell -File 前缀,不像 fastsearch 的 ps1 载体)
ls "$HOME/.claude/skills/fastdeai/fastdeai.exe"
bash 调用约定:
# 方式一(推荐):定义一次 bash 函数,后续像命令一样用
fastdeai() { "$HOME/.claude/skills/fastdeai/fastdeai.exe" "$@"; }
fastdeai report.md # → 生成 report_out.md
fastdeai report.md cleaned.md # → 指定输出名
# 方式二:批量(需经 ps1 包装;exe 本身不支批量)
powershell.exe -NoProfile -ExecutionPolicy Bypass \
-File "$HOME/.claude/skills/fastdeai/fastdeai.ps1" -Batch "D:\docs" -Recurse
下文示例一律用 fastdeai ... 简写(假定已按方式一定义函数;或自行脑补 exe 全路径)。
无参数运行 fastdeai 可显示官方 usage(权威,以它为准)。
2. 完整用法
fastdeai.exe <input.md> [output.md] # 单文件,输出可选
fastdeai.ps1 -Batch <dir> [-Recurse] # 批量(ps1 包装,exe 不支持)
| 参数 / 选项 |
作用 |
<input.md> |
输入 Markdown 文件(必填) |
[output.md] |
输出路径(可选)。缺省 → 输入文件旁的 <原名>_out.md |
-h --help /? |
显示 usage |
-Batch <dir> |
(ps1 包装)批量处理目录下所有 *.md,自动跳过已生成的 *_out.md |
-Recurse |
(ps1 包装)递归子目录 |
退出码:0=成功 · 1=异常 · 2=参数错误(如输入不存在、输入==输出路径) · 3=ps1 包装找不到 exe / 批量目录不存在。无参运行=显示 usage 并返回 0。
输出编码:统一 UTF-8 无 BOM、\n 换行(实测确认),中文安全。
3. 清洗规则(权威,源自源码)
关键原则:代码围栏块是"原文保护区"——以下所有转换/删除只在围栏外生效,围栏内任何符号(**、`、>、emoji、---)都保持原样。
原样保护(不动):
- YAML front matter(首行
--- … 闭合 ---)
- 代码围栏块(
``` 或 ~~~,≥3 个)及其内部全部内容
保留结构(内容仍走 inline 清洗):
- 标题(ATX
#、setext,见 §4.2)、表格(GFM)、列表(有序/无序/任务列表 - [x])、段落文本
转换(去格式,留内容):
- 加粗
**x** / __x__ / ***x*** → 去标记,留文字
- 行内代码
`code` → 去反引号,留内容
- 斜体
*x*、删除线 ~~x~~ → 去标记,留文字
- 链接
[文字](url) / [文字][ref] → 纯文字
- 引用块
> → 去标记,留正文
删除:
- 图片

- 分隔线
--- / *** / ___(≥3,孤立时)
- 装饰 emoji(🎯📌✅💡🚀🔥⭐✨📊📈🔍📝⚠❗❓🔔🆕👍 等 ~45 种 + variation selector)
- HTML 标签 / 块 / 注释(
<div>、<details>、<!-- --> 等)
- 脚注定义
[^x]: 与引用 [^x]
4. ⚠️ 已验证语义坑(清洗前必读)
实测沉淀,绕过这些会误判结果。下列行为逐条经样本验证。
- 代码围栏块绝对保护:围栏内的
**bold**、`code`、> quote、🎯 emoji、--- 全部原样保留,清洗规则不生效。不确定某符号为何没被去掉时,先看它是否在代码块里。
- Setext heading 自动转 ATX(README 未提,易误判):「正文行」紧跟
=== → # 正文;紧跟 --- → ## 正文。坑:文档里一段正文下面跟了一条 --- 当分隔线,但前面紧挨着非空正文行 → 它会把那行升成 ## 标题(而非删除分隔线)!只有 --- 前面是空行/标题/表格行(不可提升)时,才当分隔线删除。想确保 --- 被删,前面留一个空行。
- snake_case 保留:字母数字之间的
_ 不当斜体(snake_case_var、a_file.txt 原样)。CommonMark 语义:开闭 _ 两侧不能是字母数字。
- 删除后残留空格:删 emoji/图片/分隔线后,原位置可能残留少量空格(如「文字 🚀 后续」→「文字 后续」)。已知限制,作者后续手动收。
- 多空行折叠为单空行;首尾空白行裁剪。输出结构干净。
- 行内代码反引号未闭合→ 当字面量保留;强调标记跨行未闭合(如
**粗\n体**)→ 按字面量处理,不强转。
- 4 空格缩进代码块不受保护:按普通文本处理(避免误伤列表续行)。要保护代码,用
``` 围栏。
- 输入==输出路径会报错退出(码 2),防覆盖源文件。
5. recipe 库(实战沉淀)
# 定义入口函数(每会话一次,或写进 ~/.bashrc)
fastdeai() { "$HOME/.claude/skills/fastdeai/fastdeai.exe" "$@"; }
# —— 单文件清洗 ——
fastdeai report.md # → report_out.md(同目录)
fastdeai report.md cleaned.md # → 指定输出名
# —— 批量目录(ps1 包装;exe 本身不支批量)——
powershell.exe -NoProfile -ExecutionPolicy Bypass \
-File "$HOME/.claude/skills/fastdeai/fastdeai.ps1" -Batch "D:\notes" -Recurse
# 自动跳过 *_out.md,末尾打印 Cleaned / Skipped / Failed 计数
# —— 先看会清成什么样,再决定要不要批量(无损:输出到独立文件)——
fastdeai sample.md _preview.md && cat _preview.md
清洗前后对照(实测样本节选):
# 🎯 Title with emoji → # Title with emoji
> This is a **blockquote** → This is a blockquote
**bold** *italic* ~~strike~~ → bold italic strike
snake_case_var a_file.txt → snake_case_var a_file.txt(下划线保留)
 image dropped. → image dropped.(图片删,残留空格)
--- → (分隔线删除,或上文升为 setext 标题,见 §4.2)
- [x] done **bold** task → - [x] done bold task
| **a** | `b` | → | a | b |(表格留,单元格内清洗)
```csharp → ```csharp(整个块原样,内部 ** ` > 🎯 不动)
var x = "🎯 stays"; → var x = "🎯 stays";
``` → ```
Setext Heading → # Setext Heading(=== 升为 #,见 §4.2)
6. 与其它工具分工
| 场景 |
工具 |
| 去 Markdown 的 AI 味儿格式(emoji/加粗/引用/分隔线…) |
fastdeai(本 skill) |
| 大海捞针 + 与或非定位文件/日志 |
fastsearch |
读干净内容 / 单关键词计数 / -o 提取 |
Grep(ripgrep) |
| 读特定行/整个文件 |
Read |
| 改特定片段 |
Edit |
典型流水线:fastsearch 布尔定位含 AI 味儿的 .md → fastdeai 批量清洗成底稿 → 作者手动重施加强调/精修。
7. 维护笔记(给维护者)
🔐 授权:用户(ElabAlice)授权——agent 可按需直接维护本 skill(SKILL.md / fastdeai.ps1);改清洗语义需改 C# 源码并重新 dotnet publish 出 exe(见下流程)。
- 载体决策:fastsearch 把 C# 内嵌进 ps1 让 PS5.1 跑;fastdeai 做不到——
System.Text.Rune(.NET Core 3.0+)在 PS5.1 的 .NET Framework 里不存在,且源码用 C#8(^1 索引/.. 范围)/C#9(target-typed new())语法,PS5.1 CodeDom 只支持 C#5。故以 self-contained exe 为权威载体(目标机免装 .NET),ps1 仅做透传 + 批量。
- 源码 source of truth:
0_FastTool/17_FastDeai/workspace/fastdeai_src/fastdeai/{Program.cs, MarkdownCleaner.cs} + fastdeai.csproj。emoji 白名单见 MarkdownCleaner.cs 的 DecorativeEmoji(HashSet<Rune>,~45 个 + 0xFE0F variation selector)。
- 改 C# → 更新 exe 流程:改源码 →
0_FastTool/17_FastDeai/workspace/fastdeai_src/build_release.ps1(dotnet publish 单文件 self-contained)→ 把生成的 fastdeai_release/fastdeai.exe 复制覆盖 ~/.claude/skills/fastdeai/fastdeai.exe。ps1 包装无需动(语义全在 exe)。
- ps1 包装边界:
fastdeai.ps1 仅透传单文件参数 + -Batch 批量(自动跳过 *_out.md),不碰清洗逻辑;PS5.1 兼容语法。批量输出固定为各自旁边的 <原名>_out.md(由 exe 决定,包装不覆盖)。
- emoji 白名单扩展:要新增删的 emoji,在源码
DecorativeEmoji 加对应 new Rune(0xXXXX),重新 publish。注意 emoji + variation selector(0xFE0F)/ZWJ(0x200D)的粘连处理已在 CleanInlineNonCode 里。
1---2name: fastdeai3description: Markdown 去'AI 味儿'清洗工具(fastdeai.exe · self-contained 单文件,.NET 9,目标机免装运行时)。何时调用——★首要触发:拿到一份 AI 生成的 Markdown,想去掉那些'人类不会写'的格式装饰(装饰 emoji、引用框 >、分隔线 ---、斜体 *x*、删除线 ~~x~~、行内代码 `x`、加粗 **x**、图片、HTML 标签、脚注),只留纯文本结构(标题/表格/列表/段落),强调由作者后续手动重施加时 → 优先本 skill。①清洗 AI 生成的文档/报告/笔记;②批量给一个目录下的 .md 统一去味儿;③粘贴进来的大模型输出太花、要变成干净底稿。核心心法:代码围栏块是绝对原文保护区(里面的 **、`、>、emoji 一律不动)+ 正文行紧跟 --- 会被当 setext 标题而非删除分隔线(易误判)+ snake_case 的下划线保留。含完整清洗规则(保护/保留/转换/删除)、已验证语义坑、bash 调用约定、批量 recipe、与 fastsearch/Read 分工。载体为 self-contained exe(依赖 System.Text.Rune,无法内嵌进 PS5.1),源码在源码树。4---56# fastdeai — Markdown 去「AI 味儿」78> 跨项目 Markdown 清洗工具。去掉 AI 生成时爱追加、但人类不会写的格式装饰(装饰 emoji、引用框、分隔线、斜体 / 删除线、行内代码、加粗、图片、HTML、脚注),只保留有信息量的纯文本结构(标题、表格、列表、段落)。强调(加粗 / 斜体)由作者后续手动重新施加。9> 实战提炼,持续维护。1011> **载体**:`~/.claude/skills/fastdeai/fastdeai.exe` —— self-contained 单文件(.NET 9,所有 DLL 折叠进 exe,**目标机无需安装 .NET 运行时**)。**为何用 exe 而非像 fastsearch 那样内嵌 C#**:fastdeai 重度依赖 `System.Text.Rune`(.NET Core 3.0+ 才有,**PS5.1 的 .NET Framework 没有该类型**)且用了 C#8/9 语法,无法内嵌进 PS5.1 的 CodeDom/C#5 即时编译。故以 exe 为权威载体,语义 100% 由源码决定。另有 `fastdeai.ps1` 薄包装提供 exe 缺的**批量目录**能力,单文件透传语义不变。1213## 何时用1415- **★ 清洗 AI 生成的 Markdown(首要触发)**:文档里满是装饰 emoji、`>` 引用框、`---` 分隔线、`**加粗**`、`` `行内代码` ``、`~~删除线~~`、``、HTML 标签等"AI 味儿",想要干净纯文本底稿时 → **优先本 skill**(比手写正则/逐个 Edit 可靠全面得多)。16- **批量去味儿**:一个目录下几十份 AI 生成的 `.md`,统一清洗成底稿。17- **大模型输出落地**:粘进来的 ChatGPT/Claude 输出太花,先去味儿再人工精修/重排版。18- **强调由作者重施加**:工具**故意**把加粗/斜体一起去掉(见维护笔记),让你按自己的强调意图重新标。1920> 不适用:只需要读/改特定行 → 用 Read/Edit;只需要在某文件里定位内容 → 用 fastsearch/Grep;要保留全部 Markdown 格式 → 别用本工具(它会剥格式)。2122## 0. 心法(一句话)2324**代码围栏块是绝对原文保护区 → 正文行紧跟 `---` 会被当 setext 标题(不是删分隔线)→ 去味儿后强调自己重新加。**2526## 1. 前置:定位入口 + 调用约定2728入口是 skill 自带的 self-contained exe(优先,固定位置);另有 ps1 薄包装提供批量能力。2930```bash31# exe 直接可调(无需 powershell -File 前缀,不像 fastsearch 的 ps1 载体)32ls "$HOME/.claude/skills/fastdeai/fastdeai.exe"33```3435**bash 调用约定**:3637```bash38# 方式一(推荐):定义一次 bash 函数,后续像命令一样用39fastdeai() { "$HOME/.claude/skills/fastdeai/fastdeai.exe" "$@"; }40fastdeai report.md # → 生成 report_out.md41fastdeai report.md cleaned.md # → 指定输出名4243# 方式二:批量(需经 ps1 包装;exe 本身不支批量)44powershell.exe -NoProfile -ExecutionPolicy Bypass \45 -File "$HOME/.claude/skills/fastdeai/fastdeai.ps1" -Batch "D:\docs" -Recurse46```4748> 下文示例一律用 `fastdeai ...` 简写(假定已按方式一定义函数;或自行脑补 exe 全路径)。49> 无参数运行 `fastdeai` 可显示官方 usage(权威,以它为准)。5051## 2. 完整用法5253```54fastdeai.exe <input.md> [output.md] # 单文件,输出可选55fastdeai.ps1 -Batch <dir> [-Recurse] # 批量(ps1 包装,exe 不支持)56```5758| 参数 / 选项 | 作用 |59|---|---|60| `<input.md>` | 输入 Markdown 文件(必填) |61| `[output.md]` | 输出路径(可选)。缺省 → 输入文件旁的 `<原名>_out.md` |62| `-h --help /?` | 显示 usage |63| `-Batch <dir>` | (ps1 包装)批量处理目录下所有 `*.md`,自动跳过已生成的 `*_out.md` |64| `-Recurse` | (ps1 包装)递归子目录 |6566**退出码**:`0`=成功 · `1`=异常 · `2`=参数错误(如输入不存在、输入==输出路径) · `3`=ps1 包装找不到 exe / 批量目录不存在。**无参运行**=显示 usage 并返回 `0`。6768**输出编码**:统一 UTF-8 **无 BOM**、`\n` 换行(实测确认),中文安全。6970## 3. 清洗规则(权威,源自源码)7172> 关键原则:**代码围栏块是"原文保护区"**——以下所有转换/删除只在围栏外生效,围栏内任何符号(`**`、`` ` ``、`>`、emoji、`---`)都保持原样。7374**原样保护(不动):**75- YAML front matter(首行 `---` … 闭合 `---`)76- 代码围栏块(` ``` ` 或 ` ~~~ `,≥3 个)及其内部全部内容7778**保留结构(内容仍走 inline 清洗):**79- 标题(ATX `#`、setext,见 §4.2)、表格(GFM)、列表(有序/无序/任务列表 `- [x]`)、段落文本8081**转换(去格式,留内容):**82- 加粗 `**x**` / `__x__` / `***x***` → 去标记,留文字83- 行内代码 `` `code` `` → 去反引号,留内容84- 斜体 `*x*`、删除线 `~~x~~` → 去标记,留文字85- 链接 `[文字](url)` / `[文字][ref]` → 纯文字86- 引用块 `>` → 去标记,留正文8788**删除:**89- 图片 ``90- 分隔线 `---` / `***` / `___`(≥3,孤立时)91- 装饰 emoji(🎯📌✅💡🚀🔥⭐✨📊📈🔍📝⚠❗❓🔔🆕👍 等 ~45 种 + variation selector)92- HTML 标签 / 块 / 注释(`<div>`、`<details>`、`<!-- -->` 等)93- 脚注定义 `[^x]:` 与引用 `[^x]`9495## 4. ⚠️ 已验证语义坑(清洗前必读)9697> 实测沉淀,绕过这些会误判结果。下列行为逐条经样本验证。98991. **代码围栏块绝对保护**:围栏内的 `**bold**`、`` `code` ``、`> quote`、`🎯 emoji`、`---` **全部原样保留**,清洗规则不生效。不确定某符号为何没被去掉时,先看它是否在代码块里。1002. **Setext heading 自动转 ATX(README 未提,易误判)**:「正文行」紧跟 `===` → `# 正文`;紧跟 `---` → `## 正文`。**坑**:文档里一段正文下面跟了一条 `---` 当分隔线,但前面紧挨着非空正文行 → 它会把那行**升成 `##` 标题**(而非删除分隔线)!只有 `---` 前面是空行/标题/表格行(不可提升)时,才当分隔线删除。想确保 `---` 被删,前面留一个空行。1013. **snake_case 保留**:字母数字之间的 `_` 不当斜体(`snake_case_var`、`a_file.txt` 原样)。CommonMark 语义:开闭 `_` 两侧不能是字母数字。1024. **删除后残留空格**:删 emoji/图片/分隔线后,原位置可能残留少量空格(如「文字 🚀 后续」→「文字 后续」)。已知限制,作者后续手动收。1035. **多空行折叠为单空行**;首尾空白行裁剪。输出结构干净。1046. **行内代码反引号未闭合**→ 当字面量保留;**强调标记跨行未闭合**(如 `**粗\n体**`)→ 按字面量处理,不强转。1057. **4 空格缩进代码块不受保护**:按普通文本处理(避免误伤列表续行)。要保护代码,用 ` ``` ` 围栏。1068. **输入==输出路径会报错退出**(码 2),防覆盖源文件。107108## 5. recipe 库(实战沉淀)109110```bash111# 定义入口函数(每会话一次,或写进 ~/.bashrc)112fastdeai() { "$HOME/.claude/skills/fastdeai/fastdeai.exe" "$@"; }113114# —— 单文件清洗 ——115fastdeai report.md # → report_out.md(同目录)116fastdeai report.md cleaned.md # → 指定输出名117118# —— 批量目录(ps1 包装;exe 本身不支批量)——119powershell.exe -NoProfile -ExecutionPolicy Bypass \120 -File "$HOME/.claude/skills/fastdeai/fastdeai.ps1" -Batch "D:\notes" -Recurse121# 自动跳过 *_out.md,末尾打印 Cleaned / Skipped / Failed 计数122123# —— 先看会清成什么样,再决定要不要批量(无损:输出到独立文件)——124fastdeai sample.md _preview.md && cat _preview.md125```126127**清洗前后对照(实测样本节选)**:128129```markdown130# 🎯 Title with emoji → # Title with emoji131> This is a **blockquote** → This is a blockquote132**bold** *italic* ~~strike~~ → bold italic strike133snake_case_var a_file.txt → snake_case_var a_file.txt(下划线保留)134 image dropped. → image dropped.(图片删,残留空格)135--- → (分隔线删除,或上文升为 setext 标题,见 §4.2)136- [x] done **bold** task → - [x] done bold task137| **a** | `b` | → | a | b |(表格留,单元格内清洗)138```csharp → ```csharp(整个块原样,内部 ** ` > 🎯 不动)139var x = "🎯 stays"; → var x = "🎯 stays";140``` → ```141Setext Heading → # Setext Heading(=== 升为 #,见 §4.2)142```143144## 6. 与其它工具分工145146| 场景 | 工具 |147|---|---|148| 去 Markdown 的 AI 味儿格式(emoji/加粗/引用/分隔线…) | **fastdeai**(本 skill) |149| 大海捞针 + 与或非定位文件/日志 | fastsearch |150| 读干净内容 / 单关键词计数 / `-o` 提取 | Grep(ripgrep) |151| 读特定行/整个文件 | Read |152| 改特定片段 | Edit |153154> 典型流水线:**fastsearch 布尔定位含 AI 味儿的 `.md` → fastdeai 批量清洗成底稿 → 作者手动重施加强调/精修**。155156## 7. 维护笔记(给维护者)157158> **🔐 授权**:用户(ElabAlice)授权——agent 可按需直接维护本 skill(SKILL.md / fastdeai.ps1);**改清洗语义需改 C# 源码并重新 `dotnet publish` 出 exe**(见下流程)。159160- **载体决策**:fastsearch 把 C# 内嵌进 ps1 让 PS5.1 跑;fastdeai **做不到**——`System.Text.Rune`(.NET Core 3.0+)在 PS5.1 的 .NET Framework 里不存在,且源码用 C#8(`^1` 索引/`..` 范围)/C#9(target-typed `new()`)语法,PS5.1 CodeDom 只支持 C#5。故以 **self-contained exe 为权威载体**(目标机免装 .NET),ps1 仅做透传 + 批量。161- **源码 source of truth**:`0_FastTool/17_FastDeai/workspace/fastdeai_src/fastdeai/{Program.cs, MarkdownCleaner.cs}` + `fastdeai.csproj`。emoji 白名单见 `MarkdownCleaner.cs` 的 `DecorativeEmoji`(`HashSet<Rune>`,~45 个 + `0xFE0F` variation selector)。162- **改 C# → 更新 exe 流程**:改源码 → `0_FastTool/17_FastDeai/workspace/fastdeai_src/build_release.ps1`(dotnet publish 单文件 self-contained)→ 把生成的 `fastdeai_release/fastdeai.exe` 复制覆盖 `~/.claude/skills/fastdeai/fastdeai.exe`。ps1 包装无需动(语义全在 exe)。163- **ps1 包装边界**:`fastdeai.ps1` 仅透传单文件参数 + `-Batch` 批量(自动跳过 `*_out.md`),不碰清洗逻辑;PS5.1 兼容语法。批量输出固定为各自旁边的 `<原名>_out.md`(由 exe 决定,包装不覆盖)。164- **emoji 白名单扩展**:要新增删的 emoji,在源码 `DecorativeEmoji` 加对应 `new Rune(0xXXXX)`,重新 publish。注意 emoji + variation selector(0xFE0F)/ZWJ(0x200D)的粘连处理已在 `CleanInlineNonCode` 里。