@lucasygu/redbook 0.1.5 → 0.1.6

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/SKILL.md ADDED
@@ -0,0 +1,224 @@
1
+ ---
2
+ description: Search, read, and analyze Xiaohongshu (小红书) content via CLI
3
+ allowed-tools: Bash, Read, Write, Glob, Grep
4
+ ---
5
+
6
+ # Redbook — Xiaohongshu CLI
7
+
8
+ Use the `redbook` CLI to search notes, read content, analyze creators, and research topics on Xiaohongshu (小红书/RED).
9
+
10
+ ## Usage
11
+
12
+ ```
13
+ /redbook search "AI编程" # Search notes
14
+ /redbook read <url> # Read a note
15
+ /redbook user <userId> # Creator profile
16
+ /redbook analyze <userId> # Full creator analysis (profile + posts)
17
+ ```
18
+
19
+ ## Instructions
20
+
21
+ When this command is invoked, determine the user's intent and run the appropriate CLI command(s).
22
+
23
+ ### Quick Reference
24
+
25
+ | Intent | Command |
26
+ |--------|---------|
27
+ | Search notes | `redbook search "keyword" --json` |
28
+ | Read a note | `redbook read <url> --json` |
29
+ | Get comments | `redbook comments <url> --json --all` |
30
+ | Creator profile | `redbook user <userId> --json` |
31
+ | Creator's posts | `redbook user-posts <userId> --json` |
32
+ | Browse feed | `redbook feed --json` |
33
+ | Search hashtags | `redbook topics "keyword" --json` |
34
+ | Check connection | `redbook whoami` |
35
+
36
+ ### Always Use `--json`
37
+
38
+ Always add `--json` to commands when you need to parse the output programmatically. The JSON output is structured and reliable. Without `--json`, output is human-formatted text.
39
+
40
+ ### Command Details
41
+
42
+ #### `redbook search <keyword>`
43
+
44
+ Search for notes by keyword. Returns note titles, URLs, likes, author info.
45
+
46
+ ```bash
47
+ redbook search "Claude Code教程" --json
48
+ redbook search "AI编程" --sort popular --json # Sort: general, popular, latest
49
+ redbook search "Cursor" --type image --json # Type: all, video, image
50
+ redbook search "MCP Server" --page 2 --json # Pagination
51
+ ```
52
+
53
+ **Options:**
54
+ - `--sort <type>`: `general` (default), `popular`, `latest`
55
+ - `--type <type>`: `all` (default), `video`, `image`
56
+ - `--page <n>`: Page number (default: 1)
57
+
58
+ #### `redbook read <url>`
59
+
60
+ Read a note's full content — title, body text, images, likes, comments count.
61
+
62
+ ```bash
63
+ redbook read "https://www.xiaohongshu.com/explore/abc123" --json
64
+ ```
65
+
66
+ Accepts full URLs or short note IDs. If the API returns a captcha, it falls back to HTML scraping automatically.
67
+
68
+ #### `redbook comments <url>`
69
+
70
+ Get comments on a note. Use `--all` to fetch all pages.
71
+
72
+ ```bash
73
+ redbook comments "https://www.xiaohongshu.com/explore/abc123" --json
74
+ redbook comments "https://www.xiaohongshu.com/explore/abc123" --all --json
75
+ ```
76
+
77
+ **Options:**
78
+ - `--all`: Fetch all comment pages (default: first page only)
79
+
80
+ #### `redbook user <userId>`
81
+
82
+ Get a creator's profile — nickname, bio, follower count, note count, likes received.
83
+
84
+ ```bash
85
+ redbook user "5a1234567890abcdef012345" --json
86
+ ```
87
+
88
+ The userId is the hex string from the creator's profile URL.
89
+
90
+ #### `redbook user-posts <userId>`
91
+
92
+ List all notes posted by a creator. Returns titles, URLs, likes, timestamps.
93
+
94
+ ```bash
95
+ redbook user-posts "5a1234567890abcdef012345" --json
96
+ ```
97
+
98
+ #### `redbook feed`
99
+
100
+ Browse the recommendation feed. Returns a batch of recommended notes.
101
+
102
+ ```bash
103
+ redbook feed --json
104
+ ```
105
+
106
+ #### `redbook topics <keyword>`
107
+
108
+ Search for topic hashtags. Useful for finding trending topics to attach to posts.
109
+
110
+ ```bash
111
+ redbook topics "Claude Code" --json
112
+ ```
113
+
114
+ #### `redbook whoami`
115
+
116
+ Check connection status. Verifies cookies are valid and shows the logged-in user.
117
+
118
+ ```bash
119
+ redbook whoami
120
+ ```
121
+
122
+ If this fails, the user needs to log into xiaohongshu.com in Chrome.
123
+
124
+ #### `redbook post` (Limited)
125
+
126
+ Publish an image note. **Note: This command frequently triggers captcha (type=124) on the creator API.** Image upload works, but the publish step is unreliable. For posting, use Chrome browser automation instead.
127
+
128
+ ```bash
129
+ redbook post --title "标题" --body "正文" --images cover.png --json
130
+ redbook post --title "测试" --body "..." --images img.png --private --json
131
+ ```
132
+
133
+ **Options:**
134
+ - `--title <title>`: Note title (required)
135
+ - `--body <body>`: Note body text (required)
136
+ - `--images <paths...>`: Image file paths (required, at least one)
137
+ - `--topic <keyword>`: Search and attach a topic hashtag
138
+ - `--private`: Publish as private note
139
+
140
+ ### Global Options
141
+
142
+ All commands accept:
143
+ - `--cookie-source <browser>`: `chrome` (default), `safari`, `firefox`
144
+ - `--json`: Output as JSON
145
+
146
+ ## Research Workflows
147
+
148
+ ### Competitive Analysis
149
+
150
+ Research competitors in a niche:
151
+
152
+ ```bash
153
+ # 1. Search for content in the niche
154
+ redbook search "Claude Code" --sort popular --json
155
+
156
+ # 2. Identify top creators from search results (extract user IDs)
157
+
158
+ # 3. Deep-dive on each creator
159
+ redbook user <userId> --json # Profile + follower stats
160
+ redbook user-posts <userId> --json # All their content + engagement
161
+
162
+ # 4. Read their top-performing notes
163
+ redbook read <noteUrl> --json # Full content
164
+ redbook comments <noteUrl> --all --json # What resonates with audience
165
+ ```
166
+
167
+ ### Topic Research
168
+
169
+ Find trending topics and hashtags:
170
+
171
+ ```bash
172
+ # Search for topics
173
+ redbook topics "AI编程" --json
174
+
175
+ # Search notes using different sort orders to understand the landscape
176
+ redbook search "keyword" --sort popular --json # What's proven
177
+ redbook search "keyword" --sort latest --json # What's new
178
+ ```
179
+
180
+ ### Creator Deep-Dive
181
+
182
+ Analyze a specific creator's strategy:
183
+
184
+ ```bash
185
+ # Get profile overview
186
+ redbook user <userId> --json
187
+
188
+ # Get all their posts to analyze content patterns
189
+ redbook user-posts <userId> --json
190
+
191
+ # Read their top posts for content structure analysis
192
+ redbook read <topPostUrl> --json
193
+ redbook comments <topPostUrl> --all --json
194
+ ```
195
+
196
+ ## Programmatic API
197
+
198
+ The package also exports a TypeScript client for scripting:
199
+
200
+ ```typescript
201
+ import { XhsClient } from "@lucasygu/redbook";
202
+ import { loadCookies } from "@lucasygu/redbook/cookies";
203
+
204
+ const cookies = await loadCookies("chrome");
205
+ const client = new XhsClient(cookies);
206
+
207
+ const results = await client.searchNotes("AI编程", 1, 20, "popular");
208
+ const topics = await client.searchTopics("Claude Code");
209
+ ```
210
+
211
+ ## Error Handling
212
+
213
+ | Error | Meaning | Fix |
214
+ |-------|---------|-----|
215
+ | "No 'a1' cookie" | Not logged into XHS in browser | Log into xiaohongshu.com in Chrome |
216
+ | "Session expired" | Cookie too old | Re-login in Chrome |
217
+ | "NeedVerify" / captcha | Anti-bot triggered | Wait and retry, or reduce request frequency |
218
+ | "IP blocked" (300012) | Rate limited | Wait or switch network |
219
+
220
+ ## Requirements
221
+
222
+ - Node.js >= 22
223
+ - Logged into xiaohongshu.com in Chrome (or Safari/Firefox with `--cookie-source`)
224
+ - macOS (cookie extraction uses native keychain access)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lucasygu/redbook",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "CLI tool for Xiaohongshu (Red Note) - read and post via private API",
5
5
  "type": "module",
