@lucasygu/redbook 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -29,6 +29,9 @@ npm install -g @lucasygu/redbook
29
29
  - **话题研究** —— 搜索关键词,分析哪些话题有流量、哪些是蓝海
30
30
  - **竞品分析** —— 找到头部博主,对比粉丝量、互动数据、内容风格
31
31
  - **爆款拆解** —— 分析爆款笔记的标题钩子、互动比例、评论主题
32
+ - **爆款模板** —— 从多篇爆款笔记提取内容模板(标题结构、正文结构、钩子模式)
33
+ - **评论管理** —— 发评论、回复评论、按策略批量回复(问题优先 / 高赞优先 / 未回复优先)
34
+ - **图文卡片** —— Markdown 渲染为小红书风格的 PNG 图文卡片(7 种配色主题)
32
35
  - **内容策划** —— 基于数据发现内容机会,生成有数据支撑的选题建议
33
36
  - **受众洞察** —— 从互动信号推断目标用户画像
34
37
 
@@ -62,6 +65,23 @@ redbook topics "Claude Code"
62
65
  # 分析爆款笔记
63
66
  redbook analyze-viral https://www.xiaohongshu.com/explore/abc123
64
67
 
68
+ # 从多篇爆款提取内容模板
69
+ redbook viral-template "<url1>" "<url2>" "<url3>" --json
70
+
71
+ # 发评论
72
+ redbook comment "<noteUrl>" --content "写得好!"
73
+
74
+ # 回复评论
75
+ redbook reply "<noteUrl>" --comment-id "<id>" --content "感谢提问!"
76
+
77
+ # 按策略批量回复(先预览再执行)
78
+ redbook batch-reply "<noteUrl>" --strategy questions --dry-run
79
+ redbook batch-reply "<noteUrl>" --strategy questions --template "感谢!{content}" --max 10
80
+
81
+ # 将 Markdown 渲染为图文卡片(需要可选依赖)
82
+ redbook render content.md --style xiaohongshu
83
+ redbook render content.md --style dark --output-dir ./cards
84
+
65
85
  # 发布图文笔记
66
86
  redbook post --title "标题" --body "正文内容" --images cover.png
67
87
  redbook post --title "测试" --body "..." --images img.png --private
@@ -81,6 +101,11 @@ redbook post --title "测试" --body "..." --images img.png --private
81
101
  | `post` | 发布图文笔记(易触发验证码,详见下方说明) |
82
102
  | `topics <关键词>` | 搜索话题/标签 |
83
103
  | `analyze-viral <url>` | 分析爆款笔记(钩子、互动、结构) |
104
+ | `viral-template <url...>` | 从 1-3 篇爆款笔记提取内容模板 |
105
+ | `comment <url>` | 发表评论 |
106
+ | `reply <url>` | 回复指定评论 |
107
+ | `batch-reply <url>` | 按策略批量回复评论(支持预览模式) |
108
+ | `render <文件>` | Markdown 渲染为小红书图文卡片 PNG(需可选依赖) |
84
109
 
85
110
  ### 通用选项
86
111
 
@@ -98,12 +123,42 @@ redbook post --title "测试" --body "..." --images img.png --private
98
123
  | `--type <类型>` | `all`(全部)、`video`(视频)、`image`(图文) | `all` |
99
124
  | `--page <页码>` | 页码 | `1` |
100
125
 
101
- ### 分析选项(analyze-viral)
126
+ ### 分析选项(analyze-viral / viral-template
102
127
 
103
128
  | 选项 | 说明 | 默认值 |
104
129
  |------|------|--------|
105
130
  | `--comment-pages <n>` | 获取评论页数 | `3` |
106
131
 
132
+ ### 批量回复选项(batch-reply)
133
+
134
+ | 选项 | 说明 | 默认值 |
135
+ |------|------|--------|
136
+ | `--strategy <策略>` | `questions`(提问)、`top-engaged`(高赞)、`all-unanswered`(未回复) | `questions` |
137
+ | `--template <模板>` | 回复模板,支持 `{author}`, `{content}` 占位符 | 无(预览模式) |
138
+ | `--max <数量>` | 最大回复数(上限 30) | `10` |
139
+ | `--delay <毫秒>` | 回复间隔(最小 180000ms/3分钟),自动添加 ±30% 随机抖动 | `300000`(5分钟) |
140
+ | `--dry-run` | 只预览不发送 | 无模板时自动开启 |
141
+
142
+ > ⚠️ **风控安全:** 小红书检测均匀时间间隔的自动化行为。回复间隔已自动添加 ±30% 随机抖动,避免触发机器人检测。建议每天每篇笔记最多批量回复 1-2 次。
143
+
144
+ ### 渲染选项(render)
145
+
146
+ 将 Markdown 文件渲染为小红书风格的 PNG 图文卡片。使用本机 Chrome 渲染,无需额外下载浏览器。
147
+
148
+ | 选项 | 说明 | 默认值 |
149
+ |------|------|--------|
150
+ | `--style <名称>` | 配色:purple, xiaohongshu, mint, sunset, ocean, elegant, dark | `xiaohongshu` |
151
+ | `--pagination <模式>` | 分页:auto(自动拆分)、separator(按 `---` 拆分) | `auto` |
152
+ | `--output-dir <目录>` | 输出目录 | 与输入文件同目录 |
153
+ | `--width <像素>` | 卡片宽度 | `1080` |
154
+ | `--height <像素>` | 卡片高度 | `1440` |
155
+ | `--dpr <倍率>` | 设备像素比 | `2` |
156
+
157
+ **可选依赖:** 需要安装 `puppeteer-core` 和 `marked`:
158
+ ```bash
159
+ npm install -g puppeteer-core marked
160
+ ```
161
+
107
162
  ### 发布选项(post)
