htlin222/ankiweb-add-card
GitHub: htlin222/ankiweb-add-card
一个零依赖的纯 Python CLI 工具,通过逆向 AnkiWeb 的 protobuf 协议实现无浏览器环境下的牌组创建与闪卡添加自动化。
Stars: 6 | Forks: 1
# ankiweb-cli
[](LICENSE)

[](https://docs.astral.sh/uv/)
-success.svg)

一个微型、无依赖的 **AnkiWeb** CLI,可以直接通过 AnkiWeb 内部的 protobuf `/svc/` endpoint 创建牌组并添加卡片——无需浏览器,无需自动化框架,也无需绕过反机器人机制。
它使用您的凭据登录一次,缓存两个会话 cookie,并使用与 AnkiWeb Web 应用相同的通信协议进行交互。
## 工作原理
AnkiWeb 将其 API 分布在两个域上,每个域都有自己的会话 cookie(相同的登录方式,但 `c` 声明不同):
| 操作 | 域 | Cookie |
| --- | --- | --- |
| 添加 / 列出卡片及 notetype | `ankiuser.net` | `c:2` |
| 创建 / 列出 / 删除牌组 | `ankiweb.net` | `c:1` |
一次登录即可获取两者:
1. `POST ankiweb.net/svc/account/login` `{username, password}` → `ankiweb.net` cookie + 一个 `ankiuser-login` token。
2. `GET ankiuser.net/account/ankiuser-login?t=` → `ankiuser.net` cookie。
两个 cookie 都会被缓存到操作系统临时目录中的会话文件里,并一直重复使用直到过期(遇到 `403` 时会自动重新登录)。请求和响应是长度分隔的 protobuf(`Content-Type: application/octet-stream`),由 `anki.py` 中一个轻量级的手写编解码器进行编码/解码。
## 设置
无依赖——该 CLI 是纯 Python stdlib,因此只要有 Python 3.10+ 的环境,`python3 anki.py …` 就能在任何地方运行。如果你喜欢,也可以使用 [`uv`](https://docs.astral.sh/uv/)(`uv run anki.py …`)。
使用您的 AnkiWeb 凭据创建 `skill/anki/.env` 文件(该 CLI 会读取 `anki.py` 旁边的 `.env` 文件):
```
ANKI_USERID=you@example.com
ANKI_PASSWORD=your-password
```
## 用法
```
# Decks(使用 :: 进行嵌套)
uv run anki.py create_deck "Spanish::Verbs"
uv run anki.py remove-deck "Spanish::Verbs" # also removes its cards
# Cards — 位置值映射到 notetype 的字段顺序
uv run anki.py add_card "hola" "hello" -d "Spanish::Verbs" -n Basic
# 按名称覆盖字段,添加标签
uv run anki.py add_card "Q" "A" -f "Extra=note here" -t "tag1 tag2"
# 省略 -d/-n 以使用您上次使用的 deck / notetype
uv run anki.py add_card "front" "back"
# Discovery
uv run anki.py list-decks # idname
uv run anki.py list-notetypes
# Session
uv run anki.py login # force re-login, refresh cached session
```
### `add_card` 选项
| 参数 | 含义 |
| --- | --- |
| 位置参数 `values...` | 按照 notetype 的字段顺序填写的字段值 |
| `-d, --deck` | 牌组**名称**(会被解析为 id)或数字 id;默认值:最近使用的 |
| `-n, --notetype` | notetype **名称**或数字 id;默认值:最近使用的 |
| `-f, --field NAME=VALUE` | 通过名称设置字段(可重复使用;会覆盖位置参数) |
| `-t, --tags` | 以空格分隔的标签 |
名称会根据您的集合进行解析;未知的名称会触发“did you mean …?”(您是指……吗?)提示。数字参数将被视为原始 id。
## Claude skill
该 CLI 同时也作为 Claude skill 提供(适用于 claude.ai / Claude Code)。使用以下命令构建包:
```
make build # -> dist/anki.skill (bundles anki.py + SKILL.md + .env)
make clean # -> remove dist/
```
在 claude.ai 的 **Settings → Capabilities → Skills**(设置 → 能力 → 技能)下上传 `dist/anki.skill`(必须启用代码执行工具)。该包捆绑了 `.env` 文件,因此包含您的真实密码——请将其妥善保管,切勿分享给他人。
## 目录结构
| 路径 | 用途 |
| --- | --- |
| `skill/anki/anki.py` | CLI 本体——唯一的真相来源(纯 stdlib,无依赖) |
| `skill/anki/SKILL.md` | skill 清单文件(说明 agent 如何驱动 CLI) |
| `skill/anki/.env` | 您的凭据(已 gitignore) |
| `anki.py` | 符号链接 → `skill/anki/anki.py`,用于在 repo 根目录下执行 `uv run anki.py` |
| `Makefile` | `make build` → `dist/anki.skill` |
| `dist/` | 构建输出(已 gitignore) |
会话缓存位于操作系统临时目录中(无论如何都会被 gitignore),而不是 repo 中。
## 免责声明
本工具会与 AnkiWeb 私有且未公开文档化的 endpoint 进行通信,这些 endpoint 可能随时发生更改。请仅限于在您自己的账号上使用。本工具不隶属于 Anki,也未获得 Anki 的认可。
标签:AnkiWeb, Protobuf, Python, 云资产清单, 无后门, 网络调试, 自动化, 逆向工具, 逆向工程