Skip to content

Repository files navigation

ur CLI

Go Version

联犀 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 已废弃,不再维护

为什么选 ur CLI?

  • 为 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 个人信息、访问令牌 个人资料、访问令牌管理

Agent Skills

安装 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 代码校验

Skills 多客户端分发

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)

安装 CLI

方式一 — 下载预编译二进制(推荐):

# 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 .

版本升级与 Skills

# 检查是否有新版本,不安装
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,已有 codemsgdata 字段保持不变:

{
  "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)

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_sourceauth_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 --decode

命令参考

全局选项

ur --version                    # 查看 CLI 版本
ur --app iot <command>          # 切换应用上下文(iot / platform-manage / org-manage / org-energy / console)
UR_APP=iot ur <command>         # 通过环境变量切换

API 调用

# 基本调用
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.go

场景联动命令

ur scene template auto                  # 自动触发场景模板
ur scene template manual               # 手动触发场景模板
ur scene validate /tmp/scene.json      # 校验场景联动 JSON

协议脚本命令

ur 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      # 校验协议脚本

Schema 与补全

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.fish

配置管理

ur 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

生成 Skills

# 为当前应用生成所有 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-list

AK/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

脚本会自动完成:

  1. 构建 39 个平台的二进制(Linux/macOS/Windows/FreeBSD/OpenBSD/NetBSD/Plan9/Solaris/Illumos/DragonFly/AIX × amd64/arm64/386/arm/mips/riscv64 等)
  2. 复制 skill 资源到每个平台的发布目录,写入版本元数据 _meta.json
  3. 打包 tar.gz(Unix)或 zip(Windows)
  4. 生成 SHA256 校验和文件 sha256sums.txt
  5. 创建 GitHub Release 并上传所有资产
  6. 创建 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.7

常见问题

Q: 升级后原账号密码配置还能使用吗?

A: 可以。先运行 ur check --json;CLI 会复用历史 profile,Token 过期时用保存的原始账号密码刷新,不要求重新执行 setup

Q: Sandbox 设置了环境变量但认证不可用?

A: 设置 UR_BASE_URL 后不会从 profile 补值。请同时注入 UR_APP_IDUR_TENANT_CODE,以及 Token、完整 AK/SK、完整账号密码三组之一。

Q: API 返回「权限不足」?

A: 使用 --auth-type 参数切换权限类型,例如 --auth-type admin

Q: 如何切换应用上下文?

A: 使用 --app 参数:ur --app iot api ...,或通过 UR_APP 环境变量设置。

Q: Token 过期了怎么办?

A: 历史 profile 有账号密码时 CLI 会自动刷新;否则按现有凭据选择 ur login --method device|password|aksk

About

联犀的cli 客户端,提供skills使用

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages