feishu-docs-cli 0.1.0-beta.9 → 1.0.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 +25 -9
- package/README.zh.md +8 -9
- package/dist/auth.js +31 -17
- package/dist/auth.js.map +1 -1
- package/dist/cli.js +5 -4
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +4 -2
- package/dist/client.js +177 -61
- package/dist/client.js.map +1 -1
- package/dist/commands/authorize.d.ts +3 -0
- package/dist/commands/authorize.js +16 -34
- package/dist/commands/authorize.js.map +1 -1
- package/dist/commands/cp.js +44 -30
- package/dist/commands/cp.js.map +1 -1
- package/dist/commands/create.js +21 -7
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/delete.js +53 -54
- package/dist/commands/delete.js.map +1 -1
- package/dist/commands/login.js +6 -2
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/ls.js +38 -38
- package/dist/commands/ls.js.map +1 -1
- package/dist/commands/mkdir.js +25 -25
- package/dist/commands/mkdir.js.map +1 -1
- package/dist/commands/mv.d.ts +2 -2
- package/dist/commands/mv.js +45 -40
- package/dist/commands/mv.js.map +1 -1
- package/dist/commands/read.d.ts +1 -1
- package/dist/commands/read.js +17 -354
- package/dist/commands/read.js.map +1 -1
- package/dist/commands/search.js +57 -55
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/share.js +135 -133
- package/dist/commands/share.js.map +1 -1
- package/dist/commands/update.js +43 -60
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/wiki.js +8 -20
- package/dist/commands/wiki.js.map +1 -1
- package/dist/parser/block-types.d.ts +0 -1
- package/dist/parser/block-types.js +0 -22
- package/dist/parser/block-types.js.map +1 -1
- package/dist/parser/blocks-to-md.d.ts +10 -18
- package/dist/parser/blocks-to-md.js +341 -450
- package/dist/parser/blocks-to-md.js.map +1 -1
- package/dist/scopes.d.ts +5 -47
- package/dist/scopes.js +9 -54
- package/dist/scopes.js.map +1 -1
- package/dist/services/block-writer.d.ts +3 -2
- package/dist/services/block-writer.js +29 -13
- package/dist/services/block-writer.js.map +1 -1
- package/dist/services/doc-blocks.d.ts +1 -1
- package/dist/services/doc-blocks.js +1 -1
- package/dist/services/doc-blocks.js.map +1 -1
- package/dist/services/doc-enrichment.d.ts +64 -0
- package/dist/services/doc-enrichment.js +397 -0
- package/dist/services/doc-enrichment.js.map +1 -0
- package/dist/services/image-download.d.ts +31 -0
- package/dist/services/image-download.js +127 -0
- package/dist/services/image-download.js.map +1 -0
- package/dist/services/markdown-convert.d.ts +20 -0
- package/dist/services/markdown-convert.js +55 -1
- package/dist/services/markdown-convert.js.map +1 -1
- package/dist/services/wiki-nodes.d.ts +1 -1
- package/dist/services/wiki-nodes.js +2 -3
- package/dist/services/wiki-nodes.js.map +1 -1
- package/dist/types/api-responses.d.ts +34 -0
- package/dist/types/api-responses.js +8 -0
- package/dist/types/api-responses.js.map +1 -0
- package/dist/types/index.d.ts +9 -17
- package/dist/utils/concurrency.d.ts +12 -0
- package/dist/utils/concurrency.js +37 -0
- package/dist/utils/concurrency.js.map +1 -0
- package/dist/utils/errors.d.ts +3 -1
- package/dist/utils/errors.js +11 -7
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/retry.d.ts +49 -0
- package/dist/utils/retry.js +70 -0
- package/dist/utils/retry.js.map +1 -0
- package/dist/utils/scope-prompt.d.ts +23 -18
- package/dist/utils/scope-prompt.js +62 -51
- package/dist/utils/scope-prompt.js.map +1 -1
- package/package.json +3 -1
- package/skills/feishu-docs/SKILL.md +22 -2
|
@@ -1,24 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Reactive scope authorization: prompt and recovery utilities.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Instead of pre-flight scope checks, this module provides:
|
|
5
|
+
*
|
|
6
|
+
* - `promptScopeAuth()` — Interactive OAuth prompt for missing scopes.
|
|
7
|
+
* - `withScopeRecovery()` — Wrapper that catches SCOPE_MISSING errors,
|
|
8
|
+
* prompts the user (if interactive), and retries the operation once.
|
|
9
|
+
*
|
|
10
|
+
* The Feishu API is the source of truth for required scopes. When an API
|
|
11
|
+
* call fails with 99991672 (app scope) or 99991679 (user scope), `fetchWithAuth`
|
|
12
|
+
* throws `CliError("SCOPE_MISSING", { missingScopes })`. This module handles
|
|
13
|
+
* the recovery.
|
|
7
14
|
*/
|
|
8
15
|
import * as readline from "node:readline";
|
|
9
16
|
import { oauthLogin, loadTokens } from "../auth.js";
|
|
10
|
-
import { createClient } from "../client.js";
|
|
11
17
|
import { CliError } from "./errors.js";
|
|
12
|
-
import { BASE_SCOPES, mergeScopes,
|
|
13
|
-
/**
|
|
14
|
-
* Check whether an error is a permission / scope error.
|
|
15
|
-
*/
|
|
16
|
-
export function isPermissionError(err) {
|
|
17
|
-
if (err instanceof CliError) {
|
|
18
|
-
return (err.errorType === "PERMISSION_DENIED" || err.errorType === "AUTH_REQUIRED");
|
|
19
|
-
}
|
|
20
|
-
return false;
|
|
21
|
-
}
|
|
18
|
+
import { BASE_SCOPES, mergeScopes, buildScopeHint } from "../scopes.js";
|
|
22
19
|
/**
|
|
23
20
|
* Ask a yes/no question on stderr, read from stdin.
|
|
24
21
|
* Returns true only if user answers "y" or "yes".
|
|
@@ -44,11 +41,8 @@ function askYesNo(question) {
|
|
|
44
41
|
*
|
|
45
42
|
* Returns `true` if authorization succeeded, `false` otherwise.
|
|
46
43
|
* Always returns `false` in non-interactive contexts (JSON mode, non-TTY).
|
|
47
|
-
*
|
|
48
|
-
* @param storedScopeStr Pre-loaded stored scope string (avoids duplicate
|
|
49
|
-
* loadTokens call when called from ensureScopes).
|
|
50
44
|
*/
|
|
51
|
-
export async function promptScopeAuth(missingScopes, globalOpts
|
|
45
|
+
export async function promptScopeAuth(missingScopes, globalOpts) {
|
|
52
46
|
// Non-interactive: skip prompt
|
|
53
47
|
if (globalOpts.json || !process.stdin.isTTY) {
|
|
54
48
|
return false;
|
|
@@ -57,6 +51,10 @@ export async function promptScopeAuth(missingScopes, globalOpts, storedScopeStr)
|
|
|
57
51
|
const appSecret = process.env.FEISHU_APP_SECRET;
|
|
58
52
|
if (!appId || !appSecret)
|
|
59
53
|
return false;
|
|
54
|
+
// Skip interactive OAuth when using env-var token — re-auth would save to file
|
|
55
|
+
// but createClient still prefers the env token, so retry would fail again.
|
|
56
|
+
if (process.env.FEISHU_USER_TOKEN)
|
|
57
|
+
return false;
|
|
60
58
|
const scopeList = missingScopes.join(", ");
|
|
61
59
|
const scopeStr = missingScopes.join(" ");
|
|
62
60
|
process.stderr.write(`\nfeishu-docs: 缺少以下权限: ${scopeList}\n` +
|
|
@@ -67,16 +65,10 @@ export async function promptScopeAuth(missingScopes, globalOpts, storedScopeStr)
|
|
|
67
65
|
if (!yes)
|
|
68
66
|
return false;
|
|
69
67
|
// Merge missing scopes with current grants and re-run OAuth
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
else {
|
|
75
|
-
const stored = await loadTokens();
|
|
76
|
-
currentScopes = stored?.tokens?.scope
|
|
77
|
-
? stored.tokens.scope.split(/\s+/).filter(Boolean)
|
|
78
|
-
: [...BASE_SCOPES];
|
|
79
|
-
}
|
|
68
|
+
const stored = await loadTokens();
|
|
69
|
+
const currentScopes = stored?.tokens?.scope
|
|
70
|
+
? stored.tokens.scope.split(/\s+/).filter(Boolean)
|
|
71
|
+
: [...BASE_SCOPES];
|
|
80
72
|
const merged = mergeScopes(currentScopes, missingScopes);
|
|
81
73
|
try {
|
|
82
74
|
await oauthLogin(appId, {
|
|
@@ -94,30 +86,49 @@ export async function promptScopeAuth(missingScopes, globalOpts, storedScopeStr)
|
|
|
94
86
|
}
|
|
95
87
|
}
|
|
96
88
|
/**
|
|
97
|
-
*
|
|
89
|
+
* Wrap an async operation with reactive scope error recovery.
|
|
90
|
+
*
|
|
91
|
+
* When the operation throws `CliError("SCOPE_MISSING")`:
|
|
92
|
+
* - If interactive (TTY + non-JSON) and scopes are known: prompt → retry once.
|
|
93
|
+
* - Otherwise: re-throw with a clear recovery hint.
|
|
98
94
|
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
95
|
+
* @param fallbackScopes Scope names to use when the API doesn't include
|
|
96
|
+
* `permission_violations` (older APIs like search). When the error has
|
|
97
|
+
* empty `missingScopes` but `fallbackScopes` is provided, these are used
|
|
98
|
+
* for the authorization prompt.
|
|
102
99
|
*/
|
|
103
|
-
export async function
|
|
104
|
-
|
|
105
|
-
return
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
100
|
+
export async function withScopeRecovery(fn, globalOpts, fallbackScopes) {
|
|
101
|
+
try {
|
|
102
|
+
return await fn();
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
if (!(err instanceof CliError) || err.errorType !== "SCOPE_MISSING") {
|
|
106
|
+
throw err;
|
|
107
|
+
}
|
|
108
|
+
const apiScopes = err.missingScopes ?? [];
|
|
109
|
+
const scopes = apiScopes.length > 0 ? apiScopes : (fallbackScopes ?? []);
|
|
110
|
+
// No scopes from API or fallback → can't prompt meaningfully, just throw
|
|
111
|
+
if (scopes.length === 0) {
|
|
112
|
+
throw err;
|
|
113
|
+
}
|
|
114
|
+
// Tenant mode: OAuth produces a user token which tenant auth ignores,
|
|
115
|
+
// so interactive recovery would be pointless — just throw with a hint.
|
|
116
|
+
if (globalOpts.auth === "tenant") {
|
|
117
|
+
throw new CliError("AUTH_REQUIRED", buildScopeHint(scopes), {
|
|
118
|
+
apiCode: err.apiCode,
|
|
119
|
+
missingScopes: scopes,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
// Try interactive recovery
|
|
123
|
+
const authorized = await promptScopeAuth(scopes, globalOpts);
|
|
124
|
+
if (!authorized) {
|
|
125
|
+
throw new CliError("AUTH_REQUIRED", buildScopeHint(scopes), {
|
|
126
|
+
apiCode: err.apiCode,
|
|
127
|
+
missingScopes: scopes,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
// Retry once — if it fails again, let the error propagate
|
|
131
|
+
return await fn();
|
|
118
132
|
}
|
|
119
|
-
// Re-create client to pick up the fresh token
|
|
120
|
-
const { authInfo: refreshed } = await createClient(globalOpts);
|
|
121
|
-
return refreshed;
|
|
122
133
|
}
|
|
123
134
|
//# sourceMappingURL=scope-prompt.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope-prompt.js","sourceRoot":"","sources":["../../src/utils/scope-prompt.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"scope-prompt.js","sourceRoot":"","sources":["../../src/utils/scope-prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAGxE;;;GAGG;AACH,SAAS,QAAQ,CAAC,QAAgB;IAChC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC;YAClC,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;QACH,EAAE,CAAC,QAAQ,CAAC,GAAG,QAAQ,SAAS,EAAE,CAAC,MAAM,EAAE,EAAE;YAC3C,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,aAAuB,EACvB,UAAsB;IAEtB,+BAA+B;IAC/B,IAAI,UAAU,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QAC5C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;IACxC,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAChD,IAAI,CAAC,KAAK,IAAI,CAAC,SAAS;QAAE,OAAO,KAAK,CAAC;IAEvC,+EAA+E;IAC/E,2EAA2E;IAC3E,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB;QAAE,OAAO,KAAK,CAAC;IAEhD,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACzC,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,0BAA0B,SAAS,IAAI;QACrC,gEAAgE;QAChE,8CAA8C;QAC9C,0CAA0C,QAAQ,OAAO,CAC5D,CAAC;IAEF,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,aAAa,CAAC,CAAC;IAC1C,IAAI,CAAC,GAAG;QAAE,OAAO,KAAK,CAAC;IAEvB,4DAA4D;IAC5D,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAClC,MAAM,aAAa,GAAG,MAAM,EAAE,MAAM,EAAE,KAAK;QACzC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;QAClD,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC;IACrB,MAAM,MAAM,GAAG,WAAW,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;IAEzD,IAAI,CAAC;QACH,MAAM,UAAU,CAAC,KAAK,EAAE;YACtB,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;YACvB,SAAS;YACT,OAAO,EAAE,UAAU,CAAC,IAAI;SACzB,CAAC,CAAC;QACH,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAChE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,MAAM,MAAM,CAAC,CAAC;QACzD,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,EAAoB,EACpB,UAAsB,EACtB,cAAyB;IAEzB,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,EAAE,CAAC;IACpB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,CAAC,GAAG,YAAY,QAAQ,CAAC,IAAI,GAAG,CAAC,SAAS,KAAK,eAAe,EAAE,CAAC;YACpE,MAAM,GAAG,CAAC;QACZ,CAAC;QAED,MAAM,SAAS,GAAG,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC;QAC1C,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC;QAEzE,yEAAyE;QACzE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,MAAM,GAAG,CAAC;QACZ,CAAC;QAED,sEAAsE;QACtE,uEAAuE;QACvE,IAAI,UAAU,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACjC,MAAM,IAAI,QAAQ,CAAC,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,EAAE;gBAC1D,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,aAAa,EAAE,MAAM;aACtB,CAAC,CAAC;QACL,CAAC;QAED,2BAA2B;QAC3B,MAAM,UAAU,GAAG,MAAM,eAAe,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAC7D,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,IAAI,QAAQ,CAAC,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,EAAE;gBAC1D,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,aAAa,EAAE,MAAM;aACtB,CAAC,CAAC;QACL,CAAC;QAED,0DAA0D;QAC1D,OAAO,MAAM,EAAE,EAAE,CAAC;IACpB,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "feishu-docs-cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "CLI tool for AI Agents to read/write Feishu docs via shell commands",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"build:check": "tsc --noEmit",
|
|
22
22
|
"pretest": "npm run build:check",
|
|
23
23
|
"test": "tsx --test test/*.test.ts",
|
|
24
|
+
"lint:dead-code": "knip",
|
|
24
25
|
"prepublishOnly": "npm run build"
|
|
25
26
|
},
|
|
26
27
|
"repository": {
|
|
@@ -47,6 +48,7 @@
|
|
|
47
48
|
},
|
|
48
49
|
"devDependencies": {
|
|
49
50
|
"@types/node": "^25.5.0",
|
|
51
|
+
"knip": "^6.0.6",
|
|
50
52
|
"tsx": "^4.21.0",
|
|
51
53
|
"typescript": "^5.9.3"
|
|
52
54
|
}
|
|
@@ -9,7 +9,23 @@ description: Read, write, search, and manage Feishu (Lark) cloud documents and k
|
|
|
9
9
|
|
|
10
10
|
## Prerequisites
|
|
11
11
|
|
|
12
|
-
Before using any command,
|
|
12
|
+
Before using any command, check that the CLI is installed and authenticated. Run these two checks in order:
|
|
13
|
+
|
|
14
|
+
### Step 1: Check installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
command -v feishu-docs >/dev/null 2>&1 && feishu-docs --version || echo "NOT_INSTALLED"
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
If the output is `NOT_INSTALLED`, install the CLI first:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install -g feishu-docs-cli
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
This installs the `feishu-docs` command globally. Requires Node.js 18+. After installation, verify with `feishu-docs --version`.
|
|
27
|
+
|
|
28
|
+
### Step 2: Check authentication
|
|
13
29
|
|
|
14
30
|
```bash
|
|
15
31
|
feishu-docs whoami
|
|
@@ -90,7 +106,7 @@ feishu-docs update <url> --body ./extra.md --append
|
|
|
90
106
|
echo "## New Section" | feishu-docs update <url> --body - --append
|
|
91
107
|
```
|
|
92
108
|
|
|
93
|
-
Overwrite mode automatically backs up the current document to `~/.feishu-docs/backups/` before writing. If the write fails, it auto-recovers from the backup.
|
|
109
|
+
Overwrite mode automatically backs up the current document to `~/.feishu-docs/backups/` before writing. If the write fails, it auto-recovers from the backup. Backups are kept for undo; old backups are rotated automatically (max 10 per document).
|
|
94
110
|
|
|
95
111
|
To restore a previous version:
|
|
96
112
|
```bash
|
|
@@ -170,6 +186,7 @@ Every command accepts these flags:
|
|
|
170
186
|
| `--auth tenant` | Force app token (CI/CD, shared docs) |
|
|
171
187
|
| `--json` | Output structured JSON instead of text |
|
|
172
188
|
| `--lark` | Use Lark (international) domain |
|
|
189
|
+
| `-v, --version` | Show version number |
|
|
173
190
|
|
|
174
191
|
Default auth mode is `auto` — tries user token first, falls back to tenant.
|
|
175
192
|
|
|
@@ -189,6 +206,9 @@ Default auth mode is `auto` — tries user token first, falls back to tenant.
|
|
|
189
206
|
|
|
190
207
|
- Only `docx` (new document format) is fully supported for read/write
|
|
191
208
|
- Legacy `doc` format is not supported
|
|
209
|
+
- Embedded `sheet` and `bitable` are rendered as tables (lossy)
|
|
210
|
+
- Embedded `board`/`whiteboard` are exported as local PNG images (temporary file paths)
|
|
211
|
+
- `mindnote` renders as a link only
|
|
192
212
|
- Images cannot be written; read returns temporary URLs valid ~24 hours
|
|
193
213
|
- Markdown conversion is lossy — use `--blocks` for lossless JSON when precision matters
|
|
194
214
|
- Search requires user-level auth (run `feishu-docs login` first)
|