108
163
 
109
164
  发布功能目前**容易触发验证码**(type=124)。图片上传正常,但发布步骤经常被拦截。如需发布笔记,建议使用浏览器自动化。
@@ -133,7 +188,30 @@ redbook post --title "测试" --body "..." --images img.png --private
133
188
  - **主 API**(`edith.xiaohongshu.com`)—— 读取:搜索、推荐页、笔记、评论、用户资料。使用 144 字节 x-s 签名(v4.3.1)
134
189
  - **创作者 API**(`creator.xiaohongshu.com`)—— 写入:上传图片、发布笔记。使用 AES-128-CBC 签名
135
190
 
136
- ## Claude Code 集成
191
+ ## 分析模块(A-L)
192
+
193
+ 内置 12 个可组合的分析模块,覆盖从关键词研究到内容发布的完整工作流:
194
+
195
+ | 模块 | 功能 |
196
+ |------|------|
197
+ | A. 关键词矩阵 | 分析各关键词的互动天花板和竞争密度 |
198
+ | B. 跨话题热力图 | 发现话题 × 场景的内容空白 |
199
+ | C. 互动信号分析 | 分类内容类型(工具型 / 认知型 / 娱乐型) |
200
+ | D. 博主画像 | 对比头部博主的粉丝、互动、风格 |
201
+ | E. 内容形式分析 | 图文 vs. 视频的表现对比 |
202
+ | F. 机会评分 | 按性价比排序关键词 |
203
+ | G. 受众推断 | 从互动信号推断用户画像 |
204
+ | H. 选题策划 | 数据驱动的内容创意 |
205
+ | I. 评论运营 | 按策略筛选和批量回复评论 |
206
+ | J. 爆款复刻 | 从爆款笔记提取内容模板 |
207
+ | K. 互动自动化 | 组合 I + J 的自动化运营工作流 |
208
+ | L. 图文卡片 | Markdown → 小红书风格 PNG 图文卡片(7 种配色) |
209
+
210
+ 详见 [SKILL.md](SKILL.md) 的模块文档和组合工作流。
211
+
212
+ ## AI 助手集成
213
+
214
+ ### Claude Code
137
215
 
138
216
  安装后自动注册为 Claude Code 技能。在 Claude Code 中使用 `/redbook` 命令:
139
217
 
@@ -144,14 +222,25 @@ redbook post --title "测试" --body "..." --images img.png --private
144
222
  /redbook analyze-viral <url> # 分析爆款笔记
145
223
  ```
146
224
 
147
- 技能内置了小红书平台专属的分析模块 —— 关键词矩阵、跨话题热力图、互动信号分类、博主画像、内容机会评分等。你可以直接用自然语言下达复杂任务:
225
+ 你可以直接用自然语言下达复杂任务:
148
226
 
149
227
  - *"分析'AI编程'在小红书的竞争格局,找出蓝海关键词"*
150
228
  - *"对比这三个博主的内容策略和互动数据"*
151
229
  - *"拆解这篇爆款笔记,告诉我为什么火了"*
230
+ - *"帮我回复这篇笔记下面的提问评论"*
152
231
 
153
232
  Claude 会自动组合多个命令,解析 JSON 数据,输出结构化分析报告。
154
233
 
234
+ ### OpenClaw / ClawHub
235
+
236
+ 官方支持 [OpenClaw](https://openclaw.ai) 和 [ClawHub](https://docs.openclaw.ai/tools/clawhub) 生态。通过 ClawHub 安装:
237
+
238
+ ```bash
239
+ clawhub install redbook
240
+ ```
241
+
242
+ 安装后在 OpenClaw 中可直接使用所有 `redbook` 命令。SKILL.md 同时兼容 Claude Code 和 OpenClaw 两个生态。
243
+
155
244
  ## 编程接口
156
245
 
157
246
  ```typescript
