yuque-cookie-plugin 0.1.2 → 0.1.3

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
@@ -9,7 +9,7 @@
9
9
  ## 当前能力
10
10
 
11
11
  - Cookie 登录、清理和登录态检测:`auth login`、`auth logout`、`auth status`
12
- - 读取语雀信息:`book inspect`、`doc inspect`
12
+ - 读取语雀信息:`book list`、`book inspect`、`doc inspect`
13
13
  - 文档快照和结构对比:`doc snapshot`、`lake diff`
14
14
  - Lake 和 Markdown 辅助转换:`lake to-markdown`、`lake serialize`
15
15
  - 安全写入:`doc apply-lake`、`doc update-lake`
@@ -78,6 +78,15 @@ npm run yuque-local -- auth login
78
78
 
79
79
  项目目录不会保存真实 Cookie。配置文件会记录保存时间、更新时间、最近成功验证时间和最近失败时间。
80
80
 
81
+ 如果你在同一台电脑上同时做全局 npm 版真实测试和本地源码开发,可以用独立配置目录隔离 Cookie:
82
+
83
+ ```bash
84
+ YUQUE_COOKIE_PLUGIN_CONFIG_DIR=/tmp/yuque-plugin-real-test yuque-local auth login
85
+ YUQUE_COOKIE_PLUGIN_CONFIG_DIR=/tmp/yuque-plugin-real-test yuque-local auth status --json
86
+ ```
87
+
88
+ 这会把配置保存到 `/tmp/yuque-plugin-real-test/config.json`,不会影响默认的 `~/.config/yuque-cookie-plugin/config.json`。
89
+
81
90
  也可以用环境变量覆盖本地配置:
82
91
 
83
92
  ```bash
@@ -121,6 +130,12 @@ yuque-local auth login --manual \
121
130
  npm run yuque-local -- book inspect https://www.yuque.com/<your-login>/<your-book>
122
131
  ```
123
132
 
133
+ 列出当前账号可访问的知识库:
134
+
135
+ ```bash
136
+ yuque-local book list --json
137
+ ```
138
+
124
139
  下载整个知识库:
125
140
 
