Skip to content

Repository files navigation

Luna CLI

English

Luna CLI 是 Luna DevOps 的命令行客户端,面向终端用户和自动化 Agent。命令采用固定的两级结构:

luna <工具分类> <具体工具> key=value

English documentation follows the Chinese section.

当前状态

CLI 目前处于预发布阶段。源码清单使用 0.0.0-development 占位版本和 private: true 防误发布,实际版本由 v* tag 在发布时注入。仓库中已经实现:

  • 单一活动实例、账号凭据和默认项目空间的配置模型与本地存储;
  • 默认使用 OAuth Device Code 登录、自动刷新与尽力吊销,并支持显式的个人访问令牌备用登录;
  • key=value、JSON、文件和标准输入参数解析;
  • 人类可读输出与稳定 JSON Envelope;
  • 本地命令注册、帮助目录、Shell Completion 和 OpenAPI 命令注册器;
  • 从 OpenAPI 生成并注册普通业务 HTTP 命令,并为特殊传输提供显式协议命令;
  • 面向人类的 loginlogoutwhoamidoctor 顶层短命令;
  • 检查当前登录、认证、服务端版本、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、 下载和终端等能力只通过对应的专用协议命令提供。highcritical 风险操作 在交互终端中必须逐次明确确认;非交互或 Agent 模式必须显式传入 --yes, 否则以稳定的 confirmation_required 错误拒绝。CLI 的确认只表示调用意图, 后端权限、适用的接口 Scope 与 Step-up MFA 仍是最终安全裁决。通用 api request 仅保留为 人类诊断逃生口,不参与业务能力伪装。终端要求 CLI OAuth 登录与对应 purpose 的有效 Step-up;个人访问令牌不能满足或绕过这一协议授权。 第一方 luna-cli 的 Device Code 登录不接受、展示或保存用户可选 Scope,也不依据 本地权限副本预检命令或生成扩大权限的重新登录命令。CLI 会话权限在每次请求时按 当前用户的平台角色、项目空间成员关系和资源策略由服务端裁决。个人访问令牌、 第三方 OAuth 应用和 Agent 服务身份仍按 OpenAPI 声明的接口 Scope 限权;机器 Help 展示这些接口要求,但 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 或更高版本运行。

不依赖 Skills 使用

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 get-projects --help

这些顶层短命令只面向人类交互,分别复用 auth loginauth statushealth doctorauth logout 的同一处理器。脚本与 AI 应使用 canonical 两级命令;严格 agent=true 模式会拒绝顶层别名,避免审计和机器契约出现两套路径。

直接运行 luna 且不传子命令时,会显示同一份本地化根帮助,不会执行远程操作。第一级列出分类和快速开始,第二级列出分类内工具,第三级显示接口、权限、风险、参数来源、必填项和示例。业务参数统一使用 key=value;JSON、文件或多行文本使用 key=@file.jsonkey=@-

未指定 server 时,luna login 固定登录官方实例 https://devops.liteyuki.org。登录其他实例时必须显式传入 server=https://...;再次登录会覆盖本地现有的实例、凭据和默认项目空间。 CLI 不提供 context 切换机制,一个本地配置始终只表示一个活动登录。

Release 交互执行

使用 OAuth 登录后,可以把本地 TTY 直接连接到 Release 当前运行容器:

luna release exec projectId=prj_example releaseId=rel_example
luna release exec projectId=prj_example releaseId=rel_example container=api

命令进入远端交互式 Shell,输入输出、ANSI 控制字节和窗口尺寸以二进制终端流传输; 执行 exit 或按 Ctrl-D 后结束远端会话并恢复本地终端。release terminal 保留为 同一命令的人工别名。该命令要求真实交互式 TTY、deployment:exec Scope 和平台端 运行终端授权,不能在 agent=true 模式下使用。

语言解析顺序为:--langLUNA_LANG、本地配置的 language、系统 LC_ALL / LC_MESSAGES / LANG、运行时语言,最后回退英文。例如:

LUNA_LANG=zh-CN luna --help
luna --lang zh-CN project get-projects --help

Agent 可观测诊断

平台管理员可以通过稳定的 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

建议按 overviewturns / toolstool-calls / trace 逐步缩小范围。列表必须显式传入有界分页,时间范围仅支持 1h6h24h7d30d1y。这些读操作要求平台管理员身份和 agent-observability:read Scope;数据源测试是人工管理员命令,严格 Agent 模式不会执行。

JSON 输出保留统一 Envelope、分页元数据、request ID 和 correlation ID。CLI 会在输出前移除原始 Trace blob、System Prompt 和受控 GenAI 内容;原始对话暂不是稳定 CLI 能力。

Tab 补全

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 zsh

Bash:

mkdir -p ~/.local/share/bash-completion/completions
luna completion bash output=table > ~/.local/share/bash-completion/completions/luna

Fish:

mkdir -p ~/.config/fish/completions
luna completion fish output=table > ~/.config/fish/completions/luna.fish