@@ -212,6 +301,9 @@ After installing, run `redbook whoami` to verify the connection. If macOS shows
212
301
  - **Topic research** — Search keywords, analyze which topics have demand vs. gaps
213
302
  - **Competitive analysis** — Find top creators, compare followers, engagement, content style
214
303
  - **Viral note breakdown** — Analyze title hooks, engagement ratios, comment themes
304
+ - **Viral templates** — Extract content templates from multiple viral notes (hook patterns, body structure, engagement profile)
305
+ - **Comment management** — Post comments, reply to comments, batch-reply with strategies (questions / top-engaged / unanswered)
306
+ - **Image cards** — Render markdown to styled PNG cards for XHS posts (7 color themes)
215
307
  - **Content planning** — Discover content opportunities with data-backed topic suggestions
216
308
  - **Audience insights** — Infer target audience from engagement signals
217
309
 
@@ -245,6 +337,23 @@ redbook topics "Claude Code"
245
337
  # Analyze a viral note
246
338
  redbook analyze-viral https://www.xiaohongshu.com/explore/abc123
247
339
 
340
+ # Extract content template from viral notes
341
+ redbook viral-template "<url1>" "<url2>" "<url3>" --json
342
+
343
+ # Post a comment
344
+ redbook comment "<noteUrl>" --content "Great post!"
345
+
346
+ # Reply to a comment
347
+ redbook reply "<noteUrl>" --comment-id "<id>" --content "Thanks for asking!"
348
+
349
+ # Batch reply with strategy (preview first, then execute)
350
+ redbook batch-reply "<noteUrl>" --strategy questions --dry-run
351
+ redbook batch-reply "<noteUrl>" --strategy questions --template "Thanks! {content}" --max 10
352
+
353
+ # Render markdown to image cards (requires optional deps)
354
+ redbook render content.md --style xiaohongshu
355
+ redbook render content.md --style dark --output-dir ./cards
356
+
248
357
  # Publish (requires image)
249
358
  redbook post --title "标题" --body "正文" --images cover.png
250
359
  redbook post --title "测试" --body "..." --images img.png --private
@@ -264,6 +373,11 @@ redbook post --title "测试" --body "..." --images img.png --private
264
373
  | `post` | Publish an image note (captcha-prone, see below) |
265
374
  | `topics <keyword>` | Search for topics/hashtags |
266
375
  | `analyze-viral <url>` | Analyze why a viral note works (hooks, engagement, structure) |
376
+ | `viral-template <url...>` | Extract a content template from 1-3 viral notes |
377
+ | `comment <url>` | Post a top-level comment |
378
+ | `reply <url>` | Reply to a specific comment |
379
+ | `batch-reply <url>` | Batch reply to comments with filtering strategy (supports dry-run) |
380
+ | `render <file>` | Render markdown to styled PNG image cards for XHS posts (optional deps) |
267
381
 
268
382
  ### Global Options
269
383
 
@@ -281,12 +395,42 @@ redbook post --title "测试" --body "..." --images img.png --private
281
395
  | `--type <type>` | `all`, `video`, `image` | `all` |
282
396
  | `--page <n>` | Page number | `1` |
283
397
 
284
- ### Analyze-Viral Options
398
+ ### Analyze-Viral / Viral-Template Options
285
399
 
286
400
  | Option | Description | Default |
287
401
  |--------|-------------|---------|
288
402
  | `--comment-pages <n>` | Number of comment pages to fetch | `3` |
289
403
 
404
+ ### Batch-Reply Options
405
+
406
+ | Option | Description | Default |
407
+ |--------|-------------|---------|
408
+ | `--strategy <name>` | `questions`, `top-engaged`, `all-unanswered` | `questions` |
409
+ | `--template <text>` | Reply template with `{author}`, `{content}` placeholders | none (dry-run) |
410
+ | `--max <n>` | Max replies to send (hard cap: 30) | `10` |
411
+ | `--delay <ms>` | Delay between replies in ms (min: 180000 / 3 min), ±30% random jitter applied automatically | `300000` (5 min) |
412
+ | `--dry-run` | Preview candidates without posting | auto when no template |
413
+
414
+ > ⚠️ **Rate limit safety:** XHS detects uniform timing patterns as bot behavior. Reply delays include ±30% random jitter automatically. Limit to 1-2 batch runs per note per day. See SKILL.md for full rate limit guidance.
415
+
416
+ ### Render Options
417
+
418
+ Render a markdown file to styled PNG image cards. Uses your existing Chrome for rendering — no browser download needed.
419
+
420
+ | Option | Description | Default |
421
+ |--------|-------------|---------|
422
+ | `--style <name>` | Color style: purple, xiaohongshu, mint, sunset, ocean, elegant, dark | `xiaohongshu` |
423
+ | `--pagination <mode>` | Pagination: auto, separator | `auto` |
424
+ | `--output-dir <dir>` | Output directory | same as input |
425
+ | `--width <n>` | Card width in pixels | `1080` |
426
+ | `--height <n>` | Card height in pixels | `1440` |
427
+ | `--dpr <n>` | Device pixel ratio | `2` |
428
+
429
+ **Optional dependencies:** Requires `puppeteer-core` and `marked`:
430
+ ```bash
431
+ npm install -g puppeteer-core marked
432
+ ```
433
+
290
434
  ### Post Options
