禅道命令行工具,支持在你喜爱的终端里访问和操作禅道数据,对 AI Agents 友好。
- ✅ 基于最新的禅道 RESTful API 2.0 实现
- ✅ 使用便捷,可通过
npx zentao-cli立即运行 - ✅ 安全的用户认证管理,支持多用户切换
- ✅ 支持对数据进行摘取、过滤、排序等处理,并自动将 HTML 转换为 Markdown
- ✅ 对 AI Agents 友好,帮助信息完善,支持输出 Markdown
- ✅ 支持以 AI 技能的方式使用,支持通过
zentao add-skill一键安装技能到 AI Agent - ✅ 支持 MCP 服务,使用
npx zentao-cli mcp启动 MCP 服务 - ✅ 使用现代的 bun 与 TypeScript 开发,具备类型安全
- ✅ 提供完善的测试覆盖,保障代码质量
待实现特性:
- 支持工作区管理,支持记住用户上次访问的产品、项目和执行信息
- 支持批量创建和更新操作
- 对象预设 pick 列表
- Markdown 输出渲染,提供适合人阅读的终端渲染模式,为 Markdown 内容应用多彩格式,代码块支持高亮
- 支持适合开发者手动使用的极客版,有友好的 TUI 界面,支持在一个界面提供交互式操作
- 一键安装脚本,支持自动根据用户环境选择安装方式
- 国际化支持,支持多语言
- 多级别日志功能
# 全局安装 zentao-cli 工具
npm install -g zentao-cli
# 其他安装与运行方式
# bun install -g zentao-cli # ← 使用 bun 安装
# npx zentao-cli # ← 通过 npx 免安装运行
# pnpm dlx zentao-cli # ← 通过 pnpm 免安装运行
# 首次使用需要进行登录
zentao login -s https://zentao.example.com -u admin -p 123456
# 直接执行获取可用命令帮助
zentao
# 查看禅道产品
zentao product
# 查看指定 ID 的产品
zentao product 1
# 更新禅道产品 #1
zentao product update --id=1 --name=产品1
# 更多功能可通过 help 查看
zentao help
# 查看禅道产品帮助
zentao product help
# 安装 zentao-cli 技能
zentao add-skill支持通过 zentao-cli 技能访问和操作禅道数据。安装技能可以通过 zentao add-skill 一键安装技能到 AI Agent,目前支持 Claude Code、Cursor、Cherry Studio、Codex、OpenCode、VS Code 等 AI Agent。
# 安装 zentao-cli 技能
$ zentao add-skill
请选择要安装的 AI Agent:
1) Claude Code
2) Cursor
3) Codex
4) OpenCode
5) VS Code
6) 全部安装
请输入编号 (1-6):6
# 安装技能到 Claude Code
$ zentao add-skill claude-code如果还未安装 zentao-cli,可以通过下面的命令,一键安装、登录和配置 Skill:
# 一键安装、登录和配置 Skill
$ pnpm install -g zentao-cli && zentao login && zentao add-skill --all安装技能后即可在对应 Agent 工具中使用禅道 CLI 技能。
禅道中有哪些产品?
产品 xxx 有哪些研发中的需求?
需求 xxx 有哪些风险?Zentao CLI 支持一键配置 MCP 服务,只需要执行 zentao add-mcp 命令,然后按照提示输入禅道 URL、用户名和密码即可。
# 一键配置 MCP 服务
$ zentao add-mcp
请输入禅道 URL: https://zentao.example.com
请输入用户名: admin
请输入密码: 123456
请选择要配置的 AI Agent:
1) Cursor
2) Claude Desktop
3) Claude Code
4) Windsurf
5) Cline
6) Trae
7) VS Code
8) Cherry Studio
9) OpenCode
10) Codex
11) 全部配置
请输入编号 (1-11): 7如果还未安装 zentao-cli,可以通过下面的命令,一键安装、登录和配置 MCP 服务:
# 一键安装、登录和配置 MCP 服务
$ pnpm install -g zentao-cli && zentao login && zentao add-mcp统一支持通过 npx -y zentao-cli mcp 手动启动 MCP 服务,然后通过 MCP 客户端访问和操作禅道数据。目前各大 Agents 工具无需提前安装 zentao-cli 本身,只需要在 MCP 服务配置中增加如下配置即可:
{
"mcpServers": {
"zentao-cli": {
"command": "npx",
"args": ["-y", "zentao-cli", "mcp"],
"env": {
"ZENTAO_URL": "https://zentao.example.com",
"ZENTAO_ACCOUNT": "admin",
"ZENTAO_PASSWORD": "123456"
}
}
}
}首次执行 zentao 时,会提示输入禅道 URL、用户名和密码完成登录。登录成功后会记住用户信息(包括禅道 URL、账号和 Token,不包括密码),方便后续使用。
也可以通过 zentao login 命令登录,支持使用 -s <zentao_url> -u <account> -p <password> 参数指定禅道 URL、用户名和密码,例如:
# 登录禅道
zentao login -s https://zentao.example.com -u admin -p 123456zentao-cli 支持从环境变量中读取禅道服务地址、用户账号和密码。如果已经显式指定了 -s、-u、-p 参数,则优先使用这些参数,环境变量不会生效。
有时即使已经设置了环境变量,之前手动登录过的身份信息仍可能被优先使用。如果希望忽略已有身份信息并强制使用环境变量重新验证,可以通过 zentao login --useEnv 来实现。
支持如下环境变量:
ZENTAO_URL:禅道服务地址ZENTAO_ACCOUNT:用户账号ZENTAO_PASSWORD:密码ZENTAO_TOKEN:TOKEN。当未提供密码时,可通过该环境变量读取 TOKEN
zentao-cli 支持登录多个禅道服务,或在同一服务下登录多个账号。登录成功后,默认将最后一次登录的服务账号设为当前账户。可以通过 zentao profile 查看当前用户信息并切换当前用户。
# 查看当前用户信息
$ zentao profile
* admin@https://zentao.example.com (当前)
* dev1@https://zentao.example.com
# 切换当前用户
$ zentao profile dev1@https://zentao.example.com
* admin@https://zentao.example.com
* dev1@https://zentao.example.com (当前)使用 zentao logout 可退出当前用户,同时移除 ~/.config/zentao/zentao.json 文件中的对应用户信息。
# 退出当前用户
$ zentao logout
# 退出指定用户
$ zentao logout dev1@https://zentao.example.com默认情况下,zentao-cli 会将用户配置保存在 ~/.config/zentao/zentao.json。也可以通过全局选项 --config <config_file> 或环境变量 ZENTAO_CONFIG_FILE 指定自定义配置文件路径;此时所有读写均作用于该文件,不再使用默认路径。
# 通过 --config 选项使用自定义配置文件
$ zentao --config /path/to/zt.json profile
# 通过环境变量指定(便于在 shell 中持久设置)
$ ZENTAO_CONFIG_FILE=~/work/zt.json zentao product路径支持 ~ 展开与相对路径(相对当前工作目录)。当 --config 与 ZENTAO_CONFIG_FILE 同时存在时,--config 优先。
禅道数据访问和操作支持两种调用方式:
第一种:原始方式,通过如下 ls、get 等命令访问和操作禅道数据,具体包括:
zentao ls:获取对象列表zentao get <moduleName> <objectID>:获取单个对象zentao delete <moduleName> <objectID>:删除对象zentao create <moduleName> [params]:创建对象zentao update <moduleName> <objectID> [params]:更新对象zentao do <moduleName> <action> <objectID> [params]:执行对象操作zentao help <moduleName>:获取模块帮助信息
第二种:简写方式,通过如下 zentao <moduleName> 命令访问和操作禅道数据,具体包括:
zentao <moduleName>:获取对象列表zentao <moduleName> <objectID>:获取单个对象zentao <moduleName> delete <objectID>:删除对象zentao <moduleName> create [params]:创建对象zentao <moduleName> update <objectID> [params]:更新对象zentao <moduleName> <action> <objectID> [params]:执行对象操作zentao <moduleName> help:获取模块帮助信息
Tip
推荐优先使用简写方式。当简写方式中的模块名与命令行一级命令冲突时,必须改用原始方式调用。
支持通过 zentao <moduleName> 的方式获取指定模块的对象列表。
# 获取禅道产品列表
$ zentao product
| id | name | ... |
| --- | --- | --- |
| 1 | 产品1 | ... |
| 2 | 产品2 | ... |
已显示 2 项,共 2 项,当前第 1 页,每页 100 条
# 获取禅道产品列表,并输出 JSON 格式
$ zentao product --format=json
{
"status": "success",
"data": [
{"id": 1, "name": "产品1", ...},
{"id": 2, "name": "产品2", ...}
],
"pager": {
"total": 2,
"page": 1,
"recPerPage": 100,
"totalPage": 1
}
}
# 获取项目 #5 下的执行列表;如果省略 --project 参数,则使用当前工作区中的项目
$ zentao execution --project=5
# 输出略原始方式
通过 zentao ls <moduleName> 获取指定模块的对象列表。
# 获取禅道产品列表
$ zentao ls product
# 输出略
已显示 2 项,共 2 项,当前第 1 页,每页 100 条
# 获取禅道产品列表,并输出 JSON 格式
$ zentao ls product --format=json
# 输出略支持通过 zentao <moduleName> <objectID> 获取指定模块、指定 ID 的对象信息。
# 获取禅道产品 #1 信息
$ zentao product 1
* id: 1
* name: 产品1
* ...原始方式
通过 zentao get <moduleName> <objectID> 获取指定模块、指定 ID 的对象信息。
# 获取禅道产品 #1 信息
$ zentao get product 1
# 输出略支持通过 zentao <moduleName> delete <objectIDs> 删除指定模块中的指定 ID 对象。删除多个对象时,可使用逗号分隔多个 ID。默认删除前会输出待删除对象的详细信息供用户确认;如果无需确认,可通过 --yes 参数强制删除。
# 删除禅道产品 #1
$ zentao product delete 1
要删除的产品 #1:
* id: 1
* name: 产品1
* ...
是否继续?(y/n): y
已删除 产品 #1
# 删除禅道产品 #1 和 #2
$ zentao product delete 1,2
要删除的产品(共 2 个):
| id | name | ... |
| --- | --- | --- |
| 1 | 产品1 | ... |
| 2 | 产品2 | ... |
是否继续?(y/n): y
已删除 2 个产品
# 强制删除禅道产品 #1 和 #2
$ zentao product delete 1,2 --yes
已删除 2 个产品:1, 2
# 使用 JSON 输出
$ zentao product delete 1,2 --yes --format=json
{
"status": "success",
"result": [
"success": [1, 2]
"failed": [],
"skipped": []
]
}原始方式
通过 zentao delete <moduleName> <objectIDs> 删除指定模块中的指定 ID 对象。删除多个对象时,可通过逗号分隔多个 ID。
# 删除禅道产品 #1
$ zentao delete product 1
# 输出略
# 删除禅道产品 #1 和 #2
$ zentao delete product 1,2
# 输出略支持通过 zentao <moduleName> create [params] 创建指定模块中的对象。
# 创建禅道产品
$ zentao product create --name=产品1也可以通过 --data='JSON_STRING' 指定创建对象所需的 JSON 数据。
# 创建禅道产品,并指定 JSON 数据
$ zentao product create --data='{"name": "产品1"}'原始方式
通过 zentao create <moduleName> [params] 创建指定模块中的对象。
# 创建禅道产品
$ zentao create product --name=产品1也可以通过 --data='JSON_STRING' 指定创建对象所需的 JSON 数据。
# 创建禅道产品,并指定 JSON 数据
$ zentao create product --data='{"name": "产品1"}'支持通过 zentao <moduleName> update [objectID] [params] 更新指定模块中指定 ID 的对象。
# 更新禅道产品 #1
$ zentao product update 1 --name=产品1也可以通过 --data='JSON_STRING' 指定更新对象所需的 JSON 数据。
# 更新禅道产品 #1,并指定 JSON 数据
$ zentao product update 1 --data='{"name": "产品1"}'原始方式
通过 zentao update <moduleName> [objectID] [params] 更新指定模块中指定 ID 的对象。
# 更新禅道产品 #1
$ zentao update product 1 --name=产品1也可以通过 --data='JSON_STRING' 指定更新对象所需的 JSON 数据。
# 更新禅道产品 #1,并指定 JSON 数据
$ zentao update product 1 --data='{"name": "产品1"}'支持通过 zentao <moduleName> <action> <objectID> [params] 对指定模块、指定 ID 的对象执行特定操作。
# 解决禅道 BUG #1
$ zentao bug resolve 1 --comment "已解决"不同对象支持的操作不同,具体可通过 zentao <moduleName> --help 查看对应模块支持的操作。
原始方式
通过 zentao do <moduleName> <action> <objectID> [params] 对指定模块、指定 ID 的对象执行特定操作。
# 解决禅道 BUG #1
$ zentao do bug resolve 1 --comment "已解决"不同对象支持的操作不同,具体可通过 zentao do <moduleName> --help 查看对应模块支持的操作。
支持通过命令行管道与标准输入(Stdin)传递 --data 参数。例如,创建产品时可以通过管道传入 JSON 数据:
# 创建禅道产品,通过管道传递 JSON 数据
$ cat products.json | zentao product create --data @-
# 或者直接通过管道传递
echo '{"name": "新产品"}' | zentao product create进行批量操作时,默认会在某个对象出错后自动跳过该对象,并继续执行后续操作。如果希望在出错后立即停止,可使用 --batch-fail-fast 参数。
也可以通过 batchFailFast 配置项在全局范围内开启此行为。下面是批量删除产品出错时的输出示例:
# 批量删除 5 个产品,但在第三个产品时出错
$ zentao product delete 1,2,3,4,5 --yes
已删除 4 个产品:1, 2, 4, 5
操作失败:3
失败原因:Error(E2006): 当前用户没有权限执行此操作
# 批量删除 5 个产品,但在第三个产品时出错,使用 batchFailFast 选项
$ zentao product delete 1,2,3,4,5 --yes --batch-fail-fast
已删除 1 个产品:1
操作失败:3
已跳过 2 个产品:4, 5
失败原因:Error(E2006): 当前用户没有权限执行此操作
# 使用 JSON 输出
$ zentao product delete 1,2,3,4,5 --yes --batch-fail-fast --format=json
{
"status": "success",
"result": {
"success": [1, 2],
"failed": [3],
"skipped": [4, 5],
"errors": [
{
"objectID": 3,
"error": {
"code": "2006",
"message": "当前用户没有权限执行此操作"
}
}
]
},
"error": {
"code": "2006",
"message": "当前用户没有权限执行此操作"
}
}支持通过 --silent 参数在执行命令时启用静默模式。启用后,不再输出普通信息,仅在出错时输出错误信息。
# 启用静默模式,仅在出错时输出错误信息
$ zentao product create --silent也可以通过 silent 配置项在全局范围内开启该功能。
# 设置全局静默模式
$ zentao config set silent true支持通过 zentao help 获取所有一级命令的帮助信息,也支持通过 zentao <command> --help 获取指定命令的帮助信息。
# 获取所有一级命令帮助信息
$ zentao help
# 获取指定命令的帮助信息
$ zentao <command> --help支持通过 --format=json|markdown|raw 参数指定输出格式。默认输出 Markdown 格式,其中 raw 表示输出原始 JSON 数据。
# 获取禅道产品信息,并输出 Markdown 格式
$ zentao product
| id | name | ... |
| --- | --- | --- |
| 1 | 产品1 | ... |
| 2 | 产品2 | ... |
已显示 2 项,共 2 项,当前第 1 页,每页 100 条
# 如果获取的是单个对象,则以列表形式输出
$ zentao product 1
* id: 1
* name: 产品1
* ...
# 获取禅道产品信息,并输出 JSON 格式
$ zentao product --format=json
{
status: "success",
data: [
{"id": 1, "name": "产品1", ...},
{"id": 2, "name": "产品2", ...}
],
pager: {
total: 2,
page: 1,
recPerPage: 100,
totalPage: 1,
}
}
# 获取禅道产品信息,并输出原始 JSON 格式
$ zentao product --format=raw
{
"status": "success",
"products": [
{"id": 1, "name": "产品1", ...},
{"id": 2, "name": "产品2", ...}
],
"pager": {
"recTotal": 5,
"recPerPage": 20,
"pageTotal": 1,
"pageID": 1
}
}zentao-cli 支持对数据进行摘取、过滤、排序等处理,方便用户快速获取所需信息。
支持通过 --pick=<field1>,<field2>,... 参数指定需要输出的字段。多个字段用逗号分隔,支持通过 . 访问子字段。
# 获取禅道产品信息,并摘取产品名称和 ID
$ zentao product --pick=id,name
| id | name |
| --- | --- |
| 1 | 产品1 |
| 2 | 产品2 |
已显示 2 项,共 2 项,当前第 1 页,每页 100 条支持通过 --filter=<field1><operator><value>,<field2><operator><value>,... 参数指定过滤条件。多个条件用逗号分隔,字段名支持通过 . 访问子字段。当参数值中包含逗号时,需要使用引号包裹。
在同一个 --filter 参数内使用逗号分隔多个条件时,会按 AND 逻辑进行过滤。如果需要 OR 逻辑,则可使用多个 --filter 参数。
支持的运算符:
:等于!=不等于>大于<小于>=大于等于<=小于等于~包含!~不包含
下面是一些使用示例:
# 获取禅道产品信息,并过滤名称包含 "产品" 的产品
$ zentao product --filter 'name~产品'
| id | name | ... |
| --- | --- | --- |
| 1 | 产品1 | ... |
| 2 | 产品2 | ... |
已显示 2 项,共 2 项,当前第 1 页,每页 100 条
# 获取禅道产品信息,并过滤名称包含 "产品" 或名称为 "项目1" 的产品
$ zentao product --filter 'name~产品' --filter 'name:项目1'
| id | name | ... |
| --- | --- | --- |
| 1 | 产品1 | ... |
| 2 | 产品2 | ... |
| 3 | 项目1 | ... |
| 4 | 项目2 | ... |
已显示 4 项,共 4 项,当前第 1 页,每页 100 条
# 当参数值中包含逗号时,需要使用引号包裹,例如:
$ zentao product --filter 'name~"产品1,产品2"'
# 输出略当输出结果为列表时,支持通过 --search=<keyword>,<keyword>,... 参数进行模糊搜索。多个关键词使用逗号分隔;通过 --search-fields=<field1>,<field2>,... 指定搜索字段,多个字段用逗号分隔,并支持通过 . 访问子字段。
如果需要 OR 逻辑,则可以使用多个 --search 参数。
# 获取禅道产品信息,并搜索名称或描述中包含 "产品" 的产品
$ zentao product --search=产品 --search-fields=name,desc
| id | name | ... |
| --- | --- | --- |
| 1 | 产品1 | ... |
| 2 | 产品2 | ... |
已显示 2 项,共 2 项,当前第 1 页,每页 100 条
# 获取禅道产品信息,并搜索名称中包含 "产品1" 或 "产品2" 的产品
$ zentao product --search=产品1 --search=产品2
| id | name | ... |
| --- | --- | --- |
| 1 | 产品1 | ... |
| 2 | 产品2 | ... |
已显示 2 项,共 2 项,当前第 1 页,每页 100 条支持通过 --sort=<field1>_asc,<field2>_desc,... 参数指定排序条件。多个排序条件用逗号分隔,字段名支持通过 . 访问子字段。
# 获取禅道产品信息,并按产品名称排序
$ zentao ls product --sort=name_asc
| id | name |
| --- | --- |
| 1 | 产品1 |
| 2 | 产品2 |
已显示 2 项,共 2 项,当前第 1 页,每页 100 条当输出结果为列表时,可以通过如下选项控制分页:
--page=<pageNumber>:指定页码,默认值为 1--recPerPage=<recPerPage>:指定分页大小,默认值为 20--all:获取全部数据,不分页--limit=<number>:指定获取数据的数量
# 获取禅道产品信息,并分页获取
$ zentao product --page=1 --recPerPage=100
| id | name |
| --- | --- |
| 1 | 产品1 |
| 2 | 产品2 |
已显示 2 项,共 2 项,当前第 1 页,每页 100 条支持通过 zentao config set <key> <value> 设置默认配置,支持的配置项包括:
defaultOutputFormat:默认输出格式,支持markdown、json、rawlang:界面语言,支持zh-cn、zh-tw、endefaultRecPerPage:默认分页大小insecure:是否忽略 SSL/TLS 证书验证timeout:请求超时时间htmlToMarkdown:是否将对象属性中的 HTML 转换为 MarkdownbatchFailFast:是否在批量操作出错时停止执行后续操作pagers:分页配置,支持product、project、execution等模块autoSetWorkspace:是否自动设置工作区,默认值为falsesilent:是否启用静默模式,默认值为falsejsonPretty:是否在 JSON 格式化时添加空格,默认值为false
# 设置默认输出格式为 JSON
$ zentao config set defaultOutputFormat json
# 设置界面语言为英文
$ zentao config set lang en通过 zentao config get [key] 查看默认配置;如果不指定 key,则返回全部默认配置。
# 查看默认输出格式
$ zentao config get defaultOutputFormat
json
# 查看所有默认配置
$ zentao config get
defaultOutputFormat: "json"
lang: "en"
defaultRecPerPage: 20
insecure: false
timeout: 10000
htmlToMarkdown: true
batchFailFast: false通过 zentao version 获取 zentao-cli 版本信息;如果已经登录禅道,还会同时输出当前登录的禅道版本信息。
# 获取 zentao-cli 版本信息
$ zentao version
Zentao CLI: 0.1.0
Zentao Server: 22.1 (https://zentao.example.com)支持通过 zentao autocomplete 命令生成自动补全脚本,支持 zsh、bash 和 fish 三种 shell。
# 生成 zsh 自动补全脚本
$ zentao autocomplete zsh
# 生成 bash 自动补全脚本
$ zentao autocomplete bash
# 生成 fish 自动补全脚本
$ zentao autocomplete fish本文档面向希望为项目做贡献或了解项目结构的开发者。
- 使用 Bun + TypeScript 开发,构建为 Node.js 兼容产物,通过 npm 发布,用户无需安装 Bun
- 用户配置存储:configstore
- 终端开发辅助库:commander.js
- 对象嵌套属性访问:dot-prop
- HTML 转 Markdown:turndown
- Node.js CLI 应用程序最佳实践
zentao-cli/
├── src/
│ ├── commands/ # 命令实现
│ ├── api/ # API 客户端(HTTP 请求封装、Token 管理)
│ ├── auth/ # 认证逻辑
│ ├── utils/ # 工具函数
│ ├── config/ # 配置管理
│ ├── types/ # TypeScript 类型定义
│ └── index.ts # 入口文件
├── tests/ # 测试
├── bin/ # CLI 入口
├── docs/ # 文档
├── scripts/ # 脚本
├── data/ # 数据文件
│ └── zentao-openapi.json # 禅道 API 2.0 规范
└── package.json使用 bun 的测试框架 bun:test 编写测试用例。
# 运行所有测试
bun test
# 运行指定测试文件
bun test tests/zentao.test.ts- 更新日志 - 记录每个版本的变更内容
- 技术方案与实现细节 - 详解内部接口调用规则、验证机制与持久化配置
- 常见错误排查与参考手册 - 使用命令遇到错误(格式:Exxxx)时进行查阅