联犀 SaaS + IoT 平台命令行工具 — 为 AI Agent 原生设计,让人类和 AI Agent 都能在终端中操作联犀平台。统一单一入口 ur,通过 --app 参数切换应用上下文,覆盖平台管理、物联网、组织管理、能源管理等核心业务域,提供 AI Agent Skills。
安装 · Agent Skills · 认证 · 命令 · 进阶用法
仓库说明:本项目已从 monorepo(
backend/cli/ur)迁移为独立仓库。
- 独立仓库地址:
https://gitee.com/unitedrhino/cli/https://github.com/unitedrhino/cli- 原 monorepo 中的
backend/cli/ur已废弃,不再维护
- 为 Agent 原生设计 —
generate-skills一键生成结构化 Skill 文档,AI Agent 无需额外适配即可调用联犀 API - 统一入口 — 单个
ur二进制,通过--app参数或UR_APP环境变量切换 5 大应用域 - AI 友好认证 — 先复用 Sandbox 环境或历史 profile,必要时再选择 Device Flow、账号密码或 AK/SK
- 全覆盖 — 平台管理、物联网、组织管理、能源管理、控制台 5 大应用域,Swagger 全量 API 自动解析
- 跨平台 — 支持 Linux/macOS/Windows 等主流平台(amd64 / arm64)
- 安全可控 — Sandbox 凭据不落盘,敏感值支持环境变量或 stdin,输出默认脱敏
| 应用 | --app 值 |
覆盖域 | 典型能力 |
|---|---|---|---|
| 平台管理 | platform-manage |
企业、用户、应用、角色、权限 | 企业 CRUD、用户管理、应用配置、授权分配 |
| 物联网 | iot |
设备、产品、项目、场景、OTA | 设备管理、物模型、项目场景、OTA 升级、协议网关 |
| 组织管理 | org-manage |
组织用户、AI 智能体 | 企业内用户/角色/Agent 管理 |
| 能源管理 | org-energy |
能耗分析、电力集抄、预付费 | 用能概况、实时监控、预付费充值 |
| 控制台 | console |
个人信息、访问令牌 | 个人资料、访问令牌管理 |
安装 CLI 后,运行 generate-skills 生成 AI Agent 可用的 Skill 文档:
# 为物联网应用生成 Skills
ur --app iot generate-skills --output ./skills/ur-iot生成的 Skill 可直接被 AI Agent 加载,实现零配置调用联犀 API。
| Skill | 说明 |
|---|---|
ur-api |
通用 API 调用指南、认证方式、角色权限说明(所有 Skill 的基础) |
ur-device |
设备管理 — 设备 CRUD、属性控制、设备分享、物模型 |
ur-device-analytics |
设备数据分析 — 属性历史查询、趋势分析、聚合统计、报表生成(物模型驱动) |
ur-device-debug |
设备调试 — 日志查询(属性/事件/命令/上下线/异常/诊断/SDK)、实时调试(属性控制/行为调用/事件发送) |
device-firmware |
设备固件 — 从产品/物模型初始化到配网、MQTT 双向通信、首刷、排障、OTA 与实机验收 |
ur-ota |
OTA 平台管理 — 固件上传登记、模块、定向/批量任务和升级结果核验 |
ur-product |
产品管理 — 产品定义、物模型、品类管理 |
ur-project |
项目管理 — 项目 CRUD、区域管理、场景编辑 |
ur-system |
系统管理 — 用户管理、角色权限、菜单资源、字典配置 |
ur-tenant |
企业管理 — 企业 CRUD、应用绑定、配额管理 |
ur-user |
用户管理 — 个人信息、企业成员、邀请码 |
ur-ai |
AI 管理 — Agent 配置、告警管理 |
scene-linkage |
场景联动 — 规则模板生成与 JSON 校验(if/when/then) |
thing-model |
物模型 — 模板生成、JSON 校验、affordance 定义 |
protocol-script |
协议脚本 — yaegi 脚本模板、Go 代码校验 |
CLI 使用同一份 ur-api 为所有 AI 客户端提供三种分发方式:已知客户端自动探测、任意本机目录登记,以及标准 ZIP 导出。自动探测当前覆盖 Claude Code、Codex 和 WorkBuddy / CodeBuddy;没有固定本机目录的平台可直接导入 ZIP。
# 查看自动发现与已登记目标
ur skills target detect
ur skills target list
# 登记任意支持本地 SKILL.md 的客户端目录
ur skills target add workbuddy --dir ~/.codebuddy/skills
ur skills target add another-ai --dir /path/to/client/skills
# 部署并检查所有目标;重复部署会原子覆盖旧 ur-api,保留其他技能
ur skills install --all
ur skills status
# 导出标准 ZIP,供扣子等支持技能包上传的平台导入
ur skills export
ur skills export --output ~/Downloads
# 下载最新 release 的 skills 包并解压(适合离线或由 AI 自行复制)
ur skills download
ur skills download --output ~/skills-pkg
ur skills download --url "https://example.com/ur-api-skills-v0.4.1.zip"
# JSON 输出(AI 解析 localPath 后自行拷贝)
ur skills download --json--json 输出示例:
{"event":"skills_downloaded","downloadUrl":"https://github.com/unitedrhino/cli/releases/download/v0.4.1/ur-api-skills-v0.4.1.zip","localPath":"/home/user/.ur/downloads/ur-api","installHint":"请将上述 ur-api 目录整体拷贝到你所用 AI 工具的 skills 目录下(各 AI 工具的 skills 目录由 AI 自行确认,例如 Claude Code 为 ~/.claude/skills/),拷贝后重启 AI 工具生效"}目标配置保存在 ~/.ur/skill-targets.json。自动化环境也可用系统路径分隔符设置多个目录:UR_SKILLS_DIRS=/path/a:/path/b。WorkBuddy / CodeBuddy 的自定义配置目录通过 CODEBUDDY_CONFIG_DIR 自动识别。
项目级目标取决于命令执行位置:CLI 会从当前工作目录向上查找 Git 仓库根,并识别其中已经存在的 .claude/skills、.agents/skills、.codebuddy/skills。运行 install --all 前先用 ur skills target detect 核对目标;如果只想写入明确目录,使用 ur skills install --dir <目录>,该次不会写入其他自动识别或已登记目标。
- 操作系统:Linux / macOS / Windows 等
- Go:1.23+(仅从源码构建时需要)
- 网络:可访问联犀 SaaS API 服务器
AI Assistant 注意:如果你是 AI Agent 且正在协助用户执行安装,请直接跳转到快速开始(AI Agent)。
方式一 — 下载预编译二进制(推荐):
# 1. 确定平台(注意使用 release 资产中的友好平台名)
PLATFORM="Linux-x86_64" # Linux-x86_64 / Linux-aarch64 / macOS-x86_64 / macOS-arm64 / Windows-x86_64
VERSION="v0.4.1"
# 2. 下载
wget "https://github.com/unitedrhino/cli/releases/download/${VERSION}/ur-cli-${VERSION}-${PLATFORM}.tar.gz"
# 3. 解压完整发布包(包内结构为 <goos>-<goarch>/{ur, skill/})
# ur 二进制必须与 skill/ 目录保持同级,否则 ur skills 相关命令找不到内置 skills
mkdir -p ~/.local/lib/ur
tar -xzf "ur-cli-${VERSION}-${PLATFORM}.tar.gz" -C ~/.local/lib/ur --strip-components=1
# 4. 把 ur 暴露到 PATH(软链不影响 skill/ 的查找)
mkdir -p ~/.local/bin && ln -sf ~/.local/lib/ur/ur ~/.local/bin/ur
# Windows: 下载 .zip 包并完整解压,保持 ur.exe 与 skill/ 目录同级,
# 再将 ur.exe 所在目录加入系统 PATH方式二 — 从源码构建:
git clone https://github.com/unitedrhino/cli.git
cd cli
go build -ldflags "-X main.version=$(git describe --tags)" -o dist/bin/ur .# 检查是否有新版本,不安装
ur upgrade --check --json
# 升级到最新版本,同时刷新内置 Skills 及自动发现、已登记客户端中的副本
ur upgrade
# 即使已是最新版也重新安装;适合恢复缺失的发布资源
ur upgrade --force
# 仅升级 CLI,不写入客户端 Skills 目录
ur upgrade --no-skills
# 手动把内置 ur-api skill 部署到本机各 AI 工具的 skills 目录
# (ur-api 是一个统一 skill,整体部署,不拆分;部署后重启对应 AI 会话即可发现)
ur skills install
ur skills install --dry-run # 预览目标,不实际写入
ur skills install --json # JSON 输出
ur skills install --dir <path> # 指定自定义目标目录(支持 ~ 路径展开)
ur skills target add <name> --dir <path> # 长期登记任意客户端目录
ur skills status # 核对版本和文件完整性
ur skills export # 导出标准 ZIP 到 ~/.ur/exports/
# 仅下载 skills 包到本地(不部署):AI 自助下载后自行拷贝到所用 AI 工具的 skills 目录,
# 对所有 AI 工具通用;详见「Agent Skills」章节
ur skills download
ur skills download --output ~/skills-pkg # 指定下载目录(支持 ~ 路径展开)
ur skills download --url <zip地址> # 直接指定 skills zip 地址(私有化/离线场景)
# 完全跳过自动版本检查
export UR_NO_UPDATE_CHECK=1
# 保留缓存刷新,仅隐藏 CLI 或 Skills 提示
export UR_NO_UPDATE_NOTIFIER=1
export UR_NO_SKILLS_NOTIFIER=1业务命令启动时会先读取 ~/.ur/update-state.json,因此短命令也能稳定返回已缓存的升级信息;缓存超过 24 小时后再异步刷新 Gitee/GitHub Release。显式 JSON 输出会在原对象顶层增加 _notice.update 或 _notice.skills,已有 code、msg、data 字段保持不变:
{
"code": 200,
"data": {},
"_notice": {
"update": {
"current": "v0.6.1",
"latest": "v0.6.2",
"command": "ur upgrade"
}
}
}AI 应先完成当前请求,再根据 _notice 简短说明升级;不要把提示原样当作业务结果。ur upgrade --install-skills 作为兼容参数继续可用,但从 v0.6.2 起 ur upgrade 默认已经同步客户端 Skills。
# 1. 先检查现有环境或历史 profile;成功时无需重新登录
ur check --json
# 仅在缺少认证时,选择一种登录方式(默认 device)
ur login --method device
# UR_PASSWORD='<原始密码>' ur login --method password --account '<账号>' --tenant-code '<企业编码>' --json
# UR_ACCESS_SECRET='<AccessSecret>' ur login --method aksk --access-key '<AccessKey>' --tenant-code '<企业编码>' --json
# 2. 验证认证状态
ur check
# 3. 开始使用(默认 org-manage 应用上下文)
ur api /api/v1/system/user/self/get-one
# 4. 切换应用上下文调用 IoT API
ur --app iot api /api/v1/things/device/info/get-list \
--body '{"page":{"page":1,"size":10}}'
# 5. 生成 AI Agent Skills(可选,推荐)
ur generate-skills --output ./my-skills/AI Agent 应先复用 Sandbox 环境或历史 profile;只有缺少认证时才启动新的登录流程。不要在对话中回显敏感值。
一键安装 + 认证(AI 自动执行)
# 1. 下载(推荐:版本无关永久直链,总是最新版,免查版本号)
# 平台名: Linux-x86_64 / Linux-aarch64 / macOS-x86_64 / macOS-arm64 / Windows-x86_64
curl -L "https://github.com/unitedrhino/cli/releases/latest/download/ur-cli-Linux-x86_64.tar.gz" -o /tmp/ur-cli.tar.gz
# 国内直连 GitHub 慢时,用 Gitee 指定版本(Gitee 无 latest 直链,版本号见 https://gitee.com/unitedrhino/cli/releases):
# curl -L "https://gitee.com/unitedrhino/cli/releases/download/v0.7.0/ur-cli-v0.7.0-Linux-x86_64.tar.gz" -o /tmp/ur-cli.tar.gz
# 需要钉住历史版本时: https://github.com/unitedrhino/cli/releases/download/${VERSION}/ur-cli-${VERSION}-${PLATFORM}.tar.gz
mkdir -p ~/.local/lib/ur && tar -xzf /tmp/ur-cli.tar.gz -C ~/.local/lib/ur --strip-components=1
mkdir -p ~/.local/bin && ln -sf ~/.local/lib/ur/ur ~/.local/bin/ur
# Windows (PowerShell):完整解压 .zip 包,保持 ur.exe 与 skill/ 同级,再把所在目录加入 PATH
# Invoke-WebRequest -Uri "https://github.com/unitedrhino/cli/releases/download/${VERSION}/ur-cli-${VERSION}-${PLATFORM}.zip" -OutFile "ur.zip"; Expand-Archive "ur.zip" -DestinationPath "$env:USERPROFILE\.local\lib\ur"
# 2. 先检查 Sandbox 环境或历史 profile
ur check --json
# 仅当 check 返回缺少认证时,才启动默认 Device Flow
ur login --method device --no-wait --json输出示例:
{
"status": "authorization_required",
"verification_url": "https://saas.unitedrhino.com/#/user/settings?tab=access-tokens&setup=ABC123&redirect=thirdparty",
"setup_code": "ABC123",
"expires_in": 600
}AI 解析 JSON,向用户发送:
请在浏览器中打开链接完成 CLI 授权:https://saas.unitedrhino.com/#/user/settings?tab=access-tokens&setup=ABC123&redirect=thirdparty
用户确认在浏览器中点击「完成第三方客户端绑定」后,AI 自动执行:
ur login --method device --setup-code ABC123 --json输出示例:
{
"event": "authorization_complete",
"status": "ok",
"method": "device",
"tenant_code": "t1",
"access_key": "ak_xxxx"
}如果 Sandbox 已注入账号密码或 AK/SK,可直接使用非交互方式;密码必须是原始密码,AK/SK 不要求 userID:
UR_PASSWORD='<原始密码>' ur login --method password \
--account '<账号>' --tenant-code '<企业编码>' --json
UR_ACCESS_SECRET='<AccessSecret>' ur login --method aksk \
--access-key '<AccessKey>' --tenant-code '<企业编码>' --json验证并生成 Skills
ur check --json
ur generate-skills --output ./skills/ur CLI 支持三种登录方式,并兼容 Sandbox 环境变量与旧 profile:
| 命令/方式 | 说明 |
|---|---|
check --json |
首先验证当前环境/profile,并输出脱敏的 auth_source、auth_method |
login --method device |
Device Flow;未指定 --method 时的默认方式 |
login --method password |
原始账号密码立即换取 Session Token |
login --method aksk |
AK/SK 立即验证并保存;不要求 userID |
setup |
人类终端的账号密码兼容向导 |
token --decode |
查看并解码当前存储的访问令牌 |
# 总是先复用现有认证
ur check --json
# Agent 模式:分步授权
ur login --method device --no-wait --json # 第 1 步:获取 URL 和绑定码
ur login --method device --setup-code ABC123 # 第 2 步:用户确认后完成轮询
# 账号密码(推荐环境变量或 --password-stdin;不要预先 SHA-256)
UR_PASSWORD='<原始密码>' ur login --method password \
--account '<账号>' --tenant-code '<企业编码>' --json
# AK/SK(推荐环境变量或 --access-secret-stdin)
UR_ACCESS_SECRET='<AccessSecret>' ur login --method aksk \
--access-key '<AccessKey>' --tenant-code '<企业编码>' --json
# 验证
ur check --json
# 查看当前 token
ur token --decodeur --version # 查看 CLI 版本
ur --app iot <command> # 切换应用上下文(iot / platform-manage / org-manage / org-energy / console)
UR_APP=iot ur <command> # 通过环境变量切换# 基本调用
ur api /api/v1/things/device/info/get-list --body '{"page":{"page":1,"size":10}}'
# 输出格式控制
ur api ... --format yaml # json(默认)/ raw / yaml
ur api ... --transform data.list.0.name # GJSON 路径提取
ur api ... --output result.json # 保存到文件
ur api ... --debug # HTTP 请求/响应详情(敏感头脱敏)
ur api ... --fields code,data.total # 字段筛选
ur api ... --summarize # 摘要模式(列表只保留前 5 条)
# 自定义请求头
ur api ... -H "X-Custom-Header: value"
# 项目上下文(标识始终作为字符串传输,不转换成数值)
ur api ... --project-id "9007199254740993"
UR_PROJECT_ID="9007199254740993" ur api ...
# 从文件读取 body
ur api ... --body-file /tmp/payload.json项目选择规则:--project-id 或显式 --header project-id:... 优先于
UR_PROJECT_ID;同时提供参数和项目头时必须一致,否则发送前报错。
未指定任何项目上下文时不注入项目头。显式空项目参数会报错,不回退到环境值。
此上下文仅设置 HTTP project-id 请求头,不改写请求体,也不代替服务端项目权限校验。
ur model template property --json # 生成属性模板
ur model template event --yaml # 生成事件模板
ur model template action --json # 生成行为模板
ur model template full --yaml # 生成完整物模型模板
ur model validate /tmp/model.json # 校验物模型 JSON
ur model generate-script model.json --mode property --output script.gour scene template auto # 自动触发场景模板
ur scene template manual # 手动触发场景模板
ur scene validate /tmp/scene.json # 校验场景联动 JSONur script template up-before # 上行前处理模板
ur script template up-after # 上行后处理模板
ur script template down-before # 下行前处理模板
ur script template down-after # 下行后处理模板
ur script validate /tmp/script.go # 校验协议脚本ur schema # 查看 API schema
ur schema --json # JSON 格式输出
ur schema --auth-type admin # 按权限过滤
ur schema /api/v1/things/device/info/create # 查看指定接口
ur completion bash >> ~/.bashrc # bash 补全
ur completion zsh >> ~/.zshrc # zsh 补全
ur completion fish > ~/.config/fish/completions/ur.fishur setup # 人类终端账号密码兼容向导
ur config --list # 列出所有配置
ur config --use prod # 切换配置
ur check --json # 验证配置、认证来源和连通性# 方式一:--app 参数
ur --app iot api /api/v1/things/device/info/get-list
ur --app platform-manage api /api/v1/system/tenant/info/get-list
# 方式二:UR_APP 环境变量
UR_APP=iot ur api /api/v1/things/device/info/get-list
# 方式三:Sandbox env-only(使用占位符,不读取磁盘 profile 补值)
UR_BASE_URL='<平台地址>' UR_APP_ID='<应用ID>' \
UR_TENANT_CODE='<企业编码>' UR_TOKEN='<Session Token>' ur check --json# 为当前应用生成所有 Skill 文档
ur --app iot generate-skills
# 输出到指定目录
ur generate-skills --output ./my-skills/生成的 Skill 文档可直接用于 AI Agent 调用联犀 API。
无需配置文件,直接通过环境变量认证。设置 UR_BASE_URL 后进入 env-only 模式,不读取或改写磁盘 profile;认证组必须完整:
export UR_BASE_URL='<平台地址>'
export UR_APP_ID='<应用ID>'
export UR_TENANT_CODE='<企业编码>'
# 以下三组任选一组,优先级为 Token → AK/SK →账号密码
export UR_TOKEN='<Session Token>'
# export UR_ACCESS_KEY='<AccessKey>' UR_ACCESS_SECRET='<AccessSecret>'
# export UR_ACCOUNT='<账号>' UR_PASSWORD='<原始密码>'
ur check --json
ur api /api/v1/things/device/info/get-listAK/SK 模式的 UR_USER_ID 可选。旧 ~/.ur/config.json 中只有账号密码,或同时遗留 Token、AK/SK 的配置会自动兼容;升级时无需迁移、清空或重新执行 setup。
.
├── main.go # CLI 入口
├── cmd/
│ ├── shared/ # 共享命令逻辑(api / check / schema / login / setup / completion / model / scene / script / generate-skills)
│ └── ur/ # 统一入口(--app 参数解析)
├── internal/
│ ├── config/ # CLIApp 类型 + Profile 配置
│ ├── auth/ # Device Flow 认证逻辑 + Token 自动刷新
│ ├── client/ # HTTP 客户端(自动重试 + Debug 日志)
│ ├── response/ # 输出格式化(json / raw / yaml + GJSON 提取)
│ └── swagger/ # Swagger 解析
├── skill/ # 预生成的 Skill 文档(供 AI Agent 使用)
├── shell/
│ ├── push.sh # 推送当前分支到 origin + gitee
│ ├── pushm.sh # 强制推送当前分支到两个远程
│ └── tag.sh # 打标签并推送到两个远程
├── scripts/
│ ├── release.sh # 跨平台 Release 构建与发布(封装脚本)
│ ├── generate-api-lists.py # 从 swagger 自动生成 skill API 端点列表
│ └── update-skills.sh # 一键更新 skill 并同步到 skills 仓库
├── skill/ # 预生成的 Skill 文档(供 AI Agent 使用)
├── SKILL_MAINTENANCE.md # Skill 混合维护模式文档(手写骨架 + 自动生成端点)
└── references/ # 参考文档
# 运行测试
go test ./...
# 单独测试某个包
go test ./internal/auth/...
# 查看测试覆盖率
go test -cover ./...需要 GitHub 和 Gitee 的 API token,写入项目根目录的 .env 文件(已被 .gitignore 忽略,不会提交):
# .env 文件内容
GITHUB_TOKEN="ghp_xxxxxxxx" # GitHub Personal Access Token(需要 repo 权限)
GITEE_TOKEN="xxxxxxxx" # Gitee 私人令牌
# 可选:设为 all 时尝试向 Gitee 上传全平台资产;默认 common
GITEE_RELEASE_ASSET_MODE="common"release.sh 启动时会自动加载 .env,无需手动 export。
# 语法:bash scripts/release.sh <版本号>
bash scripts/release.sh v0.3.7脚本会自动完成:
- 构建 39 个平台的二进制(Linux/macOS/Windows/FreeBSD/OpenBSD/NetBSD/Plan9/Solaris/Illumos/DragonFly/AIX × amd64/arm64/386/arm/mips/riscv64 等)
- 复制 skill 资源到每个平台的发布目录,写入版本元数据
_meta.json - 打包 tar.gz(Unix)或 zip(Windows)
- 生成 SHA256 校验和文件
sha256sums.txt - 创建 GitHub Release 并上传所有资产
- 创建 Gitee Release,默认上传校验文件、Skills 包和 Linux x86_64 常用包;完整跨平台资产由 GitHub Release 提供
上传使用超时和 HTTP 状态检查,任一资产失败都会明确报错。认证信息通过文件描述符或标准输入传给 curl,不会出现在进程参数中。
如果只需要发布单个平台,可手动运行对应步骤:
# 临时设置 token
export GITHUB_TOKEN="ghp_xxxxxxxx"
export GITEE_TOKEN="xxxxxxxx"
# 仅构建和发布
bash scripts/release.sh v0.3.7A: 可以。先运行 ur check --json;CLI 会复用历史 profile,Token 过期时用保存的原始账号密码刷新,不要求重新执行 setup。
A: 设置 UR_BASE_URL 后不会从 profile 补值。请同时注入 UR_APP_ID、UR_TENANT_CODE,以及 Token、完整 AK/SK、完整账号密码三组之一。
A: 使用 --auth-type 参数切换权限类型,例如 --auth-type admin。
A: 使用 --app 参数:ur --app iot api ...,或通过 UR_APP 环境变量设置。
A: 历史 profile 有账号密码时 CLI 会自动刷新;否则按现有凭据选择 ur login --method device|password|aksk。