PowerShell:

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 的 latestbeta 是独立更新通道。测试预发布版本时必须显式安装 @beta,普通的全局更新不会从稳定版自动切换到预发布版。

AI Skills 会在此基础上使用 luna help catalog ... output=json interactive=false agent=trueluna 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 的系统上,目录和文件分别限制为 07000600。校验长度、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-coverage

v* tag 只发布 Luna CLI 与同版本 Skill。Luna DevOps 平台在 LiteyukiStudio/luna-devops 仓库独立发版。


English

Luna CLI is the command-line client for Luna DevOps, designed for both people and automation agents:

luna <category> <tool> key=value

Current status

The CLI is in prerelease. The source manifest uses the 0.0.0-development placeholder and private: true to prevent accidental publication; release versions are injected from v* tags. It includes one active server/account login, OAuth Device Code authentication with refresh and revocation, an explicit personal-access-token fallback, a default project, structured input and output, OpenAPI-generated business commands, dedicated protocol commands, command discovery, and release validation. Live coverage totals and ratios come only from pnpm check:platform-cli-coverage.

src/entry.ts is the shared npm and Bun entry point, and workspace packages are bundled safely into the distribution. Prereleases are available on npm and pass npm/pnpm global-install, localized Help, machine Help, and supported standalone-binary smoke tests.

Canonical OpenAPI commands automatically negotiate the API generation and minimum CLI version through /api/v1/meta. The exact OpenAPI digest is diagnostic metadata: luna doctor reports a mismatch, while compatible commands in the same API generation remain available. Hidden browser callbacks, webhooks, internal receivers, and low-level protocol operations are not registered as canonical raw commands; SSE, downloads, and terminals are exposed only through their dedicated protocol commands. High- and critical-risk operations require an explicit interactive confirmation, or --yes in non-interactive and agent mode. CLI confirmation records caller intent only: server permissions, scopes, and step-up MFA remain authoritative. Terminal protocols require a CLI OAuth login and a valid step-up assertion for the matching purpose; personal access tokens cannot satisfy or bypass that authorization. First-party luna-cli Device Code login does not accept, display, or persist user-selectable scopes, and commands do not preflight a copied grant or synthesize a broader login request. The server authorizes every CLI request from the user's current platform role, project membership, and resource policy. Personal access tokens, third-party OAuth apps, and Agent service identities remain restricted by the endpoint scopes declared in OpenAPI; machine Help exposes those endpoint requirements without replacing RBAC. Generic api request remains a human-only diagnostic escape hatch. Stored OAuth credentials are refreshed automatically by auth status and remote commands when the access token is within 30 seconds of expiry or already expired. Concurrent CLI processes coalesce the refresh so the refresh token is rotated only once. luna auth refresh remains available for forced refresh and diagnostics; routine use does not require it. LUNA_TOKEN and personal access tokens do not participate in OAuth refresh. If the grant is invalid or a refresh outcome cannot be confirmed safely, the CLI returns oauth_refresh_reauthentication_required, blocks reuse of the old refresh token, and requires luna login. The safe underlying classification is available only as details.causeCode.

Interactive release exec

luna release exec projectId=prj_example releaseId=rel_example
luna release exec projectId=prj_example releaseId=rel_example container=api

The command attaches the local raw TTY until exit or Ctrl-D, then restores the local terminal. UTF-8, ANSI, and control bytes remain binary end to end; release terminal is the human-facing alias. This OAuth-only command requires deployment:exec and cannot run in Agent mode.

Installation

npm install --global @liteyuki/luna-cli@beta
pnpm add --global @liteyuki/luna-cli@beta

Standalone binaries will also be attached to GitHub Releases. Stable releases currently include only Linux glibc binaries that pass target-environment smoke tests. Until Apple signing is configured, macOS binaries are available only on prereleases and are explicitly suffixed with -unsigned. Windows and Alpine/musl use the npm or pnpm distribution on Node.js 22.14.0 or later.

See the documentation links above for installation, release channels, checksums, SBOMs, provenance, and current limitations.

The CLI includes layered human Help without requiring 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 get-projects --help

The four root shortcuts reuse the canonical auth login, auth status, health doctor, and auth logout handlers. Scripts and agents must use the canonical two-level paths; strict Agent mode rejects root aliases.

Running luna without a subcommand displays the same localized root Help and does not perform a remote operation. A bare luna login always targets the official https://devops.liteyuki.org instance. Pass server=https://... to log in elsewhere; a new login replaces the locally active server, credential, and default project. There is no context-switching layer. Locale precedence is --lang, LUNA_LANG, configured language, system locale, then English. Use LUNA_LANG=zh-CN luna --help for Chinese. npm latest and beta are separate update channels, so prerelease testing must explicitly install @beta. Skills build on the CLI's machine-readable Help for more precise agent operation; the CLI does not depend on Skills. Skills use the exact same version and ship in the same v* GitHub Release as the CLI.

About

Luna DevOps command-line client and paired AI Skill

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages