Community写作与编辑github.com

m4bwav/readwright

从电子书和文档中分段读取文本,而不是将整个文件倾倒入上下文:先列出大纲,然后只读取需要的章节,最后搜索。一个命令行工具(标准库Python),支持 EPUB、MOBI、AZW3、FB2、DOCX、ODT、RTF、PPTX、XLSX、HTML、EML、CSV、JSON、Markdown 及其压缩包,以及 PDF 和旧版 DOC、XLS、PPT(当安装了 poppler、calibre 或 LibreOffice 时)。当用户要求从文件中读取、引用、总结、搜索或提取文本时使用。

readwright 是什么?

readwright 是一个专门为 AI 代理(如 Claude Code、Cursor)设计的技能,用于高效处理电子书和文档。它的核心思想是避免将整个文档(可能包含 15 万到 30 万 token)一次性地扔进上下文窗口,而是通过分步操作:首先输出带字数的目录(大纲),然后只读取用户需要的特定章节,最后进行搜索。这大大节省了 token 预算,并让 AI 专注于任务所需的文本。该技能支持广泛的格式,包括 EPUB、MOBI、AZW3、PDF、DOCX 等,内置格式仅需 Python 3.10 以上,外部格式则依赖可选工具(如 poppler、calibre、LibreOffice)。它通过 `RW` 命令(例如 `RW info`, `RW toc`, `RW read`, `RW grep`)与代理交互,并提供细粒度的控制,如按章节编号、标题正则表达式、单词数量限制(--max-words)、字符数量限制(--max-chars)、语言过滤、去重、代码块跳过等。对于没有文本层的扫描 PDF,它还支持 OCR(利用 Windows 内置或 tesseract)。readwright 的设计强调版权合规——它从不移除 DRM,并建议用户通过合法途径获取内容;同时,它鼓励代理在引用受版权保护的书籍时,只引用一两句话并注明出处。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/m4bwav/readwright/tree/HEAD/skills/readwright

Installed? Explore more 写作与编辑 skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

readwright 是做什么的?

一本小说有 15 万到 30 万个 token。如果使用转换器(如 epr -d、pandoc -t plain、ebook-convert book.txt)将整个文档倒入上下文,会在回答之前就填满上下文。readwright 先为代理提供带有字数的目录,然后提供选定的章节,最后提供带有章节和段落编号的搜索结果,这样它只读取任务所需的内容,而不会多读任何东西。

下文中的 RW 表示 python "<this folder>/scripts/rw.py"(macOS 和 Linux 上为 python3)。启动脚本 scripts/rw.sh 和 scripts/rw.ps1 执行相同的操作。它需要 Python 3.10 或更高版本,并且对于内置格式不需要其他任何东西;RW formats 会显示这台机器上有哪些外部工具。

步骤 0:新鲜度

阅读 evergreen.json。如果设置了 contradiction 或者今天在 next_due 当天或之后,请用一行说明,然后执行任务,最后刷新(MAINTENANCE.md)。转换器版本和电子书格式会变化;下面的流程不依赖于它们。

Discord:实时频道不是文件;使用 everscout 的 scripts/es_discord.py 读取它(用户自己邀请的机器人,everscout kb/discord.md)。用户制作的频道导出文件(JSON 或 HTML)可以像此处的任何 JSON 或 HTML 文件一样读取。

步骤 1:评估大小

运行 RW info FILE。它会打印检测到的格式(根据文件字节,而非扩展名)、标题、作者、语言、章节数量、字数以及近似 token 数(字符数除以 4)。如果 token 数低于约 6,000(25,000 个字符),则 RW read FILE 会打印整个文本,你可以在此停止。

如果 info 报告了 DRM,请直说并停止。readwright 从不移除 DRM,你也不应该这样做:建议使用商店自带的阅读器或从卖家处获取无 DRM 的副本。如果它提示缺少某个工具(pdftotext、calibre 的 ebook-convert、LibreOffice),请传递它打印的安装命令。未经用户同意,绝不安装任何东西。对于 PDF,代理自己的阅读工具配合页码范围通常是更好的选择。