291
435
 
292
436
  Publishing **frequently triggers captcha** (type=124). Image upload works, but the publish step is unreliable. For posting, consider using browser automation instead.
@@ -316,7 +460,30 @@ Publishing **frequently triggers captcha** (type=124). Image upload works, but t
316
460
  - **Main API** (`edith.xiaohongshu.com`) — for reading: search, feed, notes, comments, user profiles. Uses x-s signature with 144-byte payload (v4.3.1).
317
461
  - **Creator API** (`creator.xiaohongshu.com`) — for writing: upload images, publish notes. Uses simpler AES-128-CBC signing.
318
462
 
319
- ## Claude Code Integration
463
+ ## Analysis Modules (A-L)
464
+
465
+ 12 composable analysis modules covering the full workflow from keyword research to content publishing:
466
+
467
+ | Module | Purpose |
468
+ |--------|---------|
469
+ | A. Keyword Matrix | Analyze engagement ceiling and competition density per keyword |
470
+ | B. Cross-Topic Heatmap | Find topic × scene content gaps |
471
+ | C. Engagement Signals | Classify content type (reference / insight / entertainment) |
472
+ | D. Creator Profiling | Compare top creators' followers, engagement, style |
473
+ | E. Content Form | Image-text vs. video performance comparison |
474
+ | F. Opportunity Scoring | Rank keywords by effort-to-reward ratio |
475
+ | G. Audience Inference | Infer user persona from engagement signals |
476
+ | H. Content Brainstorm | Data-backed content ideas |
477
+ | I. Comment Operations | Filter and batch-reply to comments by strategy |
478
+ | J. Viral Replication | Extract content templates from viral notes |
479
+ | K. Engagement Automation | Combined I + J workflow for operations |
480
+ | L. Card Rendering | Markdown → styled PNG image cards for XHS posts (7 color themes) |
481
+
482
+ See [SKILL.md](SKILL.md) for full module documentation and composed workflows.
483
+
484
+ ## AI Agent Integration
485
+
486
+ ### Claude Code
320
487
 
321
488
  Installs automatically as a Claude Code skill. Use `/redbook` in Claude Code:
322
489
 
@@ -327,14 +494,25 @@ Installs automatically as a Claude Code skill. Use `/redbook` in Claude Code:
327
494
  /redbook analyze-viral <url> # Analyze a viral note
328
495
  ```
329
496
 
330
- The skill includes XHS-native analysis modules — keyword engagement matrix, cross-topic heatmaps, engagement signal classification, creator profiling, opportunity scoring, and more. You can give natural language instructions for complex tasks:
497
+ You can give natural language instructions for complex tasks:
331
498
 
332
499
  - *"Analyze the competitive landscape for 'AI编程' on Xiaohongshu and find blue ocean keywords"*
333
500
  - *"Compare the content strategies of these three creators"*
334
501
  - *"Break down this viral note and tell me why it worked"*
502
+ - *"Reply to the question comments on my latest post"*
335
503
 
336
504
  Claude will automatically combine multiple commands, parse JSON data, and produce structured analysis reports.
337
505
 
506
+ ### OpenClaw / ClawHub
507
+
508
+ Officially supports [OpenClaw](https://openclaw.ai) and [ClawHub](https://docs.openclaw.ai/tools/clawhub). Install via ClawHub:
509
+
510
+ ```bash
511
+ clawhub install redbook
512
+ ```
513
+
514
+ All `redbook` commands are available in OpenClaw after installation. The SKILL.md is compatible with both Claude Code and OpenClaw ecosystems.
515
+
338
516
  ## Programmatic Usage
339
517
 
340
518
  ```typescript
package/SKILL.md CHANGED
@@ -53,6 +53,7 @@ Use the `redbook` CLI to search notes, read content, analyze creators, automate
53
53
  | Post a comment | `redbook comment <url> --content "text"` |
54
54
  | Reply to comment | `redbook reply <url> --comment-id <id> --content "text"` |
