Metadata-Version: 2.4
Name: yuque-cli
Version: 0.1.0
Summary: 针对企业语雀实例的命令行客户端：cookie 认证，驱动内部 web 接口，提供文档与评论的 CRUD
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Requires-Dist: typer>=0.12
Requires-Dist: websocket-client>=1.9.0
Description-Content-Type: text/markdown

# yuque-cli

面向语雀(含企业版)的通用命令行客户端:以浏览器 cookie 认证,驱动语雀内部 web 接口,提供文档(doc)与评论(comment)的增删改查。默认连接 `www.yuque.com`,企业实例用环境变量 `YUQUE_HOST` 指定。

> 术语(知识库/文档/评论/login/namespace/slug)见 [CONTEXT.md](./CONTEXT.md);关键设计取舍见 [docs/adr](./docs/adr)。

## 特性

- **复用浏览器登录态**:默认探测本地 Chrome 远程调试(CDP)自动抓取 cookie,无需手动复制;失败可回退手动粘贴。
- **干净的 Markdown 输出**:`doc get` 默认输出纯 Markdown,便于管道与落盘;`--json` 输出含 Lake 正文的完整详情。
- **先取后合并的更新**:`doc update` 只改你指定的字段,其余保持原值。
- **脚本友好**:全局 `--json` 输出原始 JSON,`-y` 跳过确认,正文支持 `--body`/`--file`/管道 stdin。

## 安装