如果 info 打印了 note: no text layer,说明这本书是页面图像(扫描件),readwright 无法读取。请按照注释中提到的路线顺序操作。首先,寻找同一本书的其他格式副本;DjVu 副本通常带有 OCR 文本。然后,对于 PDF,运行 RW ocr FILE:它会渲染页面并运行 Windows 10 和 11 中内置的 OCR(或已安装的 tesseract),大约每秒一页,每 25 页保存一次,并将文本保留在 ~/.readwright/ocr/ 中,以便后续对同一文件执行 info、toc、read 和 grep 时直接使用(--pages N-M 用于少数页面,--force 用于重新执行)。整本书可以在后台运行。OCR 会误读一些字母,并且没有标题,因此章节就是页面;请对照页面图像检查引用。最后,可以使用 RW page FILE 1-5(60 dpi,--dpi,--out-dir)渲染几页,然后用自己的图像阅读器查看。在安装 OCR 工具前请先询问。

步骤 2:大纲

运行 RW toc FILE。每一行格式为 N. title (words w),按层级缩进;--ids 会添加每个章节的 id(文件路径和片段、页码、工作表),你很少需要它。EPUB 的标题来自书籍自身的导航(nav 文档或 NCX),DOCX 和 ODT 的标题来自标题样式,HTML 来自 h1 到 h3,纯文本和 Markdown 来自标题或 CHAPTER 行。没有结构的文本会被切割成大约 3,000 词的部分。对于 zip 压缩包,toc 会列出其中的成员;需要在之后的所有命令中添加 --member NAME(或其编号)。