126
141
  ```bash
@@ -240,6 +255,7 @@ npm run real:acceptance -- \
240
255
  ## 文档
241
256
 
242
257
  - `docs/usage-zh.md`:中文完整使用指南
258
+ - `docs/ai-dialogue-test-cases.md`:用户和 AI 对话测试用例
243
259
  - `docs/real-acceptance.md`:真实语雀验收流程
244
260
  - `docs/native-lake-capability.md`:原生 Lake 能力矩阵
245
261
  - `docs/development-plan.md`:开发计划和迭代日志
package/dist/auth.js CHANGED
@@ -6,16 +6,20 @@ import { createInterface } from 'node:readline/promises';
6
6
  import os from 'node:os';
7
7
  import path from 'node:path';
8
8
  import process from 'node:process';
9
- const CONFIG_DIR = path.join(os.homedir(), '.config', 'yuque-cookie-plugin');
10
- const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
9
+ export const CONFIG_DIR_ENV = 'YUQUE_COOKIE_PLUGIN_CONFIG_DIR';
10
+ export function getConfigDirPath() {
11
+ const override = process.env[CONFIG_DIR_ENV]?.trim();
12
+ return override ? path.resolve(override) : path.join(os.homedir(), '.config', 'yuque-cookie-plugin');
13
+ }
11
14
  export function getConfigFilePath() {
12
- return CONFIG_FILE;
15
+ return path.join(getConfigDirPath(), 'config.json');
13
16
  }
14
17
  export async function clearSavedCredentials() {
15
- const existed = existsSync(CONFIG_FILE);
16
- await rm(CONFIG_FILE, { force: true });
18
+ const configFile = getConfigFilePath();
19
+ const existed = existsSync(configFile);
20
+ await rm(configFile, { force: true });
17
21
  return {
18
- config_file: CONFIG_FILE,
22
+ config_file: configFile,
19
23
  removed: existed
20
24
  };
21
25
  }
@@ -34,7 +38,7 @@ export function getCredentials(flags = {}) {
34
38
  }
35
39
  const saved = readSavedCredentials();
36
40
  if (saved?.session && saved?.ctoken) {
37
- return { ...saved, extraCookies: { ...(saved.extraCookies || {}), ...extraCookies }, source: CONFIG_FILE };
41
+ return { ...saved, extraCookies: { ...(saved.extraCookies || {}), ...extraCookies }, source: getConfigFilePath() };
38
42
  }
39
43
  throw new Error('Missing Yuque credentials. Run "yuque-local auth login" to configure them in your browser.');
40
44
  }
@@ -56,12 +60,12 @@ export function getCredentialStatus(flags = {}) {
56
60
  if (!saved?.session || !saved?.ctoken) {
57
61
  return {
58
62
  configured: false,
59
- source: CONFIG_FILE
63
+ source: getConfigFilePath()
60
64
  };
61
65
  }
62
66
  return {
63
67
  configured: true,
64
- source: CONFIG_FILE,
68
+ source: getConfigFilePath(),
65
69
  home_url: saved.homeUrl || null,
66
70
  saved_at: saved.saved_at || null,
67
71
  updated_at: saved.updated_at || null,
@@ -111,7 +115,7 @@ export async function loginWithBrowser(flags = {}) {
111
115
  await openBrowser(result.url);
112
116
  const credentials = await result.done;
113
117
  await saveCredentials(credentials);
114
- console.log(`Saved Yuque credentials to ${CONFIG_FILE}`);
118
+ console.log(`Saved Yuque credentials to ${getConfigFilePath()}`);
115
119
  }
116
120
  export async function loginManually(flags = {}) {
117
121
  const sessionFromFlag = typeof flags.session === 'string' ? flags.session.trim() : '';
@@ -124,7 +128,7 @@ export async function loginManually(flags = {}) {
124
128
  homeUrl: normalizeYuqueHomeUrl(homeUrlFromFlag),
125
129
  saved_at: new Date().toISOString()
126
130
  });
127
- console.log(`Saved Yuque credentials to ${CONFIG_FILE}`);
131
+ console.log(`Saved Yuque credentials to ${getConfigFilePath()}`);
128
132
  return;
129
133
  }
130
134
  if (!process.stdin.isTTY) {
@@ -145,17 +149,18 @@ export async function loginManually(flags = {}) {
145
149
  homeUrl: normalizeYuqueHomeUrl(homeUrlInput.trim()),
146
150
  saved_at: new Date().toISOString()
147
151
  });
148
- console.log(`Saved Yuque credentials to ${CONFIG_FILE}`);
152
+ console.log(`Saved Yuque credentials to ${getConfigFilePath()}`);
149
153
  }
150
154
  finally {
151
155
  rl.close();
152
156
  }
153
157
  }
154
158
  function readSavedCredentials() {
155
- if (!existsSync(CONFIG_FILE))
159
+ const configFile = getConfigFilePath();
160
+ if (!existsSync(configFile))
156
161
  return null;
157
162
  try {
158
- return JSON.parse(readFileSync(CONFIG_FILE, 'utf8'));
163
+ return JSON.parse(readFileSync(configFile, 'utf8'));
159
164
  }
160
165
  catch {
161
166
  return null;
@@ -163,14 +168,16 @@ function readSavedCredentials() {
163
168
  }
164
169
  async function saveCredentials(credentials) {
165
170
  const now = new Date().toISOString();
171
+ const configDir = getConfigDirPath();
172
+ const configFile = getConfigFilePath();
166
173
  const data = {
167
174
  ...credentials,
168
175
  saved_at: credentials.saved_at || now,
169
176
  updated_at: now
170
177
  };
171
- await mkdir(CONFIG_DIR, { recursive: true, mode: 0o700 });
172
- await writeFile(CONFIG_FILE, `${JSON.stringify(data, null, 2)}\n`, { mode: 0o600 });
173
- await chmod(CONFIG_FILE, 0o600);
178
+ await mkdir(configDir, { recursive: true, mode: 0o700 });
179
+ await writeFile(configFile, `${JSON.stringify(data, null, 2)}\n`, { mode: 0o600 });
180
+ await chmod(configFile, 0o600);
174
181
  }
175
182
  function ageHours(value) {
176
183
  if (!value)
@@ -326,6 +333,7 @@ function sendHtml(res, html, status = 200) {
326
333
  res.end(html);
327
334
  }
328
335
  function loginPage(error = '') {
336
+ const configFile = getConfigFilePath();
329
337
  return `<!doctype html>
330
338
  <html lang="zh-CN">
