@chiimagnus/applebookscli 0.1.6 → 0.2.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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# AppleBooksCLI
|
|
2
2
|
|
|
3
|
-
AppleBooksCLI 是一个用于 macOS Apple Books 的命令行工具。你可以直接查询自己的书库、阅读状态、划线与笔记,读取可用的 EPUB/PDF 内容,导出笔记,并在需要时安全地修改笔记或藏书。
|
|
3
|
+
[AppleBooksCLI](https://github.com/chiimagnus/AppleBooksCLI) 是一个用于 macOS Apple Books 的命令行工具。你可以直接查询自己的书库、阅读状态、划线与笔记,读取可用的 EPUB/PDF 内容,导出笔记,并在需要时安全地修改笔记或藏书。
|
|
4
4
|
|
|
5
5
|
## 主要功能
|
|
6
6
|
|
|
@@ -10,35 +10,36 @@ AppleBooksCLI 是一个用于 macOS Apple Books 的命令行工具。你可以
|
|
|
10
10
|
- 读取可用 EPUB 的目录、章节、元数据与批注上下文。
|
|
11
11
|
- 提取 PDF 划线与笔记。
|
|
12
12
|
- 导出 JSON、CSV、Markdown 或 HTML。
|
|
13
|
-
-
|
|
14
|
-
-
|
|
13
|
+
- **安全修改笔记、管理藏书,并在写入前自动备份。**
|
|
14
|
+
- 提供标准 `applebookscli` Agent Skill。
|
|
15
15
|
|
|
16
16
|
## 系统要求
|
|
17
17
|
|
|
18
|
-
- macOS 12 或更高版本。
|
|
19
|
-
- npm 发布的预编译版本目前支持 Apple Silicon(arm64)。
|
|
20
18
|
- 读取 Apple Books 数据时,macOS 可能要求为终端或调用进程授予 Full Disk Access。
|
|
21
19
|
- 未下载的 EPUB、DRM 内容或当前系统无法读取的内容会明确提示不可用或能力受限;AppleBooksCLI 不绕过系统保护。
|
|
22
20
|
|
|
23
21
|
## 安装
|
|
24
22
|
|
|
25
|
-
安装稳定版:
|
|
26
|
-
|
|
27
23
|
```sh
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
```
|
|
24
|
+
# 安装 CLI
|
|
25
|
+
npm install --global @chiimagnus/applebookscli@latest
|
|
31
26
|
|
|
32
|
-
|
|
27
|
+
# 安装 SKILL.md;首次安装时由 Agent Skills CLI 选择目标 Agent
|
|
28
|
+
CLI_VERSION="$(applebookscli --version)"
|
|
29
|
+
npx -y skills@1.5.23 add "chiimagnus/AppleBooksCLI#v${CLI_VERSION}" --skill applebookscli --global
|
|
33
30
|
|
|
34
|
-
```sh
|
|
35
|
-
npm install --global @chiimagnus/applebookscli@beta
|
|
36
31
|
```
|
|
37
32
|
|
|
38
|
-
|
|
33
|
+
之后通过 npm 升级 CLI 时,若该 Skill 仍由 Agent Skills CLI 管理,npm `postinstall` 会把它自动切到相同的 `v<CLI版本>` tag 并调用官方 updater;没有安装 Skill 的用户不会受到影响。使用 `--ignore-scripts` 会显式关闭这条自动联动。此前手工复制的 Skill 没有 source tracking,只需按上面的标准命令重新安装一次即可接入后续自动更新。
|
|
34
|
+
|
|
35
|
+
## 获取帮助
|
|
36
|
+
|
|
37
|
+
CLI 自带完整帮助,具体命令与参数以当前安装版本为准:
|
|
39
38
|
|
|
40
39
|
```sh
|
|
41
|
-
|
|
40
|
+
applebookscli --help
|
|
41
|
+
applebookscli <group> --help
|
|
42
|
+
applebookscli <group> <subcommand> --help
|
|
42
43
|
```
|
|
43
44
|
|
|
44
45
|
## 快速开始
|
|
@@ -144,40 +145,17 @@ applebookscli sync --json
|
|
|
144
145
|
|
|
145
146
|
`sync` 只处理已存在的 pending collection/member/annotation cloud records;无 pending 时不触发生命周期。acknowledgement 只证明**当前 Mac** 已完成 Apple Books CloudKit upload,不等于另一台设备已经显示。post-commit `cloud_sync_failed` 不能触发自动重试;BKLibrary restore 也不等同于可逐条 flush 的 cloud mutation。
|
|
146
147
|
|
|
147
|
-
## 安装 AppleBooksCLI Skill
|
|
148
|
-
|
|
149
|
-
npm 包中包含配套的 `applebookscli` Skill:
|
|
150
|
-
|
|
151
|
-
```sh
|
|
152
|
-
applebookscli skill install
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
它会安装到 `${CODEX_HOME:-~/.codex}/skills/applebookscli`。如果目标已经存在,CLI 默认不会覆盖;需要明确替换时使用:
|
|
156
|
-
|
|
157
|
-
```sh
|
|
158
|
-
applebookscli skill install --force
|
|
159
|
-
```
|
|
160
|
-
|
|
161
148
|
## 可选配置
|
|
162
149
|
|
|
163
150
|
大多数用户不需要配置文件。只有需要指定额外的 EPUB 目录,或给历史批注补充书名/作者信息时,才需要 `~/.config/applebookscli/config.json`。
|
|
164
151
|
|
|
165
152
|
示例见 [`Config/applebookscli.example.json`](Config/applebookscli.example.json)。
|
|
166
153
|
|
|
167
|
-
## 获取帮助
|
|
168
|
-
|
|
169
|
-
CLI 自带完整帮助,具体命令与参数以当前安装版本为准:
|
|
170
|
-
|
|
171
|
-
```sh
|
|
172
|
-
applebookscli --help
|
|
173
|
-
applebookscli <group> --help
|
|
174
|
-
applebookscli <group> <subcommand> --help
|
|
175
|
-
```
|
|
176
|
-
|
|
177
154
|
## 开发与维护
|
|
178
155
|
|
|
179
156
|
架构、CLI contract、写入安全、发布流程和其它维护者文档从 [`docs/index.md`](docs/index.md) 开始。
|
|
180
157
|
|
|
181
158
|
## License
|
|
182
159
|
|
|
183
|
-
AppleBooksCLI 使用
|
|
160
|
+
AppleBooksCLI 使用 [AGPLv3 LICENSE](LICENSE) 。
|
|
161
|
+
第三方 notice 与许可证文本见 [`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md) 和 [`ThirdPartyLicenses/`](ThirdPartyLicenses/)。
|
package/bin/applebookscli
CHANGED
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { readFile, rename, stat, writeFile } from "node:fs/promises";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { spawn } from "node:child_process";
|
|
5
|
+
|
|
6
|
+
const skillName = "applebookscli";
|
|
7
|
+
const source = "chiimagnus/AppleBooksCLI";
|
|
8
|
+
const sourceURL = "https://github.com/chiimagnus/AppleBooksCLI.git";
|
|
9
|
+
const skillsVersion = "1.5.23";
|
|
10
|
+
|
|
11
|
+
async function runUpdater() {
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
const child = spawn(
|
|
14
|
+
"npx",
|
|
15
|
+
["-y", `skills@${skillsVersion}`, "update", skillName, "-g", "-y"],
|
|
16
|
+
{
|
|
17
|
+
stdio: "ignore",
|
|
18
|
+
env: { ...process.env, DISABLE_TELEMETRY: "1" },
|
|
19
|
+
},
|
|
20
|
+
);
|
|
21
|
+
child.once("error", reject);
|
|
22
|
+
child.once("exit", resolve);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async function main() {
|
|
27
|
+
const packageJSON = JSON.parse(
|
|
28
|
+
await readFile(new URL("../../package.json", import.meta.url), "utf8"),
|
|
29
|
+
);
|
|
30
|
+
// ponytail: skills@1.5.23 还没有公开的“只重绑 ref”命令;只改它自己的 source ref,target 更新仍完全交给官方 updater。
|
|
31
|
+
const lockPath = process.env.XDG_STATE_HOME
|
|
32
|
+
? join(process.env.XDG_STATE_HOME, "skills", ".skill-lock.json")
|
|
33
|
+
: join(homedir(), ".agents", ".skill-lock.json");
|
|
34
|
+
|
|
35
|
+
let rawLock;
|
|
36
|
+
try {
|
|
37
|
+
rawLock = await readFile(lockPath, "utf8");
|
|
38
|
+
} catch {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const lock = JSON.parse(rawLock);
|
|
43
|
+
const entry = lock.skills?.[skillName];
|
|
44
|
+
if (
|
|
45
|
+
!entry ||
|
|
46
|
+
entry.sourceType !== "github" ||
|
|
47
|
+
(entry.source !== source && entry.sourceUrl !== sourceURL)
|
|
48
|
+
) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const targetRef = `v${packageJSON.version}`;
|
|
53
|
+
if (entry.ref !== targetRef) {
|
|
54
|
+
const mode = (await stat(lockPath)).mode & 0o777;
|
|
55
|
+
const temporary = `${lockPath}.${process.pid}.tmp`;
|
|
56
|
+
entry.ref = targetRef;
|
|
57
|
+
await writeFile(temporary, `${JSON.stringify(lock, null, 2)}\n`, { mode });
|
|
58
|
+
await rename(temporary, lockPath);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const code = await runUpdater();
|
|
62
|
+
if (code !== 0) {
|
|
63
|
+
console.warn(
|
|
64
|
+
`applebookscli: Skill update to ${targetRef} did not complete; Agent Skills CLI can retry later.`,
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
await main();
|
|
71
|
+
} catch (error) {
|
|
72
|
+
console.warn(
|
|
73
|
+
`applebookscli: optional Skill update skipped: ${error instanceof Error ? error.message : String(error)}`,
|
|
74
|
+
);
|
|
75
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chiimagnus/applebookscli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Native Apple Books CLI for macOS on Apple Silicon.",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"repository": {
|
|
@@ -17,16 +17,16 @@
|
|
|
17
17
|
"cpu": [
|
|
18
18
|
"arm64"
|
|
19
19
|
],
|
|
20
|
-
"publishConfig": {
|
|
21
|
-
"access": "public"
|
|
22
|
-
},
|
|
23
20
|
"bin": {
|
|
24
21
|
"applebookscli": "bin/applebookscli"
|
|
25
22
|
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"postinstall": "node libexec/applebookscli/sync-installed-skill.mjs"
|
|
25
|
+
},
|
|
26
26
|
"files": [
|
|
27
27
|
"bin/applebookscli",
|
|
28
28
|
"libexec/applebookscli/applebookscli-pdf-worker",
|
|
29
|
-
"
|
|
29
|
+
"libexec/applebookscli/sync-installed-skill.mjs",
|
|
30
30
|
"LICENSE",
|
|
31
31
|
"THIRD_PARTY_NOTICES.md",
|
|
32
32
|
"ThirdPartyLicenses"
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: applebookscli
|
|
3
|
-
description: 通过 `applebookscli` 查询、定位、导出或受保护地修改 Apple Books 图书、阅读状态、EPUB/PDF、批注笔记与藏书,以及执行云同步、备份恢复或访问诊断时使用。
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# AppleBooksCLI
|
|
7
|
-
|
|
8
|
-
使用已安装的 `applebookscli` 作为 Apple Books 数据操作入口。用户询问自己的数据时,实际查询后再回答,不用能力说明代替结果。
|
|
9
|
-
|
|
10
|
-
## 命令与 identity
|
|
11
|
-
|
|
12
|
-
命令、参数和枚举以当前 `--help` 为准;需要机器结果时优先 `--json`,`export` 使用 `--format json`。`doctor` 只用于诊断实际的 permission / unavailable / schema 问题。
|
|
13
|
-
|
|
14
|
-
优先使用稳定 identity:book asset ID、annotation UUID、collection ID、backup handle。标题/作者/名称先 search/list 并确认唯一;local PK 只在用户明确指定或没有稳定 identity 时使用。不要静默选择多候选中的第一项。
|
|
15
|
-
|
|
16
|
-
## Annotation 与写入
|
|
17
|
-
|
|
18
|
-
“最新笔记”只在 nonempty note 中比较;“最新”默认按创建时间,“最近修改”按修改时间。具体 annotation 优先返回高亮、note、必要时间与 `appleBooksURL`;需要前后正文时才用 `content context`。
|
|
19
|
-
|
|
20
|
-
`annotations update-note --note` 是整段替换。用户要求追加时先读原 note,再构造完整新值。`annotations delete` soft-delete 整条 annotation,不用于清空 note。
|
|
21
|
-
|
|
22
|
-
只有用户明确要求修改或 restore 时才写。不要直接读写 Apple Books SQLite,也不要额外手工 quit/launch Books;guarded mutation rail 已负责 backup、Books lifecycle、事务、read-back 与 cloud projection。
|
|
23
|
-
|
|
24
|
-
`committed=true` 后出现 warning 不能自动重试;结果未知时先做最窄只读确认。单条 mutation 只有在用户要求立即确认上传时才加 `--sync`。连续多条写入先正常执行,最后一次 `applebookscli sync --json`,避免每条都触发 lifecycle。
|
|
25
|
-
|
|
26
|
-
`--sync` / `sync` 成功只证明当前 Mac 的 Apple Books cloud records 获得 CloudKit acknowledgement;没有 second-device 证据时不要声称另一设备已经显示。`cloud_sync_failed` 是 post-commit warning。`backups restore` 是 BKLibrary snapshot replacement,不要把 restore 后的 `sync` 解释成 snapshot diff 已逐条上传。
|
|
27
|
-
|
|
28
|
-
## EPUB、PDF 与导出
|
|
29
|
-
|
|
30
|
-
EPUB 不可用时按需要用 `content status --json` 解释原因;不绕过 DRM,也不主动 hydration。PDF 只处理当前可解析的本地 source;不要把 PDF 命令当作已证明 non-hydrating 的 iCloud placeholder probe。
|
|
31
|
-
|
|
32
|
-
完整笔记归档使用 `--complete-notes` 的 fail-closed 路径;失败时不能降级成普通 export 后声称完整。普通导出遵守用户给定的输出与 overwrite 策略。
|
|
33
|
-
|
|
34
|
-
## 完成判断
|
|
35
|
-
|
|
36
|
-
不要把 exit 0 当成目标完成;以返回数据证明结果,并区分 empty、not found、unavailable、degraded、warning 与 CloudKit acknowledgement。
|