55
55
  | Batch reply (preview) | `redbook batch-reply <url> --strategy questions --dry-run` |
56
+ | Render markdown to cards | `redbook render content.md --style xiaohongshu` |
56
57
  | Check connection | `redbook whoami` |
57
58
 
58
59
  **Always add `--json`** when parsing output programmatically. Without it, output is human-formatted text.
@@ -340,10 +341,10 @@ redbook comments "<noteUrl>" --all --json
340
341
  # 2. Preview reply candidates (dry run)
341
342
  redbook batch-reply "<noteUrl>" --strategy questions --dry-run --json
342
343
 
343
- # 3. Execute replies with template
344
+ # 3. Execute replies with template (5 min delay with ±30% jitter)
344
345
  redbook batch-reply "<noteUrl>" --strategy questions \
345
346
  --template "感谢提问!关于{content},..." \
346
- --max 10 --delay 3000
347
+ --max 10
347
348
  ```
348
349
 
349
350
  **Fields to extract from `--dry-run` JSON:**
@@ -364,7 +365,7 @@ redbook batch-reply "<noteUrl>" --strategy questions \
364
365
  - High top-engaged comments (>100 likes) = reply to visible comments for maximum reach
365
366
  - Many unanswered comments = engagement gap, opportunity to increase reply rate
366
367
 
367
- **Safety:** Hard cap 50 replies per batch, minimum 2s delay, `--dry-run` by default (no template = preview only), immediate stop on captcha.
368
+ **Safety:** Hard cap 30 replies per batch, minimum 3-minute delay with ±30% jitter (default 5 min), `--dry-run` by default (no template = preview only), immediate stop on captcha. See [Rate Limits & Safety](#rate-limits--safety) for details.
368
369
 
369
370
  **Output:** Reply plan table with candidate comments, strategy match reason, and status.
370
371
 
@@ -422,15 +423,75 @@ This module is a workflow that composes Modules I and J with human oversight.
422
423
 
423
424
  **Safety rules:**
424
425
  - Always `--dry-run` first, human approval before execution
425
- - Maximum 50 replies per session
426
- - Minimum 2-second delay between replies
426
+ - Maximum 30 replies per session (hard cap)
427
+ - Minimum 3-minute delay between replies, default 5 minutes, with ±30% random jitter
427
428
  - Never reply to the same comment twice (check `hasSubReplies`)
428
429
  - Stop immediately on captcha — do not retry
430
+ - See [Rate Limits & Safety](#rate-limits--safety) for XHS risk control thresholds
429
431
 
430
432
  **Anti-spam guidelines:**
431
433
  - Vary reply templates across batches
432
434
  - Limit to 1-2 batch runs per note per day
433
435
  - Prioritize quality (targeted strategy) over quantity
436
+ - Uniform timing patterns trigger bot detection — jitter is applied automatically
437
+
438
+ ---
439
+
440
+ ### Module L: Card Rendering
441
+
442
+ **Answers:** How do I turn markdown content into Xiaohongshu-ready image cards?
443
+
444
+ **Commands:**
445
+ ```bash
446
+ # Render markdown to styled PNG cards
447
+ redbook render content.md --style xiaohongshu
448
+
449
+ # Custom style and output directory
450
+ redbook render content.md --style dark --output-dir ./cards
451
+
452
+ # JSON output (for programmatic use)
453
+ redbook render content.md --json
454
+ ```
455
+
456
+ **Input:** Markdown file with YAML frontmatter:
457
+ ```markdown
458
+ ---
459
+ emoji: "🚀"
460
+ title: "5个AI效率技巧"
461
+ subtitle: "Claude Code 实战"
462
+ ---
463
+
464
+ ## 技巧一:...
465
+ Content here...
466
+
467
+ ---
468
+
469
+ ## 技巧二:...
470
+ More content...
471
+ ```
472
+
473
+ **Output:** `cover.png` + `card_1.png`, `card_2.png`, ... in the same directory.
474
+
475
+ **Card specs:**
476
+ - **Size:** 1080×1440 (3:4 ratio, standard XHS image)
477
+ - **DPR:** 2 (retina quality, actual output 2160×2880)
478
+ - **Styles:** purple, xiaohongshu, mint, sunset, ocean, elegant, dark
479
+
480
+ **Pagination modes:**
481
+ - `auto` (default) — smart split on heading/paragraph boundaries using character-count heuristic
482
+ - `separator` — manual split on `---` in markdown
483
+
484
+ **How to interpret:**
485
+ - Uses the user's existing Chrome for rendering (via `puppeteer-core`) — no browser download needed
486
+ - Purely offline — no XHS API or cookies required
487
+ - Output images are ready for `redbook post --images cover.png card_1.png ...`
488
+
489
+ **Dependencies:** Requires `puppeteer-core` and `marked` (optional, install with `npm install -g puppeteer-core marked`).
490
+
491
+ **Composition with other modules:**
492
+ - Pairs with Module H (Content Brainstorm) — generate content ideas, write markdown, render to cards
493
+ - Pairs with Module J (Viral Replication) — extract template, write content matching the template, render
494
+ - Output feeds into `redbook post --images` for publishing
434
495
 
435
496
  ---
436
497
 
@@ -480,9 +541,14 @@ redbook viral-template "<url1>" "<url2>" "<url3>" --json
480
541
  Single-module workflow for managing comment engagement on your notes. Use `batch-reply --dry-run` to audit, then execute with a template.
481
542
 
482
543
  ### Content Replication
483
- **Modules:** A → J → H
544
+ **Modules:** A → J → H → L
545
+
546
+ Keyword research → viral template extraction → data-backed content brainstorm → render to image cards. The template provides structural constraints that guide Module H's content ideas. Module L renders the final markdown to XHS-ready PNGs.
547
+
548
+ ### Content Creation End-to-End
549
+ **Modules:** A → J → H → L → `post`
484
550
 
485
- Keyword research → viral template extraction data-backed content brainstorm. The template provides structural constraints that guide Module H's content ideas.
551
+ The full pipeline: research keywords extract viral template → brainstorm content write markdown render to styled image cards publish via `redbook post --images cover.png card_1.png ...`
486
552
 
487
553
  ### Full Operations
488
554
  **Modules:** A → C → I → J → K
@@ -491,6 +557,44 @@ Comprehensive automation playbook — keyword analysis, engagement classificatio
491
557
 
492
558
  ---
493
559
 
560
+ ## Rate Limits & Safety
561
+
562
+ XHS enforces aggressive anti-spam (风控) that detects automated behavior through device fingerprinting, activity ratio monitoring, and timing pattern analysis. The CLI applies safe defaults based on platform research.
563
+
564
+ ### Safe Thresholds
565
+
566
+ | Action | Safe Interval | CLI Default | Hard Cap |
567
+ |--------|--------------|-------------|----------|
568
+ | Post a note | 3-4 hours (2-3 notes/day max) | N/A (manual) | — |
569
+ | Comment | ≥3 minutes | N/A (manual) | — |
570
+ | Reply | ≥3 minutes | N/A (manual) | — |
571
+ | Batch reply delay | ≥3 minutes | 5 min ±30% jitter | — |
572
+ | Batch reply count | — | 10 | 30 |
573
+
574
+ ### Anti-Detection Measures
575
+
576
+ - **Timing jitter:** ±30% random variation on all batch delays. Uniform intervals are a bot signature.
577
+ - **Hard caps:** Maximum 30 replies per batch (down from 50). No override.
578
+ - **Rate limit warnings:** `post`, `comment`, and `reply` commands display safe interval reminders after each action.
579
+ - **Captcha circuit breaker:** Batch operations stop immediately on captcha (NeedVerify).
580
+
581
+ ### What Triggers Risk Control
582
+
583
+ - **Uniform timing** — replying at exact 3-second intervals flags bot detection
584
+ - **High frequency** — >50 interactions/minute across any action type
585
+ - **Activity ratio anomaly** — more comments than post views signals inauthentic behavior
586
+ - **Device fingerprint mismatch** — XHS fingerprints 21 hardware parameters
587
+
588
+ ### Best Practices for Agents
589
+
590
+ 1. Always `--dry-run` first, review candidates, then execute
591
+ 2. Use the default 5-minute delay — do not override `--delay` below 180000 (3 min)
592
+ 3. Limit batch runs to 1-2 per note per day
593
+ 4. Vary reply templates between batches
594
+ 5. Space `post` commands 3-4 hours apart (2-3 notes/day maximum)
595
+
596
+ ---
597
+
494
598
  ## API vs Browser Limitations
495
599
 
496
600
  The following operations work reliably via API:
@@ -655,19 +759,41 @@ Reply to multiple comments using a filtering strategy. Always preview with `--dr
655
759
  # Preview which comments match the strategy
