关于 clawops
clawops 是用于在 AWS、GCP、Azure 或 Linux 虚拟机上部署和运维自托管 OpenClaw 的命令行工具及 MCP 服务。它面向 OpenClaw 用户和基础设施运维人员,提供带类型定义的工具、只读模式、破坏性操作确认和审计日志。
主要功能
- 01部署到三家云服务或虚拟机
- 02管理状态、日志和备份
- 03带类型定义的 MCP 工具
- 04只读运行模式
- 05破坏性操作需确认
- 06支持脚本使用的 JSON 输出
适用场景
- 01部署自托管 OpenClaw 实例
- 02检查部署状态和日志
- 03让 AI 编辑器安全地操作基础设施
- 04使用 JSON 输出自动化运维
MCP 相关
将基础设施运维操作作为带类型定义的 MCP 工具提供给 Claude Code、Cursor 等客户端。只读模式和破坏性操作的明确确认机制用于控制风险。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
30收录的工具列表 · 更新于 1 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| stackName | string | 否 | 堆栈名称。默认为配置中的活动堆栈。 |
详细介绍
clawops
面向 OpenClaw 的 MCP 原生基础设施运维,内置只读模式、破坏性操作确认和审计日志。
clawops 是一个 CLI 和 MCP 服务,用于部署和运维 自托管的 OpenClaw 实例。可在 AWS、GCP、 Azure 或任意 Linux 虚拟机上进行配置,然后通过终端管理日常运维,或让 Claude Code 和 Cursor 通过带有明确安全控制的类型化 MCP 工具来执行操作。
最新动态: 下方的 2.4 版本说明,以及完整历史记录 见 CHANGELOG.md。
适用对象
- OpenClaw 用户:希望以最简单的方式在云端或本地虚拟机上自托管,并通过一个 CLI 完成 可靠部署、状态检查、日志查看、备份和升级。
- Claude Code / Cursor / MCP 用户:希望参考通过 MCP 安全执行基础设施运维的真实案例。 类型化工具架构、只读模式、破坏性操作确认和审计日志。
- 自托管 AI 和本地优先的开发者:希望运行自己的 AI 助手,但不想依赖 Kubernetes、托管 SaaS 平台或单一云服务商。
clawops 的功能
- 使用 Pulumi Automation API 在 AWS、GCP、Azure 和本地虚拟机上配置和销毁 OpenClaw 基础设施。
无需安装 Pulumi;clawops 会在首次使用时将所需 CLI 安装到
~/.clawops/.pulumi-cli。 - 管理日常运维:状态、日志、SSH、隧道、配置、Agent、网关、备份。
- 将每项操作都作为类型化 MCP 工具公开,让 AI Agent 能够安全地执行运维操作。
- 对云端部署强制执行规划 → 审查 → 应用流程。
- 所有输出均为 JSON(
--json),便于脚本和自动化处理。 - 绝不存储云凭据,而是从环境中现有的 CLI 配置文件读取。
clawops 不会做什么
- **不支持高可用或集群。**针对单节点部署进行了优化。
- **不使用 Kubernetes。**它部署到虚拟机,而不是容器编排平台。
- **不编写 OpenClaw 技能或 Agent。**clawops 管理基础设施;在其上运行什么由你和 OpenClaw 决定。
- 不提供 TLS 或域名自动化(暂不支持)。请自行配置反向代理,或参阅
docs/limitations.md了解手动操作方式。 - **不存储凭据。**使用 clawops 前,必须先在环境中配置云凭据。
凭据绝不会写入
~/.clawops/config.json。 - **不原生支持 Windows。**完全支持 WSL2;请参阅
docs/support-matrix.md。
快速开始
npm install -g @clawops/cli
clawops setup
clawops setup 是一个交互式向导,可在约 2 分钟内让 OpenClaw 运行起来。它会在一个流程中处理所有事项,无需手动编写配置文件,也无需记忆命令。
向导的功能
步骤 1. 选择部署目标
选择一台可通过 SSH 登录的现有服务器(Linux 或 macOS),或在 AWS、GCP 或 Azure 上新建一台云 VM。如果尚未登录,云部署会引导你通过提供商的 CLI 完成身份验证。
步骤 2. 选择大模型提供商
从 Anthropic、OpenAI、Amazon Bedrock、Ollama 等提供商中选择。向导会提示你输入 API 密钥,并将其保存在本地(位于 ~/.clawops/secrets/,权限为 chmod 600);密钥绝不会发送到其他任何地方,只会在应用配置时发送给目标主机上的 OpenClaw。
步骤 3. 添加聊天集成(可选)
选择 Discord、Telegram、Slack、WhatsApp 或 Teams,可任意组合。向导会以与 API 密钥相同的方式收集每个集成的机器人令牌。你可以直接粘贴、引用环境变量,或指定文件。
步骤 4. 配置 AI 编辑器
选择要允许访问 clawops 的 AI 应用。支持 Claude Desktop、Claude Code、Cursor、Windsurf、VS Code 和 Zed。向导会使用绝对二进制文件路径,在每个应用的配置文件中写入一条 MCP 服务条目,以便应用能够独立启动它。
步骤 5. 部署
向导通过 SSH 在目标主机上引导安装 OpenClaw(安装 Docker、拉取镜像、启动容器),应用大模型和集成配置,生成网关身份验证令牌,并输出可直接访问的仪表板 URL:
✔ All done! OpenClaw is running.
ℹ Open dashboard: http://192.168.1.50:18789?token=<your-token>
ℹ Token saved to ~/.clawops/secrets/GATEWAY_TOKEN_my-stack
**先决条件:**Node.js ≥ 22、SSH 密钥,以及一台可通过 SSH 访问的 Linux/macOS 主机或配置了 CLI 凭据的云账户(aws configure、gcloud auth login 或 az login)。你不需要 Pulumi。首次云部署会将 clawops 驱动的 CLI 安装到 ~/.clawops/.pulumi-cli,并在安装过程中告知你。
如需查看带示例输出的完整讲解,请参阅 docs/demo-script.md。
手动设置:现有服务器
如果你更希望逐步控制,或要将 clawops 添加到正在运行的部署中:
npm install -g @clawops/cli
clawops doctor # verify environment
clawops init --provider local --host 192.168.1.50 --user ubuntu --key-path ~/.ssh/id_ed25519
clawops up # installs Docker + OpenClaw over SSH
clawops status
有关 SSH 先决条件、防火墙设置和故障排除,请参阅 docs/examples/local-vm.md。
手动设置:云(AWS)
npm install -g @clawops/cli
# Requires AWS credentials in your environment (AWS_PROFILE or ~/.aws/credentials)
clawops init --provider aws
# Edit ~/.clawops/config.json: set stateUrl to your S3 bucket
clawops plan --provider aws --stack default --ssh-cidr auto --out /tmp/plan.json
clawops apply /tmp/plan.json
--ssh-cidr auto 允许从本机的公网 IP 进行 SSH 访问;生成计划时会解析该 IP 并将其写入计划。若不使用此选项,计划将禁止所有入站流量,包括 clawops 在内的任何内容都无法连接。
连接 AI 编辑器
setup 向导会自动完成此操作(第 4 步)。如需随时配置或重新配置编辑器:
clawops mcp install
这会打开与向导中相同的交互式复选框。选择 Claude Desktop、Claude Code、 Cursor、Windsurf、VS Code 或 Zed,clawops 会使用正确的绝对二进制文件路径, 将 MCP 条目写入各应用的配置中。
如果要手动添加条目,请将以下内容粘贴到编辑器的 MCP 配置中:
{
"mcpServers": {
"clawops": {
"command": "npx",
"args": ["-y", "@clawops/cli", "mcp", "serve", "--read-only"]
}
}
}
此格式无需在 $PATH 中设置任何内容,也是目录或安装程序会复制的格式。如果
你更愿意指向已有的二进制文件,请使用其绝对路径——即 which clawops 的输出——
并传入相同的参数:
{
"mcpServers": {
"clawops": {
"command": "/path/to/clawops",
"args": ["mcp", "serve", "--read-only"]
}
}
}
无论哪种方式,都要传入参数。mcp serve 才是负责处理协议的命令,而显式配置
即使一年后再看也依然清晰。clawops 不会让省略参数的客户端无法启动:
完全不带命令运行,并在 stdin 中传入管道——这是每个 MCP 客户端启动服务的方式——
它就会启动 mcp serve,并在 stderr 中说明这一点。在终端中直接输入 clawops,
仍会显示帮助信息。
在 env 中传入云凭证。 客户端会使用其配置指定的环境启动服务,而不是你的
shell 环境,因此在终端中导出的 AWS_PROFILE 不会传递给它,所有读取堆栈的工具
都会失败,并显示“Could not read the state of stack”。请在服务的 env 块中
指定配置文件名称,或状态后端所需的变量:
{
"mcpServers": {
"clawops": {
"command": "npx",
"args": ["-y", "@clawops/cli", "mcp", "serve"],
"env": { "AWS_PROFILE": "my-profile" }
}
}
}
其中保存的是配置文件名称,而不是密钥:凭证本身仍保存在云 CLI 存放凭证的位置(R6)。
配置文件位置:
| 应用 | 路径 |
|---|---|
| Claude Desktop(macOS) | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Claude Desktop(Linux) | ~/.config/Claude/claude_desktop_config.json |
| Claude Code | ~/.claude.json |
| Cursor | ~/.cursor/mcp.json |
| Windsurf | ~/.codeium/windsurf/mcp_config.json |
| VS Code(macOS) | ~/Library/Application Support/Code/User/mcp.json |
| VS Code(Linux) | ~/.config/Code/User/mcp.json |
| Zed | ~/.config/zed/settings.json(键:context_servers) |
请先使用 --read-only 启动。 它允许查看状态、日志、配置和诊断信息,同时
阻止更改。查看
docs/security/mcp-safety.md 后,再移除该选项。
破坏性工具(clawops_destroy、clawops_up、clawops_config_set 等)执行前
需要明确确认,绝不会静默运行。
HTTP 模式的配置方法请参见 docs/mcp/。
日常操作
clawops status # Stack outputs: IP, gateway URL, SSH info
clawops logs -f # Tail OpenClaw logs over SSH
clawops ssh # Interactive SSH session
clawops ssh --command "docker ps"
clawops config get maxAgents
clawops config set maxAgents 8
clawops tunnel # Port-forward gateway UI to localhost
clawops destroy --yes # Destroy cloud-provider stack
clawops down --yes # Destroy local-provider stack
命令
| 命令 | 说明 |
|---|---|
setup | 首次运行向导:引导配置 LLM、集成、支出限额并生成部署计划 |
init | 在 ~/.clawops/config.json 中注册一个堆栈,不进行配置。此操作为增量式,保留现有堆栈;仅在需要覆盖堆栈时才需使用 --force |
up | 配置或更新堆栈(使用 --dry-run 预览,使用 --gateway-port 指定非默认端口) |
down | 销毁本地提供商的堆栈(需要 --yes;--dry-run 显示当前输出) |
destroy | 销毁云提供商的堆栈,并提示确认(--dry-run 显示当前输出) |
status | 显示堆栈输出:IP、网关 URL、区域、配置时间,以及堆栈的主机 Agent 留给你的任何请求 |
plan | 生成部署计划 JSON 工件(可安全地进行试运行)。--ssh-cidr <list|auto> 和 --gateway-cidr 决定允许哪些人连接;--publish-gateway loopback|all 决定监听范围;对于通过 tailnet 访问的堆栈,--private-only 会关闭公共访问 |
apply | 应用先前审核过的计划文件(--dry-run 会验证并显示差异,但不会应用) |
ssh | 建立交互式 SSH 会话或运行远程命令 |
logs | 流式查看 OpenClaw 日志(-f、--tail N、--since 5m) |
tunnel | 通过 SSH 将本地端口转发到网关 UI |
config | 获取或设置远程 OpenClaw 配置值(--dry-run 显示将写入的 JSON) |
agents | 列出 OpenClaw Agent,或流式查看某个 Agent 的日志 |
agent install | 在堆栈的网关主机上安装主机 Agent,仅供操作员可访问的一个 OpenClaw Agent 使用(--agent、--operator <channel>:<peer>、--allow 交接工具、--strict)。除非网关路由只允许操作员访问,否则拒绝安装;并拒绝 clawops 访问所有其他 Agent。--serve-peers <tag> 和 --peer <stack>=<tailnet name> 可将主机设为机群成员,其主机 Agent 会通过 tailnet 读取对等主机(2.5,ADR 0015;参见 运维) |
agent uninstall | 移除主机 Agent 并解除网关配置(--purge 还会移除其审计日志) |
fleet status | 通过 SSH 读取每个堆栈的主机,并列出其主机 Agent 的状态:是否正在运行、服务于哪个 OpenClaw Agent;对于机群成员,还会列出其标签、对等主机、防火墙表和 tailnet 状态。在报告中指出无法正常工作的对等主机,并注明报告它们的主机。--stack a,b 仅读取指定堆栈;--json 输出 JSON。未部署任何内容的堆栈也会列出并注明。任何主机出现问题或无响应时,退出码为 1 |
gateway | 重启 OpenClaw 网关服务 |
backup | 创建和还原 OpenClaw 状态备份(restore 会解压到暂存目录,不会直接覆盖;--activate 会将其切换为当前状态,并在网关无法启动时回滚) |
stacks | 列出命名堆栈及其状态 |
doctor | 检查本地计算机;使用 --stack 时也检查部署的运行状况;使用 --provider 时检查某个云提供商的凭据和账户设置,无论是否存在堆栈;使用 --instance-type 时,账户检查会针对指定规格,而非提供商默认规格。使用 --json 输出报告。任何检查失败时,退出码为 1 |
secret | 管理机密:list、set、delete、rotate、audit |
monitor | 实时仪表板:网关运行状况、容器统计信息、日志尾部、堆栈选择器 |
mcp serve | 启动内嵌 MCP 服务(stdio,或使用 --http <port> --token <t> 启动 HTTP 服务)。--host-agent 会提供网关主机自身的 Agent(ADR 0014) |
mcp install | 交互式地将 clawops 接入 AI 编辑器 |
mcp wire | 将网关的 AI 接入为 clawops 的 MCP 客户端(保存前会验证连接) |
help | 列出所有命令和全局标志 |
harden | 对已部署的堆栈应用安全加固(SSH、UFW、fail2ban、unattended-upgrades、Docker socket;AWS:安全组审计、SSM 检查、Flow Logs、GuardDuty)。--tailscale 会将堆栈加入你的 tailnet,并在其响应后将 clawops 切换到该地址;--tailscale-revert 会撤销此操作 |
bug | 创建预先填写了 doctor 系统信息的 GitHub 问题 |
完整的标志参考:clawops <command> --help |
计划 → 应用工作流
对于非本地提供商,clawops 会强制执行先审查、后应用的流程:
# 1. Generate a plan: runs `pulumi preview` internally, produces JSON
# --ssh-cidr decides who may connect. `auto` means this machine; omit it and nobody can.
clawops plan --provider aws --region us-east-1 --ssh-cidr auto --out /tmp/plan.json
# 2. Review plan.json: the `diff` field shows projected changes at plan-generation time
cat /tmp/plan.json | jq .diff
# 3. Apply: reads and validates the plan file, then runs `pulumi up`
clawops apply /tmp/plan.json
# Without --yes, apply prompts: "Continue? (y/N)"
clawops apply /tmp/plan.json --yes # skip prompt in automation
计划 JSON 符合 spec/deploy-plan.schema.json(经 AJV 验证),并记录已审查的意图:提供商、区域、实例类型、CIDR 范围和 OpenClaw 版本。apply 会使用这些参数,根据当前实时状态重新运行 pulumi up,而不是重放锁定的执行产物。请在同一会话中完成审查和应用,以尽量降低状态偏差风险。
有关完整语义、状态偏差指南和安全的 CI 模式,请参阅 docs/plan-apply.md。
MCP 服务
clawops 内置了 MCP 服务。Claude Code、Cursor 以及任何兼容 MCP 的 Agent,都能在聊天界面中直接管理部署。
连接编辑器
clawops mcp install # interactive checkbox: writes config for selected apps
向导会自动解析二进制文件的绝对路径,让应用启动器无需继承 shell 的 PATH 即可找到 clawops。有关手动配置路径,请参阅上文的连接 AI 编辑器。
连接网关 AI
OpenClaw 网关运行自己的 AI Agent。连接后,该 Agent 可以直接调用 clawops,而不必猜测基础设施状态:
clawops mcp wire --stack prod # openclaw mcp add, which connects before it saves
网关需要运行 OpenClaw 2026.7.1-2 或更高版本。成功部署后,clawops setup 向导会提供此步骤。
网关上的每个 Agent 都能使用所有 clawops 工具,包括默认 Agent;它会回复任何能向网关发送消息的人。OpenClaw 的 MCP 服务适用于整个网关。连接后,mcp wire 会列出现在可以调用 clawops 的每个 Agent。如需禁止某个 Agent 使用这些工具,请将 "clawops__*" 添加到其 agents.entries.<id>.tools.deny。若要让某个 Agent 将破坏性更改交由你处理,而不是自行执行,请使用 clawops agent install。
Stdio 模式(Claude Code / Cursor / VS Code)
手动启动服务,或确认配置正确:
clawops mcp serve --read-only # safe for first evaluation
clawops mcp serve # full mode: enables provisioning, config write, ssh exec
HTTP 模式(远程 / 多客户端)
clawops mcp serve --http 3333 --bind 127.0.0.1
# MCP HTTP server listening on 127.0.0.1:3333
如果没有额外的身份验证措施,请勿将其绑定到非回环地址。
可用工具
| 工具 | 工具集 | 描述 |
|---|---|---|
clawops_status | cli | 显示堆栈输出(已部署的内容,而非其是否正常运行) |
clawops_doctor | cli | 运行诊断:本地先决条件;若有堆栈,还会检查远程健康状况 |
clawops_logs_tail | cli | 实时查看 OpenClaw 日志 |
clawops_monitor | cli | 采样网关和主机指标 |
clawops_stacks_list | admin | 列出所有堆栈及其状态;设置 fleet: true 时,还会列出每个主机 Agent 和集群的对等节点,与 clawops fleet status 报告的内容一致 |
clawops_config_get | cli | 读取远程配置值 |
clawops_agents_list | cli | 列出正在运行的 Agent |
clawops_agents_logs | cli | 分页查看单个 Agent 的近期活动 |
clawops_gateway_status | cli | 查看网关容器是否正在运行及其镜像 |
clawops_secret_list | cli | 按名称和状态列出已存储的密钥(绝不显示密钥值) |
clawops_secret_audit | cli | 报告缺失的密钥和无法解析的 $secret: 引用 |
clawops_up | cli | 配置或更新堆栈 |
clawops_destroy | cli | 销毁堆栈(会要求确认) |
clawops_apply | cli | 应用计划文件 |
clawops_plan | cli | 生成部署计划 |
clawops_config_set | cli | 写入远程配置值 |
clawops_config_unset | cli | 移除远程配置键 |
clawops_config_validate | cli | 根据 OpenClaw 架构验证已部署的配置 |
clawops_gateway_restart | cli | 重启网关(会要求确认) |
clawops_gateway_update | cli | 将网关升级到指定的 OpenClaw 版本(会要求确认) |
clawops_backup_create | cli | 将网关状态备份到本地存档 |
clawops_backup_restore | cli | 将备份还原到暂存环境;或设置 activate 后将其投入使用(会要求确认) |
clawops_migrate | cli | 将 1.x 部署迁移到 2.0 运行时(会要求确认) |
clawops_stacks_delete | admin | 从配置中移除堆栈;不会销毁基础设施(会要求确认) |
clawops_secret_delete | cli | 删除已存储的密钥(会要求确认) |
clawops_harden | cli | 应用加固模块;加入或离开 tailnet(会要求确认) |
clawops_init | cli | 注册堆栈并写入 ~/.clawops/config.json(不创建云资源) |
clawops_workflow_deploy_app | workflow | 端到端部署:计划 → 确认 → 应用 → 状态 |
clawops_workflow_recover | workflow | 诊断不健康的堆栈:状态、失败的健康检查、近期日志,以及每种问题对应的修复工具 |
clawops_task_status | cli | 轮询长时间运行的任务 |
read 工具集中的工具也可在 --read-only 模式下使用;表格中的“工具集”列显示主要工具集。其他所有工具集都需要完整模式。
除非传入 yes: true,否则破坏性工具都需要明确确认(征询确认)。
有关每个工具的完整风险分类,请参阅 docs/security/tool-risk-matrix.md。
配置
配置位于 ~/.clawops/config.json(可通过 $CLAWOPS_HOME 覆盖)。
{
"version": 1,
"defaults": {
"provider": "aws",
"stack": "default"
},
"stacks": {
"default": {
"provider": "aws",
"region": "us-east-1",
"stateUrl": "s3://my-clawops-state"
}
},
"ssh": {
"keyPath": "~/.clawops/id_ed25519",
"knownHostsPath": "~/.clawops/known_hosts"
}
}
云凭据绝不会存储在配置中。Clawops 从环境中读取凭据:
| 提供商 | 凭据来源 |
|---|---|
| AWS | AWS_PROFILE 或标准 AWS 凭据链(~/.aws/credentials) |
| GCP | GOOGLE_APPLICATION_CREDENTIALS 或 gcloud auth application-default login |
| Azure | AZURE_CLIENT_ID / AZURE_CLIENT_SECRET 或 az login |
| 本地 | 在 stacks[name].localOpts 中配置的 SSH 主机和密钥 |
支出限额
可选的 policy 区块会限制 clawops 从此机器部署的内容,无论发起请求的是哪个工具:
"policy": {
"allowedInstanceTypes": { "aws": ["micro", "small"] },
"maxStacks": 3
}
对于该云服务商,若服务器规格不在 allowedInstanceTypes 允许范围内,plan、apply 和 up 都会拒绝部署
(可以使用 clawops 规格名称或云服务商自己的规格名称;在 AWS 上,small 和 t3.small 表示同一规格),而
init 会拒绝创建超出 maxStacks 限制的新堆栈。每个 MCP 部署工具都遵循相同的限制,措辞一致,而且没有工具可以更改这些限制。clawops setup 会询问是否要设置这些限制,然后只提供你允许的规格。限额设在这里,而不是计划中,
因为计划是由 Agent 编写的。
已知限制
完整列表请参阅 docs/limitations.md。要点如下:
- 仅支持单节点部署,不是高可用或集群平台。
clawops apply不会执行不可变计划。请参阅docs/plan-apply.md。- 当前版本不支持 TLS/域名自动化。
- MCP 工具会执行特权操作,首次评估时请使用
--read-only。
架构
clawops
├── src/cli/ citty-based commands (one file per verb)
├── src/config/ ~/.clawops/config.json management
├── src/providers/ Cloud adapters (AWS, GCP, Azure, local)
│ ├── aws/ Pulumi inline program + ProviderAdapter
│ ├── gcp/
│ ├── azure/
│ └── local/ SSH bootstrap (no Pulumi)
├── src/pulumi/ Pulumi Automation API wrapper + output helpers
├── src/transport/ SSH client (ssh2) + connection pool + tunnels
├── src/mcp/ MCP server, tool handlers, progress tracking
├── src/plan/ Maker plan generation, AJV validation, apply
├── src/output/ ASCII table, spinner, JSON, human-readable output
├── src/errors/ Typed error hierarchy with exit codes
└── spec/ Machine-readable ground truth (JSON Schema, YAML)
关键设计决策:
- Pulumi Automation API: 用户无需安装 Pulumi。Clawops 会将该 API 驱动的 CLI 安装到
~/.clawops/.pulumi-cli,并固定为随附的 SDK 版本,不修改$PATH(ADR 0010);Pulumi 主目录隔离在~/.clawops/.pulumi中;堆栈程序为内联 TypeScript 闭包 - 将状态保存在云端 Blob 存储中: GCS(
gs://)、S3(s3://)、Azure Blob;不使用本地状态文件,也不使用pulumi.yaml - 通过
ssh2使用 SSH: 绝不调用/usr/bin/ssh;通过~/.clawops/known_hosts执行 TOFU 主机验证;连接池空闲 TTL 为 5 分钟 - 计划 → 应用规范: 每次非本地部署都必须经过
generatePlan()→ 审核 →applyPlan();破坏性更改始终需要人工审核计划 JSON - MCP 优先: 每项 CLI 操作都有类型化的 MCP 工具;架构根据
spec/mcp-tools.yaml生成;所有破坏性工具都使用征询
完整说明请参阅 docs/architecture.md,ADR 请参阅 docs/decisions/。
云服务商堆栈
每个云服务商都通过内联 Pulumi 程序创建下列资源。三者共享相同的输出(publicIp、gatewayUrl、sshHost、sshPort、sshUser),供 SSH 和配置覆盖层使用。
AWS
flowchart LR
subgraph NET["Networking"]
VPC["VPC (10.0.0.0/16)"]
IGW[Internet Gateway]
SUBNET["Subnet (10.0.1.0/24)"]
RT[Route Table]
SG["Security Group (ports 22, 18789)"]
end
subgraph IAM["IAM"]
ROLE[IAM Role]
SSM[SSM Policy Attachment]
BED["Bedrock Policy Attachment (optional)"]
IP[Instance Profile]
end
subgraph COMPUTE["Compute"]
KP[EC2 Key Pair]
EC2["EC2 Instance (Ubuntu 22.04, IMDSv2)"]
EIP[Elastic IP]
end
GCP
flowchart LR
subgraph NET["Networking"]
NW[VPC Network]
SN["Subnetwork (10.0.0.0/24)"]
FW1["Firewall: SSH port 22 (conditional)"]
FW2["Firewall: Gateway port 18789 (conditional)"]
ADDR[Static External IP]
end
subgraph COMPUTE["Compute"]
VM["Compute Instance (Debian 12, 20 GB)"]
end
Azure
flowchart LR
RG[Resource Group]
subgraph NET["Networking"]
VNET["Virtual Network (10.0.0.0/16)"]
SUBNET["Subnet (10.0.1.0/24)"]
NSG["Network Security Group (ports 22, 18789)"]
PIP["Public IP Address (Static)"]
NIC[Network Interface]
end
subgraph COMPUTE["Compute"]
VM["VM (Ubuntu 22.04, managed identity)"]
end
subgraph KV["Key Vault (optional)"]
VAULT["Key Vault (RBAC, name max 24 chars)"]
RA["Role Assignment (Secrets User)"]
SECRET["Secret: gateway-token"]
end
开发
设置
git clone https://github.com/dfridkin/clawops.git
cd clawops
# Node 22+ required; use nvm: nvm use
pnpm install
pnpm dev doctor # verify toolchain
脚本
pnpm dev # run CLI from src/ via tsx
pnpm build # tsup → dist/
pnpm test # vitest (2420 tests, ~14s)
pnpm test:changed # vitest --changed (fast edit loop)
pnpm test:integration # Docker-based SSH integration tests
pnpm test:e2e:local # builds, then bootstrap, the host-touching MCP tools and a 1.x migration, in systemd containers
pnpm test:e2e:fleet # builds, then a two-host fleet on a Headscale tailnet (about 10 GB of images; CI runs it)
pnpm typecheck # tsc --noEmit
pnpm lint # eslint src/ tests/ scripts/ (--max-warnings=0)
pnpm gen:schemas # regenerate src/providers/types.ts + src/mcp/tools/_generated.ts
pnpm gen:schemas --check # CI guard: committed generated files match spec
pnpm graph # local coupling report (--base <ref> for this branch's delta)
pnpm verify:pack # install the packed tarball elsewhere and run it (CI gate)
pnpm sync:server-json # write package.json's version into server.json
pnpm changeset # record a release note before merging
项目结构
| 路径 | 用途 |
|---|---|
spec/ | 机器可读的事实来源:JSON Schema、YAML。应将其视为事实来源。 |
SPEC.md | 完整技术规范(里程碑、规则、架构) |
DESIGN_RULES.md | 代码库中引用的 25 条规范性规则(R1–R25) |
docs/architecture.md | 系统概述说明 |
docs/plan-apply.md | 计划/应用语义、漂移指南、CI 模式 |
docs/ci.md | CI 集成指南:OIDC、环境变量、在 CI 中执行计划 → 应用 |
docs/security/ | MCP 安全模型、工具风险矩阵、脱敏、审计日志 |
docs/providers/matrix.md | 各云服务商的能力矩阵 |
docs/decisions/ | 架构决策记录 |
.claude/skills/ | 可调用流程:/add-provider、/release、/tdd、/mcp-tool |
.claude/rules/ | 由 Claude Code 加载的路径范围 lint 规则 |
代码生成
以下两个文件由 spec/ 生成,不得手动编辑:
src/providers/types.ts。根据spec/providers.schema.json生成的ProviderAdapter接口src/mcp/tools/_generated.ts。根据spec/mcp-tools.yaml生成的 Zod 架构和类型导出
修改任一 spec 文件后,运行 pnpm gen:schemas。CI 会通过 --check 强制执行此要求。
添加提供程序
在 Claude Code 中使用 /add-provider 技能,或参阅 src/providers/CLAUDE.md。每个适配器都必须满足 src/providers/types.ts 中的 ProviderAdapter。不要为了适配器而放宽架构。
添加 MCP 工具
使用 /mcp-tool 技能。该技能会将工具添加到 spec/mcp-tools.yaml,运行 pnpm gen:schemas,在 src/mcp/tools/<toolset>/<name>.ts 中创建处理程序,并将其接入注册表。每个工具都必须包含全部四个注解提示(readOnlyHint、destructiveHint、idempotentHint、openWorldHint)。
Conventional commits
feat(scope): description
fix(scope): description
docs / refactor / chore / test / perf / ci
在合并 feat 或 fix 之前,使用 pnpm changeset 记录发布说明。
2.4 版新增内容
一个主机 Agent:在网关主机上的 clawops,供一个只有你能访问的 OpenClaw Agent 使用。它会读取有关自身主机的所有信息,但不会进行任何更改。对于破坏性请求,它会返回要由你运行的准确命令(ADR 0014)。
**GCP 升级说明:**下一次运行 clawops up 时会停止并启动 VM(见下文)。
主机 Agent
clawops agent install --stack prod --agent ops --operator telegram:12345- 先检查。 除非网关的路由配置确保只有你能访问该 Agent,否则它不会写入任何内容。
- 拒绝其余访问。 它会从其他所有 Agent 中移除 clawops,并检查网关是否保留了这些条目。
- 然后安装固定版本且经过校验和验证的 Node 运行时,以及你自己的 clawops 构建版本。它通过 Docker 桥接网络以
clawops-agent.service运行,并将网关接入其中。 - 卸载命令为
clawops agent uninstall。
- 它负责读取,并移交操作。 12 个读取工具在本地运行,主机上无需 SSH、Pulumi 状态或云凭据。你通过
--allow指定的破坏性工具不会进行任何更改。相反,每个工具都会返回供你在自己的机器上运行的clawops命令,并像往常一样要求确认。yes: true会被忽略。clawops_destroy、clawops_stacks_delete和clawops_migrate会被直接拒绝。 - 待处理请求会显示在
clawops status中,可供复制。运行命令会清除对应请求;未处理的请求会在 7 天后过期。clawops_status也会报告这些请求。 - 每次调用都会重新检查。 如果网关配置发生变化,导致其他任何人也能访问该 Agent,那么在问题修复前,所有调用都会被拒绝。例如,绑定群组或新增未设置拒绝规则的 Agent。无需重新安装。
- 网关容器中的其他 Agent。 在默认部署中,每个 Agent 都能在容器中运行命令和读取文件,包括主机 Agent 的令牌和对话记录。安装过程和
clawops_status会列出这些 Agent;只要还有任何 Agent 存在,--strict就会拒绝操作。请参阅运维说明和披露审查。
GCP 主机不再使用服务账号
VM 之前使用项目的默认 Compute 服务账号运行。该账号具有 cloud-platform 范围,并且在大多数项目中拥有 Editor 角色,因此主机上的任何进程都能操作整个项目。主机上没有程序会调用 Google API,因此现在 VM 不再配置此账号。对于现有堆栈,下一次运行 clawops up 时会将其移除。这会停止并启动 VM;启动磁盘不会受到影响。
修复
clawops_logs_tail会再次读取网关自身的日志。 自 2.0.1 起,它在所有主机上都会回退到容器输出,并在网关实际正常响应时错误地报告网关无响应。clawops logs不受影响。clawops config set|unset --restart会像gateway restart一样重启网关。 之前,它自身的重启会将一个发布到所有接口的网关恢复为仅监听 loopback。无法读取镜像时,它还会回退到不断变化的stable标签,并在网关启动前就报告成功。
2.3.1 版本更新
一项安全修复。如果你通过 MCP 设置网关配置,请升级。
- 之前:
clawops_config_set会将你设置的值以明文写入审计日志 (~/.clawops/mcp-audit.log),而不是对配置路径进行脱敏。因此,通过 Agent 设置models.providers.openai.apiKey会将 API 密钥记录到日志中。确认提示也会显示该值。 - **现在:**只要路径中包含密钥,该值就会被脱敏;JSON 对象值中的密钥字段也会逐一脱敏。日志会按原样记录路径。请参阅 脱敏。
- **不会重写现有日志。**如果你在 2.3.1 之前使用
clawops_config_set设置过密钥,请检查审计日志并轮换该密钥。
2.3 版本更新
Agent 无法解除的支出限制,以及一批积压问题修复。
支出限制
~/.clawops/config.json中的可选policy区块会限制 clawops 可在每个服务提供商上部署的服务器规格,以及可管理的部署数量。plan、apply和up会拒绝列表之外的规格;init会拒绝超出上限的堆栈。- 每个会进行部署的 MCP 工具都受相同限制约束,措辞也一致,而且没有任何工具可以更改这些限制。确认操作可以由 Agent 自行回答;但支出限制不行。
clawops setup会询问是否设置限制,然后只提供你允许的规格。请参阅 支出限制。
修复
- **设置向导中的计划向云服务请求了一台名为
small的机器。**它把 clawops 规格写到了应该填写服务提供商自有类型的位置。现在会像clawops plan一样进行映射。 - **
clawops_workflow_recover会运行堆栈的健康检查,并且只推荐真实存在的工具。**它只运行了自己描述的四个步骤中的两个,最后还建议使用不存在的clawops refresh。 - MCP 审计日志会对凭据参数进行脱敏。
GOOGLE_APPLICATION_CREDENTIALS在spec/errors.yaml中被标记为敏感信息,却以明文记录。现在,如果规范与代码对错误类别、退出代码或脱敏模式的定义不一致,测试就会失败(#185)。
2.2 版本更新
恢复操作现在有了标志位,Agent 可以使用所需的所有命令,SSH 故障也会说明具体失败原因。2.2.1 随后带来了下方的修复。
恢复操作可让备份投入使用
clawops backup restore --file <archive> --activate会替换为恢复后的状态,在该状态上重启网关,并检查网关是否正常响应。不带--activate时,恢复操作仍会先验证并将内容解压到暂存目录,不会触碰任何正在运行的内容。- 被替换的状态会保留,不会删除。如果网关无法启动,clawops 会恢复旧状态并再次重启;失败的状态会作为证据保存在
.failed-restore-<timestamp>中。 - 恢复后的状态会放在主机上,与被替换的目录并列。之前,它会留在容器的
/tmp中,下一次gateway restart就会将其销毁。 - 解压归档前会检查可用空间。
clawops backup --help不再称恢复功能不可用。该功能自 2.0 起就已可用。
Agent 所需的每个命令现在都有对应的 MCP 工具
- 新增 10 个工具,工具目录总数达到 30 个:备份创建和恢复(带
activate)、网关状态和更新、单个 Agent 的日志、迁移、堆栈删除,以及密钥列表、审计和删除。每个工具都调用与对应命令相同的代码,因此两者会以相同措辞拒绝相同的操作。 clawops ssh和clawops secret set/rotate特意仅保留为 CLI 命令:root shell 或密钥值不应交到 Agent 手中,也不应出现在其对话记录中。密钥工具绝不会返回密钥值。
SSH 故障会说明原因
- 超时表示没有收到任何响应。在 clawops 技术栈中,这通常意味着安全组不再允许你的地址访问。提示会打印出可修复此问题的重新规划和应用命令。
- 连接被拒绝表示主机已启动,但 sshd 未运行。密钥遭拒时会指出 clawops 提供了哪个密钥。无法解析的名称,以及找不到共同算法的握手,都会分别说明原因。每条消息都会保留 ssh2 自己的措辞。
clawops doctor --stack <name>会在单独一行打印相同的建议。
通过在真实主机上运行每个工具发现的修复
我们通过 MCP,在一台 systemd 主机、一个由 clawops 1.7.9 创建的 1.x 部署以及 AWS 上端到端运行了新工具。这发现了单元测试无法发现的缺陷,其中还有几个出现在 CLI 中:
clawops gateway update可以正常工作。 自升级门控发布以来,每次更新都会在进行任何操作前拒绝执行,因为状态快照被指定到容器内的一个主机路径,而容器无法在该路径创建文件。- 本地提供方主机不再与 systemd 发生竞争。 网关在这些主机上作为
openclaw单元运行,并设置了Restart=always,这会在 clawops 执行重启、更新、迁移或恢复约 5 秒后撤销这些操作。现在 clawops 会通过该单元更改网关。 clawops gateway、agents、config和logs现在可在本地技术栈上正常工作。 这些命令此前都会报错:“The local provider does not use Pulumi stacks”,但对应的 MCP 工具却可以正常工作。clawops migrate遇到已运行 2.x 的技术栈时会拒绝执行;此前它会为该技术栈生成一份全新的最小配置;运行前会询问确认,正如--yes一直宣称的那样;并且会在停止 1.x 之前拉取 2.x 镜像,因此停机只需重启,而不必等待下载数 GB 的内容。- 密钥名称现在无法越出密钥目录。
clawops secret delete ../config.json曾会删除 clawops 配置。 clawops_gateway_restart会保留网关在所有接口上的发布状态,不会再将其移到环回地址。- 无法读取状态的技术栈现在会说明原因,而不是显示 Pulumi 的
code: -2,并且会指出 MCP 服务常见的原因:客户端配置的env块中缺少凭据。
其他修复
- 流式 Docker 命令(例如备份上传或持续跟踪日志)不再复用从无关命令中获取的 sudo 决策。在 AWS 上,由于登录用户不属于
docker组,备份完成后上传备份曾因“permission denied”而失败。 - 备份和升级回滚指南现在介绍
--activate,而不是手动操作流程;CI 会检查仓库内的每个 Markdown 链接和锚点(pnpm verify:docs)。 - 本地提供方的引导流程现在会在其端到端测试套件中真实运行,使用以 systemd 为 PID 1 的容器,而不是使用模拟测试。同一套件现在也会驱动会操作主机的 MCP 工具,并执行 1.x 迁移(
pnpm test:e2e:local,在每晚构建和带有e2e标签的 PR 上运行);E2E_MCP=1 pnpm test:cloud <cloud>则会在真实云主机上通过 MCP 备份和恢复。 - clawops.fyi 现在包含结构化数据、
/llms.txt、常见问题页面和比较页面。
2.2.1
clawops config validate和config set现在会根据固定版本的 OpenClaw(2026.9.2)实际使用的架构进行检查。 clawops 提供的架构来自不同的构建版本,而每周用于对比两者的检查每周都会发现差异,却因缺少 issue 标签而未能报告。现在会正常报告。实际效果是:网关会拒绝的messages.suppressToolErrors也会被拒绝,而transcripts.autoStart[].whenOccupied则会被接受。- 在 OpenClaw 2026.9.2 中,Agent 默认可以读取彼此的会话。 跨 Agent 会话访问(
tools.agentToAgent)和采集器模式子 Agent(tools.swarm)默认启用。若同一网关上的 Agent 不应查看彼此的会话: 可运行clawops config set tools.agentToAgent.enabled false,或为其设置allow列表。
2.1 新增内容
私有网络、适用于所有云平台的安全加固,以及两项无法启动的命令修复。 2.1.1 随后发布,包含以下修复。
通过 tailnet 访问堆栈
clawops harden --tailscale会在堆栈上安装 Tailscale,将其加入你的 tailnet,名称为clawops-<stack>,并报告分配给它的地址。- 随后,同一命令会将 clawops 切换到该地址,但前提是先与其建立 SSH 会话——并依据已通过可信公共连接固定的主机密钥进行验证。
- Tailscale 身份验证密钥通过
clawops secret set TAILSCALE_AUTH_KEY提供,并通过 SSH 数据通道传送到主机。 它绝不会出现在命令行、进程列表或日志中。 clawops plan --private-only→clawops apply会关闭通过 tailnet 访问的堆栈上的公共 SSH 和网关访问。 只有该地址当时能够响应 SSH 时,两条命令才会执行 (ADR 0013)。clawops harden --tailscale-revert会将主机移出 tailnet,并让 clawops 恢复使用其公共地址。对于仅限私有网络的堆栈,该命令会拒绝执行,并打印重新开放 SSH 的命令。clawops destroy会从堆栈 tailnet 上移除主机两个地址的主机密钥,而不是继续固定已不复存在的实例所对应的公共地址。
安全加固覆盖三种云平台
- Azure:NSG 审计、磁盘加密、Defender for Cloud 和 JIT VM 访问,均仅检查。
- GCP:VPC 防火墙审计、Shielded VM 和 OS Login,均仅检查。
- GCP 实例启动时会启用 Secure Boot。现有堆栈会通过更新启用该功能,同时保留启动磁盘和所有 OpenClaw 状态。
- 无法执行的检查会报告为已跳过,并说明缺少什么,而不会报告为通过。
计划会说明将影响哪些内容
clawops plan会统计并列出将被替换的资源。此前,它会把一个将销毁实例及其启动磁盘的预览总结为“创建 0 项,更新 0 项”。- 如果计划会更改正在运行的部署,会在应用前发出警告:替换操作会说明哪些内容将一并移除,并指向
clawops backup create;更新操作会说明网关将会停机。
修复
- 从 npm 安装时,
clawops mcp serve完全无法启动——它会在导入阶段崩溃,尚未发送任何协议内容,因此所有 MCP 客户端都收不到任何内容。现在pnpm verify:pack会与打包后的 tarball 通过 MCP 通信,确保此类故障不再发布。 - MCP 注册表清单
server.json现在与软件包一同进行版本管理,而不是在发布时重写。已提交的文件曾显示1.7.3,而发布版本却是2.0.2。 - 已发布的软件包现在包含许可证、关键词和问题跟踪器信息,因此可以在 npm 上搜索到,且软件包页面信息完整。
2.1.1
clawops不带命令启动且标准输入为管道时,会提供 MCP 服务,而不是打印帮助信息。 每个 MCP 客户端都是这样启动服务的,能推断运行命令的目录也会这样启动;此前有几个目录收到 帮助文本后,报告服务已损坏。在终端中输入clawops仍会打印帮助信息,clawops | less也一样。- MCP 配置示例为
npx -y @clawops/cli mcp serve,可以直接运行。以前写的是/path/to/clawops,无法运行,也没有目录能复制使用。 - 描述符合 MCP 注册表的 100 个字符限制。2.1.0 随附的描述有 110 个字符,npm 发布后注册表以 422 错误拒绝了它,因此 2.1.0 发布到了 npm,却没有发布到注册表。
clawops harden会说明堆栈尚未部署,或无法读取其状态,而不是直接传递code: -2和子进程转储。- MCP 注册表回填会注册已发布的版本,而不是发布工具正在准备的版本,因此落后的条目可以得到修复。
- Docker 镜像现在可以构建了。此前它从未成功构建过:
npm pack --pack-destination不会创建目标目录。CI 中的pnpm verify:docker会构建镜像,并通过入口点和裸二进制与运行中的容器通信,验证 MCP 服务。
2.1.2 and 2.1.3
- 每个 MCP 工具都会发送描述,其每个参数也都有说明。客户端此前看到的 19 个工具只有名称和架构,没有描述。
clawops_init可以通过 MCP 注册堆栈,让客户端从零开始完成初始化。它会写入配置并生成 SSH 密钥,但不会配置任何资源。- 无法显示确认提示的客户端会收到指示,要求询问用户并以
yes: true再次调用,而不是遇到Client does not support form elicitation崩溃。 - Docker 镜像包含
ssh-keygen和 CA 证书包;缺少它们就无法生成密钥,也无法访问任何 HTTPS 端点。
2.0.1 新增内容
这是一个内容丰富的补丁版本:在 2.0.0 中,无论通过哪种方式都无法成功部署到云端。以下各项都是 2.0.1 中的修复或新增内容。
每项背后的原因都写在对应的提交说明中,由此做出的决策记录在 docs/decisions/ 中。
部署到云端
clawops plan→clawops apply会配置云堆栈,并在其上部署 OpenClaw。clawops up会部署到 AWS、GCP 和 Azure,执行与plan→apply相同的流程。- clawops 会将所需的 Pulumi CLI 安装到
~/.clawops/.pulumi-cli,或者使用$PATH中已有的兼容版本 (ADR 0010)。 - clawops 会创建并存储其状态后端所需的密码短语 (ADR 0011)。
clawops plan接受--ssh-cidr、--gateway-cidr和--publish-gateway,apply会将这些参数传递给云防火墙。auto会解析此计算机的地址。- 无法打开状态后端时,
clawops plan会停止并说明原因。 --instance-type接受 clawops 别名(micro–gpu),或云服务商命名的机器类型;计划会记录具体类型。- 部署会固定使用生成计划时所针对的账户:GCP 上的
gcp:project,Azure 上的azure-native:subscriptionId。
付费前检查账户
clawops doctor --provider <cloud>会检查一个云平台的凭据和账户设置,无论是否已有堆栈。--instance-type用于指定要部署的实例规格,以便检查该规格。- AWS:凭据解析出的账户、状态存储桶,以及该区域是否提供此实例规格。
- GCP:项目、部署所需的 API,以及状态存储桶。
- Azure:订阅、资源提供程序、VM 规格,以及 Pulumi 用于身份验证的 azblob 凭据。
clawops setup会运行相同的检查,并提供修复它能够安全修复的问题;例如启用 API,或创建启用了版本控制且禁止公开访问的状态存储桶,并在操作前说明变更内容。- clawops 无法执行的检查会报告为警告,并指出错误,而不是报告为通过或失败。
- Azure 支持使用你的
az login;不再需要服务主体。
命名、配置和设置
- clawops 会根据部署目标账户为状态后端命名,而不是要求你提供名称或写入占位名称 (ADR 0012)。
- 如果你自行输入名称,系统会根据相应云平台的命名规则进行检查。
clawops init会保留配置中已有的堆栈。clawops init会生成 clawops 能够读取的 SSH 密钥。如果你在此版本发布前运行过init,clawops doctor会告知你的密钥是否可用。- 系统会遵循
gcloud config set project的设置。 - 设置向导会写入 OpenClaw 接受的模型配置,并安装所选提供商所需的插件。
- Amazon Bedrock 可正常使用:采用正确的传输方式,并根据部署区域解析推理配置文件,再将其记录到计划中。需要
bedrock:ListInferenceProfiles。
部署运行期间
apply会先等待 SSH 就绪,再等待网关响应,然后才报告成功。apply会持续报告进度,不再静默等待数分钟。- 部署超时时,会从主机的引导日志中打印主机正在执行的操作。
- 主机仍在安装 Docker 时,会被视为仍在启动,而不是部署失败。
部署后的日常命令
clawops logs会从 AWS 上的网关读取日志。doctor --stack、ssh、logs、gateway、config和agents可用于刚部署完成的堆栈。clawops doctor会验证云凭据。- clawops 会区分被拒绝访问的 Docker 套接字和缺失的容器,并说明检测到的是哪一种情况。
clawops destroy会清除实例的主机密钥,因此重新部署到云平台回收后重新分配的地址时,不再会因验证失败而报错。
文档
- GCP 指南会说明 clawops 实际读取的凭据来源,并介绍 2.0 的防火墙行为。
- 冒烟测试计划涵盖 2.0,
pnpm test:cloud aws|gcp|azure会针对真实部署运行该计划,并在之后销毁部署。
2.0 新增内容
clawops 2.x 面向 OpenClaw >= 2026.9.2。1.x 系列会以 legacy dist-tag 继续支持 OpenClaw
<= 2026.7.1-2,直至 2027-03-31:
npm install -g @clawops/cli # 2.x
npm install -g @clawops/cli@legacy # 1.x maintenance
在 CI 中固定标签。latest 会指向 2.x,因此未固定版本的流水线将切换到新系列。
CHANGELOG.md 记录了完整的更新历史;本节介绍的是 clawops 行为方式 的变化。
部署状态会得到保留
OpenClaw 2.0 使用 SQLite 存储会话、转录记录和凭据。clawops 之前完全没有挂载状态,因此每次重启都会将它们全部清除;而 gateway restart、gateway update 和 config set 都会触发重启。
现在,主机目录 /var/lib/clawops/openclaw 会绑定挂载到 OpenClaw 自己的默认位置,用于保存配置、数据库和任何提供商插件。现有部署会在下次运行 up/apply 时迁移。
clawops up / clawops apply
flowchart TD
A["clawops plan"] --> B{"config valid<br/>against OpenClaw schema?"}
B -- no --> B1["refuse: plan is still<br/>a file you can edit"]
B -- yes --> C["clawops apply"]
C --> D{"OpenClaw version<br/>in supported range?"}
D -- no --> D1["refuse: names<br/>@clawops/cli@legacy"]
D -- yes --> E["provision host"]
E --> F["state dir, owned 1000:1000<br/>migrate any pre-2.0 config"]
F --> G["write config<br/>validated before writing"]
G --> H["install provider plugins<br/>while egress exists"]
H --> I["start gateway"]
I --> J{"/startupz says started?"}
J -- no --> J1["fail with the reason"]
J -- yes --> K{"configured providers<br/>all loaded?"}
K -- no --> K1["warn: healthy gateway,<br/>missing model backend"]
K -- yes --> L["done"]
其中有三个步骤是新增的,每个步骤的存在都是因为旧流程可能在出错时仍报告成功:写入前从未验证配置,提供商插件要等到启动时才获取(或者在默认拒绝所有流量的主机上悄无声息地缺失),而“已启动”则是根据 docker run 以 0 退出码结束来推断的。
clawops gateway update
以前的流程是:拉取、运行、报告成功。docker run 以 0 退出码结束,表示容器已创建,而它替换的容器已经消失。
flowchart TD
A["clawops gateway update X"] --> B{"X in supported range?"}
B -- no --> B1["refuse before pulling"]
B -- yes --> C["docker pull X"]
C --> D["snapshot state database"]
D -- cannot snapshot --> D1["refuse: no rollback point"]
D --> E{"target release understands<br/>this schema?"}
E -- no --> E1["refuse: downgrade across<br/>a schema boundary"]
E -- yes --> F["swap container"]
F --> G{"/startupz says started?"}
G -- yes --> H["done"]
G -- no --> I["one-shot doctor --fix<br/>in a throwaway container"]
I --> J["re-run, re-gate"]
J -- started --> K["done: reported as repaired"]
J -- still not --> L["roll back to previous image"]
L -- started --> M["rolled back, reason reported"]
L -- still not --> N["failed: snapshot path named"]
快照不仅是回滚点:database preflight 会拒绝正在运行的数据库,因为架构版本位于 WAL 中,直到检查点操作完成才会写入数据库;因此,只有整合后的快照才能进行兼容性检查。
clawops gateway restart
重启既不会改变已部署的版本,也不会改变谁能访问网关。这两项信息都会从正在运行的容器中读取,而不是靠猜测:
flowchart LR
A["gateway restart"] --> B["read current image"]
B -- no container --> B1["refuse: nothing to reuse.<br/>latest and stable point at 2.0"]
B --> C["read current publish scope"]
C --> D["recreate with the same<br/>version and reachability"]
D --> E{"/startupz says started?"}
E -- no --> E1["fail with the reason"]
E -- yes --> F["done"]
迁移现有的 1.x 部署
flowchart TD
A["clawops migrate"] --> B{"1.x container running?"}
B -- no --> B1["nothing to rescue: state was<br/>already lost to an earlier restart"]
B -- yes --> C["verified backup, inside the running container"]
C -- "backup fails" --> C1["refused: nothing touched"]
C --> D["extract state from the RUNNING container"]
D --> E["chown 1000:1000"]
E --> F["stop and remove 1.x"]
F --> G["synthesise a valid 2.0 config"]
G --> H["start 2.0 with the state directory"]
H --> I{"/startupz started?"}
I -- "no: schema still migrating" --> J["restart once"]
J --> K{"started?"}
K -- no --> K1["failed: points at the backup"]
K --> L["report"]
I -- yes --> L
L --> M["what carried over,<br/>device identity, config to review"]
这种迁移方式有两点不太显而易见,而它们都来自一次真实的迁移:
从正在运行的容器中提取状态。 所有 1.x 状态都位于容器内,clawops 没有挂载任何内容,因此先停止容器会摧毁此次迁移要挽救的数据。
配置是合成生成的,不是沿用旧配置。 1.x 从未有过可用的配置;clawops 挂载的文件没有任何程序读取。旧设置会被报告为待审核意向,绝不会盲目应用。它们的通道配置块无论如何都无法通过 2.0 的验证。
网关还需要启动两次:第一次会执行状态架构迁移,并报告迁移仍在等待完成。migrate 会等待第二次启动,而不会过早宣告成功。
如果你在 2.0 之前对 clawops 运行过 gateway restart、gateway update 或 config set,那么你的状态已经丢失;当时没有挂载任何内容来让它在容器替换后保留下来。migrate 会如实说明,而不会假装能够挽救它。
clawops backup restore 恢复可用,但绝不会原地还原
v1.7.5 会说明原因并让还原失败,因为它支持的 OpenClaw 没有可调用的还原子命令。2.0 有了,因此 clawops 会将操作交给它:
flowchart TD
A["clawops backup restore --file X"] --> B["upload archive to the host"]
B --> C["openclaw backup restore --target <staging>"]
C -- "target not empty" --> C1["refused by OpenClaw"]
C --> D["archive verified, expanded<br/>into a fresh directory"]
D --> E["warnings printed verbatim<br/>time travel, channel relink,<br/>approvals, plugins"]
E --> F["nothing activated"]
F --> G["you stop the gateway, swap the<br/>state dir, restart, re-apply"]
clawops 不会自行解压归档,也不会原地还原。最后一步特意保留为手动操作;重新应用配置也很重要:归档不包含插件的 node_modules,因此还原后的部署启动时不会有模型提供商,看起来健康,实际上却无法工作。
归档文件包含凭据。 其中包含状态数据库、mcp_oauth_stores、secret_store_entries、worker_environment_credentials、device_auth_tokens,且均未加密。clawops 现在会在本地以 0600 权限写入;此前使用的是默认权限 0644。
需要插件的模型提供商会自动为你安装
OpenClaw 2.0 将模型提供商变成了必须安装插件才能使用的组件。镜像中包含 24 个插件,其中有 anthropic、openai、google、ollama、openrouter,但并非全部。如果配置了未捆绑的提供商却没有安装它,网关仍会启动并报告健康,但没有模型后端。
clawops 会在 apply 期间安装配置所需的组件,并固定到确切版本:
Resolving clawhub:@openclaw/[email protected]…
Downloading plugin @openclaw/[email protected] from ClawHub…
Installed plugin: deepseek
这增加了 1.x 系列没有的出站依赖:clawhub.ai。 运行 apply 时需要访问它,启动时则不需要。之所以这样设计,是为了让失败直接告知运行命令的人,而不是凌晨 3 点才让受限主机暴露问题。若访问被阻止,情况会是这样:
fetch failed | getaddrinfo EAI_AGAIN clawhub.ai | EAI_AGAIN
clawops 随后会检查已安装的提供商 ID;如果配置的提供商缺失,就不会将部署标记为完成。所需的出站访问列出了每个目标地址及其所需时机。
也会为你安装聊天渠道
OpenClaw 2.0 中的每个渠道都是需要安装的插件。clawops apply 会在部署期间、网络出口可用时安装配置中指定的渠道,然后询问网关确认它们是否确实已安装:
[clawops] warning: the gateway is running, but these configured channels are not installed:
discord. They will never connect.
它必须先询问。openclaw channels add 这个看似显而易见的命令,即使插件安装失败也会返回成功,因此 clawops 使用 openclaw plugins install,并通过 channels list --all --json 验证。
渠道插件会固定到受支持的运行时版本。当前的 latest 版本无法安装:plugin "discord" requires plugin API >=2026.9.3, but this OpenClaw runtime exposes 2026.9.2。这与模型提供商需要固定版本的原因相同。
Telegram 无需安装任何东西:它已包含在镜像中。
错误配置会在写入前被拦截
配置会依据从镜像中获取的 OpenClaw 自有架构 进行验证,而非依据手写的架构;在发送到主机之前会验证一次,在写入替换现有可用文件之前还会再验证一次。clawops plan 会拒绝网关会拒收的配置方案,此时方案仍是可编辑的文件。
被拒绝的配置会保存在 <path>.rejected.<timestamp>,现有配置文件保持不变,因此验证失败不会导致你想写入的配置丢失。
其中一条规则由 clawops 自行规定:架构中 gateway.mode 是可选项,但实际使用时必填。不包含该项的配置可以通过 openclaw config validate,随后程序却会以退出码 78 退出。
容器已加固
网关使用 --cap-drop=ALL、--security-opt no-new-privileges、--init 和 --pids-limit 512 运行。状态文件的所有者以数字 1000:1000 指定,与容器内的用户匹配,而不是使用可能没有该 uid 的主机账户。
版本固定会在所有可能更改版本的操作中强制执行
doctor、plan、up 和 apply 都会拒绝不在受支持范围内的 OpenClaw 版本;gateway restart 会沿用已部署的版本,而不会解析可能变化的标签。重启既不会更改版本,也不会改变可访问该网关的人员。
网关不再暴露给你的网络
容器现在发布到 127.0.0.1:18789,而不是 0.0.0.0:18789。请使用 clawops tunnel,或在主机上使用反向代理来访问。
此前,向导会根据你提供的 SSH CIDR 设置 allowedGatewayCidrs,因此明文 HTTP 控制面板(URL 中包含令牌)会因一个无关的回答而向整个可通过 Shell 访问的网络开放。若要有意绑定到所有网络接口,请设置 network.publishGateway: "all"。
如果 另一台机器上的客户端或反向代理会直接访问网关,或者外部监控会访问 /health,你必须采取措施。主机上的代理不受影响;主机上的容器内的代理需要使用 --network host。
健康检查现在确实能检测到故障
网关通过兜底路由提供其控制界面,因此 任何未匹配的路径都会返回 200 和 HTML:
/healthz 200 application/json {"ok":true,"status":"live"}
/health-typo 200 text/html <!doctype html>…
clawops 使用 curl -fsS … >/dev/null 进行探测,拼错路径也会成功。这只能证明端口上有进程在监听,并不能证明网关健康。现在探测会读取响应正文,重启门控则使用 /startupz 而非存活检查;重启后,进程开始监听的时间远早于启动完成的时间。
clawops mcp wire 现在确实会进行配置
它以前从未正常工作过,无论是 2.0 还是任何 1.x 版本。它会写入 gateway.mcpClients,但 OpenClaw 并没有这个键:我们核对了 2026.4.5、2026.7.1-2 和 2026.9.2 的配置架构。真正的键是顶层的 mcp.servers。而且它写入的条目是通过 stdio 执行 command: "clawops",这会在网关容器内启动 clawops,但容器里既没有安装 clawops,也没有任何安装它的操作。
在 1.x 版本中,写入的配置不会经过验证,因此 clawops 会存储一个无人读取的键,重启你的网关,然后报告:“网关的 AI 现在可以运行 clawops 命令了。” 实际上并不能。
flowchart TD
A["clawops mcp wire"] --> B["openclaw mcp add --transport streamable-http"]
B --> C{"gateway connects<br/>to the URL?"}
C -- no --> C1["probe fails, nothing saved,<br/>clawops prints the reason"]
C -- yes --> D["saved to mcp.servers.clawops"]
D --> E["openclaw mcp reload"]
它现在会委托给 openclaw mcp add,该命令会在保存前探测服务,因此“已配置”意味着网关已连接,而不只是写入了文件。
你必须自行运行服务。 网关主机上没有安装 clawops:
clawops mcp serve --http 18790 --bind 0.0.0.0 --token "$(openssl rand -hex 16)"
clawops mcp wire --stack prod --token <same token>
在网关主机上安装 clawops 是有意留待后续处理的事项,不属于 2.0 的范围:这会将部署凭据放在已部署的主机上,而且网关的 AI 可通过它连接的每个渠道访问。请参阅 docs/security/threat-model.md T11。
clawops mcp serve --http 可以为多个客户端提供服务,并会询问你是谁
通过对真实网关而非模拟对象进行测试,我们发现了两个 bug。
它为整个进程创建了一个传输,因此第一个连接的客户端会独占它,之后的客户端都无法使用。第二个编辑器、重新连接的客户端以及网关自身的探测都会收到 "Server already initialized"。HTTP 模式本来就是多客户端模式。
它没有身份验证,却暴露了包括 clawops_destroy 在内的所有工具。现在它会接收一个 bearer token,以恒定时间进行比较,并且没有令牌时会拒绝绑定到回环地址以外的任何地址。
防火墙规则会与部署保持一致
flowchart TD
A["clawops plan"] --> B{"publishGateway?"}
B -- "loopback (default)" --> C{"allowedGatewayCidrs empty?"}
C -- no --> C1["refuse: those rules would admit<br/>traffic to a closed port"]
C -- yes --> D["SSH rules only"]
B -- all --> E["SSH rules + gateway rules<br/>on spec.network.gatewayPort"]
D --> F["clawops harden"]
E --> F
F --> G["read the container's port bindings"]
G --> H{"published to the network?"}
H -- no --> H1["ufw: SSH only"]
H -- yes --> H2["ufw: SSH + the published port"]
有三项安全控制的实际行为与其声明完全相反。
clawops harden 会在每次部署时开放网关端口。 ufw 模块会无条件运行 ufw allow 18789/tcp。由于网关发布在 127.0.0.1 上,这会开放一个没有任何程序在监听的端口。加固步骤反而扩大了防火墙开放范围,超出了部署实际暴露的范围。现在它会读取运行中容器的端口绑定,并且仅当网关确实已发布时才添加规则,使用网关实际发布的端口。
AWS 安全组审计豁免了它本应检查的两个端口。 22 和 18789 端口列在“预期”清单中,因此,如果某个安全组将 SSH 或网关开放给 0.0.0.0/0,审计结果仍会是“未发现意外的开放入站规则”。此外,它从未读取 IPv6 规则,因此看不到 ::/0。
设置向导默认将 SSH 访问范围设为 0.0.0.0/0。 按 Enter 键就会将 SSH 开放给整个互联网,而这是大多数首次使用者会采用的流程。现在它会将你的 IP 地址作为 /32 提供;如果无法检测到 IP 地址,则不提供默认值,必须由你填写。
clawops plan 无法表达这些设置,而且 apply 从未将它们传递给 Pulumi。 这两个问题已在 2.0.1 中修复。请参阅本节顶部的列表。
网关端口取自计划
"network": {
"allowedSshCidrs": ["203.0.113.4/32"],
"allowedGatewayCidrs": [],
"publishGateway": "loopback",
"gatewayPort": 9443
}
现在,安全组规则、容器发布标志、默认的 gateway.port 和网关 URL 都使用同一个值。之前该值是在 11 个地方重复声明的常量,因此更改时必须逐一查找,漏掉任何一个地方都会导致容器发布一个端口、网关监听另一个端口、防火墙却开放第三个端口。
本地部署可使用 clawops up --gateway-port 9443。
clawops doctor 会判断服务是否正常,并通过退出码报告结果
flowchart TD
A["clawops doctor"] --> B["local: Node, Pulumi CLI + home,<br/>config, SSH key, credentials"]
B --> C{"--stack given?"}
C -- no --> Z["report"]
C -- yes --> D["container state"]
D --> E["deployed OpenClaw version"]
E --> F["probe /startupz<br/>and read the body"]
F --> G["published scope, disk,<br/>log rotation, hardening drift"]
G --> Z
Z --> Y{"any check failed?"}
Y -- no --> Y1["exit 0"]
Y -- yes --> Y2["exit 1"]
有三项变更:
它会向网关发起请求。 以前,doctor 会读取 docker inspect 的健康检查字段,但 OpenClaw 镜像未设置该字段,因此它会报告“未配置健康检查”后继续执行。容器正在运行,只能说明进程已启动,并不代表它能提供服务。现在它会探测 /startupz 并读取响应正文。
出现故障时,它会以 1 退出。 以前,只有 Node.js 版本过旧时才会这样;SSH 密钥无法读取或网关不受支持时,退出码都是 0,因此运行 clawops doctor 的 CI 步骤会把故障部署误判为成功。警告仍以 0 退出;没有任何堆栈的新机器属于尚未配置,而不是发生故障。
它是一个 MCP 工具。 clawops_doctor 会以结构化数据返回相同的报告,因此遇到故障的 Agent 可以查明原因。它只报告问题;绝不会运行 openclaw doctor --fix。--json 会让 CLI 返回相同的报告。
clawops agents list 不再编造空列表
该命令末尾有 || echo '[]',所以容器已停止、网关仍在启动或 Docker 权限错误都会导致它显示 “没有正在运行的 Agent。”,这不是错误提示,而是错误答案。现在命令会失败,并说明原因。
日常运维命令现已支持 AWS
gateway restart、logs、monitor、backup、agents、config set 以及 doctor 的容器检查在 AWS 上都无法正常运行:clawops 以 ubuntu 身份连接,但配置过程只将 clawops 加入了 docker 组,因此所有 Docker 命令都会因 permission denied 而失败。GCP 和 Azure 使用 clawops 身份连接,因此只有 AWS 受影响。
已移除
clawops agents restart 和 clawops_agents_restart MCP 工具。OpenClaw 2.0 不支持重启单个 Agent,只有 gateway restart 和 daemon restart,这两者都会中断主机上的所有 Agent。请使用 clawops gateway restart,或继续使用 @clawops/cli@legacy。
clawops agents list 和 clawops agents logs 不受影响。
里程碑
| 里程碑 | 状态 | 发布内容 |
|---|---|---|
| M0:脚手架 | ✅ | 工具链、CI、存根、生成的类型 |
| M1:GCP MVP | ✅ | 在 GCP 上支持 init / up / down / status / ssh / logs |
| M2:远程管理 | ✅ | tunnel、config、agents、gateway;SSH 连接池 |
| M3:AWS + Azure | ✅ | AWS EC2 + Azure VM 适配器;stacks list |
| M4:本地 VM | ✅ | 本地适配器(SSH 引导,无需 Pulumi);doctor |
| M5:MCP 层 | ✅ | mcp serve(stdio)、所有 CLI 操作均可作为 MCP 工具使用、进度跟踪 |
| M6:计划/应用 | ✅ | plan + apply;deploy-plan 架构;MCP HTTP 传输;workflow_deploy_app |
| M7:v1.0 润色 | ✅ | 完整的 doctor 功能;destroy 命令;各命令均支持 --dry-run;CI 指南 |
有关公开路线图和后续工作,请参阅 docs/roadmap.md。
许可证
MPL-2.0,详见 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。