@getnote/cli 1.5.6 → 1.5.8

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
@@ -35,13 +35,14 @@ getnote auth login
35
35
 
36
36
  或者从 [Releases](https://github.com/iswalle/getnote-cli/releases) 下载对应平台的二进制文件,放到 `$PATH` 里。
37
37
 
38
- **Windows 用户**:推荐直接从 [Releases](https://github.com/iswalle/getnote-cli/releases) 下载 `.exe` 文件,放到 PATH 里。用 `npm install -g` 安装时,如果遇到 `Expand-Archive` 相关报错,可尝试:
38
+ **pnpm 10+ 用户**:pnpm 默认会拦截依赖包的构建脚本。请在工作区的 `pnpm-workspace.yaml` 中允许 `@getnote/cli` 运行安装脚本:
39
39
 
40
- ```bash
41
- npm install -g @getnote/cli --ignore-scripts
40
+ ```yaml
41
+ allowBuilds:
42
+ '@getnote/cli': true
42
43
  ```
43
44
 
44
- 然后手动从 Releases 下载对应平台的二进制文件。
45
+ 然后重新执行 `pnpm install`。也可以直接从 [Releases](https://github.com/iswalle/getnote-cli/releases) 下载对应平台的二进制文件并放入 `$PATH`。
45
46
 
46
47
  ---
47
48
 
@@ -137,8 +138,9 @@ getnote search "产品设计" --kb vnrOAaGY
137
138
 
138
139
  **场景 3:管理知识库**
139
140
  ```bash
140
- # 列出所有知识库
141
+ # 列出默认知识库;特殊类型使用 --scope
141
142
  getnote kbs
143
+ getnote kbs --scope BOOKSPACE
142
144
 
143
145
  # 查看某个知识库的笔记
144
146
  getnote kb vnrOAaGY --all
@@ -279,7 +281,8 @@ getnote tag list <note_id> 查看笔记的所有标签
279
281
  ### 知识库
280
282
 
281
283
  ```
282
- getnote kbs 列出所有可访问知识库(DEFAULT / BOOKSPACE / CUSTOMER / TEAMSPACE)
284
+ getnote kbs 列出 DEFAULT 知识库
285
+ --scope <scope> 指定 DEFAULT / BOOKSPACE / CUSTOMER / TEAMSPACE
283
286
 
284
287
  getnote kb <topic_id> 知识库内的笔记
285
288
  --limit <n>
@@ -299,7 +302,9 @@ getnote kb directory-delete <topic_id> <id> --yes 删除空文件夹
299
302
  getnote kb blogger-follow <topic_id> <抖音链接> 订阅抖音博主
300
303
  getnote kb live-follow <topic_id> <url> 订阅得到直播课,直播结束后 AI 摘要自动入库
301
304
 
302
- getnote kbs-sub 获取我订阅的知识库列表
305
+ getnote kbs [--scope DEFAULT] 获取我创建/管理的知识库,默认只返回 DEFAULT
306
+ getnote kbs-sub [--scope DEFAULT] 获取我订阅的知识库,默认只返回 DEFAULT
307
+ # --scope 可选:DEFAULT、CUSTOMER、BOOKSPACE、TEAMSPACE
303
308
  ```
304
309
 
305
310
  常用目录命令提供短别名,旧命令继续兼容:
@@ -391,6 +396,7 @@ $ getnote search "工作日志" --limit 7 -o json
391
396
 
392
397
  | 日期 | 版本 | 新能力 | 适合怎么用 |
393
398
  |------|------|--------|------------|
399
+ | 2026-09-02 | **v1.5.8** | 1. `kbs` 与 `kbs-sub` 默认只返回 `DEFAULT` 知识库<br>2. 新增 `--scope`,可按 `CUSTOMER`、`BOOKSPACE`、`TEAMSPACE` 精确读取<br>3. 订阅列表不再混入自己创建的知识库 | 避免书籍库和自有库挤占订阅列表分页;需要特殊知识库时显式选择 scope |
394
400
  | 2026-08-19 | **v1.5.6** | 1. `getnote update` 默认升级 CLI、同步五个领域 Skill 并运行诊断<br>2. capabilities 2.2 提供机器可读的安装、更新、验证与平台托管边界<br>3. 移除失效的 `install.sh` 引导 | 用户只说“安装”或“更新”即可,AI Agent 无需让用户选择内部组件,并能按统一成功条件完成验收 |
395
401
  | 2026-08-19 | **v1.5.5** | 1. 一键安装自动识别本机 AI Agent,并按平台显示安装结果<br>2. 新增 GitHub Copilot、Gemini CLI、Windsurf、OpenCode 和 Cline 自动安装<br>3. OpenClaw(小龙虾)和 QClaw 仅在检测到时提供 ClawHub 确认入口<br>4. 保留 `SKILLS` 品牌开场,隐藏底层安装术语<br>5. `doctor` 按平台真实目录检查 Skill 状态 | 用户只需运行一次安装命令;AI 能根据结构化结果判断安装状态并给出明确修复动作 |
396
402
  | 2026-08-17 | **v1.5.3** | 1. `doctor` 新增稳定问题码、阻断级别、修复动作、平台 Skill 状态和在线/离线就绪语义<br>2. 诊断失败提供可靠退出码,JSON 保持单一、可解析<br>3. npm 与独立二进制采用匹配的升级路径,Release 下载增加 SHA-256 校验<br>4. WorkBuddy Skills 整套预检并支持失败回滚<br>5. 严格校验输出格式与多余参数 | 让技术用户和 AI 都能准确判断环境是否真正可用,并根据结构化结果完成修复;同时避免版本分裂、半安装和未校验更新包 |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getnote/cli",
3
- "version": "1.5.6",
3
+ "version": "1.5.8",
4
4
  "description": "CLI tool for 得到大脑(Get笔记) — manage notes and knowledge bases from the terminal",
5
5
  "keywords": [
6
6
  "getnote",
@@ -19,7 +19,8 @@
19
19
  "gnote": "./bin/getnote.js"
20
20
  },
21
21
  "scripts": {
22
- "postinstall": "node scripts/postinstall.js"
22
+ "postinstall": "node scripts/postinstall.js",
23
+ "test": "node --test scripts/postinstall.test.js"
23
24
  },
24
25
  "files": [
25
26
  "bin/getnote.js",
@@ -37,6 +37,45 @@ function getDownloadURL(platform) {
37
37
  return `https://github.com/${REPO}/releases/download/v${VERSION}/${asset}`;
38
38
  }
39
39
 
40
+ function getWindowsExtractArgs(archivePath, destinationPath) {
41
+ return [
42
+ '-NoProfile',
43
+ '-Command',
44
+ '& { Expand-Archive -LiteralPath $args[0] -DestinationPath $args[1] -Force }',
45
+ archivePath,
46
+ destinationPath,
47
+ ];
48
+ }
49
+
50
+ async function installArchive({
51
+ platform,
52
+ binDir,
53
+ binaryName,
54
+ binaryPath,
55
+ url,
56
+ tmpFile,
57
+ downloadFn = download,
58
+ verifyChecksumFn = verifyChecksum,
59
+ runFn = run,
60
+ chmodFn = fs.chmodSync,
61
+ unlinkFn = fs.unlinkSync,
62
+ }) {
63
+ try {
64
+ await downloadFn(url, tmpFile);
65
+ await verifyChecksumFn(url, path.basename(url), tmpFile);
66
+ if (platform.platform === 'windows') {
67
+ runFn('powershell', getWindowsExtractArgs(tmpFile, binDir));
68
+ } else {
69
+ runFn('tar', ['-xzf', tmpFile, '-C', binDir, binaryName]);
70
+ }
71
+
72
+ chmodFn(binaryPath, 0o755);
73
+ console.log(`getnote installed at ${binaryPath}`);
74
+ } finally {
75
+ try { unlinkFn(tmpFile); } catch (_) {}
76
+ }
77
+ }
78
+
40
79
  async function main() {
41
80
  const platform = getPlatform();
42
81
  const binDir = path.join(__dirname, '..', 'bin');
@@ -63,24 +102,7 @@ async function main() {
63
102
 
64
103
  fs.mkdirSync(binDir, { recursive: true });
65
104
 
66
- try {
67
- await download(url, tmpFile);
68
- await verifyChecksum(url, path.basename(url), tmpFile);
69
- if (platform.platform === 'windows') {
70
- run('powershell', ['-NoProfile', '-Command', 'Expand-Archive -LiteralPath $args[0] -DestinationPath $args[1] -Force', tmpFile, binDir]);
71
- } else {
72
- run('tar', ['-xzf', tmpFile, '-C', binDir, binaryName]);
73
- }
74
-
75
- fs.chmodSync(binaryPath, 0o755);
76
- console.log(`getnote installed at ${binaryPath}`);
77
-
78
- } catch (err) {
79
- console.error('Failed to install getnote:', err.message);
80
- process.exit(1);
81
- } finally {
82
- try { fs.unlinkSync(tmpFile); } catch (_) {}
83
- }
105
+ await installArchive({ platform, binDir, binaryName, binaryPath, url, tmpFile });
84
106
  }
85
107
 
86
108
  function run(command, args) {
@@ -128,7 +150,11 @@ async function verifyChecksum(assetURL, assetName, archivePath) {
128
150
  }
129
151
  }
130
152
 
131
- main().catch(err => {
132
- console.error('Failed to install getnote:', err.message);
133
- process.exit(1);
134
- });
153
+ if (require.main === module) {
154
+ main().catch(err => {
155
+ console.error('Failed to install getnote:', err.message);
156
+ process.exitCode = 1;
157
+ });
158
+ }
159
+
160
+ module.exports = { getWindowsExtractArgs, installArchive };
@@ -0,0 +1,37 @@
1
+ 'use strict';
2
+
3
+ const assert = require('node:assert/strict');
4
+ const test = require('node:test');
5
+
6
+ const { getWindowsExtractArgs, installArchive } = require('./postinstall');
7
+
8
+ test('Windows extraction invokes Expand-Archive inside a script block', () => {
9
+ assert.deepEqual(getWindowsExtractArgs('C:\\Temp\\getnote.zip', 'C:\\Program Files\\getnote'), [
10
+ '-NoProfile',
11
+ '-Command',
12
+ '& { Expand-Archive -LiteralPath $args[0] -DestinationPath $args[1] -Force }',
13
+ 'C:\\Temp\\getnote.zip',
14
+ 'C:\\Program Files\\getnote',
15
+ ]);
16
+ });
17
+
18
+ test('temporary archive is removed when installation fails', async () => {
19
+ const removed = [];
20
+ await assert.rejects(
21
+ installArchive({
22
+ platform: { platform: 'windows', arch: 'amd64' },
23
+ binDir: 'C:\\getnote\\bin',
24
+ binaryName: 'getnote.exe',
25
+ binaryPath: 'C:\\getnote\\bin\\getnote.exe',
26
+ url: 'https://example.invalid/getnote.zip',
27
+ tmpFile: 'C:\\Temp\\getnote-download.zip',
28
+ downloadFn: async () => { throw new Error('download failed'); },
29
+ verifyChecksumFn: async () => {},
30
+ runFn: () => {},
31
+ chmodFn: () => {},
32
+ unlinkFn: file => removed.push(file),
33
+ }),
34
+ /download failed/,
35
+ );
36
+ assert.deepEqual(removed, ['C:\\Temp\\getnote-download.zip']);
37
+ });
@@ -13,8 +13,8 @@ description: 查看和管理得到大脑的默认知识库、书籍、客户档
13
13
 
14
14
  | 意图 | 命令入口 |
15
15
  |---|---|
16
- | 自有/可管理知识库 | `getnote kbs` |
17
- | 我订阅的知识库 | `getnote kbs-sub` |
16
+ | 自有/可管理知识库 | `getnote kbs --scope <scope>` |
17
+ | 我订阅的知识库 | `getnote kbs-sub --scope <scope>` |
18
18
  | 知识库笔记 | `getnote kb <topic_id>` |
19
19
  | 新建个人知识库 | `getnote kb create` |
20
20
  | 加入笔记 | `getnote kb add` |
@@ -35,8 +35,8 @@ description: 查看和管理得到大脑的默认知识库、书籍、客户档
35
35
 
36
36
  ## 选择知识库和权限
37
37
 
38
- 1. 用户问“我管理的/我的知识库”时执行 `getnote kbs -o json`;问“所有能访问的知识库”时还要执行 `getnote kbs-sub -o json`,分别标明自有/可管理与已订阅,按各自 `has_more` 翻完页,不能混成同一种权限。
39
- 2. `getnote kbs` 必须保留接口实际返回的全部 Scope,例如 `DEFAULT`、`BOOKSPACE`、`CUSTOMER`、`TEAMSPACE`,不能只返回默认知识库,也不能虚构未返回的 Scope。
38
+ 1. `getnote kbs` 和 `getnote kbs-sub` 默认只查询 `DEFAULT`。用户明确要书籍、客户档案或团队知识库时,分别传 `--scope BOOKSPACE`、`--scope CUSTOMER`、`--scope TEAMSPACE`;不能把多个 Scope 混在同一分页结果里。
39
+ 2. 用户问“我管理的/我的知识库”时执行 `getnote kbs --scope <scope> -o json`;问“我订阅的知识库”时执行 `getnote kbs-sub --scope <scope> -o json`。订阅列表只包含他人创建且当前账号真实订阅的知识库,分别按 `has_more` 翻完页。
40
40
  3. 按名称和 `scope` 匹配;同名或用户意图不明确时让用户选择,不猜 `topic_id`。目标名称既可能是知识库也可能是文件夹时,先问清楚。
41
41
  4. 订阅知识库通常只读。若列表结果明确返回角色或可写标记,按真实字段判断;当前 CLI 契约未保证权限字段时,不得声称已经预检为 owner/admin,可在用户明确授权后尝试写入,并忠实处理权限失败。
42
42
  5. 普通成员写入失败时明确说明权限不足,不尝试绕过。当前不代替用户新建团队知识库。
@@ -59,8 +59,8 @@ description: 查看和管理得到大脑的默认知识库、书籍、客户档
59
59
 
60
60
  | 命令 | 成功结果必须包含 | 回复规则 |
61
61
  |---|---|---|
62
- | `getnote kbs -o json` | `success=true`、`data.topics[].topic_id/name/scope/stats`、`has_more/total` | 展示全部真实 Scope,不只展示默认知识库。 |
63
- | `getnote kbs-sub -o json` | `success=true`、`data.topics[].topic_id/name`、`has_more/total` | 订阅知识库通常只读,不能把它当作可写知识库。 |
62
+ | `getnote kbs --scope <scope> -o json` | `success=true`、`data.topics[].topic_id/name/scope/stats`、`has_more/total` | 默认 scope 为 `DEFAULT`;特殊类型必须显式传 scope。 |
63
+ | `getnote kbs-sub --scope <scope> -o json` | `success=true`、`data.topics[].topic_id/name/scope`、`has_more/total` | 只返回该 scope 下真实订阅的他人知识库,通常只读。 |
64
64
  | `getnote kb <topic_id> -o json` | `success=true`、`data.notes[].note_id/title/note_type`、`has_more/total` | 返回知识库内真实笔记;需要链接时再用 `note` 读取详情。 |
65
65
  | `getnote kb create <name> -o json` | `success=true`、`data?` | 仅创建个人知识库;不得在没有返回 ID 时虚构 `topic_id`。 |
66
66
  | `getnote kb add <topic_id> <note_id…> -o json` | `success=true`、`data?` | 最多 20 条;需要确认最终目录归属时重新读取目录。 |
@@ -16,7 +16,7 @@ description: 在得到大脑的全部笔记或指定知识库中按自然语言
16
16
  ## 执行步骤
17
17
 
18
18
  1. 用户没有指定知识库时,直接执行 `getnote search <query> --limit <1-10> -o json`。默认上限是 10,不能自行放大。
19
- 2. 用户指定知识库名称时,先执行 `getnote kbs -o json`,用返回的真实 `topic_id` 和 `scope` 匹配;同名、多个团队知识库或意图不明确时必须让用户选择。
19
+ 2. 用户指定知识库名称时,先按其类型执行 `getnote kbs --scope <scope> -o json`;默认查 `DEFAULT`,书籍、客户档案和团队知识库分别使用 `BOOKSPACE`、`CUSTOMER`、`TEAMSPACE`。用返回的真实 `topic_id` 和 `scope` 匹配;同名或意图不明确时必须让用户选择。
20
20
  3. 已确认知识库后执行 `getnote search <query> --kb <topic_id> --limit <1-10> -o json`。
21
21
  4. 只从返回值读取标题、摘要、字符串 `note_id` 和真实 `note_url`。没有 `note_id/note_url` 的非笔记结果可以展示内容,但不能伪造“打开笔记”链接。
22
22
  5. 同一篇笔记可能因命中多个片段出现多次。面向用户列“几篇笔记”时必须按字符串 `note_id` 去重;若去重后不足用户要求的数量,可在上限 10 内增大 `--limit` 重搜,仍不足时如实返回实际数量。