656
760
  redbook batch-reply "<noteUrl>" --strategy questions --dry-run --json
657
761
 
658
- # Execute replies with a template
762
+ # Execute replies with a template (default 5 min delay with jitter)
659
763
  redbook batch-reply "<noteUrl>" --strategy questions \
660
- --template "感谢提问!{content}" --max 10 --delay 3000
764
+ --template "感谢提问!{content}" --max 10
661
765
  ```
662
766
 
663
767
  **Options:**
664
768
  - `--strategy <name>`: `questions` (default), `top-engaged`, `all-unanswered`
665
769
  - `--template <text>`: Reply template with `{author}`, `{content}` placeholders
666
- - `--max <n>`: Max replies (default: 10, hard cap: 50)
667
- - `--delay <ms>`: Delay between replies in ms (default: 3000, min: 2000)
770
+ - `--max <n>`: Max replies (default: 10, hard cap: 30)
771
+ - `--delay <ms>`: Delay between replies in ms (default: 300000 / 5 min, min: 180000 / 3 min). ±30% random jitter applied automatically.
668
772
  - `--dry-run`: Preview candidates without posting (default when no template)
669
773
 
670
- **Safety:** Stops immediately on captcha. No template = dry-run only.
774
+ **Safety:** Stops immediately on captcha. No template = dry-run only. Delays include random jitter to avoid uniform timing patterns that trigger XHS bot detection.
775
+
776
+ ### `redbook render <file>`
777
+
778
+ Render a markdown file with YAML frontmatter into styled PNG image cards. Uses the user's existing Chrome installation — no browser download needed.
779
+
780
+ ```bash
781
+ redbook render content.md --style xiaohongshu
782
+ redbook render content.md --style dark --output-dir ./cards
783
+ redbook render content.md --pagination separator --json
784
+ ```
785
+
786
+ **Options:**
787
+ - `--style <name>`: `purple`, `xiaohongshu` (default), `mint`, `sunset`, `ocean`, `elegant`, `dark`
788
+ - `--pagination <mode>`: `auto` (default), `separator` (split on `---`)
789
+ - `--output-dir <dir>`: Output directory (default: same as input file)
790
+ - `--width <n>`: Card width in px (default: 1080)
791
+ - `--height <n>`: Card height in px (default: 1440)
792
+ - `--dpr <n>`: Device pixel ratio (default: 2)
793
+
794
+ **Requires:** `puppeteer-core` and `marked` (`npm install -g puppeteer-core marked`). Does NOT require XHS cookies — purely offline rendering.
795
+
796
+ **Override Chrome path:** Set `CHROME_PATH` environment variable if Chrome is not in the standard location.
671
797
 
672
798
  ### `redbook whoami`
673
799
 
@@ -808,3 +934,4 @@ const topics = await client.searchTopics("Claude Code");
808
934
  - Node.js >= 22
809
935
  - Logged into xiaohongshu.com in Chrome (or Safari/Firefox with `--cookie-source`)
810
936
  - macOS (cookie extraction uses native keychain access)
937
+ - **For card rendering only:** `puppeteer-core` and `marked` (`npm install -g puppeteer-core marked`). Uses your existing Chrome — no additional browser download.
package/dist/cli.js CHANGED
@@ -21,7 +21,7 @@ import { dirname, join } from "node:path";
21
21
  import { extractCookies } from "./lib/cookies.js";
22
22
  import { XhsClient, XhsApiError } from "./lib/client.js";
23
23
  import { analyzeViral, formatViralAnalysis } from "./lib/analyze.js";
24
- import { selectCandidates, executeReplies, } from "./lib/reply-strategy.js";
24
+ import { selectCandidates, executeReplies, DEFAULT_DELAY_MS, MIN_DELAY_MS as MIN_REPLY_DELAY, MAX_REPLIES_HARD_CAP, } from "./lib/reply-strategy.js";
25
25
  import { extractTemplate, formatTemplate } from "./lib/template.js";
26
26
  const __dirname = dirname(fileURLToPath(import.meta.url));
27
27
  const pkg = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-8"));
@@ -330,6 +330,7 @@ postCmd.action(async (opts) => {
330
330
  if (r.note_id) {
331
331
  console.log(` URL: https://www.xiaohongshu.com/explore/${r.note_id}`);