那些将每个章节编号列为近似空章节的书籍(Packt,某些 O'Reilly 的书籍)会被合并显示:Ch. 12: Title,打印在标题的章节编号下(仅编号的章节被隐藏,但保留其编号且仍可读取)。RW toc FILE --depth 1 只打印顶层(部分和章节),每行汇总其下所有章节的字数(--depth 2 添加下一层级;JSON 格式会得到 chapter 和 words_total)。用它来计算章节数,而不是手动计数。没有大纲的 PDF 会每页列出一个章节;RW toc FILE --group 会将共享页眉的页面折叠成页面范围(章节)以便使用 --section 20-40 读取;如果没有共享页眉,则使用打印的目录页,其中每个条目是一行标题后跟一行页码(0.26.0),或者条目连续显示为 Title ... 21 Next ... 26(0.35.0),toc 会在注释中说明这一点。

将用户的用词与 toc 行匹配。“第 14 章”通常指的是标题为 CHAPTER FOURTEEN 的行,在许多电子书中,该行只包含章节标题和一段题词:其正文是下一个章节。字数统计可以说明这一点(72 词,然后 6,330 词)。章节编号不是章号:前言排在前面,所以小说的第 16 章可能是第 24 节。

步骤 3:只读需要的部分

  • RW read FILE --section 43-44(也支持 N、N-、N,M;重复使用 --section 会累加)或 --title "REGEX"(不区分大小写,与标题和 id 匹配;若无匹配,则忽略空格,因此 westgate 可以匹配 WEST GATE)。
  • 当 --title 定位到一个少于 300 词的章节时,会添加该章节之后的下一节,并输出一条注释。--with-next 对任何选择都执行相同的操作。
  • 对于标题在书中重复 3 次或以上的章节(例如“准备就绪”、“如何做...”、“更多内容...”),会在 read 的页眉和 toc 中显示其最近的前一个独特标题:How to do it... (in: Following a path)(在 toc JSON 中为 in)。
  • --max-words N 将每个选定的章节限制在 N 词以内,因此像 --section 27-58 --max-words 80 这样的批处理会保持简短;被截断的章节末尾为 [cut at N of M words; continue with --section S --offset C]。
  • --drop-repeated(read)会删除在 30% 或更多章节中重复出现的短段落(40 词或更少),无论是逐字重复还是折叠数字后最后四个词相同的重复(例如 EPUB 中的图片注记和版权声明)。它还会删除在一个章节内部重复 10 次以上的八词或更少词的行(如每条尾注后的“返至文中注释参照”回链)。默认关闭。
  • --skip-code(read 和 grep)会删除通过结构识别出的代码块(EPUB 和 HTML 的 <pre>、Markdown 的围栏代码块;PDF 无标记,故不适用),并报告删除了多少词。提示信息会作为一行输出在末尾;--quiet 会去掉提示。
  • --lang CODE(read 和 grep,0.43.0;支持 en、de、es、fr、it、nl、pt)会保留那些短常见词偏向该语言的段落,适用于同时印刷多语言的版本。短于 4 词的片段和不确定的段落会被删除,但标题除外;代码和表格保留;OCR 粘连的单词仍会计数。页脚会报告删除了多少,--max-chars 会统计剩余内容。info 会标注包含大量两种或更多语言段落的书籍。
  • --headings(read,0.20.0)只打印所选章节的标题段落,按层级缩进,每个标题附带其段落编号及其下的字数;使用 --at-para P 跳转到指定段落。如果章节没有标题(如无结构的 PDF),会给出提示:请使用 toc --group 或 grep。
  • --strip-boilerplate(read 和 grep)会删除在 PDF 页面间重复出现的行:页脚、纯页码、页眉,根据重复频率识别。在两个命令中都使用它,以便 grep 的段落编号与 --at-para 匹配。
  • 每个章节都以页眉行开头:=== [43/80] title | id ... | words | starts at word N of TOTAL (P%) ===。
  • 输出会在 --max-chars(默认为 25,000)处停止。截断会在接近限制的段落、行或句子边界处结束(0.11.1),最后一行会说明在哪里继续:--offset N。确保每次读取都在你的 shell 工具输出限制之内:Claude Code 显示命令输出的 30,000 个字符,并将剩余部分保存到一个你需要另行打开的文件中。对于两个长章节,每次调用只读取一个。对于更多内容,使用 --out <scratch>/part.txt 写入选择,然后使用你自己的阅读工具打开。要将多个章节传递给另一个阅读代理,可以使用 --out-dir <scratch>/secs 将每个选定的章节写入单独的文件(NNN-title.txt)并列出它们的大小(0.12.0)。
  • --section 可以在一次调用中接受列表和范围:--section 61,80,87 或 --section 12,189-190。章节按该顺序打印,每个都有自己的页眉。
  • 简短的章节选择会以提示结束,指明下一个可能延续文本的章节:当前选择是标题页或题词(少于 60 词),或者下一节无标题、标记为“接上页”、或重复了当前标题(0.15.0;不再对每个小分节都触发)。
  • 当文本超出限制时,read 在没有选择器的情况下会拒绝(退出码 2)并打印 toc。这个拒绝是工具在工作:请选择章节。
  • --format md 保留标题和列表为 Markdown 格式;--out FILE 将选择写入文件;结合 --max-chars 时,会在一个干净的断点处截断并打印 cut at chars A-B of N; write the rest with --offset B(0.15.1)。--compact 会删除段落之间的空行(0.13.0);再次配合 --offset 使用。

步骤 4:搜索

RW grep FILE "PATTERN" -C 1 --max 5 打印每个匹配的段落,附带章节编号和标题、段落编号以及两侧各一段的上下文。长段落会在匹配周围被修剪(--width)。--after N(-A N)在每条匹配后添加 N 个段落,以 --width 限制显示并保留其换行符:这可以捕获命名它的句子之后的代码块或列表(0.15.0)。不包含大写字母的模式会匹配任何大小写(--case-sensitive 强制精确大小写,-i 强制忽略大小写),-F 接受纯字符串;--count 给出每节的匹配数,是查找角色或术语出现位置的最快方式。每条匹配行末尾为 | offset N,即字符偏移量,read --section S --offset N 从该处开始;read --section S --at-para P 从某个段落开始。当 toc 标注一个巨大部分时使用它们(书签提前结束);自 0.17.0 起,这样的部分会首先根据打印的目录页或“第 N 章,标题”列表命名进行切割,因此只有当该操作失败时才会显示注释。退出码 1 表示无匹配。当用户询问某个内容在哪里或是否存在时,请先搜索再读取。

RW rank FILE topic words(0.24.0)根据 BM25 算法对几个主题词对章节进行排序,并打印得分、字数以及每个章节包含的术语:确定优先读取哪个章节,而 grep 按书籍顺序打印命中结果。停用词以及复数、-ed 和 -ing 结尾会被折叠,因此 shingles 可以找到 shingling;书中不存在的词会被指出。--paras 对段落进行排序(标题行通常胜出:从那里开始阅读),--top N、--section、--k1 和 --b 与 BM25 中的含义相同。在长书上的大型 grep 之前先进行排序,然后在排名靠前的章节内进行 grep。

步骤 5:将整本书写入临时文件

对于需要对长书进行多次遍历的工作(例如,查找每个场景中的每个角色、时间线),请运行一次 RW dump FILE --out <scratch>/book.txt。然后在该文件上使用你自己的搜索和阅读工具,切勿使用 cat。章节标记是以 === [N/ 开头的行;--format md 会写入带有 Markdown 标题的 <!-- readwright section N/... --> 注释。只有当文本少于 25,000 个字符时,dump 才会写入标准输出。将该文件放在会话的 scratch 或 tmp 文件夹中,切勿放在用户的仓库中。

步骤 6:回答

请简短引用。对于受版权保护的书籍,一次只总结并引用一两句话,绝不引用整页或整章,即使使用者拥有该副本。请注明每个观点的出处(章节编号和标题),以便使用者核实。如果打印了转换注释(calibre、LibreOffice、pdftotext),且措辞重要,请说明文本是通过转换器获得的。

提炼一本书

  • 基于早期阅读笔记构建:在重复使用之前,先 grep 两到三条他们引用的段落,并阅读笔记略过的一章,以便新的撰写增加价值且不包含复制的错误。
  • 在 toc 行中,与同行显示 (0 w) 意味着该文本落入了相邻章节:使用 --section N-M 读取整个组。实践类书籍将框架或公差水平描述为经验:请将其视为作者的经验引用,而非测量结果。
  • 查找作者为某个有力主张引用的研究,并记录其局限性。通俗读物可能省略这些:一篇报告了性别差异,但没有说明该论文仅在部分年龄范围内发现该差异。
  • 已为其他主题阅读过的广泛参考资料:检查早期笔记针对你主题的内容,然后阅读他们为你的工作而略过的章节(评估附录、分析章节),按类型分配给两个阅读代理。
  • 为声音或编辑主题再次阅读的电影或广播教科书:早期笔记通常记录了理论章节;请阅读编辑和预混部分(音轨布局、分轨、场景转换),其中包含工作规则。在一次调用中读取所选章节,即 read --section 248,250,251,而不是每次调用一个。
  • 通过 OCR 阅读的扫描版实践类书籍(每页一个章节):toc --chapters 提供章节页码范围;然后在所需章节内使用 --section N-M 对主题词进行 grep,并只阅读命中的页面,因为大部分页面是轶事和旧设备。
  • 具有编号或全大写标题的平面 PDF 章节:read --headings 列出它们,然后使用 --at-para 跳转到你想要的标题。
  • 书签仅覆盖部分的 PDF(toc 警告一个章节占用了大部分文本):对每个大章节使用 read --section N --headings,可以获得真实的章节映射,以及用于 --at-para 的段落编号。
  • 编辑手册:首先阅读编辑的介绍,因为它说明了每章涵盖的内容,然后只阅读这些章节的开头部分和任何关于方法的段落。每章有自己的作者,因此请引用章节并单独判断。
  • 来自相邻行业的手册(为游戏效果而阅读的剧院音响):跳过人员和场地硬件,阅读关于制作材料的章节,并在其余部分对工作词汇进行 grep。像 mu?ed 这样的文本可能存在于出版商的文件中;在责怪阅读器之前请先检查来源。
  • 长篇历史综述:跳过乐器章节。对方法词汇进行 grep,阅读这些章节、结论部分,以及作者判断...

...

[翻译截断]

相关技能