clawops
Implementa y opera OpenClaw autoalojado en AWS, GCP, Azure y máquinas virtuales locales: una CLI y un servidor MCP en uno. Los cambios de infraestructura pasan por un plan de despliegue que revisas antes de aplicar, las herramientas destructivas confirman primero, y cada llamada se registra en un registro de auditoría.
Documentación
clawops
Operaciones de infraestructura nativas de MCP para OpenClaw, con modo de solo lectura, confirmación de acciones destructivas y registros de auditoría integrados.
clawops es una CLI y un servidor MCP para implementar y operar instancias de OpenClaw autoalojadas. Aprovisiona en AWS, GCP, Azure o cualquier VM Linux, y luego gestiona las operaciones diarias desde la terminal, o permite que Claude Code y Cursor las controlen mediante herramientas MCP tipadas con controles de seguridad explícitos.
Novedades: notas de la versión 2.0.1 y 2.0 a continuación, y el historial completo en CHANGELOG.md.
Para quién es esto
- Usuarios de OpenClaw que quieren la ruta más simple para autoalojarse en la nube o en VMs locales, con implementación confiable, verificaciones de estado, registros, copias de seguridad y actualizaciones en una sola CLI.
- Usuarios de Claude Code / Cursor / MCP que buscan una implementación de referencia del mundo real de operaciones de infraestructura seguras a través de MCP. Esquemas de herramientas tipados, modo de solo lectura, confirmación de acciones destructivas y registros de auditoría.
- Desarrolladores de IA autoalojada y local-first que quieren ejecutar su propio asistente de IA sin comprometerse con Kubernetes, una plataforma SaaS gestionada o un único proveedor de nube.
Qué hace clawops
- Aprovisiona y elimina infraestructura de OpenClaw en AWS, GCP, Azure y VMs locales usando
la API de Automatización de Pulumi. No necesitas instalar Pulumi; clawops instala la CLI que necesita en
~/.clawops/.pulumi-clien el primer uso. - Gestiona las operaciones diarias: estado, registros, SSH, túneles, configuración, agentes, gateway, copias de seguridad.
- Expone cada operación como una herramienta MCP tipada para que los agentes de IA puedan operar de forma segura.
- Aplica una disciplina de plan → revisión → aplicación para implementaciones en la nube.
- Emite salida JSON en todas partes (
--json) para scripting y automatización. - Nunca almacena credenciales de nube. Las lee de los perfiles CLI existentes en tu entorno.
Qué no hace clawops
- Sin alta disponibilidad ni clustering. Optimizado para implementaciones de un solo nodo.
- Sin Kubernetes. Implementa en VMs, no en plataformas de orquestación de contenedores.
- Sin creación de habilidades/agentes de OpenClaw. clawops gestiona la infraestructura; lo que se ejecuta en ella depende de ti y de OpenClaw.
- Sin automatización de TLS o dominios (por ahora). Trae tu propio proxy inverso o consulta
docs/limitations.mdpara la ruta manual. - Sin almacenamiento de credenciales. Las credenciales de nube deben configurarse en tu entorno antes de usar
clawops. Nunca se escriben en
~/.clawops/config.json. - Sin Windows nativo. WSL2 es totalmente compatible; consulta
docs/support-matrix.md.
Inicio rápido
npm install -g @clawops/cli
clawops setup
clawops setup es un asistente interactivo que pone OpenClaw en funcionamiento en unos 2 minutos. Maneja
todo en un solo flujo, sin archivos de configuración que escribir a mano, sin comandos que memorizar.
Qué hace el asistente
Paso 1. Elige un objetivo de implementación
Elige un servidor existente al que puedas acceder por SSH (Linux o macOS), o una nueva VM en la nube en AWS, GCP o Azure. Las implementaciones en la nube te guían para autenticarte con la CLI del proveedor si aún no has iniciado sesión.
Paso 2. Elige un proveedor de LLM
Elige entre Anthropic, OpenAI, Amazon Bedrock, Ollama u otros. El asistente solicita tu
clave de API y la guarda localmente (en ~/.clawops/secrets/, chmod 600); nunca se envía a ningún lugar
excepto a OpenClaw en el host de destino cuando se aplica la configuración.
Paso 3. Añade integraciones de chat (opcional)
Selecciona cualquier combinación de Discord, Telegram, Slack, WhatsApp o Teams. El asistente recopila el token de bot de cada integración de la misma manera que la clave de API. Pégalo, referencia una variable de entorno o apunta a un archivo.
Paso 4. Conecta tu editor de IA
Selecciona qué aplicaciones de IA deben tener acceso a clawops. Claude Desktop, Claude Code, Cursor, Windsurf, VS Code y Zed son compatibles. El asistente escribe una entrada de servidor MCP en el archivo de configuración de cada aplicación usando la ruta binaria absoluta para que la aplicación pueda iniciarlo de forma independiente.
Paso 5. Implementa
El asistente arranca OpenClaw en el host de destino a través de SSH (instala Docker, extrae la imagen, inicia el contenedor), aplica tu configuración de LLM e integraciones, genera un token de autenticación de gateway e imprime una URL directa del panel:
✔ 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
Requisitos previos: Node.js ≥ 22, una clave SSH y un host Linux/macOS accesible por SSH o una
cuenta en la nube con credenciales CLI configuradas (aws configure, gcloud auth login o az login).
No necesitas Pulumi. La primera implementación en la nube instala la CLI que clawops utiliza en
~/.clawops/.pulumi-cli y lo indica mientras lo hace.
Para un recorrido completo narrado con salida de ejemplo, consulta docs/demo-script.md.
Configuración manual, servidor existente
Si prefieres un control paso a paso, o estás añadiendo clawops a una implementación ya en ejecución:
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
Consulta docs/examples/local-vm.md para requisitos previos de SSH, configuración
del firewall y solución de problemas.
Configuración manual, nube (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 permite SSH desde la IP pública de esta máquina, resuelta mientras se genera el plan y
escrita en él. Sin él, el plan no permite ninguna entrada y nada,
incluido clawops, podrá conectarse.
Conecta un editor de IA
El asistente setup maneja esto automáticamente (Paso 4). Para conectar o reconectar editores en cualquier momento:
clawops mcp install
Esto abre la misma casilla de verificación interactiva utilizada en el asistente; selecciona Claude Desktop, Claude Code, Cursor, Windsurf, VS Code o Zed y clawops escribe la entrada MCP en la configuración de cada aplicación usando la ruta binaria absoluta correcta.
Para añadir la entrada manualmente, pega esto en la configuración MCP de tu editor:
{
"mcpServers": {
"clawops": {
"command": "npx",
"args": ["-y", "@clawops/cli", "mcp", "serve", "--read-only"]
}
}
}
Esa forma no necesita nada en $PATH y es lo que un directorio o un instalador copiará. Si
prefieres apuntar al binario que ya tienes, usa su ruta absoluta — la salida de
which clawops — con los mismos argumentos:
{
"mcpServers": {
"clawops": {
"command": "/path/to/clawops",
"args": ["mcp", "serve", "--read-only"]
}
}
}
De cualquier manera, pasa los argumentos. mcp serve es lo que habla el protocolo, y una configuración explícita
es una que aún se lee claramente un año después. clawops no abandona a un cliente que los omita:
ejecuta sin ningún comando y con una tubería en stdin — así es como cada cliente MCP inicia un servidor — y
inicia mcp serve, indicándolo en stderr. Escrito en una terminal, clawops aún imprime ayuda.
Ubicaciones de archivos de configuración:
| Aplicación | Ruta |
|---|---|
| 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 (clave: context_servers) |
Comienza con --read-only. Habilita estado, registros, lecturas de configuración y diagnósticos mientras
bloquea mutaciones. Elimínalo solo después de revisar
docs/security/mcp-safety.md.
Las herramientas destructivas (clawops_destroy, clawops_up, clawops_config_set, etc.) requieren confirmación
explícita antes de ejecutarse; nunca se ejecutarán en silencio.
Para la configuración del modo HTTP, consulta docs/mcp/.
Operaciones diarias
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
Comandos
| Comando | Descripción |
|---|---|
setup | Asistente de primera ejecución: LLM guiado, integraciones y generación de plan de implementación |
init | Registra un stack en ~/.clawops/config.json sin aprovisionar. Aditivo; los stacks existentes se conservan; --force solo se necesita para sobrescribir uno |
up | Aprovisiona o actualiza el stack (--dry-run para vista previa, --gateway-port para un puerto no predeterminado) |
down | Destruye el stack del proveedor local (requiere --yes; --dry-run muestra las salidas actuales) |
destroy | Destruye el stack del proveedor de nube con mensaje de confirmación (--dry-run muestra las salidas actuales) |
status | Muestra las salidas del stack: IP, URL del gateway, región, tiempo de aprovisionamiento |
plan | Genera un artefacto JSON de plan de implementación (seguro en seco). --ssh-cidr <list|auto> y --gateway-cidr deciden quién puede conectarse; --publish-gateway loopback|all decide qué está escuchando; --private-only cierra el acceso público en un stack alcanzado a través de su tailnet |
apply | Aplica un archivo de plan previamente revisado (--dry-run valida y muestra el diff sin aplicar) |
ssh | Sesión SSH interactiva o ejecuta un comando remoto |
logs | Transmite registros de OpenClaw (-f, --tail N, --since 5m) |
tunnel | Reenvío de puerto local a la interfaz del gateway a través de SSH |
config | Obtiene/establece valores de configuración remotos de OpenClaw (--dry-run muestra el JSON que se escribiría) |
agents | Lista los agentes de OpenClaw o transmite los registros de un agente |
gateway | Reinicia el servicio del gateway de OpenClaw |
backup | Crea y restaura copias de seguridad del estado de OpenClaw (restore se expande en un directorio de preparación, nunca en el lugar) |
stacks | Lista los stacks nombrados y su estado |
doctor | Verifica la máquina local; con --stack, también la salud de la implementación; con --provider, las credenciales y la configuración de la cuenta de una nube exista o no un stack; con --instance-type, las verificaciones de cuenta preguntan sobre ese tamaño en lugar del predeterminado del proveedor. --json para el informe. Sale con 1 en cualquier fallo |
secret | Gestiona secretos: list, set, delete, rotate, audit |
monitor | Panel en vivo: salud del gateway, estadísticas de contenedores, cola de registros, selector de stacks |
mcp serve | Inicia el servidor MCP integrado (stdio, o HTTP con --http <port> --token <t>) |
mcp install | Conecta interactivamente clawops a editores de IA |
mcp wire | Conecta la IA del gateway como cliente MCP de clawops (verifica la conexión antes de guardar) |
help | Lista todos los comandos y banderas globales |
harden | Aplica endurecimiento de seguridad a un stack implementado (SSH, UFW, fail2ban, unattended-upgrades, socket de Docker; AWS: auditoría de SG, verificación de SSM, Flow Logs, GuardDuty). --tailscale une el stack a tu tailnet y mueve clawops a esa dirección una vez que responde; --tailscale-revert lo deshace |
bug | Abre un problema de GitHub prellenado con contexto del sistema desde doctor |
Referencia completa de banderas: clawops <command> --help
Flujo de trabajo Plan → Aplicar
Para proveedores no locales, clawops aplica una disciplina de revisión antes de aplicar:
# 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
El JSON del plan se ajusta a spec/deploy-plan.schema.json (validado por AJV) y captura la intención
revisada: proveedor, región, tipo de instancia, rangos CIDR y versión de OpenClaw. apply vuelve a ejecutar
pulumi up usando esos parámetros contra el estado vivo actual; no reproduce un artefacto de ejecución
bloqueado. Revisa y aplica en la misma sesión para minimizar el riesgo de desviación.
Consulta docs/plan-apply.md para la semántica completa, la guía de desviación y el patrón CI seguro.
Servidor MCP
clawops incluye un servidor MCP integrado. Claude Code, Cursor y cualquier agente compatible con MCP pueden controlar implementaciones sin salir de la interfaz de chat.
Conecta tu editor
clawops mcp install # interactive checkbox: writes config for selected apps
El asistente resuelve la ruta binaria absoluta automáticamente para que los lanzadores de aplicaciones puedan encontrar clawops
sin heredar el PATH de tu shell. Consulta Conecta un editor de IA arriba
para rutas de configuración manuales.
Conecta la IA del gateway
El gateway de OpenClaw ejecuta su propio agente de IA. Una vez conectado, ese agente puede llamar a clawops directamente en lugar de adivinar el estado de la infraestructura:
clawops mcp wire --stack prod # write MCP client entry into gateway config + restart
Requiere OpenClaw ≥ 2026.4 en el gateway. El asistente clawops setup ofrece este paso
automáticamente después de una implementación exitosa.
Modo Stdio (Claude Code / Cursor / VS Code)
Inicia el servidor manualmente o confirma que tu configuración es correcta:
clawops mcp serve --read-only # safe for first evaluation
clawops mcp serve # full mode: enables provisioning, config write, ssh exec
Modo HTTP (remoto / multi-cliente)
clawops mcp serve --http 3333 --bind 127.0.0.1
# MCP HTTP server listening on 127.0.0.1:3333
No te vincules a una dirección que no sea de loopback sin controles de autenticación adicionales delante de ella.
Herramientas disponibles
| Herramienta | Conjunto de herramientas | Descripción |
|---|---|---|
clawops_status | cli | Mostrar salidas del stack (qué está desplegado, no si funciona) |
clawops_doctor | cli | Ejecutar diagnósticos: requisitos previos locales y, con un stack, salud remota |
clawops_logs_tail | cli | Seguir los registros de OpenClaw |
clawops_monitor | cli | Muestrear métricas de gateway y host |
clawops_stacks_list | admin | Listar todos los stacks y su estado |
clawops_config_get | cli | Leer un valor de configuración remoto |
clawops_agents_list | cli | Listar agentes en ejecución |
clawops_up | cli | Aprovisionar o actualizar un stack |
clawops_destroy | cli | Destruir un stack (solicita confirmación) |
clawops_apply | cli | Aplicar un archivo de plan |
clawops_plan | cli | Generar un plan de despliegue |
clawops_config_set | cli | Escribir un valor de configuración remoto |
clawops_config_unset | cli | Eliminar una clave de configuración remota |
clawops_config_validate | cli | Validar la configuración desplegada contra el esquema de OpenClaw |
clawops_gateway_restart | cli | Reiniciar el gateway (solicita confirmación) |
clawops_harden | cli | Aplicar módulos de endurecimiento; unirse o abandonar una tailnet (solicita confirmación) |
clawops_init | cli | Registrar un stack y escribir ~/.clawops/config.json (sin recursos en la nube) |
clawops_workflow_deploy_app | workflow | Despliegue de extremo a extremo: plan → confirmar → aplicar → estado |
clawops_workflow_recover | workflow | Flujo de trabajo de diagnóstico para un stack no saludable |
clawops_task_status | cli | Consultar una tarea de larga duración |
Las herramientas del conjunto de herramientas read también están disponibles en modo --read-only; la columna Conjunto de herramientas de la tabla muestra el conjunto principal. Todos los demás conjuntos de herramientas requieren modo completo.
Las herramientas destructivas requieren confirmación explícita (solicitación) a menos que se pase yes: true.
Consulta docs/security/tool-risk-matrix.md para la clasificación de riesgo completa de cada herramienta.
Configuración
La configuración se encuentra en ~/.clawops/config.json (anular con $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"
}
}
Las credenciales de la nube nunca se almacenan en la configuración. Clawops las lee del entorno:
| Proveedor | Fuente de credenciales |
|---|---|
| AWS | AWS_PROFILE o cadena de credenciales estándar de AWS (~/.aws/credentials) |
| GCP | GOOGLE_APPLICATION_CREDENTIALS o gcloud auth application-default login |
| Azure | AZURE_CLIENT_ID / AZURE_CLIENT_SECRET o az login |
| Local | Host SSH + clave configurados en stacks[name].localOpts |
Limitaciones conocidas
Consulta docs/limitations.md para la lista completa. Puntos clave:
- Solo despliegues de un solo nodo, no una plataforma de alta disponibilidad o agrupamiento.
clawops applyno es una ejecución de plan inmutable. Consultadocs/plan-apply.md.- Sin automatización de TLS/dominio en la versión actual.
- Las herramientas MCP ejecutan operaciones privilegiadas, usa
--read-onlypara la primera evaluación.
Arquitectura
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)
Decisiones de diseño clave:
- API de automatización de Pulumi: el usuario no instala Pulumi. Clawops instala la CLI que la API controla en
~/.clawops/.pulumi-cli, fijada al SDK incluido, sin editar$PATH(ADR 0010); el directorio de inicio de Pulumi está aislado en~/.clawops/.pulumi; los programas de stack son cierres TypeScript en línea - Estado en almacenamiento de blobs en la nube: GCS (
gs://), S3 (s3://), Azure Blob, sin archivos de estado locales, sinpulumi.yaml - SSH a través de
ssh2: nunca invoca/usr/bin/ssh; verificación de host TOFU contra~/.clawops/known_hosts; grupo de conexiones con TTL de inactividad de 5 minutos - Disciplina de plan → aplicar: cada despliegue no local pasa por
generatePlan()→ revisión →applyPlan(); los cambios destructivos siempre requieren revisión humana del JSON del plan - MCP primero: cada operación de CLI tiene una herramienta MCP tipada; los esquemas se generan desde
spec/mcp-tools.yaml; todas las herramientas destructivas usan solicitación
Consulta docs/architecture.md para una narrativa completa y docs/decisions/ para los ADR.
Stacks de proveedores de nube
Cada proveedor de nube es un programa Pulumi en línea que crea los recursos siguientes. Los tres comparten las mismas salidas (publicIp, gatewayUrl, sshHost, sshPort, sshUser) consumidas por las capas de SSH y superposición de configuración.
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
Desarrollo
Configuración
git clone https://github.com/dfridkin/clawops.git
cd clawops
# Node 22+ required; use nvm: nvm use
pnpm install
pnpm dev doctor # verify toolchain
Scripts
pnpm dev # run CLI from src/ via tsx
pnpm build # tsup → dist/
pnpm test # vitest (1897 tests, ~13s)
pnpm test:changed # vitest --changed (fast edit loop)
pnpm test:integration # Docker-based SSH integration tests
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
Estructura del proyecto
| Ruta | Propósito |
|---|---|
spec/ | Fuente de verdad legible por máquina: JSON Schema, YAML. Trátalo como fuente de verdad. |
SPEC.md | Especificación técnica completa (hitos, reglas, esquemas) |
DESIGN_RULES.md | 25 reglas normativas (R1–R25) referenciadas en todo el código |
docs/architecture.md | Resumen narrativo del sistema |
docs/plan-apply.md | Semántica de plan/aplicar, guía de deriva, patrón de CI |
docs/ci.md | Guía de integración de CI: OIDC, variables de entorno, plan → aplicar en CI |
docs/security/ | Modelo de seguridad de MCP, matriz de riesgo de herramientas, redacción, registros de auditoría |
docs/providers/matrix.md | Matriz de capacidades por proveedor |
docs/decisions/ | Registros de decisiones de arquitectura |
.claude/skills/ | Procedimientos invocables: /add-provider, /release, /tdd, /mcp-tool |
.claude/rules/ | Reglas de lint por ruta cargadas por Claude Code |
Generación de código
Dos archivos se generan desde spec/ y no deben editarse a mano:
src/providers/types.ts. InterfazProviderAdapterdesdespec/providers.schema.jsonsrc/mcp/tools/_generated.ts. Esquemas Zod y exportaciones de tipos desdespec/mcp-tools.yaml
Ejecuta pnpm gen:schemas después de modificar cualquiera de los archivos de especificación. CI lo aplica con --check.
Añadir un proveedor
Usa la habilidad /add-provider en Claude Code, o sigue src/providers/CLAUDE.md. Cada adaptador debe cumplir ProviderAdapter en src/providers/types.ts. No relajes el esquema para ajustar el adaptador.
Añadir una herramienta MCP
Usa la habilidad /mcp-tool. La habilidad añade la herramienta a spec/mcp-tools.yaml, ejecuta pnpm gen:schemas, crea el manejador en src/mcp/tools/<toolset>/<name>.ts y lo conecta al registro. Las cuatro pistas de anotación (readOnlyHint, destructiveHint, idempotentHint, openWorldHint) son obligatorias en cada herramienta.
Commits convencionales
feat(scope): description
fix(scope): description
docs / refactor / chore / test / perf / ci
Usa pnpm changeset para registrar una nota de versión antes de fusionar un feat o fix.
Novedades en 2.1
Redes privadas, endurecimiento en todas las nubes y dos correcciones a comandos que no podían iniciar. 2.1.1 sigue con las correcciones que se indican a continuación.
Alcanza un stack a través de tu tailnet
clawops harden --tailscaleinstala Tailscale en un stack, lo une a tu tailnet comoclawops-<stack>e informa la dirección que se le asignó.- El mismo comando mueve luego clawops a esa dirección, pero solo después de abrir una sesión SSH hacia ella, contra claves de host fijadas sobre la conexión pública que ya confía.
- La clave de autenticación de Tailscale proviene de
clawops secret set TAILSCALE_AUTH_KEYy llega al host a través del canal de datos SSH. Nunca aparece en una línea de comandos, una lista de procesos o un registro. clawops plan --private-only→clawops applycierra el acceso público SSH y de gateway en un stack alcanzado a través de su tailnet. Ambos se niegan a menos que esa dirección responda SSH en ese momento (ADR 0013).clawops harden --tailscale-revertsaca un host de la tailnet y devuelve clawops a su dirección pública. En un stack solo privado se niega e imprime los comandos que reabren SSH.clawops destroyolvida las claves de host para ambas direcciones de un stack en su tailnet, en lugar de dejar la pública fijada para una instancia que ya no existe.
El endurecimiento cubre las tres nubes
- Azure: auditoría de NSG, cifrado de disco, Defender for Cloud y acceso JIT a VM, todo solo verificación.
- GCP: auditoría de firewall de VPC, Shielded VM y OS Login, todo solo verificación.
- Las instancias de GCP arrancan con Secure Boot activado. Los stacks existentes lo reciben como una actualización que conserva el disco de arranque y todo el estado de OpenClaw.
- Una verificación que no puede ejecutarse se informa como omitida, nombrando lo que faltaba, en lugar de como aprobada.
Los planes dicen qué perturbarán
clawops plancuenta y lista los recursos que se reemplazarían. Solía resumir una vista previa que destruiría la instancia y su disco de arranque como "0 para crear, 0 para actualizar".- Un plan que cambia un despliegue en vivo advierte antes de aplicarlo: un reemplazo nombra qué va
con él y apunta a
clawops backup create; una actualización dice que el gateway se cae.
Correcciones
clawops mcp serveno podía iniciar en absoluto cuando se instalaba desde npm: fallaba en la importación antes de emitir ningún protocolo, por lo que cada cliente MCP no recibía nada.pnpm verify:packahora habla MCP con el tarball empaquetado, por lo que esta clase de fallo no puede volver a publicarse.server.json, el manifiesto del registro MCP, se versiona con el paquete en lugar de reescribirse en el momento de la publicación. El archivo confirmado había leído1.7.3contra un2.0.2publicado.- El paquete publicado lleva su licencia, palabras clave y rastreador de problemas, por lo que se puede encontrar en npm y su listado está completo.
2.1.1
clawopsiniciado sin comando y con una tubería en stdin sirve MCP en lugar de imprimir ayuda. Así es como cada cliente MCP inicia un servidor, y cómo los directorios que infieren un comando de ejecución inician uno; varios estaban recibiendo el texto de ayuda e informando el servidor como roto. Escrito en una terminal,clawopsaún imprime ayuda, y también lo haceclawops | less.- El ejemplo de configuración de MCP es
npx -y @clawops/cli mcp serve, que se ejecuta tal como está escrito. Solía decir/path/to/clawops, que nada podía ejecutar y ningún directorio podía copiar. - La descripción está dentro del límite de 100 caracteres del registro MCP. La que envió 2.1.0 era 110, y el registro la rechazó con un 422 después de que npm ya había publicado, por lo que 2.1.0 llegó a npm y no al registro.
clawops hardendice que un stack no está desplegado, o que su estado no pudo leerse, en lugar de transmitircode: -2y un volcado de subproceso.- El relleno del registro MCP registra la versión que se publicó en lugar de la que la herramienta de publicación está preparando, por lo que una entrada que se queda atrás puede repararse realmente.
- La imagen de Docker se compila. Nunca se había compilado, y no lo hacía:
npm pack --pack-destinationno crea su destino.pnpm verify:dockerla compila y habla MCP con el contenedor en ejecución, tanto a través de su punto de entrada como como binario simple, en CI.
Novedades en 2.0.1
Una versión de parche, y una grande: en 2.0.0 ningún despliegue en la nube tuvo éxito por ninguna vía. Cada elemento
a continuación es una corrección o una adición en 2.0.1. El razonamiento detrás de cada uno está en su mensaje de commit,
y las decisiones que surgieron de ellos están en docs/decisions/.
Desplegar en una nube
clawops plan→clawops applyaprovisiona un stack en la nube y despliega OpenClaw en él.clawops updespliega en AWS, GCP y Azure, ejecutando la misma ruta queplan→apply.- clawops instala la CLI de Pulumi que necesita en
~/.clawops/.pulumi-cli, o usa una compatible ya presente en$PATH(ADR 0010). - clawops crea y almacena la frase de contraseña que su backend de estado requiere (ADR 0011).
clawops plantoma--ssh-cidr,--gateway-cidry--publish-gateway, yapplylos pasa al firewall de la nube.autoresuelve la dirección de esta máquina.clawops planse detiene, y nombra la causa, cuando no puede abrir el backend de estado.--instance-typetoma un alias de clawops (micro–gpu) o un tipo de máquina que tu nube nombra por sí misma, y el plan registra el tipo concreto.- Los despliegues fijan la cuenta contra la que se planificaron:
gcp:projecten GCP,azure-native:subscriptionIden Azure.
Verificar la cuenta antes de gastar
clawops doctor --provider <cloud>verifica las credenciales y la configuración de la cuenta de una nube, con o sin una pila.--instance-typeapunta la verificación de tamaño al tamaño que estás desplegando.- AWS. La cuenta a la que resuelven las credenciales, el bucket de estado y si el tipo de instancia está disponible en la región.
- GCP. El proyecto, las API que necesita un despliegue y el bucket de estado.
- Azure. La suscripción, los proveedores de recursos, el tamaño de la VM y las credenciales de azblob con las que Pulumi se autentica.
clawops setupejecuta las mismas verificaciones y ofrece corregir lo que puede de forma segura, habilitando una API, creando un bucket de estado con versionado activado y acceso público bloqueado, nombrando el cambio antes de realizarlo.- Una verificación que clawops no pudo realizar se reporta como una advertencia que nombra el error, en lugar de como un aprobado o un fallo.
- Azure acepta tu
az login; ya no se requiere una entidad de servicio.
Nomenclatura, configuración y preparación
- clawops nombra el backend de estado según la cuenta en la que está desplegando, en lugar de pedirte un nombre o escribir un marcador de posición (ADR 0012).
- Un nombre que escribas se verifica contra las reglas de la nube que debe aceptarlo.
clawops initconserva las pilas que ya están en tu configuración.clawops initgenera una clave SSH que clawops puede leer. Si ejecutasteinitantes de esta versión,clawops doctorte dirá si la tuya es utilizable.gcloud config set projectse respeta.- El asistente de configuración escribe la configuración del modelo que OpenClaw acepta e instala el plugin que necesita tu proveedor elegido.
- Amazon Bedrock funciona: el transporte correcto y un perfil de inferencia resuelto contra tu
región de despliegue y registrado en el plan. Necesita
bedrock:ListInferenceProfiles.
Mientras se ejecuta un despliegue
applyespera a SSH y luego espera a que la puerta de enlace responda, antes de reportar éxito.applyreporta el progreso a medida que avanza en lugar de quedarse en silencio durante minutos.- Un despliegue que agota el tiempo imprime lo que el host estaba haciendo, desde su registro de arranque.
- Un host que aún está instalando Docker se trata como si aún estuviera arrancando, en lugar de como un despliegue fallido.
Comandos de segundo día
clawops logslee desde la puerta de enlace en AWS.doctor --stack,ssh,logs,gateway,configyagentsfuncionan contra una pila recién desplegada.clawops doctorvalida las credenciales de la nube.- clawops distingue un socket de Docker rechazado de un contenedor faltante y dice cuál encontró.
clawops destroyolvida la clave de host de la instancia, por lo que volver a desplegar en una dirección que la nube ha reciclado ya no falla en la verificación.
Documentación
- La guía de GCP nombra la fuente de credenciales que clawops realmente lee y describe el comportamiento del firewall 2.0.
- El plan de prueba de humo cubre 2.0, y
pnpm test:cloud aws|gcp|azurelo ejecuta contra un despliegue real y lo destruye después.
Novedades en 2.0
clawops 2.x está dirigido a OpenClaw >= 2026.9.2. La línea 1.x continúa para OpenClaw
<= 2026.7.1-2 bajo la etiqueta de distribución legacy hasta 2027-03-31:
npm install -g @clawops/cli # 2.x
npm install -g @clawops/cli@legacy # 1.x maintenance
Fija la etiqueta en CI. latest se mueve a 2.x, por lo que una canalización sin fijar cambiará de líneas.
CHANGELOG.md contiene el historial completo; esta sección cubre lo que cambió
sobre cómo se comporta clawops.
Tu despliegue conserva su estado
OpenClaw 2.0 almacena sesiones, transcripciones y credenciales en SQLite. clawops no montaba
ningún estado, por lo que cada reinicio las destruía, y un reinicio es lo que gateway restart,
gateway update y config set hacen todos.
Un directorio del host (/var/lib/clawops/openclaw) ahora está montado por enlace en la
ubicación predeterminada de OpenClaw, que contiene la configuración, la base de datos y cualquier plugin de proveedor. Los
despliegues existentes migran en el próximo 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"]
Tres de esos pasos son nuevos, y cada uno existe porque el flujo anterior podía reportar éxito
mientras algo estaba mal: la configuración nunca se validaba antes de escribirse, los plugins de
proveedor se dejaban para obtenerlos al arrancar (o faltaban silenciosamente en un host con denegación total), y
"iniciado" se infería de que docker run saliera con 0.
clawops gateway update
Anteriormente: extraer, ejecutar, reportar éxito. Que docker run salga con 0 significa que el contenedor fue
creado, y el contenedor que reemplaza ya no existe.
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"]
La instantánea no es solo un punto de reversión: database preflight rechaza una base de datos
en vivo porque la versión del esquema reside en el WAL hasta que se marca como punto de control, por lo que la instantánea
consolidada es lo que hace posible la verificación de compatibilidad.
clawops gateway restart
Un reinicio no cambia ni la versión desplegada ni quién puede acceder a la puerta de enlace. Ambos se leen del contenedor en ejecución en lugar de adivinarse:
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"]
Migrar un despliegue 1.x existente
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"]
Dos cosas sobre esa forma no son obvias, y ambas provienen de ejecutar una migración real:
El estado se extrae del contenedor en ejecución. Todo el estado 1.x vivía dentro de él; clawops no montaba nada, por lo que detener primero destruye lo que la migración vino a salvar.
La configuración se sintetiza, no se traslada. 1.x nunca tuvo una que se aplicara; el archivo que clawops montaba no lo leía nada. Tus configuraciones antiguas se reportan como intención de revisión, nunca se aplican a ciegas. Sus bloques de canal no se validarían contra 2.0 de todos modos.
La puerta de enlace también necesita dos arranques: el primero realiza la migración del esquema de estado y lo reporta
como pendiente. migrate espera al segundo en lugar de declarar éxito temprano.
Si ejecutaste gateway restart, gateway update o config set en un clawops antes de 2.0, tu
estado ya no existe; no se montó nada para sobrevivir al reemplazo del contenedor. migrate
lo dice claramente en lugar de fingir rescatarlo.
clawops backup restore funciona de nuevo, y nunca en el lugar
v1.7.5 hizo que la restauración fallara con una explicación, porque el OpenClaw que soportaba no tenía subcomando de restauración al que llamar. 2.0 lo tiene, y clawops se lo delega:
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 no extrae archivos por sí mismo y no restaura en el lugar. El paso final es
manual a propósito, y volver a aplicar importa: el archivo no lleva el plugin
node_modules, por lo que un despliegue restaurado arranca sin sus proveedores de modelo, luciendo
saludable mientras lo hace.
El archivo es una credencial. Lleva la base de datos de estado, mcp_oauth_stores,
secret_store_entries, worker_environment_credentials, device_auth_tokens, sin cifrar.
clawops ahora lo escribe 0600 localmente; anteriormente usaba el 0644 predeterminado.
Los proveedores de modelo que necesitan un plugin se instalan por ti
OpenClaw 2.0 convirtió los proveedores de modelo en plugins con puerta de instalación. Veinticuatro vienen en la imagen,
anthropic, openai, google, ollama, openrouter entre ellos, pero no todos.
Configurar uno que no está incluido, sin instalarlo, produce una puerta de enlace que arranca,
reporta saludable y no tiene backend de modelo.
clawops instala lo que tu configuración necesita, fijado a una versión exacta, durante apply:
Resolving clawhub:@openclaw/deepseek-provider@2026.9.2…
Downloading plugin @openclaw/deepseek-provider@2026.9.2 from ClawHub…
Installed plugin: deepseek
Esto añade una dependencia saliente que la línea 1.x no tenía: clawhub.ai. Se necesita
mientras apply se está ejecutando, no al arrancar. Deliberadamente, para que un fallo llegue a la persona que ejecuta
el comando en lugar de a un host bloqueado a las 3 a. m. Bloqueado, se ve así:
fetch failed | getaddrinfo EAI_AGAIN clawhub.ai | EAI_AGAIN
clawops verifica los ID de proveedor instalados después y no llamará al despliegue terminado mientras falte un proveedor configurado. Acceso saliente requerido enumera cada destino y cuándo se necesita.
Los canales de chat también se instalan por ti
Cada canal en OpenClaw 2.0 es un plugin con puerta de instalación. clawops apply instala los que
tu configuración nombra, durante el despliegue mientras existe la salida, y luego pregunta a la puerta de enlace si
realmente están instalados:
[clawops] warning: the gateway is running, but these configured channels are not installed:
discord. They will never connect.
Tiene que preguntar. openclaw channels add. El comando obvio devuelve éxito incluso cuando la
instalación del plugin falla, por lo que clawops usa openclaw plugins install y verifica contra
channels list --all --json.
Los plugins de canal están fijados al runtime compatible. El latest actual no se instala en
él: plugin "discord" requires plugin API >=2026.9.3, but this OpenClaw runtime exposes 2026.9.2. La misma deriva que forzó los pines de versión en los proveedores de modelo.
Telegram no necesita que se instale nada: viene en la imagen.
La configuración incorrecta se detecta antes de escribirse
La configuración se valida contra el propio esquema de OpenClaw, capturado de la imagen, no
escrito a mano, antes de enviar cualquier cosa al host, y de nuevo antes de que una escritura reemplace un
archivo que funciona. clawops plan rechaza un plan cuya configuración la puerta de enlace rechazaría, mientras
el plan sigue siendo un archivo que puedes editar.
Una configuración rechazada se conserva en <path>.rejected.<timestamp> y la activa se deja intacta, por lo que
un fallo de validación nunca te cuesta lo que intentabas escribir.
Una regla es propia de clawops: gateway.mode es opcional en el esquema y obligatoria en la
práctica. Una configuración sin ella pasa openclaw config validate y luego sale con 78.
Los contenedores están endurecidos
La puerta de enlace se ejecuta con --cap-drop=ALL, --security-opt no-new-privileges, --init y
--pids-limit 512. El estado es propiedad numérica de 1000:1000, que coincide con el usuario del contenedor
en lugar de una cuenta del host que puede no tener ese uid.
El pin de versión se aplica en todos los lugares donde puede cambiar
doctor, plan, up y apply rechazan una versión de OpenClaw fuera del rango compatible, y
gateway restart reutiliza la versión ya desplegada en lugar de resolver una etiqueta móvil. Un
reinicio no cambia ni la versión ni quién puede acceder a ella.
La puerta de enlace ya no está expuesta a tu red
El contenedor publica en 127.0.0.1:18789 en lugar de 0.0.0.0:18789. Accede a ella con
clawops tunnel o un proxy inverso en el host.
Anteriormente, el asistente establecía allowedGatewayCidrs a partir del CIDR que diste para SSH, por lo que
un panel HTTP en texto plano. Token en la URL. Se abría a toda tu red de acceso de shell
como efecto secundario de una respuesta no relacionada. Para vincular todas las interfaces deliberadamente, establece
network.publishGateway: "all".
Debes actuar si un cliente o proxy inverso en otra máquina accede a la puerta de enlace
directamente, o si la monitorización externa golpea /health. Un proxy en el host no se ve afectado; uno en un
contenedor en el host necesita --network host.
Las verificaciones de salud pueden fallar de verdad
La puerta de enlace sirve su UI de control en una ruta de captura total, por lo que cualquier ruta no coincidente responde 200 con HTML:
/healthz 200 application/json {"ok":true,"status":"live"}
/health-typo 200 text/html <!doctype html>…
clawops sondeaba con curl -fsS … >/dev/null, que tiene éxito en un error tipográfico. Probaba que algo
estaba escuchando en el puerto, no que la puerta de enlace estuviera saludable. Los sondeos ahora leen el cuerpo
de la respuesta, y la puerta de reinicio usa /startupz en lugar de vivacidad; después de un reinicio, el
proceso escucha mucho antes de que el arranque termine.
clawops mcp wire ahora realmente conecta algo
Nunca ha funcionado, ni en 2.0, ni en ninguna versión 1.x. Escribía gateway.mcpClients,
que no es una clave que OpenClaw tenga: verificado contra los esquemas de configuración de 2026.4.5,
2026.7.1-2 y 2026.9.2. La clave real es de nivel superior mcp.servers. Y la entrada que escribía
era command: "clawops" sobre stdio, que se genera dentro del contenedor de la puerta de enlace, donde
clawops no está instalado y nada lo instala.
En 1.x nada validaba la escritura, por lo que clawops almacenaba una clave que nada leía, reiniciaba tu puerta de enlace y reportaba: "La IA de la puerta de enlace ahora puede ejecutar comandos de clawops." No podía.
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"]
Ahora delega en openclaw mcp add, que sondea el servidor antes de guardar, por lo que
"conectado" significa que la puerta de enlace se conectó, no que se escribió un archivo.
Tienes que ejecutar el servidor tú mismo. clawops no está instalado en el host de la puerta de enlace:
clawops mcp serve --http 18790 --bind 0.0.0.0 --token "$(openssl rand -hex 16)"
clawops mcp wire --stack prod --token <same token>
Instalar clawops en el host de la puerta de enlace es un seguimiento deliberado, no parte de 2.0: coloca
credenciales de implementación en la máquina implementada, y la IA de la puerta de enlace es accesible desde cada
canal al que está conectada. Ver docs/security/threat-model.md T11.
clawops mcp serve --http sirve a más de un cliente, y pregunta quién eres
Dos errores, encontrados al probar contra una puerta de enlace real en lugar de un simulacro.
Construyó un transporte para todo el proceso, así que el primer cliente en conectarse lo reclamó
y todos los posteriores. Un segundo editor, una reconexión, la propia sonda de la puerta de enlace, recibió
"Server already initialized". El modo HTTP es el modo multi-cliente.
No tenía autenticación, mientras exponía todas las herramientas incluyendo clawops_destroy. Ahora
toma un token de portador, lo compara en tiempo constante, y se niega a vincularse en cualquier lugar que no sea loopback
sin uno.
El firewall sigue a la implementación
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"]
Tres controles de seguridad estaban haciendo lo contrario de lo que dicen.
clawops harden abrió el puerto de la puerta de enlace en cada implementación. El módulo ufw ejecutó
ufw allow 18789/tcp incondicionalmente. Dado que la puerta de enlace publica en 127.0.0.1, eso
abrió un puerto en el que nada estaba escuchando. Un paso de endurecimiento que amplía el firewall más allá de lo que la
implementación expone. Ahora lee los enlaces de puerto del contenedor en ejecución y agrega la regla solo
cuando la puerta de enlace está realmente publicada, en cualquier puerto en el que esté publicada.
La auditoría del grupo de seguridad de AWS eximió los dos puertos que existe para verificar. Los puertos 22 y
18789 estaban en una lista "esperada", así que un grupo que abre SSH o la puerta de enlace a 0.0.0.0/0 volvió
como "No se encontraron reglas de entrada abiertas inesperadas". Tampoco leyó nunca las reglas IPv6, así que ::/0
era invisible.
El asistente de configuración predeterminó el acceso SSH a 0.0.0.0/0. Presionar Enter abrió SSH a todo
internet, en el camino que la mayoría de los usuarios primerizos toman. Ahora ofrece tu propia IP como /32,
y cuando eso no se puede detectar, no ofrece un valor predeterminado y requiere una respuesta.
clawops plan no podía expresar nada de eso, y apply nunca pasó nada de eso a Pulumi.
Ambos están corregidos en 2.0.1. Ver la lista al principio de esta sección.
El puerto de la puerta de enlace proviene del plan
"network": {
"allowedSshCidrs": ["203.0.113.4/32"],
"allowedGatewayCidrs": [],
"publishGateway": "loopback",
"gatewayPort": 9443
}
Un valor ahora llega a las reglas del grupo de seguridad, la bandera de publicación del contenedor, el
gateway.port predeterminado y la URL de la puerta de enlace. Era una constante redeclarada en once lugares, así que
cambiarla significaba encontrarlos todos, y omitir uno producía un contenedor publicando un
puerto, una puerta de enlace escuchando en otro, y un firewall abriendo un tercero.
Las implementaciones locales usan clawops up --gateway-port 9443.
clawops doctor responde si funciona, y lo dice en su código de salida
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"]
Tres cambios:
Le pregunta a la puerta de enlace. doctor solía leer el campo de healthcheck de docker inspect, que
la imagen de OpenClaw no establece, así que reportaba "no hay healthcheck configurado" y seguía adelante. Un
contenedor en ejecución significa que el proceso comenzó, no que sirve. Ahora sondea /startupz
y lee el cuerpo.
Sale con 1 cuando algo falló. Solo un Node.js antiguo solía hacer eso; una clave SSH ilegible
o una puerta de enlace no compatible salía con 0, así que un paso de CI ejecutando clawops doctor leía una implementación
rota como éxito. Las advertencias aún salen con 0, una máquina nueva sin stacks está
sin configurar, no rota.
Es una herramienta MCP. clawops_doctor devuelve el mismo informe como datos estructurados, así que un
agente que encuentra una falla puede descubrir por qué. Solo informa; nunca ejecuta openclaw doctor --fix. --json le da al CLI el mismo informe.
clawops agents list deja de inventar una lista vacía
El comando terminaba en || echo '[]', así que un contenedor detenido, una puerta de enlace aún iniciando, o un
error de permisos de Docker producían "No hay agentes ejecutándose.", una respuesta incorrecta en lugar de un
error. Ahora falla, y dice cuál.
Los comandos del día dos funcionan en AWS
gateway restart, logs, monitor, backup, agents, config set y las verificaciones de contenedor de doctor estaban todas rotas en AWS: clawops se conecta como ubuntu, pero el aprovisionamiento solo puso clawops en el grupo docker, así que cada comando de Docker fallaba con permission denied. GCP and Azure connect as clawops, así que solo AWS se vio afectado.
Eliminado
clawops agents restart y la herramienta MCP clawops_agents_restart. OpenClaw 2.0 no tiene
reinicio por agente, solo gateway restart y daemon restart, ambos de los cuales interrumpen
cada agente en el host. Usa clawops gateway restart, o quédate en @clawops/cli@legacy.
clawops agents list y clawops agents logs no se ven afectados.
Hitos
| Hito | Estado | Qué incluye |
|---|---|---|
| M0: Andamiaje | ✅ | Herramientas, CI, stubs, tipos generados |
| M1: MVP de GCP | ✅ | init / up / down / status / ssh / logs en GCP |
| M2: Gestión remota | ✅ | tunnel, config, agents, gateway; grupo de conexiones SSH |
| M3: AWS + Azure | ✅ | Adaptadores de AWS EC2 + Azure VM; stacks list |
| M4: VM local | ✅ | Adaptador local (bootstrap SSH, sin Pulumi); doctor |
| M5: Capa MCP | ✅ | mcp serve (stdio), todas las operaciones CLI como herramientas MCP, seguimiento de progreso |
| M6: Plan/Aplicar | ✅ | plan + apply; esquema de plan de implementación; transporte HTTP MCP; workflow_deploy_app |
| M7: Pulido v1.0 | ✅ | Superficie completa de doctor; comando destroy; --dry-run en todos los comandos; guía de CI |
Ver docs/roadmap.md para la hoja de ruta pública y el trabajo próximo.
Licencia
MPL-2.0, ver LICENSE.