332
332
  }
333
+ console.error(kleur.yellow("⚠ Rate limit: wait ≥3-4 hours before the next post (2-3 notes/day max)."));
333
334
  }
334
335
  }
335
336
  catch (err) {
@@ -591,6 +592,7 @@ commentCmd.action(async (url, opts) => {
591
592
  }
592
593
  else {
593
594
  console.log(kleur.green("Comment posted!"));
595
+ console.error(kleur.yellow("⚠ Rate limit: wait ≥3 minutes before the next comment to avoid risk control."));
594
596
  }
595
597
  }
596
598
  catch (err) {
@@ -615,6 +617,7 @@ replyCmd.action(async (url, opts) => {
615
617
  }
616
618
  else {
617
619
  console.log(kleur.green("Reply posted!"));
620
+ console.error(kleur.yellow("⚠ Rate limit: wait ≥3 minutes before the next reply to avoid risk control."));
618
621
  }
619
622
  }
620
623
  catch (err) {
@@ -627,8 +630,8 @@ const batchReplyCmd = program
627
630
  .description("Reply to multiple comments using a strategy")
628
631
  .option("--strategy <name>", "Filter strategy: questions, top-engaged, all-unanswered", "questions")
629
632
  .option("--template <text>", "Reply template with {author}, {content} placeholders")
630
- .option("--max <n>", "Max replies to send (hard cap: 50)", "10")
631
- .option("--delay <ms>", "Delay between replies in ms (min: 2000)", "3000")
633
+ .option("--max <n>", `Max replies to send (hard cap: ${MAX_REPLIES_HARD_CAP})`, "10")
634
+ .option("--delay <ms>", `Delay between replies in ms (min: ${MIN_REPLY_DELAY / 1000}s)`, String(DEFAULT_DELAY_MS))
632
635
  .option("--dry-run", "Preview candidates without posting");
633
636
  addCookieOption(batchReplyCmd);
634
637
  addJsonOption(batchReplyCmd);
@@ -637,7 +640,7 @@ batchReplyCmd.action(async (url, opts) => {
637
640
  const client = await getClient(opts.cookieSource, opts.chromeProfile);
638
641
  const { noteId, xsecToken } = parseNoteUrl(url);
639
642
  const strategy = opts.strategy;
640
- const max = Math.min(parseInt(opts.max) || 10, 50);
643
+ const max = Math.min(parseInt(opts.max) || 10, MAX_REPLIES_HARD_CAP);
641
644
  const isDryRun = opts.dryRun || !opts.template;
642
645
  // Fetch all comments
643
646
  console.error(kleur.dim("Fetching comments..."));
@@ -675,8 +678,10 @@ batchReplyCmd.action(async (url, opts) => {
675
678
  return;
676
679
  }
677
680
  // Execute replies
678
- console.error(kleur.dim(`Sending ${plan.candidates.length} replies (delay: ${opts.delay}ms)...`));
679
- const results = await executeReplies(client, noteId, plan.candidates, opts.template, parseInt(opts.delay) || 3000, {});
681
+ const delayMs = parseInt(opts.delay) || DEFAULT_DELAY_MS;
682
+ console.error(kleur.dim(`Sending ${plan.candidates.length} replies (delay: ~${Math.round(delayMs / 60000)}min ±30% jitter)...`));
683
+ console.error(kleur.yellow("⚠ Rate limit: XHS enforces anti-spam — replies spaced ≥3min apart with jitter."));
684
+ const results = await executeReplies(client, noteId, plan.candidates, opts.template, delayMs, {});
680
685
  const succeeded = results.filter((r) => r.success).length;
681
686
  const failed = results.filter((r) => !r.success).length;
682
687
  if (opts.json) {
@@ -696,6 +701,43 @@ batchReplyCmd.action(async (url, opts) => {
696
701
  handleError(err);
697
702
  }
698
703
  });
704
+ // ─── render ──────────────────────────────────────────────────────────────────
705
+ const renderCmd = program
706
+ .command("render <file>")
707
+ .description("Render markdown to styled PNG cards for Xiaohongshu posts")
708
+ .option("--style <name>", "Color style: purple, xiaohongshu, mint, sunset, ocean, elegant, dark", "xiaohongshu")
709
+ .option("--pagination <mode>", "Pagination: auto, separator", "auto")
710
+ .option("--output-dir <dir>", "Output directory (default: same as input file)")
711
+ .option("--width <n>", "Card width in px", "1080")
712
+ .option("--height <n>", "Card height in px", "1440")
713
+ .option("--dpr <n>", "Device pixel ratio", "2");
714
+ addJsonOption(renderCmd);
715
+ renderCmd.action(async (file, opts) => {
716
+ try {
717
+ const { renderCards } = await import("./lib/render.js");
718
+ const result = await renderCards(file, {
719
+ style: opts.style,
720
+ pagination: opts.pagination,
721
+ outputDir: opts.outputDir,
722
+ width: parseInt(opts.width),
723
+ height: parseInt(opts.height),
724
+ dpr: parseInt(opts.dpr),
725
+ });
726
+ if (opts.json) {
727
+ output(result, true);
728
+ }
729
+ else {
730
+ console.log(kleur.green(`\nRendered ${result.totalCards + 1} images:`));
731
+ console.log(` Cover: ${kleur.bold(result.coverPath)}`);
732
+ for (const p of result.cardPaths) {
733
+ console.log(` Card: ${kleur.bold(p)}`);
734
+ }
735
+ }
736
+ }
737
+ catch (err) {
738
+ handleError(err);
739
+ }
740
+ });
699
741
  // ─── Helpers ────────────────────────────────────────────────────────────────
700
742
  function parseNoteUrl(url) {
701
743
  // Handle full URLs like https://www.xiaohongshu.com/explore/abc123?xsec_token=xxx