需要 Python ≥ 3.10 与 [uv](https://docs.astral.sh/uv/)。

```bash
uv sync                 # 安装依赖
uv run yuque --help     # 在项目内运行
```

或作为工具安装,得到全局 `yuque` 命令:

```bash
uv tool install .
yuque --help
```

## 快速开始

```bash
yuque auth login                       # 登录(自动 CDP,失败回退手动粘贴)
yuque auth status                      # 查看当前身份
yuque book list                        # 列出我的知识库
yuque doc list  <login>/<book>         # 列出知识库下的文档
yuque doc get   <login>/<book>/<slug>  # 取文档正文(Markdown)
```

`<login>/<book>/<slug>` 既可写成去掉 host 的路径形态,也可直接粘贴完整浏览器 URL(见 [URL 形态](#url-形态))。

## 认证

### 自动(CDP)

`yuque auth login` 默认尝试从**你当前的 Chrome**(已登录目标语雀站点)直接抓取 cookie。前提是 Chrome 以远程调试端口启动:

```bash
# 完全退出 Chrome 后,带远程调试重新启动(默认 profile 即可),再登录你的语雀站点
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --remote-debugging-port=9222
```

随后 `yuque auth login` 会自动连接、抓取目标站点的全部 cookie(含 `_yuque_session` 与 CSRF `yuque_ctoken`)并保存会话。

### 手动

未检测到远程调试、或自动抓取失败时,会提示粘贴 cookie;也可直接 `yuque auth login --manual` 跳过 CDP。cookie 取自浏览器 DevTools → Application → Cookies,或控制台 `document.cookie`。

### 会话与退出

- 会话保存在 `~/.config/yuque-cli/session.json`(权限 `0600`)。
- `yuque auth logout` 清除本地会话。

### 代理说明

对语雀的 API 请求**默认直连,不读取 `*_proxy` 环境变量**(`trust_env=False`),避免请求被本地代理(如 Clash)拦截,也免去 SOCKS 代理触发 `socksio` 缺失的报错。如果你的网络必须经代理才能访问目标实例,需要移除该参数并引入 `httpx[socks]` 依赖。

## 命令参考

### 全局选项

置于子命令之前,如 `yuque --json book list`。

| 选项 | 说明 |
| --- | --- |
| `--json` | 输出原始 JSON(便于脚本解析) |
| `-y`, `--yes` | 跳过所有确认(删除等危险操作) |
| `-v`, `--verbose` | 打印内部 HTTP 请求到 stderr |
| `-V`, `--version` | 显示版本 |

### auth — 登录态管理

| 命令 | 说明 |
| --- | --- |
| `auth login [--manual]` | 登录;默认探测 CDP 自动获取,`--manual` 直接手动粘贴 |
| `auth status` | 显示当前登录身份(`GET /api/mine`) |
| `auth logout` | 清除本地会话 |

### book — 知识库

| 命令 | 说明 |
| --- | --- |
| `book list` | 列出我的知识库(`GET /api/mine/books`) |

### doc — 文档

| 命令 | 说明 |
| --- | --- |
| `doc list <login>/<book>` | 列出知识库下的文档 |
| `doc get <login>/<book>/<slug>` | 取正文;默认干净 Markdown,`--json` 出详情(含 Lake) |
| `doc create <login>/<book> -t <标题> [选项]` | 在知识库中创建文档 |
| `doc update <login>/<book>/<slug> [选项]` | 更新文档(先取后合并,未给的字段保持原值) |
| `doc delete <login>/<book>/<slug>` | 删除文档(软删,可在回收站恢复) |

`doc create` 选项:`-t/--title`(必填)、`--slug`(省略则自动生成)、`--public/--private`、`-b/--body`、`-F/--file`。

`doc update` 选项:`-t/--title`、`--public/--private`、`-b/--body`、`-F/--file`;至少给其一,否则报错。

可见性 `--public/--private`:不给则创建时继承知识库默认、更新时保持原值。

```bash
# 创建(内联正文)
yuque doc create your-team/handbook -t "上手指南" --body "# 标题\n正文"

# 从文件创建,并设为私有
yuque doc create your-team/handbook -t "周报" -F report.md --private

# 仅改标题(正文与可见性保持不变)
yuque doc update your-team/handbook/getting-started -t "新标题"

# 删除(非交互环境需 -y)
yuque -y doc delete your-team/handbook/old-draft
```

### comment — 评论

| 命令 | 说明 |
| --- | --- |
| `comment list <login>/<book>/<slug>` | 列出文档评论 |
| `comment add <login>/<book>/<slug> [-b/--body \| -F/--file]` | 添加评论(正文不能为空) |
| `comment delete <comment_id>` | 删除一条评论(id 取自 `comment list`) |

## URL 形态

凡接受文档/知识库地址的命令,既可用**完整浏览器 URL**,也可用**去掉 host 的路径形态**,二者等价:

```
https://<host>/<login>/<book>/<slug>   ←→   <login>/<book>/<slug>   (文档)
https://<host>/<login>/<book>          ←→   <login>/<book>          (知识库)
```

数字 id 不属于用户语汇,仅内部解析时使用。

## 正文输入

`doc create` / `comment add` 的正文按以下优先级取值(`--body` 与 `--file` 互斥):

1. `-b/--body`(内联字符串)
2. `-F/--file`(从文件读;`-F -` 表示读 stdin)
3. 管道 stdin(直接 `... | yuque doc create ...`)

```bash
echo "# 来自管道的正文" | yuque doc create your-team/handbook -t "标题"
```

`doc update` 略有不同:只有显式给 `-b/--body` 或 `-F/--file`(含 `-F -` 读 stdin)才会改正文;**裸管道不会被读取**——不给正文来源即表示保持原正文不变。

## 环境变量

| 变量 | 作用 | 默认 |
| --- | --- | --- |
| `YUQUE_HOST` | 目标语雀 host | `www.yuque.com` |
| `YUQUE_CONFIG_DIR` | 配置/会话目录 | `$XDG_CONFIG_HOME/yuque-cli` 或 `~/.config/yuque-cli` |
| `XDG_CONFIG_HOME` | 配置根目录 | `~/.config` |
| `NO_COLOR` | 设置后禁用彩色输出 | — |

## 开发

本项目遵循 TDD,并用 [mise](https://mise.jdx.dev/) 管理工具链(锁定 uv)与常用任务。

```bash
mise run deps     # 安装依赖(uv sync)
mise run test     # 运行测试(pytest)
mise run lint     # ruff check && ruff format
mise run check    # ty 类型检查
mise run cli -- --help   # 运行 CLI(-- 之后为 yuque 的参数)
```

- 源码:`src/yuque_cli/`;测试:`test/`。
- 设计文档:术语表 [CONTEXT.md](./CONTEXT.md)、决策记录 [docs/adr](./docs/adr)、内部接口速查 [docs/internal-api.md](./docs/internal-api.md)。
