Luna CLI 是 Luna DevOps 的命令行客户端,面向终端用户和自动化 Agent。命令采用固定的两级结构:
luna <工具分类> <具体工具> key=value
英文说明见上方链接。
CLI 目前处于预发布阶段。源码清单使用 0.0.0-development 占位版本和 private: true 防误发布,实际版本由 v* tag 在发布时注入。仓库中已经实现:
- 单一活动实例、账号凭据和默认项目空间的配置模型与本地存储;
- 默认使用 OAuth Device Code 登录、自动刷新与尽力吊销,并支持显式的个人访问令牌备用登录;
key=value、JSON、文件和标准输入参数解析;- 人类可读输出与稳定 JSON Envelope;
- 本地命令注册、帮助目录、Shell Completion 和 OpenAPI 命令注册器;
- 从 OpenAPI 生成并注册普通业务 HTTP 命令,并为特殊传输提供显式协议命令;
- 面向人类的
login、logout、whoami、doctor顶层短命令; - 检查当前登录、认证、服务端版本、OpenAPI 契约和能力开关的
health doctor诊断; - 在每个 OpenAPI 业务命令前自动协商 API 代际和最低 CLI 版本,并记录精确契约摘要供诊断;
- npm 包、Linux/macOS Bun 独立二进制的 CI、打包、安装 smoke 与发布门禁。
src/entry.ts 已作为 npm 与 Bun 二进制的统一入口,共享契约和客户端会被安全打包进发布产物。预发布版本已经发布到 npm,且发布产物会经过 npm/pnpm 全局安装、中文帮助、机器 Help 和受支持独立二进制的 smoke。
普通 OpenAPI 业务命令会自动读取 /api/v1/meta,在 API 代际不受支持或 CLI
低于服务端最低版本时 fail closed。精确 OpenAPI 摘要不同通常表示服务端新增了接口
或更新了契约,不会阻断同一 API 代际的已有命令;luna doctor 会将其作为诊断警告。
标记为 hidden 的浏览器回调、
Webhook、内部接收器和底层协议操作不会注册为 canonical raw command,SSE、
下载和终端等能力只通过对应的专用协议命令提供。high 和 critical 风险操作
在交互终端中必须逐次明确确认;非交互或 Agent 模式必须显式传入 --yes,
否则以稳定的 confirmation_required 错误拒绝。CLI 的确认只表示调用意图,
后端权限与 Step-up MFA 仍是最终安全裁决。通用 api request 仅保留为
人类诊断逃生口,不参与业务能力伪装。终端要求 CLI OAuth 登录与对应 purpose
的有效 Step-up;个人访问令牌不能满足或绕过这一协议授权。
CLI 会话权限在每次请求时按当前用户的平台角色、项目空间成员关系和资源策略由服务端
裁决,不在本地复制授权结论。个人访问令牌、第三方 OAuth 应用和 Agent 服务身份仍由
服务端按 OpenAPI 声明的接口 Scope 限权。
本地存储的 OAuth 凭据会在 Access Token 到期前 30 秒或已经过期时,
由 auth status 和远程命令自动刷新;多个 CLI 进程会合并同一轮刷新,
避免重复旋转 Refresh Token。luna auth refresh 仅用于强制手动刷新或
认证诊断,日常使用无需执行。LUNA_TOKEN 和个人访问令牌不参与 OAuth
刷新。若 Grant 已失效,或刷新请求已发出但结果无法安全确认,CLI 会返回
oauth_refresh_reauthentication_required 并禁止再次使用旧 Refresh Token;
此时需要重新执行 luna login。原始分类只作为安全的 details.causeCode 诊断信息。
覆盖数量与比例不在本文维护,以 pnpm check:platform-cli-coverage 的实时输出为准。
可以通过 npm 或 pnpm 安装预发布通道:
npm install --global @liteyuki/luna-cli@beta
pnpm add --global @liteyuki/luna-cli@beta也可以从 GitHub Release 下载独立二进制。稳定版当前只计划发布经过目标环境 smoke test 的 Linux glibc 制品;macOS 在接入代码签名与公证之前,只会在预发布版本提供名称带 -unsigned 的测试制品。Windows 与 Alpine/musl 请使用 npm 或 pnpm 安装,并通过 Node.js 22.14.0 或更高版本运行。
CLI 自带面向人类的分层帮助,不需要先安装 AI Skills:
luna
luna --help
luna login
luna login server=https://devops.example.com
printf '%s' "$LUNA_TOKEN" | luna login mode=access-token token=@-
luna whoami
luna doctor
luna logout
luna project --help
luna project list --help这些顶层短命令只面向人类交互,分别复用 auth login、auth status、
health doctor 和 auth logout 的同一处理器。脚本与 AI 应使用 canonical
两级命令;严格 agent=true 模式会拒绝顶层别名,避免审计和机器契约出现两套路径。
直接运行 luna 且不传子命令时,会显示同一份本地化根帮助,不会执行远程操作。第一级列出分类和快速开始,第二级列出分类内工具,第三级显示接口、权限、风险、参数来源、必填项和示例。业务参数统一使用 key=value;JSON、文件或多行文本使用 key=@file.json 或 key=@-。
未指定 server 时,luna login 固定登录官方实例
https://devops.liteyuki.org。登录其他实例时必须显式传入
server=https://...;再次登录会覆盖本地现有的实例、凭据和默认项目空间。
CLI 不提供 context 切换机制,一个本地配置始终只表示一个活动登录。
projectId、applicationId 和 targetId 参数既接受稳定 ID,也接受逐层作用域内的精确不可变标识:项目标识符、应用标识符和部署阶段。稳定 ID 会直接使用;自然标识会通过受权限约束的精确查询解析为 ID,再进入确认和执行流程。CLI 不会用显示名称做模糊匹配。
releaseId 只表示 rel_... 格式的单次发布记录。Kubernetes 工作负载名称不是 Release ID;进入部署目标当前容器应使用 deployment exec。
使用 OAuth 登录后,可以把本地 TTY 直接连接到部署目标当前运行容器:
luna deployment exec projectId=xnn-api applicationId=postgres-api targetId=prod
luna deployment exec projectId=prj_111111111111111111111111 applicationId=app_222222222222222222222222 targetId=dplt_333333333333333333333333 container=api命令进入远端交互式 Shell,输入输出、ANSI 控制字节和窗口尺寸以二进制终端流传输;
执行 exit 或按 Ctrl-D 后结束远端会话并恢复本地终端。deployment terminal 是
同一命令的人工别名;release exec 只作为旧调用的兼容入口保留。该命令要求真实交互式 TTY、CLI OAuth 登录和平台端运行终端授权,
不能在 agent=true 模式下使用。
语言解析顺序为:--lang、LUNA_LANG、本地配置的 language、系统
LC_ALL / LC_MESSAGES / LANG、运行时语言,最后回退英文。例如:
LUNA_LANG=zh-CN luna --help
luna --lang zh-CN project list --help平台管理员可以通过稳定的 agent-observability 分类读取跨用户 Agent 运营数据。先动态发现当前 CLI 和服务端共同支持的命令,再读取目标命令的完整 Schema:
luna help catalog category=agent-observability limit=20 output=json interactive=false agent=true
luna help command path=agent-observability.overview output=json interactive=false agent=true建议按 overview → turns / tools → tool-calls / trace 逐步缩小范围。列表必须显式传入有界分页,时间范围仅支持 1h、6h、24h、7d、30d 和 1y。这些读操作要求平台管理员身份;数据源测试是人工管理员命令,严格 Agent 模式不会执行。
JSON 输出保留统一 Envelope、分页元数据、request ID 和 correlation ID。CLI 会在输出前移除原始 Trace blob、System Prompt 和受控 GenAI 内容;原始对话暂不是稳定 CLI 能力。
Luna CLI 从同一份命令注册表生成静态 Shell Completion,不会在每次按 Tab 时启动 CLI 或请求 Luna API。补全覆盖分类、命令与别名、key=value 参数、枚举值和全局选项;敏感参数只会提示空的 key,不读取凭据。
Zsh(macOS 默认 Shell):
mkdir -p ~/.zfunc
luna completion zsh output=table > ~/.zfunc/_luna
# 确保 ~/.zshrc 在 compinit 之前包含:fpath=(~/.zfunc $fpath)
exec zshBash:
mkdir -p ~/.local/share/bash-completion/completions
luna completion bash output=table > ~/.local/share/bash-completion/completions/lunaFish:
mkdir -p ~/.config/fish/completions
luna completion fish output=table > ~/.config/fish/completions/luna.fishPowerShell:
New-Item -ItemType Directory -Force (Split-Path $PROFILE) | Out-Null
$completionFile = Join-Path (Split-Path $PROFILE) 'luna-completion.ps1'
luna completion powershell output=table | Set-Content -Encoding utf8 $completionFile
# 仅需在 $PROFILE 中添加一次:. $completionFile升级 Luna CLI 后重新生成一次脚本,即可同步最新命令契约。output=json 仍保留给自动化消费结构化的 { shell, script } 数据。
npm 的 latest 与 beta 是独立更新通道。测试预发布版本时必须显式安装
@beta,普通的全局更新不会从稳定版自动切换到预发布版。
AI Skills 会在此基础上使用
luna help catalog ... output=json interactive=false agent=true 和
luna help command ... output=json interactive=false agent=true
获取稳定 JSON 契约。Skill 发起的每条命令都固定使用这三个参数,不依赖本地
默认输出或交互状态;CLI 本身不依赖 Skills。
Skills 与 CLI 使用相同版本并由同一个 v* GitHub Release 发布,安装时
必须选择与本地 CLI 完全相同版本的
luna-devops-<version>.skill。该文件内部按领域拆分 references/,由 Agent
根据任务按需加载,不需要分别安装多个 Skill。
详细说明:
数据卷列表、详情、创建、更新、删除、纳管和传输记录均使用服务端分页与权限判断:
luna volume list page=1 pageSize=20
luna volume get volumeId=pvol_example
luna volume create body=@volume.json idempotencyKey=volume-create-001
luna volume adopt displayName=shared clusterId=cluster_example claimName=shared-pvc ownershipMode=referenced idempotencyKey=volume-adopt-001
luna volume update volumeId=pvol_example revision=3 capacity=20Gi
luna volume delete volumeId=pvol_example revision=3 dataAction=delete --yes
luna volume-transfer list page=1 pageSize=20
luna volume-transfer get transferId=vtx_example
luna volume-transfer retry transferId=vtx_example idempotencyKey=volume-retry-001 --yes
luna volume-transfer cancel transferId=vtx_example --yes本地归档导入会先创建并校验不可变的私有暂存副本,再等待 Transfer 进入 ready,最后用单次
PUT 上传完整归档;导出会等待 Transfer 进入 ready,申请一次性票据后用单次 GET 下载
完整归档。两种传输都不支持断点续传:
luna volume import file=backup.tar.gz displayName=data clusterId=cluster_example capacity=10Gi storageClassName=standard idempotencyKey=volume-import-001
luna volume export volumeId=pvol_example destination=backup.tar.gz consistency=auto idempotencyKey=volume-export-001
luna volume export volumeId=pvol_block destination=block.raw.zst format=raw_zst consistency=snapshot idempotencyKey=volume-export-block-001
luna volume export transferId=vtx_example destination=backup.tar.gz导入暂存需要约等于归档大小的额外本地可用空间。副本完成校验后会在创建远端 Transfer 之前从
文件系统命名空间分离,只保留当前进程的只读句柄;成功或失败都会关闭句柄并释放空间。如果本地
文件系统无法安全完成该步骤,CLI 会在创建远端资源前停止。对于同一幂等键返回的 succeeded
Transfer,CLI 仅在方向、长度和 SHA-256 与当前暂存副本完全一致时收敛为成功;streaming 状态
不会重放单次 PUT。
CLI 不保存传输状态或一次性票据。导出使用目标目录内随机命名的私有事务目录暂存完整归档;在
支持 POSIX mode 的系统上,目录和文件分别限制为 0700 与 0600。校验长度、SHA-256 和文件
身份后才原子提交。若权威回读、Block manifest 或提交失败,错误中的 recoveryPath /
recoveryPaths 只列出再次验证过的私有恢复文件;无法确认身份的冲突路径列在
preservedUnknownPaths。CLI 不创建公共 <destination>.part,但会把它及 Block sidecar 的
.part 名称保留为冲突保护:既有或传输期间出现的文件即使传入 overwrite=true 也不会被删除或
覆盖。文件系统不能提供可靠文件身份或安全硬链接时,导出会在申请一次性票据前停止。
安全恢复还要求当前操作期间同一操作系统账号不移动或替换目标父目录;发生这类外部目录变更时,
CLI 会停止并把无法重新确认的路径报告为未知,而不会将其声称为可用恢复文件。
传输进度只在人类表格输出中显示,JSON/Agent 输出保持稳定且不包含进度文本。Block 卷的
raw_zst 导出会为 manifest 单独申请一次性票据,校验后将归档与同名
<archive>.manifest.json sidecar 一并提交;Filesystem 导出不会请求 sidecar。导入和导出需要
访问本地文件,因此不能在 Agent 模式中执行。
从仓库根目录执行:
pnpm install --frozen-lockfile
pnpm typecheck
pnpm lint
pnpm test
pnpm build
node --test scripts/cli/tests/*.test.mjs
node scripts/cli/verify-skills-sync.mjs需要和 Luna DevOps 本地联调时,可以把本仓库克隆到平台仓库中被忽略的
cli/ 目录:
cd /path/to/luna-devops
git clone git@github.com:LiteyukiStudio/luna-cli.git cli
cd cli
pnpm install
pnpm sync:openapi
LUNA_PLATFORM_ROOT=.. pnpm check:platform-coveragev* tag 只发布 Luna CLI 与同版本 Skill。Luna DevOps 平台在
LiteyukiStudio/luna-devops 仓库独立发版。