@magical-index/alidocs-html-skills
v0.1.0
Published
把本地 HTML 文件上传到钉钉并对外分享(互联网公开发布 / 分享到 IM)的 Agent Skill,底层驱动 dws (DingTalk Workspace CLI)
Readme
@magical-index/alidocs-html-skills
把本地 HTML 文件上传到钉钉,并对外分享——互联网公开发布、分享到钉钉 IM 会话。
以 Agent Skill(SKILL.md + name / description frontmatter)形式提供,不绑定某一家 agent:Claude Code、Cursor、Codex、Gemini CLI 等读取 skills/ 目录的 agent 都能用。底层全部驱动 dws(DingTalk Workspace CLI),不直接调用钉钉 OpenAPI。
skill 本身只是一份 Markdown 说明书,真正干活的是 alidocs-html 这个 CLI——所以即使你的 agent 不支持 skill 机制,直接让它调 CLI 也一样能用。
前置依赖
需要先安装并授权 dws:
# macOS / Linux
curl -fsSL https://raw.githubusercontent.com/DingTalk-Real-AI/dingtalk-workspace-cli/main/scripts/install.sh | sh
# 或 npm
npm install -g dingtalk-workspace-cli
# 国内加速(GitHub 不可达时走 Gitee 镜像)
DWS_GITEE_REPO=DingTalk-Real-AI/dingtalk-workspace-cli \
curl -fsSL https://gitee.com/DingTalk-Real-AI/dingtalk-workspace-cli/raw/main/scripts/install.sh | sh装完后完成一次授权(交互式 OAuth,会打开浏览器):
dws auth logindws 装了但不在 PATH 上时,用 DWS_BIN=/绝对路径/dws 指定。
检测不到 dws 时会发生什么
在交互式终端里,命令会先打印上面这份安装指引,然后征询一次:
是否现在用 npm 安装?将执行: npm install -g dingtalk-workspace-cli
(约 60MB;它的 postinstall 还会把 dws 自带的 agent skill 写入
~/.agents/skills/dws 等已存在的 agent 目录,若已存在则覆盖)
(选 n 则不做任何改动,你可以从上面的指引里自行挑一种安装方式)
现在安装? [y/N]- 只有明确输入
y/yes才会安装;回车、n、Ctrl+C、Ctrl+D 一律视为不安装,退出码 127,不做任何改动。 - 只代跑 npm 这一条。
curl | sh与 Gitee 镜像永远只给指引不代跑——那等于让远端脚本在你机器上任意执行,该由你自己决定。 - 之所以选 npm 而不是官方首推的
curl | sh:你既然在用本包,npm 与 registry 一定是通的,而 curl 装法依赖 GitHub 可达(国内要另设DWS_GITEE_REPO);npm 包把各平台二进制打进了 tarball,安装过程不联网取产物;且npm uninstall -g dingtalk-workspace-cli可回退。 - dws 的 postinstall 会把它自己的 skill 写入
~/.agents/skills/dws与其它已存在的 agent skill 目录(.claude/.cursor/.codex/.gemini等),并重写~/.dws/skills/缓存——规则和本包一样。npm 路径没有跳过这一步的开关(curl装法有DWS_NO_SKILLS=1)。这不会影响本包自己的alidocs-html目录,两者目录名不同。 - 装成功后会自动重跑你原来那条命令(此时还没产生任何副作用,重跑是安全的),并提醒你
dws auth login。最多重试一次。
以下情况不提问,直接打印指引并退 127(保持旧行为,便于程序化调用):
| 情况 | 原因 |
|---|---|
| 非终端(管道 / CI / Agent 调用) | 没人能回答 |
| 传了 --json | 调用方要的是可解析输出,不能插入提问 |
| 设了 DWS_BIN | 显式路径找不到属于配置错误,装新的也不会被用到 |
安装
npm install -g @magical-index/alidocs-html-skillspostinstall 会自动把 skill 装进你家目录下已经存在的各 agent skills 目录。若被跳过或失败,手动补一次:
alidocs-html install-skill # 用户级(家目录)
alidocs-html install-skill --project # 装到当前目录,便于随仓库提交给团队装到哪些目录
~/.agents/skills/alidocs-html/(厂商中立位置)无条件安装;下列目录只在其父目录已存在时才装——不替你给没在用的 agent 新建目录:
.claude .cursor .qoder .qoderwork .gemini .codex .github
.windsurf .augment .cline .amp .kiro .trae .openclaw .hermes这份列表与 dws 的 AGENT_DIRS 保持一致,两个 skill 会落在同一批目录里。同名目录会被先删后拷(新版本文件变少时不留残余)。
相关环境变量:
| 变量 | 作用 |
|---|---|
| AGENT_SKILLS_DIR | 置位则只装到该目录,不再铺开 |
| ALIDOCS_SKIP_POSTINSTALL | 置位则跳过 postinstall 自动安装 |
| CI | 置位则跳过 postinstall 自动安装 |
用法
先体检:
alidocs-html doctor退出码:0 一切正常 / 127 未安装 dws / 4 未登录。
上传
alidocs-html upload ./report.html默认落在文档空间的「我的文档」。该空间的 workspaceId 每个用户不同,CLI 运行时通过 dws wiki space list --type myWikiSpace 自动解析,无需手动配置。HTML 保持原文件形态,不会被转成钉钉在线文档。
| 参数 | 说明 |
|---|---|
| --name <显示名> | 文件显示名,默认用原文件名 |
| --workspace <id> | 指定其它文档空间 / 知识库 |
| --space-id <id> | 改为上传到钉盘空间(⚠️ 钉盘节点不支持互联网公开) |
| --folder <id> | 父目录节点 ID |
| --mime-type <type> | 覆盖自动推断的 MIME 类型 |
输出里的 nodeId 是后续操作的入口。
为什么默认不是钉盘「我的文件」? 实测发现钉盘节点无法互联网公开,
publish会直接报「当前节点不支持互联网公开」。只有文档空间 / 知识库的节点可以公开。
互联网公开发布
⚠️ 公开后互联网上任何拿到链接的人都能访问。
⚠️ 多数组织把这个能力设成了管理员审批制。 此时
publish只是提交一条审批申请,而该申请无法通过 dws 撤销(unpublish会报「组织管理员已禁止互联网公开分享」),只能联系管理员。请把publish当成事实上不可撤销的操作。
alidocs-html publish <nodeId> --permission READER --yes
alidocs-html publish-status <nodeId>
alidocs-html unpublish <nodeId> --yes--permission 可选 READER(仅查看)/ DOWNLOADER(可查看下载,dws 默认)/ EDITOR(可编辑)。
不传 --yes 时会走 dws 自己的交互确认——这是有意保留的闸门,自动化场景才需要显式跳过。
退出码 0 不等于已公开。 只有 published: true 才是真公开,此时才会输出公开链接:
| 输出 | 含义 |
|---|---|
| 状态: 已公开到互联网 + 公开链接: ... | 已生效 |
| 状态: 申请已提交,等待组织管理员审批 | pendingApproval: true、published: false,链接尚不可用 |
| 状态: 未公开 | 未生效 |
未公开时 CLI 不会输出任何链接。dws 响应里的 docUrl 只是文件自身链接(未公开时同样返回),外部访问不了,不要当成公开链接。
分享到钉钉 IM
⚠️ 会真实发送消息。
# 发链接
alidocs-html share-im --group <openConversationId> --title "Q1 报告" --text "报告:<url>" --yes
# 直接发 HTML 文件
alidocs-html share-im --user <userId> --as-file ./report.html --yes--group / --user 二选一,--text / --as-file 二选一。找群 ID 用 dws chat search。
通用参数
| 参数 | 说明 |
|---|---|
| --dry-run | 预览将要执行的 dws 调用,不实际生效。未登录也能跑 |
| --json | 结构化输出 |
<nodeId> 处也可以直接传钉钉文件 URL。
已知限制
- 不支持「企业内公开」。 dws 目前没有「组织内可见」这种权限范围开关,
dws drive permission add/update只能按 userId 逐个授权协作者。需要全公司可见时,只能逐个授权或到钉钉客户端手动改分享范围。 - 钉盘节点不能互联网公开(见上)。需要公开就别用
--space-id。 - 互联网公开可能受管理员审批门槛约束,且申请提交后 dws 撤不回。这是钉钉侧的组织策略,本项目只能如实回显状态。
- 「我的文档」里的节点走
publish后是否也落到审批流,取决于你所在组织的策略,未在本仓库端到端验证过(为避免产生无法撤销的审批申请)。publish-status读操作已验证可用。 - HTML 上传后在钉钉客户端里的预览 / 渲染表现取决于钉钉对
text/html的处理,本项目不做干预。 nodeId/ 公开链接采用多候选键的宽容提取,因为钉盘与文档空间两条上传路径的响应结构不同(钉盘是result.fileId,文档空间是顶层nodeId)。万一取不到,命令会原样回显 dws 响应并提示人工确认。
开发
npm install # 装依赖
npm run build # tsc 编译到 dist/
npm test # 编译 + 跑单测
npm run smoke # 实跑 doctor零运行时依赖(用 node:util 的 parseArgs,测试用 node:test),devDependencies 只有 typescript 与 @types/node。
免登录冒烟:
node dist/src/cli.js upload test/fixtures/sample.html --dry-runLicense
MIT