6
6
  "main": "./dist/lib/client.js",
@@ -14,6 +14,8 @@
14
14
  },
15
15
  "files": [
16
16
  "dist/",
17
+ "scripts/",
18
+ "SKILL.md",
17
19
  "LICENSE",
18
20
  "README.md"
19
21
  ],
@@ -21,6 +23,8 @@
21
23
  "build": "tsc && chmod +x dist/cli.js",
22
24
  "dev": "tsc --watch",
23
25
  "prepublishOnly": "npm run build",
26
+ "postinstall": "node scripts/postinstall.js",
27
+ "preuninstall": "node scripts/preuninstall.js",
24
28
  "start": "node dist/cli.js"
25
29
  },
26
30
  "engines": {
@@ -31,7 +35,9 @@
31
35
  "redbook",
32
36
  "xhs",
33
37
  "red-note",
34
- "cli"
38
+ "cli",
39
+ "claude-code",
40
+ "claude-code-skill"
35
41
  ],
36
42
  "author": "lucasygu",
37
43
  "license": "MIT",
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Post-install script for redbook CLI.
4
+ *
5
+ * Sets up Claude Code skill by creating a symlink:
6
+ * ~/.claude/skills/redbook -> <npm-package-location>
7
+ *
8
+ * This gives Claude Code a /redbook slash command automatically.
9
+ */
10
+
11
+ import { existsSync, mkdirSync, unlinkSync, symlinkSync, lstatSync, readlinkSync, rmSync } from 'fs';
12
+ import { join, dirname } from 'path';
13
+ import { fileURLToPath } from 'url';
14
+ import { homedir } from 'os';
15
+
16
+ const __filename = fileURLToPath(import.meta.url);
17
+ const __dirname = dirname(__filename);
18
+
19
+ const PACKAGE_ROOT = join(__dirname, '..');
20
+ const SKILL_DIR = join(homedir(), '.claude', 'skills');
21
+ const SKILL_LINK = join(SKILL_DIR, 'redbook');
22
+
23
+ function setupClaudeSkill() {
24
+ try {
25
+ if (!existsSync(SKILL_DIR)) {
26
+ mkdirSync(SKILL_DIR, { recursive: true });
27
+ }
28
+
29
+ if (existsSync(SKILL_LINK)) {
30
+ try {
31
+ const stats = lstatSync(SKILL_LINK);
32
+ if (stats.isSymbolicLink()) {
33
+ const currentTarget = readlinkSync(SKILL_LINK);
34
+ if (currentTarget === PACKAGE_ROOT) {
35
+ console.log('[redbook] Claude Code skill already configured.');
36
+ return true;
37
+ }
38
+ unlinkSync(SKILL_LINK);
39
+ } else {
40
+ rmSync(SKILL_LINK, { recursive: true });
41
+ }
42
+ } catch (err) {
43
+ console.log(`[redbook] Warning: ${err.message}`);
44
+ }
45
+ }
46
+
47
+ symlinkSync(PACKAGE_ROOT, SKILL_LINK);
48
+ console.log('[redbook] Claude Code skill installed:');
49
+ console.log(`[redbook] ~/.claude/skills/redbook -> ${PACKAGE_ROOT}`);
50
+ return true;
51
+ } catch (error) {
52
+ console.error(`[redbook] Failed to set up skill: ${error.message}`);
53
+ console.log('[redbook] You can manually create the symlink:');
54
+ console.log(`[redbook] ln -s "${PACKAGE_ROOT}" "${SKILL_LINK}"`);
55
+ return false;
56
+ }
57
+ }
58
+
59
+ function main() {
60
+ console.log('[redbook] Running post-install...');
61
+ const success = setupClaudeSkill();
62
+ console.log('');
63
+ console.log('[redbook] Installation complete!');
64
+ if (success) {
65
+ console.log('[redbook] Use /redbook in Claude Code, or run: redbook --help');
66
+ }
67
+ }
68
+
69
+ main();
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Pre-uninstall script for redbook CLI.
4
+ *
5
+ * Removes the Claude Code skill symlink at ~/.claude/skills/redbook
6
+ * (only if it points to this package).
7
+ */
8
+
9
+ import { existsSync, unlinkSync, lstatSync, readlinkSync } from 'fs';
10
+ import { join, dirname } from 'path';
11
+ import { fileURLToPath } from 'url';
12
+ import { homedir } from 'os';
13
+
14
+ const __filename = fileURLToPath(import.meta.url);
15
+ const __dirname = dirname(__filename);
16
+
17
+ const PACKAGE_ROOT = join(__dirname, '..');
18
+ const SKILL_LINK = join(homedir(), '.claude', 'skills', 'redbook');
19
+
20
+ function main() {
21
+ console.log('[redbook] Running pre-uninstall...');
22
+
23
+ if (!existsSync(SKILL_LINK)) {
24
+ console.log('[redbook] No skill symlink found, nothing to clean up.');
25
+ return;
26
+ }
27
+
28
+ try {
29
+ const stats = lstatSync(SKILL_LINK);
30
+ if (!stats.isSymbolicLink()) {
31
+ console.log('[redbook] Skill path is not a symlink, leaving it alone.');
32
+ return;
33
+ }
34
+
35
+ const target = readlinkSync(SKILL_LINK);
36
+ if (target === PACKAGE_ROOT || target.includes('node_modules/@lucasygu/redbook')) {
37
+ unlinkSync(SKILL_LINK);
38
+ console.log('[redbook] Removed Claude Code skill symlink.');
39
+ } else {
40
+ console.log('[redbook] Skill symlink points elsewhere, leaving it alone.');
41
+ }
42
+ } catch (error) {
43
+ console.error(`[redbook] Warning: Could not remove skill: ${error.message}`);
44
+ }
45
+
46
+ console.log('[redbook] Uninstall cleanup complete.');
47
+ }
48
+
49
+ main();