CLI 使用指南
HAiNA CLI 命令行工具:安装、认证、完整命令面、AI 友好的输出契约
CLI 使用指南
@hainaio/cli 是官方的命令行工具,把全部 API 能力收口成本地命令——认证存储、文件上传、限流退避、状态轮询都由 CLI 兜底,适合脚本集成与 AI agent 调用。
版本说明:本文档对应 CLI ≥ 1.5.1。命令树为
haina <平台码> <资源> <动作>——平台码tt= TikTok /tts= TikTok Shop(全称别名tiktok/tiktok-shop/shop等价),平台无关命令(seats/videos/images/webhooks/events 等)在顶层。1.4.x/1.5.0 的旧扁平命令已更名——敲旧名会得到精确的新写法指引(exit 1,零网络请求),新旧对照:publish tt=tt video publish、comments list=tt comment list、products query=tts product query。1.4.x 不升级则一切照旧。旧 flag 在新版均保留别名(如--share-id→--publish-id),旧脚本不炸。
素材在自家 OSS、想在 Cursor / Claude Code 里零安装直连?用 MCP Server 更合适(本地文件场景才需要 CLI 的
videos upload)。
版本与能力:以
haina --help输出为准(含videos upload即具备写能力)。
安装
npm install -g @hainaio/cli
# 或免安装直接跑
npx @hainaio/cli@latest version要求 Node.js ≥ 22。
认证
# 交互式保存凭据(写入 ~/.config/vidgate/config.json,权限 0600)
haina auth login --token vg_live_xxx
# 或用环境变量(CI / AI agent 推荐,不落盘)
export HAINA_API_TOKEN=vg_live_xxx # VIDGATE_API_TOKEN 为兼容别名(同设时 HAINA_ 优先)
haina auth status # 查看当前凭据(脱敏)与来源
haina auth logout # 清除本地凭据凭据优先级:--token 命令行参数 > 环境变量 > 配置文件。Token 在任何输出中都只显示前缀(脱敏)。网关地址同理:--base-url > HAINA_BASE_URL / VIDGATE_BASE_URL(兼容别名)> 配置文件 > 默认 https://cli.haina.io。
全局 flag(可前可后,haina --json seats list 与 haina seats list --json 等价):--json / --token / --base-url / --timeout <ms>。--help 仅命令词之前生效(haina --help)。
命令面
与 haina --help 输出一一对应。「读/写」列含义:写 = 套餐过期后被订阅守卫拒绝(1003)的操作;读 = 不受影响。
坐席与视频库
| 命令 | 读/写 | 说明 |
|---|---|---|
haina seats list | 读 | 坐席列表:slotNo/status/绑定账号(TT=businessId,TTS=creatorUserOpenId)/authStatus |
haina videos upload <file> | 写 | 上传视频。--library tt|tts(默认 tt)、--account-id(library=tts 时必填)。TTS 响应 videoUrl 恒为 null,以 code=0 判成功 |
haina videos list [--cursor <c>] [--limit <n>] [--library tt|tts] | 读 | 游标分页(nextCursor 为 null = 无下一页);--library 按库过滤;已软删的记录仍返回(status=expired,字段保留),勿以「列表消失」判断删除成功 |
haina videos get <id> | 读 | 视频库记录详情(已删记录同样返回,status=expired) |
haina videos delete <id> | 写 | 软删=立即失效:发布/预审立即拒绝(2005);记录仍留列表/详情(status=expired),属预期 |
haina images upload <file> | 写 | 上传图片素材(jpg/png/webp ≤20MB):返回已过 TikTok 域名验证的 imageUrl,作 tt video publish --cover-url(自定义封面)或图片帖 --photo-urls 供源。不落库无列表,响应即取即用 |
发布(TikTok / TikTok Shop / 图片帖)
| 命令 | 读/写 | 必填 | 可选 |
|---|---|---|---|
haina tt video publish | 写 | --video-url --account(username 或 businessId;--account-id 为兼容别名) | --caption --brand-organic --branded-content --disable-comment --disable-duet --disable-stitch --thumbnail-offset <ms>(视频内取帧封面)--cover-url <https 图>(自定义封面,与取帧互斥;images upload 拿已验证域名 URL)BGM:--music-id <songClipId>(其余音乐 flag 需配合它使用)--music-volume 0-100 --original-sound-volume 0-100(缺省平台补 50,显式 0=静音)--music-start/--music-end <ms> --wait --via direct|beervid(默认 direct 新版通道;beervid 为旧版通道不支持音乐参数,将要废弃,1.6.x 移除) |
haina tts video publish | 写 | --file-id --account-id --product-id --title(官方必填) | --product-title --cover-uri --cover-timestamp-ms --music-id(TikTok Shop 电商库,覆盖原声)--ai-generated --wait |
haina tt photo publish | 写 | --account --photo-urls <u,…> --privacy-level <档> | --title --caption --cover-index --auto-add-music --music-id <songClipId>(指定 CML 曲目)品牌双开关 --draft --disable-comment --location-id(随动 --location-name)--wait;仅新版提供,无 --via |
haina tt hashtag suggest --account <id> --keyword <kw> | 读 | account + keyword | --language(默认 en);caption 写作辅助 |
haina tt location search --account <id> --query <q> | 读 | account + query(≤100 字符) | 地域标签搜索;返回 locationId/locationName 配对用于发布入参 |
haina tt music trending --account <id> | 读 | account | CML 热门商用音乐选曲(发布 BGM 用)。--genre <官方枚举> --country(默认 US)--date-range 1DAY|7DAY|30DAY|90DAY(默认 7DAY);发布用 trendingSongClipId/fullSongClipId 列,不是 commercialMusicId |
haina tt music trending-videos --account <id> --commercial-music-id <id> | 读 | account + commercialMusicId | 曲目关联热门视频 Top 20(选曲参考);--country(默认 US) |
haina tt video publish-status --publish-id <id> | 读 | publishId(官方 publish_id = 发布响应的 shareId,不是发布记录 id——误传记录 id 会被本地拦截提示;--share-id 为兼容别名) | 命中发布记录即自动回写 |
haina tts video publish-status --video-id <id> | 读 | videoId(官方 video_id:tts video publish 响应的 videoId,或 records 里的 shareId 字段;勿用 records 的 videoId——那是平台库 ID,必 1005) | — |
haina publish records [--capability TT|TTS] [--page <n>] [--page-size <n>] | 读 | — | 只读快照,不刷新状态。字段口径:videoId=平台视频库 ID;shareId=官方句柄(TikTok 发布记录=share_id,TikTok Shop 记录=video_id,查 status 用它) |
haina publish stats <itemId> | 读 | itemId(=postId) | ⛔ 将要废弃(1.6.x 移除)——请改用 haina tt insight videos --account <id> --video-ids <postId>(与官方路由一致,字段更多)。postId 官方生成延迟约 3 分钟:刚发布成功查不到属预期 |
haina tts precheck submit | 写 | --file-id --account-id --product-id | --product-title --wait |
haina tts precheck query <taskId> | 读 | taskId | — |
商品与素材(TikTok Shop)
| 命令 | 读/写 | 说明 |
|---|---|---|
haina tts product query --account-id <id> [--type shop|showcase] [--page-token <t>] [--page-size <n>] [--fresh] | 读 | 可挂车商品;翻页只认 nextPageToken(勿按 totalCount 推算页数),两组游标各自独立(见 TikTok Shop 挂车全流程) |
haina tts photo upload <file> --account-id <id> | 写 | 上传 TikTok Shop 封面图,返回 photoUri(发布时作 coverUri) |
haina tts music search --account-id <id> --keyword <kw> | 读 | 电商授权音乐搜索。--page-token --search-id(第 2 页起必带)--page-size(≤50)--region --language。官方分页怪癖:token=数值 offset、searchId 逐次变化、小 page-size 首调可能空页(带返回 token 再查即有) |
评论管理(TikTok)
| 命令 | 读/写 | 说明 |
|---|---|---|
haina tt comment list --account <id> --video-id <postId> | 读 | 评论列表(--cursor --status PUBLIC|ALL;videoId 是官方数字 postId,非视频库 uuid) |
haina tt comment replies --account <id> --video-id <postId> --comment-id <id> | 读 | 评论的回复列表(已隐藏评论不可拉) |
haina tt comment create --account <id> --video-id <postId> --text <t> | 写 | 发顶层评论 |
haina tt comment reply --account <id> --video-id <postId> --comment-id <id> --text <t> | 写 | 回复评论 |
haina tt comment like --account <id> --comment-id <id> --action LIKE|UNLIKE | 写 | 点赞/取消(幂等) |
haina tt comment hide --account <id> --video-id <postId> --comment-id <id> --action HIDE|UNHIDE | 写 | 隐藏/恢复(UNHIDE 不保证生效,见评论规则) |
haina tt comment delete --account <id> --comment-id <id> | 写 | 删除评论(仅限自己账号发出的) |
私信与自动消息(TikTok)
| 命令 | 读/写 | 说明 |
|---|---|---|
haina tt message conversations --account <id> --type SINGLE|STRANGER [--limit <n>] [--cursor <c>] | 读 | 私信会话列表(--type 必填;--account 为 username 或 businessId) |
haina tt message list --account <id> --conversation-id <id> | 读 | 会话消息列表(官方固定最近 20 条,无分页) |
haina tt message send --account <id> --conversation-id <id> | 写 | 发送私信,内容形态恰选其一:--text(可配 --reply-to)/ --image-file / --share-post / --qa-card / --typing / --mark-read。前置:坐席账号在 TikTok App 开启「接收所有人私信」 |
haina tt message upload-image --account <id> --file <f> | 写 | 上传私信图片拿 mediaId(≤3MB JPG/PNG,30 天有效) |
haina tt message download --account <id> --conversation-id <id> --message-id <id> --media-id <id> | 读 | 取媒体下载地址(24h 有效) |
haina tt message capabilities --account <id> --conversation-id <id> --type SINGLE|STRANGER | 读 | 会话能力自检(发图前查 IMAGE_SEND) |
haina tt message auto get --account <id> --type <类型> [--id <mid>] | 读 | 自动消息查询(含整类开关与审核状态) |
haina tt message auto create / update / delete | 写 | 自动消息增改删(welcome 带 --content;suggested 带 --question --answer;chat_prompt 带 --title --content;update/delete 另带 --id <mid>;欢迎语不可删) |
haina tt message auto sort --account <id> --ids id1,id2,… | 写 | CHAT_PROMPT 排序(按展示顺序给全部条目 id) |
haina tt message auto status --account <id> --type <类型> --action ENABLE|DISABLE | 写 | 自动消息整类开关 |
类型枚举:WELCOME_MESSAGE(≤1 条)/ SUGGESTED_QUESTION(≤3 条)/ CHAT_PROMPT(≤6 条)。审核状态机见私信规则。
数据洞察(TikTok)
| 命令 | 读/写 | 说明 |
|---|---|---|
haina tt insight account --account <id> [--fields a,b] [--start-date <d> --end-date <d>] | 读 | 账号数据概览(给日期范围才回 metrics 时间序列) |
haina tt insight videos --account <id> [--cursor <c>] [--max-count ≤20] [--fields a,b] [--video-ids id,…] | 读 | 视频列表指标(官方原样字段透传;max_count 官方上限 20)。TikTok / TikTok Shop 视频通用:TikTok Shop 挂车视频也在账号视频列表里(拉列表按标题/时间定位) |
haina tt insight benchmark --account <id> --category <类目> | 读 | 行业基准(官方 25 类目枚举,如 BEAUTY) |
haina tt insight video-settings --account <id> | 读 | 发布隐私档位/最大时长查询(发布前自检) |
事件推送(webhook / listen)
| 命令 | 读/写 | 说明 |
|---|---|---|
haina webhooks list | 读 | webhook 端点列表 |
haina webhooks create --url <https> [--events <t,…>] | 写 | 创建端点(secret 仅此一次返回,立即保存) |
haina webhooks delete <id> | 写 | 删除端点 |
haina events list [--type <t>] [--cursor <c>] [--limit <n>] | 读 | 事件流拉取(push 兜底对账) |
haina events redeliver <id> [--endpoint-id <e>] | 写 | 事件重投(Stripe 式 resend) |
haina listen [--events <t,…>] [--forward-to <url>] | 长连 | SSE 本地监听(无需公网地址;断线自动重连 + Last-Event-ID 续传),详见事件推送指南 |
本地命令(不访问网关)
| 命令 | 说明 |
|---|---|
haina version | 打印 CLI 版本 |
haina auth login / status / logout | 凭据管理(见上文「认证」) |
haina skill install [--global] [--agent <name>...] [--yes] | 把 Agent Skill 装进本机 AI agent(见 Agent Skill);不消耗配额。默认项目级(按已存在的 agent 目录探测:.claude/.agents/…,全无则兜底 .agents/skills/haina-cli);--global 装用户级;--agent 可选 claude-code / opencode / codex / cursor / universal(可多个);目标已存在时 TTY 询问、--yes/非 TTY 直接覆盖。使用自有 skills 目录的 agent(如 Hermes ~/.hermes/skills)需安装后手动同步/软链 |
--wait 轮询(publish / precheck submit)
- 默认关;
--wait开启后轮询到终态:5s 起步 + 抖动,10 分钟封顶(--timeout覆盖)。 - 发布终态:
publish_complete/publish_failed/beervid_error;预审终态:passed/failed。 - 退出码:成功终态 → 0;失败终态 → 3(业务失败);等待超时 → 1。
- JSON 模式下 stdout 只有终态一份 envelope(
json.load(stdout)可直接解析);提交回执的完整 JSON 走 stderr,信息不丢。TTY 模式提交回执照常显示。注意:用2>&1或工具把 stderr 合并进 stdout 捕获时会看到两份 JSON(提交回执 + 终态)——这不是 stdout 出了两份,是合并捕获把 stderr 卷进来了;脚本消费请只接 stdout。
AI 友好的输出契约
--json:恒输出服务端 envelope 原文 JSON(成功失败都走 stdout);非 TTY 环境(管道/AI 调用)自动启用,无需显式声明- 注意边界:
--json契约只覆盖服务端响应——本地参数校验错误(缺必填/非法值/文件不存在,退出码 1)不发请求,输出人类可读文本到 stderr,不是 envelope - 限流自动退避:遇到 429 按
Retry-After等待重试(至多 3 次) - 退出码语义化,不看输出也能定处置策略:
| 退出码 | 含义 |
|---|---|
| 0 | 成功 |
| 1 | 本地错误(参数缺失/配置问题) |
| 2 | 认证/权限(1001/1002/1003) |
| 3 | 业务拒绝(1004-1008/2001/2005) |
| 4 | 限流/配额(2002) |
| 5 | 平台官方错误(3001/3002) |
| 6 | 内部错误/网络故障 |