npm package: @suibiji/dida-cli
Description: 滴答清单命令行工具（DIDA CLI）
Latest version: 0.1.5

# DIDA CLI（滴答清单）

使用 TypeScript 编写的滴答清单（[DIDA](https://dida365.com)）命令行工具，封装 [DIDA Open API v1](https://developer.dida365.com/docs#/openapi)，提供更便捷的 CLI。

## 安装

从源码（构建并全局 link）：

```bash
cd dida-cli
npm install
npm run build
npm link
```

完成后，终端中会有 `dida` 命令。

## 登录认证

推荐使用 OAuth（PKCE，无需 client secret）：

```bash
dida auth login
```

浏览器会打开进行授权。

推荐通过浏览器 OAuth 登录；如果环境不支持浏览器验证，可使用 token 方式。

```bash
dida auth login            # OAuth 浏览器登录（推荐）
dida auth token <token>    # 直接写入 access token（无浏览器环境可用）
dida auth status           # 查看是否已登录
dida auth logout           # 清除本地 token
```

**获取 Token**：前往网页版滴答清单，点击「头像」→「设置」→「账户与安全」→「API 口令」中创建并复制使用。

## 常用命令

### 任务

```bash
# 获取任务
dida task get <projectId> <taskId>

# 创建任务
dida task create --title "买牛奶" --project <projectId>
dida task create --title "开会" --project <projectId> --priority 5 --due-date "2026-03-10T09:00:00+0000"
dida task create --title "复盘" --project <projectId> --tags 工作,紧急

# 更新任务
dida task update <taskId> --id <taskId> --project <projectId> --title "新标题"
dida task update <taskId> --id <taskId> --project <projectId> --tags 工作,紧急

# 完成任务
dida task complete <projectId> <taskId>

# 删除任务
dida task delete <projectId> <taskId>

# 在清单间移动任务
dida task move --from <sourceProjectId> --to <destProjectId> --task <taskId>

# 列出已完成任务
dida task completed --projects <projectId> --start-date "2026-03-01T00:00:00+0000" --end-date "2026-03-09T23:59:59+0000"

# 过滤任务
dida task filter --projects <projectId> --priority 3,5 --status 0
```

### 清单

```bash
dida project list                    # 列出清单
dida project get <projectId>         # 清单详情
dida project data <projectId>        # 清单 + 任务 + 分组
dida project create --name "工作" --color "#F18181" --view-mode list --kind TASK
dida project update <projectId> --name "新名字" --color "#4AB8A9"
dida project delete <projectId>
```

### JSON 输出

任意命令加 `--json` 可输出原始 API JSON：

```bash
dida project list --json
dida task get <projectId> <taskId> --json
```

更多选项：`dida --help` 与 `dida <command> --help`。

## API mapping

| 命令             | Endpoint                                           |
| ---------------- | -------------------------------------------------- |
| `task get`       | `GET /project/{projectId}/task/{taskId}`           |
| `task create`    | `POST /task`                                       |
| `task update`    | `POST /task/{taskId}`                              |
| `task complete`  | `POST /project/{projectId}/task/{taskId}/complete` |
| `task delete`    | `DELETE /project/{projectId}/task/{taskId}`        |
| `task move`      | `POST /task/move`                                  |
| `task completed` | `POST /task/completed`                             |
| `task filter`    | `POST /task/filter`                                |
| `project list`   | `GET /project`                                     |
| `project get`    | `GET /project/{projectId}`                         |
| `project data`   | `GET /project/{projectId}/data`                    |
| `project create` | `POST /project`                                    |
| `project update` | `POST /project/{projectId}`                        |
| `project delete` | `DELETE /project/{projectId}`                      |

## JSON 字段与命令对应关系

**API mapping** 表里是每个命令对应的 HTTP 接口。加上 **`--json`**（见上文「JSON 输出」）时，终端里就是接口返回的原始对象，字段名为 **camelCase**。**`task create` / `task update`** 请求体里的字段名也一致，并与下列长选项对应。

### 任务（Task）

会出现在：**`task get … --json`**、带 **`--json`** 的 **`task create` / `task update`**、**`task completed` / `task filter` 的 JSON 每一行**，以及 **`project data … --json`** 里的 `tasks` 数组。

| 字段                      | 含义                                                 | CLI（create / update）            |
| ------------------------- | ---------------------------------------------------- | --------------------------------- |
| `id`                      | 任务 id（ObjectId 十六进制）                         | 仅 `update`：`<taskId>` 与 `--id` |
| `projectId`               | 所属清单                                             | `--project`                       |
| `sortOrder`               | 列表排序                                             | `--sort-order`                    |
| `title`                   | 标题，宜短；长文用 `content`                         | `--title`                         |
| `content`                 | 普通/笔记类任务的正文                                | `--content`                       |
| `desc`                    | 清单类任务的说明                                     | `--desc`                          |
| `startDate` / `dueDate`   | 时间；若 `dueDate` 与 `startDate` 不同，表示一段区间 | `--start-date`、`--due-date`      |
| `timeZone`                | 时区                                                 | `--time-zone`                     |
| `isAllDay`                | 是否全天                                             | `--all-day`                       |
| `priority`                | `0` 无，`1` 低，`3` 中，`5` 高                       | `--priority`                      |
| `reminders`               | 提醒触发字符串（格式见下文）                         | `--reminders`                     |
| `repeatFlag`              | 重复规则：`RRULE` 或 `ERULE`（格式见下文）           | `--repeat`                        |
| `completedTime`           | 完成时间                                             | —                                 |
| `status`                  | `0` 未完成，`-1` 已放弃，`2` 已完成                  | —                                 |
| `items`                   | 检查事项                                             | `--items`（见下 **检查事项**）    |
| `tags`                    | 标签                                                 | `--tags`（逗号分隔）              |
| `columnId` / `columnName` | 分组                                                 | —                                 |
| `parentId` / `childIds`   | 子任务关系                                           | —                                 |
| `assignor`                | 分配相关信息                                         | —                                 |
| `etag`                    | 服务端乐观锁                                         | —                                 |
| `kind`                    | 如 `TASK`、`NOTE`、`CHECKLIST`                       | —                                 |

#### `reminders` 格式

数组中每一项须符合以下模式：

`TRIGGER(;RELATED=START|END)?:(-)?P[nY][nM][nW][nD][T[nH][nM][nS]]`

- **TRIGGER** — 必填前缀。
- **`;RELATED=START` 或 `;RELATED=END`** — 可选；相对任务开始或结束时间。
- **冒号后的 `-`** — 可选；表示在参考时间**之前**触发；不写则表示在参考时间**之后**。
- **`P` 及后续片段** — 时长表示；**`nY` `nM` `nW` `nD`** 为年月周日；**`T`** 分隔日期与时间部分；**`nH` `nM` `nS`** 为时分秒（语义上类似 ISO-8601 时长，并带有方向与参考点）。

示例：

| 字符串 | 含义 |
| ------ | ---- |
| `TRIGGER:-PT60M` | 参考时间点前 60 分钟 |
| `TRIGGER:-P1DT2H` | 参考时间点前 1 天 2 小时 |
| `TRIGGER;RELATED=END:-PT15M` | **结束时间**前 15 分钟 |
| `TRIGGER:PT0S` | 准时（恰在参考时刻） |

#### `repeatFlag` 格式

须为一条合法的重复规则字符串：

- **`RRULE`** — 标准重复（类 RFC 规则）。
- **`ERULE`** — 自定义或高级重复。

**不要**在同一条 `repeatFlag` 里混用 `RRULE` 与 `ERULE`。

示例：

- `RRULE:FREQ=DAILY`
- `RRULE:FREQ=WEEKLY;BYDAY=MO,WE`
- `ERULE:NAME=CUSTOM;BYDATE=20260325,20260330`

### 检查事项（`items[]`）

清单型任务中，`items` 数组的每个元素是一条 **检查事项**：

| 字段                                                 | 含义                             |
| ---------------------------------------------------- | -------------------------------- |
| `id`                                                 | 检查事项 id（ObjectId 十六进制） |
| `status`                                             | `0` 未完成，`1` 已完成           |
| `title`                                              | 检查事项文案                     |
| `sortOrder`                                          | 检查事项之间的排序               |
| `startDate`、`isAllDay`、`timeZone`、`completedTime` | 可选时间与完成信息               |

### 清单（Project）

**`project list` / `project get --json`** 的对象，以及 **`project data --json`** 里的 `project`。**`project create` / `project update`** 写入的也是同类字段。

| 字段         | 含义                         | CLI                                      |
| ------------ | ---------------------------- | ---------------------------------------- |
| `id`         | 清单 id（ObjectId 十六进制） | `get`、`update`、`data`、`delete` 的参数 |
| `name`       | 名称                         | `--name`                                 |
| `color`      | 颜色                         | `--color`                                |
| `sortOrder`  | 侧栏顺序                     | —                                        |
| `closed`     | 是否关闭/归档                | —                                        |
| `groupId`    | 文件夹 id                    | —                                        |
| `viewMode`   | `list`、`kanban`、`timeline` | `--view-mode`                            |
| `permission` | `read`、`comment`、`write`   | —                                        |
| `kind`       | `TASK` 或 `NOTE`             | `--kind`                                 |

### 分组（`columns[]`）

**`project data … --json`** 中 `columns` 数组的元素：

| 字段        | 含义                       |
| ----------- | -------------------------- |
| `id`        | 列 id（ObjectId 十六进制） |
| `projectId` | 所属清单                   |
| `name`      | 列标题                     |
| `sortOrder` | 看板上的顺序               |

### `project data` 根对象

| 字段      | 含义                      |
| --------- | ------------------------- |
| `project` | 一个 **清单** 对象        |
| `tasks`   | 该清单下未完成的 **任务** |
| `columns` | 该清单的 **分组**         |

### `task completed` 请求体

对应 **`task completed`** 与 **API mapping** 中的 `POST /task/completed`：

| JSON 字段               | 命令行                                   |
| ----------------------- | ---------------------------------------- |
| `projectIds`            | `--projects`（逗号分隔）                 |
| `startDate` / `endDate` | `--start-date`、`--end-date`（ISO 8601） |

### `task filter` 请求体

对应 **`task filter`**（`POST /task/filter`）：

| JSON 字段               | 命令行                                            |
| ----------------------- | ------------------------------------------------- |
| `projectIds`            | `--projects`                                      |
| `startDate` / `endDate` | `--start-date`、`--end-date`                      |
| `priority`              | `--priority`（逗号分隔：`0`、`1`、`3`、`5`）      |
| `tag`                   | `--tag`（逗号分隔）                               |
| `status`                | `--status`（逗号分隔；如 `0` 未完成、`2` 已完成） |

### `task move` 请求体

**`--from`、`--to`、`--task`** 各写同样次数，每次三元组对应一个对象：`fromProjectId`、`toProjectId`、`taskId`。接口还可带 `sortOrder` 指定在目标清单中的位置；CLI 不传该字段。

## 开发

```bash
npm install
npm run build       # 编译
npm run dev         # watch 模式
npm run type-check  # 类型检查
npm test            # 运行测试
```

## License

MIT