331
339
  <head>
@@ -370,7 +378,7 @@ function loginPage(error = '') {
370
378
  <p>本地保存语雀网页 Session,让 CLI 使用浏览器同款 Cookie 访问语雀。</p>
371
379
  </div>
372
380
  <div class="facts">
373
- <div class="fact"><strong>保存位置</strong><span>~/.config/yuque-cookie-plugin/config.json</span></div>
381
+ <div class="fact"><strong>保存位置</strong><span>${escapeHtml(configFile)}</span></div>
374
382
  <div class="fact"><strong>安全边界</strong><span>只写入本机配置,不写入项目仓库。</span></div>
375
383
  <div class="fact"><strong>失效处理</strong><span>后续可用 auth-status 检测并提示重新登录。</span></div>
376
384
  </div>
package/dist/cli.js CHANGED
@@ -26,6 +26,7 @@ Usage:
26
26
  yuque-local auth status [doc-or-book-url] [--json]
27
27
  yuque-local doctor [--json]
28
28
  yuque-local skill install|status|uninstall [--json]
29
+ yuque-local book list [--json]
29
30
  yuque-local book create --name <name> --slug <slug> [--description <text>] [--public]
30
31
  yuque-local book download <book-url> [--dist-dir download] [--incremental]
31
32
  yuque-local doc create <book-url> --title <title> --markdown-file <file> [--number-headings]
@@ -136,6 +137,7 @@ function normalizeInvocation(argv) {
136
137
  status: 'auth-status'
137
138
  },
138
139
  book: {
140
+ list: 'list-books',
139
141
  create: 'create-book',
140
142
  download: 'download-book',
141
143
  inspect: 'inspect'
@@ -463,6 +465,12 @@ async function main() {
463
465
  printCommandResult(info, flags, 'inspect completed');
464
466
  return;
465
467
  }
468
+ if (command === 'list-books') {
469
+ const result = await client.listBooks();
470
+ await recordCredentialValidation(true);
471
+ printCommandResult(result, flags, 'book list completed');
472
+ return;
473
+ }
466
474
  if (command === 'snapshot') {
467
475
  const [url] = positional;
468
476
  if (!url)
@@ -54,6 +54,17 @@ export class YuqueCookieClient {
54
54
  const appData = await this.fetchAppData(url);
55
55
  return summarizeAppData(appData);
56
56
  }
57
+ async listBooks() {
58
+ const result = await this.requestJson('GET', '/api/mine/books?offset=0&limit=100', undefined, `${this.host}/dashboard`);
59
+ const books = normalizeBookListResponse(result)
60
+ .map((book) => normalizeBookSummary(book, this.host))
61
+ .filter((book) => Boolean(book));
62
+ return {
63
+ ok: true,
64
+ count: books.length,
65
+ books
66
+ };
67
+ }
57
68
  async getBookInfo(url) {
58
69
  const appData = await this.fetchAppData(url);
59
70
  if (!appData.book?.id)
@@ -490,6 +501,40 @@ function buildDocUrl(host, appData, book, doc) {
490
501
  return `${host}/${bookSlug}/${docSlug}`;
491
502
  return `${host}/api/docs/${doc.id || ''}`;
492
503
  }
504
+ function normalizeBookListResponse(result) {
505
+ const data = result.data;
506
+ if (Array.isArray(data))
507
+ return data;
508
+ if (Array.isArray(data?.books))
509
+ return data.books;
510
+ if (Array.isArray(data?.repos))
511
+ return data.repos;
512
+ if (Array.isArray(result.books))
513
+ return result.books;
514
+ if (Array.isArray(result.repos))
515
+ return result.repos;
516
+ return [];
517
+ }
518
+ function normalizeBookSummary(book, host) {
519
+ const slug = typeof book.slug === 'string' ? book.slug : '';
520
+ const login = typeof book.login === 'string'
521
+ ? book.login
522
+ : typeof book.user?.login === 'string'
523
+ ? book.user.login
524
+ : undefined;
525
+ if (!slug)
526
+ return null;
527
+ return {
528
+ id: typeof book.id === 'number' ? book.id : undefined,
529
+ name: typeof book.name === 'string' ? book.name : slug,
530
+ slug,
531
+ login,
532
+ public: typeof book.public === 'number' || typeof book.public === 'boolean' ? book.public : undefined,
533
+ items_count: typeof book.items_count === 'number' ? book.items_count : undefined,
534
+ updated_at: typeof book.updated_at === 'string' ? book.updated_at : undefined,
535
+ url: login ? `${host}/${login}/${slug}` : `${host}/${slug}`
536
+ };
537
+ }
493
538
  function guessContentType(fileName) {
494
539
  const ext = extname(fileName).toLowerCase();
495
540
  const types = {
package/docs/usage-zh.md CHANGED
@@ -17,6 +17,21 @@
17
17
 
18
18
  项目目录不会保存真实 Cookie。
19
19
 
20
+ 如果需要把全局 npm 版、源码开发版、Docker 或 AI 真实测试环境隔离开,可以通过 `YUQUE_COOKIE_PLUGIN_CONFIG_DIR` 指定独立配置目录:
21
+
22
+ ```bash
23
+ YUQUE_COOKIE_PLUGIN_CONFIG_DIR=/tmp/yuque-plugin-real-test yuque-local auth login
24
+ YUQUE_COOKIE_PLUGIN_CONFIG_DIR=/tmp/yuque-plugin-real-test yuque-local auth status --json
25
+ ```
26
+
27
+ 指定后,Cookie 会保存到:
28
+
29
+ ```bash
30
+ /tmp/yuque-plugin-real-test/config.json
31
+ ```
32
+
33
+ 不会影响默认的 `~/.config/yuque-cookie-plugin/config.json`。
34
+
20
35
  ## 2. 安装和准备
21
36
 
22
37
  普通用户推荐从 npm 安装:
@@ -103,6 +118,12 @@ yuque-local auth login --manual
103
118
  yuque-local auth logout
104
119
  ```
105
120
 
121
+ 如果你使用了隔离配置目录,清理时也要带上同一个环境变量:
122
+
123
+ ```bash
124
+ YUQUE_COOKIE_PLUGIN_CONFIG_DIR=/tmp/yuque-plugin-real-test yuque-local auth logout
125
+ ```
126
+
106
127
  正常执行 `inspect`、`snapshot`、`download-book`、`download-doc` 等真实语雀命令成功后,也会刷新 `last_validated_at`。如果检测到 401、403、页面无法解析等登录态问题,CLI 会提示重新登录。
107
128
 
108
129
  ### 额外 Cookie
@@ -129,7 +150,38 @@ export YUQUE_EXTRA_COOKIE_VALUE='<cookie-value>'
129
150
 
130
151
  额外 Cookie 不会改变本项目的主链路,只用于兼容特殊访问场景。
131
152
 
132
- ## 4. 下载整个知识库
153
+ ## 4. 列出知识库
154
+
155
+ 查看当前账号可访问的语雀知识库:
156
+
157
+ ```bash
158
+ yuque-local book list --json
159
+ ```
160
+
161
+ 这个命令会通过网页 Session 调用语雀列表接口,只输出知识库摘要,不会打印本机配置文件或 Cookie。
162
+
163
+ 输出示例:
164
+
165
+ ```json
166
+ {
167
+ "status": "success",
168
+ "message": "book list completed",
169
+ "data": {
170
+ "ok": true,
171
+ "count": 2,
172
+ "books": [
173
+ {
174
+ "name": "工控",
175
+ "slug": "ydv5i5",
176
+ "login": "your-login",
177
+ "url": "https://www.yuque.com/your-login/ydv5i5"
178
+ }
179
+ ]
180
+ }
181
+ }
182
+ ```
183
+
184
+ ## 5. 下载整个知识库
133
185
 
134
186
  推荐先下载到临时目录验证:
135
187
 
@@ -234,7 +286,7 @@ AI 或脚本可以用 `retry.args` 只重试失败文档。
234
286
 
235
287
  `resources.files` 只记录本地相对路径和大小,不保存 Cookie。
236
288
 
237
- ## 4.1 创建知识库和文档
289
+ ## 6. 创建知识库和文档
238
290
 
239
291
  创建私密测试知识库:
240
292
 
@@ -261,7 +313,7 @@ npm run yuque-local -- create-doc https://www.yuque.com/<your-login>/<your-book>
261
313
  - 不默认修改标题文本。
262
314
  - 返回 JSON 中 `format` 表示语雀创建接口的初始格式;如果默认 Lake 写回成功,会额外返回 `final_format: "lake"`。
263
315
 
264
- ## 4.2 上传和插入附件
316
+ ## 7. 上传和插入附件
265
317
 
266
318
  只上传文件,不写入正文:
267
319
 
@@ -333,7 +385,7 @@ npm run yuque-local -- create-doc https://www.yuque.com/<your-login>/<your-book>
333
385
  - 语雀会把 Markdown 创建结果自动转换成 Lake 文档,工具随后会默认写回 Lake,后续修改应按 Lake 链路处理。
334
386
  - 当前原生写入能力矩阵见 `docs/native-lake-capability.md`。图片、附件、思维导图、画板属于下一阶段真实探索项,不能在未验证前手写 card。
335
387
 
336
- ## 4.2 上传图片或附件探索
388
+ ## 8. 上传图片或附件探索
337
389
 
338
390
  只上传本地文件,不写入正文:
339
391
 
@@ -392,7 +444,7 @@ npm run yuque-local -- insert-attachment https://www.yuque.com/user/book/doc \
392
444
 
393
445
  和图片一样,`insert-attachment --dry-run` 会真实上传附件以获得语雀附件 URL,但不会修改文档正文。
394
446
 
395
- ## 5. 下载单篇或多篇文档
447
+ ## 9. 下载单篇或多篇文档
396
448
 
397
449
  下载单篇:
398
450
 
@@ -409,7 +461,7 @@ npm run yuque-local -- download-doc \
409
461
  --dist-dir /tmp/yuque-doc-test
410
462
  ```
411
463
 
412
- ## 6. 本地预览下载结果
464
+ ## 10. 本地预览下载结果
413
465
 
414
466
  只生成或检查 VitePress 配置,不启动长驻服务:
415
467
 
@@ -441,7 +493,7 @@ http://localhost:5173/
441
493
  npm run yuque-local -- serve-book /tmp/yuque-download-test/工控 --port 5173 --force
442
494
  ```
443
495
 
444
- ## 7. 快照和差异比较
496
+ ## 11. 快照和差异比较
445
497
 
446
498
  抓取语雀文档快照:
447
499
 
@@ -461,7 +513,7 @@ npm run yuque-local -- diff-lake /tmp/before.json /tmp/after.json
461
513
  npm run yuque-local -- lake-to-markdown /tmp/doc.snapshot.json --out /tmp/doc.md
462
514
  ```
463
515
 
464
- ## 8. HTML 转语雀 Lake
516
+ ## 12. HTML 转语雀 Lake
465
517
 
466
518
  把本地 HTML 交给语雀 Lake editor runtime 序列化:
467
519
 
@@ -477,7 +529,7 @@ npm run yuque-local -- editor-serialize --html-file article.html --out article.l
477
529
 
478
530
  说明使用的是 vendored Lake editor,而不是 fallback。
479
531
 
480
- ## 9. 安全写入语雀文档
532
+ ## 13. 安全写入语雀文档
481
533
 
482
534
  强烈建议先 dry-run:
483
535
 
@@ -503,7 +555,7 @@ backups/
503
555
  reports/
504
556
  ```
505
557
 
506
- ## 10. 文章格式化流程
558
+ ## 14. 文章格式化流程
507
559
 
508
560
  本地 HTML 到语雀文档的完整流程:
509
561
 
@@ -517,7 +569,7 @@ npm run yuque-local -- format-article https://www.yuque.com/user/book/doc --html
517
569
  npm run yuque-local -- format-article https://www.yuque.com/user/book/doc --html-file article.html
518
570
  ```
519
571
 
520
- ## 11. 常用选项
572
+ ## 15. 常用选项
521
573
 
522
574
  忽略图片下载:
523
575
 
@@ -565,15 +617,16 @@ npm run yuque-local -- format-article https://www.yuque.com/user/book/doc --html
565
617
 
566
618
  如果需要严格的 JSON 输出,建议加 `--quiet`。
567
619
 
568
- ## 12. 安全规则
620
+ ## 16. 安全规则
569
621
 
570
622
  - 不要把真实 `_yuque_session` 或 `yuque_ctoken` 写入项目文件。
571
623
  - 不要提交 `~/.config/yuque-cookie-plugin/config.json`。
624
+ - 真实测试多个版本时,用 `YUQUE_COOKIE_PLUGIN_CONFIG_DIR` 隔离配置目录。
572
625
  - 线上写入必须先 dry-run。
573
626
  - 批量写入前先对单篇文档做实验。
574
627
  - 章节编号不要直接改标题文本硬塞编号,必须先做 snapshot before/after diff。
575
628
 
576
- ## 13. 当前已验证场景
629
+ ## 17. 当前已验证场景
577
630
 
578
631
  已真实验证:
579
632
 
@@ -584,7 +637,7 @@ npm run yuque-local -- format-article https://www.yuque.com/user/book/doc --html
584
637
  - 第二次增量下载全部跳过。
585
638
  - 导出文件名保留正常空格。
586
639
 
587
- ## 14. 当前未完全覆盖场景
640
+ ## 18. 当前未完全覆盖场景
588
641
 
589
642
  仍需继续补齐:
590
643
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yuque-cookie-plugin",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "type": "module",
5
5
  "description": "Cookie-based Yuque CLI for AI agents, without MCP or OpenAPI token limits.",
6
6
  "homepage": "https://github.com/c-sunc6/yuque-cookie-plugin#readme",
@@ -2,7 +2,7 @@
2
2
  name: yuque-cookie-plugin
3
3
  description: Use when an AI agent needs to operate Yuque through the local yuque-local CLI with _yuque_session and yuque_ctoken, including login, auth status, inspect, snapshot, download, create, native Lake update, image/PDF insertion, and safe document formatting. This skill is for CLI orchestration, not MCP or Yuque OpenAPI token usage.
4
4
  metadata:
5
- version: "0.1.0"
5
+ version: "0.1.3"
6
6
  author: "c-sunc6"
7
7
  ---
8
8
 
@@ -36,6 +36,7 @@ yuque-local auth login --manual
36
36
  yuque-local auth logout --json
37
37
  yuque-local auth status <doc-or-book-url> --json
38
38
  yuque-local doctor --json
39
+ yuque-local book list --json
39
40
  yuque-local book download <book-url> --dist-dir download --incremental --quiet --json
40
41
  yuque-local doc download <doc-url> --dist-dir download --quiet --json
41
42
  yuque-local doc create <book-url> --title "Title" --markdown-file article.md --number-headings --json
@@ -50,9 +51,10 @@ yuque-local skill uninstall --json
50
51
 
51
52
  1. Run `yuque-local doctor --json` to inspect local installation and credential state.
52
53
  2. If credentials are missing or stale, ask the user to run `yuque-local auth login` or `yuque-local auth login --manual`.
53
- 3. For reads and downloads, call the relevant `book` or `doc` command with `--json`.
54
- 4. For writes, snapshot first, prepare the change, run a dry run when available, then apply after user approval.
55
- 5. Save local reports and paths from the CLI result for later audit.
54
+ 3. For book discovery, use `yuque-local book list --json`; do not read or print the local config file.
55
+ 4. For reads and downloads, call the relevant `book` or `doc` command with `--json`.
56
+ 5. For writes, snapshot first, prepare the change, run a dry run when available, then apply after user approval.
57
+ 6. Save local reports and paths from the CLI result for later audit.
56
58
 
57
59
  ## References
58
60
 
@@ -42,6 +42,13 @@ skill.uninstall:
42
42
  example: "yuque-local skill uninstall --json"
43
43
  reference: "reference/agent-spec.md"
44
44
 
45
+ book.list:
46
+ cli: "yuque-local book list"
47
+ description: "List Yuque books available to the current cookie-authenticated account without printing local credential files"
48
+ optional: ["--json"]
49
+ example: "yuque-local book list --json"
50
+ reference: "reference/agent-spec.md"
51
+
45
52
  book.download:
46
53
  cli: "yuque-local book download"
47
54
  description: "Download a Yuque knowledge base with resources and reports"
@@ -46,6 +46,16 @@ yuque-local auth logout --json
46
46
 
47
47
  Never request raw cookie values in the conversation.
48
48
 
49
+ ## Book Discovery
50
+
51
+ Use the dedicated command:
52
+
53
+ ```bash
54
+ yuque-local book list --json
55
+ ```
56
+
57
+ Do not inspect, print, or copy the local `config.json` file to discover books. The CLI reads credentials internally and returns only book summaries.
58
+
49
59
  ## Safe Write Flow
50
60
 
51
61
  1. Snapshot the online document.