clawops

Implante e opere o OpenClaw auto-hospedado na AWS, GCP, Azure e VMs locais — um CLI e um servidor MCP em um só. Mudanças de infraestrutura passam por um plano de deploy que você revisa antes de aplicar, ferramentas destrutivas confirmam primeiro, e cada chamada é registrada em log de auditoria.

Documentação

clawops

npm version npm downloads clawops MCP server – quality and maintenance score on Glama

Operações de infraestrutura nativas de MCP para OpenClaw, com modo somente leitura, confirmação de ações destrutivas e logs de auditoria integrados.

clawops é uma CLI e um servidor MCP para implantar e operar instâncias OpenClaw auto-hospedadas. Provisione na AWS, GCP, Azure ou em qualquer VM Linux e, em seguida, gerencie as operações do dia a dia pelo terminal, ou deixe o Claude Code e o Cursor conduzi-las por meio de ferramentas MCP tipadas com controles de segurança explícitos.


Novidades: notas de versão 2.0.1 e 2.0 abaixo, e o histórico completo em CHANGELOG.md.


Para quem é este projeto

  • Usuários do OpenClaw que buscam o caminho mais simples para auto-hospedagem em VMs locais ou na nuvem, com implantação confiável, verificação de status, logs, backups e atualizações em uma única CLI.
  • Usuários de Claude Code / Cursor / MCP que procuram uma implementação de referência real de operações seguras de infraestrutura por meio de MCP. Esquemas de ferramentas tipados, modo somente leitura, confirmação de ações destrutivas e logs de auditoria.
  • Desenvolvedores de IA auto-hospedada e local-first que desejam executar seu próprio assistente de IA sem se comprometer com Kubernetes, uma plataforma SaaS gerenciada ou um único provedor de nuvem.

O que o clawops faz

  • Provisiona e remove a infraestrutura do OpenClaw na AWS, GCP, Azure e VMs locais usando a Pulumi Automation API. Você não instala o Pulumi; o clawops instala a CLI necessária em ~/.clawops/.pulumi-cli no primeiro uso.
  • Gerencia as operações do dia a dia: status, logs, SSH, túneis, configuração, agentes, gateway, backups.
  • Expõe cada operação como uma ferramenta MCP tipada para que agentes de IA possam conduzir operações com segurança.
  • Aplica uma disciplina de planejar → revisar → aplicar para implantações em nuvem.
  • Emite saída JSON em todos os lugares (--json) para scripts e automação.
  • Nunca armazena credenciais de nuvem. Elas são lidas dos perfis CLI existentes no seu ambiente.

O que o clawops não faz

  • Sem alta disponibilidade ou clustering. Otimizado para implantações de nó único.
  • Sem Kubernetes. Ele implanta em VMs, não em plataformas de orquestração de contêineres.
  • Sem criação de skills/agentes do OpenClaw. O clawops gerencia a infraestrutura; o que roda nela é decisão sua e do OpenClaw.
  • Sem automação de TLS ou domínio (ainda). Use seu próprio proxy reverso ou consulte docs/limitations.md para o caminho manual.
  • Sem armazenamento de credenciais. As credenciais de nuvem devem ser configuradas no seu ambiente antes de usar o clawops. Elas nunca são gravadas em ~/.clawops/config.json.
  • Sem Windows nativo. O WSL2 é totalmente suportado; consulte docs/support-matrix.md.

Início rápido

npm install -g @clawops/cli
clawops setup

clawops setup é um assistente interativo que coloca o OpenClaw em funcionamento em cerca de 2 minutos. Ele cuida de tudo em um único fluxo, sem arquivos de configuração para escrever manualmente, sem comandos para memorizar.

O que o assistente faz

Etapa 1. Escolha um destino de implantação

Escolha um servidor existente ao qual você possa acessar via SSH (Linux ou macOS) ou uma nova VM na nuvem na AWS, GCP ou Azure. As implantações em nuvem orientam você na autenticação com a CLI do provedor, caso ainda não esteja conectado.

Etapa 2. Escolha um provedor de LLM

Escolha entre Anthropic, OpenAI, Amazon Bedrock, Ollama ou outros. O assistente solicita sua chave de API e a salva localmente (em ~/.clawops/secrets/, chmod 600). Ela nunca é enviada para nenhum lugar, exceto para o OpenClaw no host de destino quando a configuração é aplicada.

Etapa 3. Adicione integrações de chat (opcional)

Selecione qualquer combinação de Discord, Telegram, Slack, WhatsApp ou Teams. O assistente coleta o token do bot de cada integração da mesma forma que a chave de API. Cole-o, faça referência a uma variável de ambiente ou aponte para um arquivo.

Etapa 4. Conecte seu editor de IA

Selecione quais aplicativos de IA devem ter acesso ao clawops. Claude Desktop, Claude Code, Cursor, Windsurf, VS Code e Zed são todos suportados. O assistente grava uma entrada de servidor MCP no arquivo de configuração de cada aplicativo usando o caminho absoluto do binário para que o aplicativo possa iniciá-lo de forma independente.

Etapa 5. Implante

O assistente inicializa o OpenClaw no host de destino via SSH (instala o Docker, baixa a imagem, inicia o contêiner), aplica sua configuração de LLM e integrações, gera um token de autenticação do gateway e imprime uma URL direta do painel:

✔ 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

Pré-requisitos: Node.js ≥ 22, uma chave SSH e um host Linux/macOS acessível via SSH ou uma conta na nuvem com credenciais CLI configuradas (aws configure, gcloud auth login ou az login). Você não precisa do Pulumi. A primeira implantação em nuvem instala a CLI que o clawops utiliza em ~/.clawops/.pulumi-cli e informa isso durante o processo.

Para um passo a passo completo com exemplos de saída, consulte docs/demo-script.md.


Configuração manual, servidor existente

Se você preferir controle passo a passo ou estiver adicionando o clawops a uma implantação já em execução:

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

Consulte docs/examples/local-vm.md para pré-requisitos de SSH, configuração de firewall e solução de problemas.

Configuração manual, nuvem (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 a partir do IP público desta máquina, resolvido enquanto o plano é gerado e gravado nele. Sem isso, o plano não permite nenhum acesso de entrada e nada, incluindo o clawops, conseguirá se conectar.


Conecte um editor de IA

O assistente setup cuida disso automaticamente (Etapa 4). Para conectar ou reconectar editores a qualquer momento:

clawops mcp install

Isso abre a mesma caixa de seleção interativa usada no assistente. Selecione Claude Desktop, Claude Code, Cursor, Windsurf, VS Code ou Zed, e o clawops grava a entrada MCP na configuração de cada aplicativo usando o caminho absoluto correto do binário.

Para adicionar a entrada manualmente, cole isto na configuração MCP do seu editor:

{
  "mcpServers": {
    "clawops": {
      "command": "npx",
      "args": ["-y", "@clawops/cli", "mcp", "serve", "--read-only"]
    }
  }
}

Essa forma não precisa de nada em $PATH e é o que um diretório ou instalador copiará. Se você preferir apontar para o binário que já possui, use o caminho absoluto dele — a saída de which clawops — com os mesmos argumentos:

{
  "mcpServers": {
    "clawops": {
      "command": "/path/to/clawops",
      "args": ["mcp", "serve", "--read-only"]
    }
  }
}

De qualquer forma, passe os argumentos. mcp serve é o que fala o protocolo, e uma configuração explícita é aquela que ainda se lê claramente um ano depois. O clawops não abandona um cliente que os omita: execute sem nenhum comando e com um pipe na entrada padrão — como todo cliente MCP inicia um servidor — e ele inicia mcp serve, informando isso no stderr. Digitado em um terminal, clawops ainda imprime a ajuda. Locais dos arquivos de configuração:

AplicativoCaminho
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 (chave: context_servers)

Comece com --read-only. Ele ativa status, logs, leituras de configuração e diagnósticos enquanto bloqueia mutações. Remova-o somente após revisar docs/security/mcp-safety.md.

Ferramentas destrutivas (clawops_destroy, clawops_up, clawops_config_set, etc.) exigem confirmação explícita antes de executar; elas nunca serão executadas silenciosamente.

Para configuração do modo HTTP, consulte docs/mcp/.


Operações do dia a dia

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

ComandoDescrição
setupAssistente de primeira execução: LLM guiado, integrações e geração de plano de implantação
initRegistra um stack em ~/.clawops/config.json sem provisionar. Aditivo; stacks existentes são mantidos; --force é necessário apenas para sobrescrever um
upProvisiona ou atualiza o stack (--dry-run para pré-visualização, --gateway-port para uma porta não padrão)
downDestrói o stack do provedor local (requer --yes; --dry-run mostra as saídas atuais)
destroyDestrói o stack do provedor de nuvem com prompt de confirmação (--dry-run mostra as saídas atuais)
statusMostra as saídas do stack: IP, URL do gateway, região, horário de provisionamento
planGera um artefato JSON de plano de implantação (seguro para dry-run). --ssh-cidr <list|auto> e --gateway-cidr decidem quem pode se conectar; --publish-gateway loopback|all decide o que está escutando; --private-only fecha o acesso público em um stack alcançado pela sua tailnet
applyAplica um arquivo de plano previamente revisado (--dry-run valida e mostra o diff sem aplicar)
sshSessão SSH interativa ou execução de um comando remoto
logsTransmite logs do OpenClaw (-f, --tail N, --since 5m)
tunnelEncaminhamento de porta local para a UI do gateway via SSH
configObtém/define valores de configuração remota do OpenClaw (--dry-run mostra o JSON que seria gravado)
agentsLista agentes do OpenClaw ou transmite os logs de um agente
gatewayReinicia o serviço do gateway do OpenClaw
backupCria e restaura backups de estado do OpenClaw (restore expande em um diretório de staging, nunca no lugar)
stacksLista stacks nomeados e seus estados
doctorVerifica a máquina local; com --stack, também a saúde da implantação; com --provider, as credenciais e a configuração da conta de uma nuvem, exista ou não um stack; com --instance-type, as verificações de conta perguntam sobre esse tamanho em vez do padrão do provedor. --json para o relatório. Sai com código 1 em qualquer falha
secretGerencia segredos: list, set, delete, rotate, audit
monitorPainel ao vivo: saúde do gateway, estatísticas do contêiner, cauda de logs, seletor de stack
mcp serveInicia o servidor MCP embutido (stdio, ou HTTP com --http <port> --token <t>)
mcp installConecta interativamente o clawops aos editores de IA
mcp wireConecta a IA do gateway como cliente MCP do clawops (verifica a conexão antes de salvar)
helpLista todos os comandos e flags globais
hardenAplica endurecimento de segurança a um stack implantado (SSH, UFW, fail2ban, unattended-upgrades, socket Docker; AWS: auditoria de SG, verificação de SSM, Flow Logs, GuardDuty). --tailscale junta o stack à sua tailnet e move o clawops para esse endereço assim que ele responder; --tailscale-revert desfaz isso
bugAbre uma issue pré-preenchida no GitHub com o contexto do sistema de doctor

Referência completa de flags: clawops <command> --help


Fluxo de trabalho Planejar → Aplicar

Para provedores não locais, o clawops aplica uma disciplina de revisão antes da aplicação:

# 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

O JSON do plano está em conformidade com spec/deploy-plan.schema.json (validado por AJV) e captura a intenção revisada: provedor, região, tipo de instância, intervalos CIDR e versão do OpenClaw. apply reexecuta pulumi up usando esses parâmetros contra o estado ativo atual; ele não reproduz um artefato de execução bloqueado. Revise e aplique na mesma sessão para minimizar o risco de desvio.

Consulte docs/plan-apply.md para a semântica completa, orientação sobre desvios e o padrão seguro de CI.


Servidor MCP

O clawops inclui um servidor MCP embutido. Claude Code, Cursor e qualquer agente compatível com MCP podem conduzir implantações sem sair da interface de chat.

Conecte seu editor

clawops mcp install   # interactive checkbox: writes config for selected apps

O assistente resolve o caminho absoluto do binário automaticamente para que os lançadores de aplicativos possam encontrar clawops sem herdar o PATH do seu shell. Consulte Conecte um editor de IA acima para os caminhos de configuração manual.

Conecte a IA do gateway

O gateway do OpenClaw executa seu próprio agente de IA. Uma vez conectado, esse agente pode chamar o clawops diretamente em vez de adivinhar o estado da infraestrutura:

clawops mcp wire --stack prod   # write MCP client entry into gateway config + restart

Requer OpenClaw ≥ 2026.4 no gateway. O assistente clawops setup oferece esta etapa automaticamente após uma implantação bem-sucedida.

Modo Stdio (Claude Code / Cursor / VS Code)

Inicie o servidor manualmente ou confirme se sua configuração está correta:

clawops mcp serve --read-only   # safe for first evaluation
clawops mcp serve               # full mode: enables provisioning, config write, ssh exec

Modo HTTP (remoto / vários clientes)

clawops mcp serve --http 3333 --bind 127.0.0.1
# MCP HTTP server listening on 127.0.0.1:3333

Não vincule a um endereço não-loopback sem controles de autenticação adicionais na frente dele.

Ferramentas disponíveis

FerramentaConjunto de ferramentasDescrição
clawops_statuscliMostrar saídas da stack (o que está implantado, não se funciona)
clawops_doctorcliExecutar diagnósticos: pré-requisitos locais e, com uma stack, saúde remota
clawops_logs_tailcliAcompanhar logs do OpenClaw
clawops_monitorcliAmostrar métricas do gateway e do host
clawops_stacks_listadminListar todas as stacks e seus estados
clawops_config_getcliLer um valor de configuração remota
clawops_agents_listcliListar agentes em execução
clawops_upcliProvisionar ou atualizar uma stack
clawops_destroycliDestruir uma stack (solicita confirmação)
clawops_applycliAplicar um arquivo de plano
clawops_plancliGerar um plano de implantação
clawops_config_setcliEscrever um valor de configuração remota
clawops_config_unsetcliRemover uma chave de configuração remota
clawops_config_validatecliValidar a configuração implantada contra o esquema do OpenClaw
clawops_gateway_restartcliReiniciar o gateway (solicita confirmação)
clawops_hardencliAplicar módulos de endurecimento; entrar ou sair de uma tailnet (solicita confirmação)
clawops_initcliRegistrar uma stack e escrever ~/.clawops/config.json (sem recursos de nuvem)
clawops_workflow_deploy_appworkflowImplantação de ponta a ponta: plano → confirmação → aplicação → status
clawops_workflow_recoverworkflowFluxo de trabalho de diagnóstico para uma stack não saudável
clawops_task_statuscliConsultar uma tarefa de longa duração

Ferramentas no conjunto de ferramentas read também estão disponíveis no modo --read-only; a coluna Conjunto de ferramentas da tabela mostra o conjunto principal. Todos os outros conjuntos de ferramentas exigem o modo completo. Ferramentas destrutivas exigem confirmação explícita (elicitação), a menos que yes: true seja passado.

Consulte docs/security/tool-risk-matrix.md para a classificação completa de risco de cada ferramenta.


Configuração

A configuração fica em ~/.clawops/config.json (substitua com $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"
  }
}

Credenciais de nuvem nunca são armazenadas na configuração. O Clawops as lê do ambiente:

ProvedorFonte de credenciais
AWSAWS_PROFILE ou cadeia de credenciais AWS padrão (~/.aws/credentials)
GCPGOOGLE_APPLICATION_CREDENTIALS ou gcloud auth application-default login
AzureAZURE_CLIENT_ID / AZURE_CLIENT_SECRET ou az login
LocalHost SSH + chave configurados em stacks[name].localOpts

Limitações conhecidas

Consulte docs/limitations.md para a lista completa. Pontos principais:

  • Apenas implantações de nó único, não uma plataforma de alta disponibilidade ou clustering.
  • clawops apply não é uma execução de plano imutável. Consulte docs/plan-apply.md.
  • Sem automação de TLS/domínio na versão atual.
  • As ferramentas MCP executam operações privilegiadas, use --read-only para a primeira avaliação.

Arquitetura

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)

Decisões de design principais:

  • Pulumi Automation API: o usuário não instala Pulumi. O Clawops instala a CLI que a API aciona em ~/.clawops/.pulumi-cli, fixada ao SDK empacotado, sem editar $PATH (ADR 0010); o diretório inicial do Pulumi é isolado em ~/.clawops/.pulumi; os programas de stack são closures TypeScript inline
  • Estado em armazenamento de blob na nuvem: GCS (gs://), S3 (s3://), Azure Blob, sem arquivos de estado locais, sem pulumi.yaml
  • SSH via ssh2: nunca invoca /usr/bin/ssh; verificação de host TOFU contra ~/.clawops/known_hosts; pool de conexões com TTL de inatividade de 5 minutos
  • Disciplina plano → aplicação: toda implantação não local passa por generatePlan() → revisão → applyPlan(); alterações destrutivas sempre exigem revisão humana do JSON do plano
  • MCP primeiro: toda operação CLI tem uma ferramenta MCP tipada; esquemas gerados a partir de spec/mcp-tools.yaml; todas as ferramentas destrutivas usam elicitação

Consulte docs/architecture.md para uma narrativa completa e docs/decisions/ para os ADRs.

Stacks de provedores de nuvem

Cada provedor de nuvem é um programa Pulumi inline que cria os recursos abaixo. Todos os três compartilham as mesmas saídas (publicIp, gatewayUrl, sshHost, sshPort, sshUser) consumidas pelas camadas de SSH e sobreposição de configuração.

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

Diagrama detalhado →

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

Diagrama detalhado →

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

Diagrama detalhado →


Desenvolvimento

Configuração

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

Estrutura do projeto

CaminhoFinalidade
spec/Fonte de verdade legível por máquina: JSON Schema, YAML. Trate como fonte de verdade.
SPEC.mdEspecificação técnica completa (marcos, regras, esquemas)
DESIGN_RULES.md25 regras normativas (R1–R25) referenciadas em todo o código
docs/architecture.mdVisão geral narrativa do sistema
docs/plan-apply.mdSemântica de plano/aplicação, orientação de deriva, padrão de CI
docs/ci.mdGuia de integração de CI: OIDC, variáveis de ambiente, plano → aplicação em CI
docs/security/Modelo de segurança MCP, matriz de risco de ferramentas, redação, logs de auditoria
docs/providers/matrix.mdMatriz de capacidades por provedor
docs/decisions/Registros de Decisão de Arquitetura
.claude/skills/Procedimentos invocáveis: /add-provider, /release, /tdd, /mcp-tool
.claude/rules/Regras de lint por caminho carregadas pelo Claude Code

Geração de código

Dois arquivos são gerados a partir de spec/ e não devem ser editados manualmente:

  • src/providers/types.ts. Interface ProviderAdapter a partir de spec/providers.schema.json
  • src/mcp/tools/_generated.ts. Esquemas Zod e exportações de tipos a partir de spec/mcp-tools.yaml

Execute pnpm gen:schemas após modificar qualquer arquivo de especificação. O CI aplica isso com --check.

Adicionando um provedor

Use a habilidade /add-provider no Claude Code, ou siga src/providers/CLAUDE.md. Todo adaptador deve satisfazer ProviderAdapter em src/providers/types.ts. Não afrouxe o esquema para caber no adaptador.

Adicionando uma ferramenta MCP

Use a habilidade /mcp-tool. A habilidade adiciona a ferramenta a spec/mcp-tools.yaml, executa pnpm gen:schemas, cria o manipulador em src/mcp/tools/<toolset>/<name>.ts e o conecta ao registro. Todas as quatro dicas de anotação (readOnlyHint, destructiveHint, idempotentHint, openWorldHint) são obrigatórias em cada ferramenta.

Commits convencionais

feat(scope): description
fix(scope): description
docs / refactor / chore / test / perf / ci

Use pnpm changeset para registrar uma nota de versão antes de mesclar um feat ou fix.


Novidades na 2.1

Rede privada, endurecimento em todas as nuvens e duas correções para comandos que não conseguiam iniciar. A 2.1.1 vem com as correções listadas abaixo dela.

Alcance uma stack pela sua tailnet

  • clawops harden --tailscale instala Tailscale em uma stack, junta-a à sua tailnet como clawops-<stack> e informa o endereço que ela recebeu.
  • O mesmo comando então move o clawops para esse endereço, mas somente após abrir uma sessão SSH para ele — contra chaves de host fixadas pela conexão pública que ele já confia.
  • A chave de autenticação do Tailscale vem de clawops secret set TAILSCALE_AUTH_KEY e chega ao host pelo canal de dados SSH. Ela nunca aparece em uma linha de comando, lista de processos ou log.
  • clawops plan --private-only → clawops apply fecha o acesso público SSH e ao gateway em uma stack alcançada pela sua tailnet. Ambos recusam a menos que esse endereço responda SSH naquele momento (ADR 0013).
  • clawops harden --tailscale-revert remove um host da tailnet e retorna o clawops ao seu endereço público. Em uma stack somente privada, ele recusa e imprime os comandos que reabrem o SSH.
  • clawops destroy esquece as chaves de host para ambos os endereços de uma stack na sua tailnet, em vez de deixar a pública fixada para uma instância que não existe mais.

Endurecimento cobre todas as três nuvens

  • Azure: auditoria de NSG, criptografia de disco, Defender for Cloud e acesso JIT a VM, todos somente verificação.
  • GCP: auditoria de firewall VPC, Shielded VM e OS Login, todos somente verificação.
  • Instâncias GCP inicializam com Secure Boot ativado. Stacks existentes recebem isso como uma atualização que mantém o disco de inicialização e todo o estado do OpenClaw.
  • Uma verificação que não consegue executar é relatada como ignorada, nomeando o que estava faltando, em vez de como aprovada.

Planos dizem o que vão perturbar

  • clawops plan conta e lista recursos que seriam substituídos. Antes, resumia uma prévia que destruiria a instância e seu disco de inicialização como "0 para criar, 0 para atualizar".
  • Um plano que altera uma implantação ativa avisa antes de você aplicá-lo: uma substituição nomeia o que vai junto e aponta para clawops backup create; uma atualização diz que o gateway fica fora do ar.

Correções

  • clawops mcp serve não conseguia iniciar quando instalado via npm — falhava no import antes de emitir qualquer protocolo, então todo cliente MCP não recebia nada. pnpm verify:pack agora fala MCP com o tarball empacotado, então essa classe de falha não pode mais ser publicada.
  • server.json, o manifesto do registro MCP, é versionado com o pacote em vez de reescrito no momento da publicação. O arquivo commitado lia 1.7.3 contra um 2.0.2 publicado.
  • O pacote publicado carrega sua licença, palavras-chave e rastreador de problemas, então é encontrável no npm e sua listagem está completa.

2.1.1

  • clawops iniciado sem comando e com pipe no stdin serve MCP em vez de imprimir ajuda. É assim que todo cliente MCP inicia um servidor, e como diretórios que inferem um comando de execução iniciam um; vários estavam recebendo o texto de ajuda e relatando o servidor como quebrado. Digitado em um terminal, clawops ainda imprime ajuda, e o mesmo faz clawops | less.
  • O exemplo de configuração MCP é npx -y @clawops/cli mcp serve, que executa como escrito. Antes dizia /path/to/clawops, que nada conseguia executar e nenhum diretório conseguia copiar.
  • A descrição está dentro do limite de 100 caracteres do registro MCP. A que a 2.1.0 enviou tinha 110, e o registro a recusou com um 422 depois que o npm já havia publicado — então a 2.1.0 chegou ao npm e não ao registro.
  • clawops harden diz que uma stack não está implantada, ou que seu estado não pôde ser lido, em vez de repassar code: -2 e um despejo de subprocesso.
  • O backfill do registro MCP registra a versão que foi lançada em vez da que a ferramenta de lançamento está preparando, então uma entrada que fica para trás pode realmente ser reparada.
  • A imagem Docker compila. Ela nunca havia sido compilada, e não compilava: npm pack --pack-destination não cria seu destino. pnpm verify:docker a compila e fala MCP com o contêiner em execução, tanto pelo entrypoint quanto como binário puro, no CI.

Novidades na 2.0.1

Uma versão de correção, e uma grande: na 2.0.0 nenhuma implantação em nuvem teve sucesso por qualquer caminho. Cada item abaixo é uma correção ou adição na 2.0.1. A justificativa de cada um está na mensagem do commit, e as decisões que resultaram deles estão em docs/decisions/.

Implantando em uma nuvem

  • clawops plan → clawops apply provisiona uma stack de nuvem e implanta o OpenClaw nela.
  • clawops up implanta em AWS, GCP e Azure, executando o mesmo caminho que plan → apply.
  • O clawops instala a CLI Pulumi que precisa em ~/.clawops/.pulumi-cli, ou usa uma compatível já existente em $PATH (ADR 0010).
  • O clawops cria e armazena a frase secreta que seu backend de estado exige (ADR 0011).
  • clawops plan aceita --ssh-cidr, --gateway-cidr e --publish-gateway, e apply os passa ao firewall da nuvem. auto resolve o endereço desta máquina.
  • clawops plan para, e nomeia a causa, quando não consegue abrir o backend de estado.
  • --instance-type aceita um alias do clawops (micro–gpu) ou um tipo de máquina que sua nuvem nomeia por si mesma, e o plano registra o tipo concreto.
  • Implantações fixam a conta contra a qual foram planejadas: gcp:project no GCP, azure-native:subscriptionId no Azure.

Verificando a conta antes de gastar

  • clawops doctor --provider <cloud> verifica as credenciais e a configuração da conta de uma nuvem, com ou sem uma stack. --instance-type aponta a verificação de tamanho para o tamanho que você está implantando.
  • AWS. A conta para a qual as credenciais resolvem, o bucket de estado e se o tipo de instância é oferecido na região.
  • GCP. O projeto, as APIs que uma implantação precisa e o bucket de estado.
  • Azure. A assinatura, os provedores de recursos, o tamanho da VM e as credenciais azblob com as quais o Pulumi autentica.
  • clawops setup executa as mesmas verificações e se oferece para corrigir o que puder com segurança, habilitando uma API, criando um bucket de estado com versionamento ativado e acesso público bloqueado, nomeando a mudança antes de fazê-la.
  • Uma verificação que o clawops não conseguiu realizar é relatada como um aviso nomeando o erro, em vez de como um sucesso ou uma falha.
  • O Azure aceita seu az login; uma entidade de serviço não é mais necessária.

Nomenclatura, configuração e setup

  • O clawops nomeia o backend de estado de acordo com a conta na qual está implantando, em vez de pedir um nome ou escrever um espaço reservado (ADR 0012).
  • Um nome que você digita é verificado contra as regras da nuvem que precisa aceitá-lo.
  • clawops init mantém as stacks já presentes na sua configuração.
  • clawops init gera uma chave SSH que o clawops pode ler. Se você executou init antes desta versão, clawops doctor informará se a sua é utilizável.
  • gcloud config set project é respeitado.
  • O assistente de setup escreve a configuração do modelo que o OpenClaw aceita e instala o plugin que o provedor escolhido precisa.
  • O Amazon Bedrock funciona: o transporte correto e um perfil de inferência resolvido em relação à sua região de implantação e registrado no plano. Precisa de bedrock:ListInferenceProfiles.

Enquanto uma implantação está em execução

  • apply aguarda o SSH e, em seguida, aguarda o gateway responder antes de relatar sucesso.
  • apply relata o progresso conforme avança, em vez de ficar em silêncio por minutos.
  • Uma implantação que expira imprime o que o host estava fazendo, a partir do seu log de bootstrap.
  • Um host que ainda está instalando o Docker é tratado como ainda em inicialização, em vez de uma implantação falha.

Comandos de segundo dia

  • clawops logs lê do gateway na AWS.
  • doctor --stack, ssh, logs, gateway, config e agents funcionam contra uma stack recém-implantada.
  • clawops doctor valida as credenciais da nuvem.
  • O clawops distingue um socket Docker recusado de um contêiner ausente e informa qual encontrou.
  • clawops destroy esquece a chave de host da instância, para que a reimplantação em um endereço que a nuvem reciclou não falhe mais na verificação.

Documentação

  • O guia do GCP nomeia a fonte de credenciais que o clawops realmente lê e descreve o comportamento do firewall 2.0.
  • O plano de teste de fumaça cobre o 2.0, e pnpm test:cloud aws|gcp|azure o executa contra uma implantação real e a destrói em seguida.

O que há de novo no 2.0

O clawops 2.x tem como alvo OpenClaw >= 2026.9.2. A linha 1.x continua para OpenClaw <= 2026.7.1-2 sob a dist-tag legacy até 2027-03-31:

npm install -g @clawops/cli            # 2.x
npm install -g @clawops/cli@legacy     # 1.x maintenance

Fixe a tag no CI. latest muda para 2.x, então um pipeline não fixado mudará de linha. CHANGELOG.md carrega o histórico completo; esta seção cobre o que mudou sobre como o clawops se comporta.

Sua implantação mantém seu estado

O OpenClaw 2.0 armazena sessões, transcrições e credenciais em SQLite. O clawops não montava nenhum estado, então cada reinicialização os destruía, e uma reinicialização é o que gateway restart, gateway update e config set todos fazem.

Um diretório do host (/var/lib/clawops/openclaw) agora é montado por bind no local padrão do próprio OpenClaw, mantendo a configuração, o banco de dados e quaisquer plugins de provedor. Implantações existentes migram no 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"]

Três dessas etapas são novas, e cada uma existe porque o fluxo antigo poderia relatar sucesso enquanto algo estava errado: a configuração nunca era validada antes de ser escrita, os plugins de provedor eram deixados para serem buscados na inicialização (ou silenciosamente ausentes em um host com tudo negado), e "iniciado" era inferido a partir de docker run saindo com 0.

clawops gateway update

Anteriormente: puxar, executar, relatar sucesso. docker run saindo com 0 significa que o contêiner foi criado, e o contêiner que ele substituiu já se foi.

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"]

O snapshot não é apenas um ponto de reversão: database preflight recusa um banco de dados ativo porque a versão do esquema fica no WAL até o checkpoint, então o snapshot consolidado é o que torna a verificação de compatibilidade possível.

clawops gateway restart

Uma reinicialização não altera nem a versão implantada nem quem pode alcançar o gateway. Ambos são lidos de volta do contêiner em execução, em vez de adivinhados:

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"]

Migrando uma implantação 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"]

Duas coisas sobre essa forma não são óbvias, e ambas vieram da execução de uma migração real:

O estado é extraído do contêiner em execução. Todo o estado 1.x vivia dentro dele, o clawops não montava nenhum, então parar primeiro destrói o que a migração veio salvar.

A configuração é sintetizada, não transportada. O 1.x nunca teve uma que se aplicasse; o arquivo que o clawops montava não era lido por nada. Suas configurações antigas são relatadas como intenção de revisão, nunca aplicadas cegamente. Seus blocos de canal não validariam contra o 2.0 de qualquer forma.

O gateway também precisa de duas inicializações: a primeira executa a migração do esquema de estado e a relata como pendente. migrate aguarda a segunda em vez de declarar sucesso cedo.

Se você executou gateway restart, gateway update ou config set em um clawops antes do 2.0, seu estado já se foi, nada foi montado para sobreviver à substituição do contêiner. migrate diz isso claramente em vez de fingir resgatá-lo.

clawops backup restore funciona novamente, e nunca no lugar

O v1.7.5 fez a restauração falhar com uma explicação, porque o OpenClaw que ele suportava não tinha subcomando de restauração para chamar. O 2.0 tem, e o clawops delega para ele:

flowchart TD
    A["clawops backup restore --file X"] --> B["upload archive to the host"]
    B --> C["openclaw backup restore --target &lt;staging&gt;"]
    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"]

O clawops não extrai arquivos por conta própria e não restaura no lugar. A etapa final é manual de propósito, e reaplicar importa: o arquivo não carrega plugins node_modules, então uma implantação restaurada inicia sem seus provedores de modelo, parecendo saudável enquanto faz isso.

O arquivo é uma credencial. Ele carrega o banco de dados de estado, mcp_oauth_stores, secret_store_entries, worker_environment_credentials, device_auth_tokens, não criptografados. O clawops agora o escreve 0600 localmente; anteriormente usava o padrão 0644.

Provedores de modelo que precisam de um plugin são instalados para você

O OpenClaw 2.0 tornou os provedores de modelo plugins com portão de instalação. Vinte e quatro vêm na imagem, anthropic, openai, google, ollama, openrouter entre eles, mas não todos. Configurar um que não está incluído, sem instalá-lo, produz um gateway que inicia, relata saudável e não tem backend de modelo.

O clawops instala o que sua configuração precisa, fixado em uma versão exata, durante apply:

Resolving clawhub:@openclaw/deepseek-provider@2026.9.2…
Downloading plugin @openclaw/deepseek-provider@2026.9.2 from ClawHub…
Installed plugin: deepseek

Isso adiciona uma dependência de saída que a linha 1.x não tinha: clawhub.ai. É necessária enquanto apply está em execução, não na inicialização. Deliberadamente, para que uma falha alcance a pessoa que executa o comando em vez de um host bloqueado às 3 da manhã. Bloqueado, fica assim:

fetch failed | getaddrinfo EAI_AGAIN clawhub.ai | EAI_AGAIN

O clawops verifica os IDs de provedor instalados depois e não chamará a implantação de concluída enquanto um provedor configurado estiver ausente. Acesso de saída necessário lista todos os destinos e quando é necessário.

Canais de chat também são instalados para você

Todo canal no OpenClaw 2.0 é um plugin com portão de instalação. clawops apply instala aqueles que sua configuração nomeia, durante a implantação enquanto o egress existe, e então pergunta ao gateway se eles estão realmente instalados:

[clawops] warning: the gateway is running, but these configured channels are not installed:
discord. They will never connect.

Ele tem que perguntar. openclaw channels add. O comando óbvio retorna sucesso mesmo quando a instalação do plugin falha, então o clawops usa openclaw plugins install e verifica contra channels list --all --json.

Os plugins de canal são fixados no runtime suportado. O latest atual não instala nele: plugin "discord" requires plugin API >=2026.9.3, but this OpenClaw runtime exposes 2026.9.2. A mesma deriva que forçou pinos de versão nos provedores de modelo.

O Telegram não precisa de nada instalado: ele vem na imagem.

Configuração ruim é detectada antes de ser escrita

A configuração é validada contra o próprio esquema do OpenClaw, capturado da imagem, não escrito à mão, antes que qualquer coisa seja enviada ao host, e novamente antes que uma escrita substitua um arquivo funcional. clawops plan recusa um plano cuja configuração o gateway rejeitaria, enquanto o plano ainda é um arquivo que você pode editar.

Uma configuração rejeitada é mantida em <path>.rejected.<timestamp> e a ativa é deixada em paz, então uma falha de validação nunca custa o que você estava tentando escrever.

Uma regra é do próprio clawops: gateway.mode é opcional no esquema e obrigatória na prática. Uma configuração sem ela passa em openclaw config validate e então sai com 78.

Contêineres são endurecidos

O gateway roda com --cap-drop=ALL, --security-opt no-new-privileges, --init e --pids-limit 512. O estado é de propriedade numérica de 1000:1000, correspondendo ao usuário do contêiner em vez de uma conta de host que pode não ter esse uid.

O pino de versão é aplicado em todos os lugares onde pode mudar

doctor, plan, up e apply recusam uma versão do OpenClaw fora do intervalo suportado, e gateway restart reutiliza a versão já implantada em vez de resolver uma tag móvel. Uma reinicialização não altera nem a versão nem quem pode alcançá-la.

O gateway não está mais exposto à sua rede

O contêiner publica em 127.0.0.1:18789 em vez de 0.0.0.0:18789. Alcance-o com clawops tunnel ou um proxy reverso no host.

Anteriormente, o assistente definia allowedGatewayCidrs a partir do CIDR que você deu para SSH, então um painel HTTP em texto puro. Token na URL. Foi aberto para toda a sua rede de acesso shell como efeito colateral de uma resposta não relacionada. Para vincular todas as interfaces deliberadamente, defina network.publishGateway: "all".

Você deve agir se um cliente ou proxy reverso em outra máquina alcançar o gateway diretamente, ou se o monitoramento externo atingir /health. Um proxy no host não é afetado; um em um contêiner no host precisa de --network host.

Verificações de saúde podem realmente falhar

O gateway serve sua UI de Controle em uma rota catch-all, então qualquer caminho sem correspondência responde 200 com HTML:

/healthz                        200  application/json   {"ok":true,"status":"live"}
/health-typo                    200  text/html          <!doctype html>…

O clawops sondava com curl -fsS … >/dev/null, que tem sucesso em um erro de digitação. Provava que algo estava ouvindo na porta, não que o gateway estava saudável. As sondas agora leem o corpo da resposta, e o portão de reinicialização usa /startupz em vez de liveness, após uma reinicialização o processo escuta muito antes de a inicialização terminar.

clawops mcp wire realmente conecta algo agora

Nunca funcionou, nem no 2.0, nem em nenhuma versão 1.x. Escrevia gateway.mcpClients, que não é uma chave que o OpenClaw tem: verificado contra os esquemas de configuração de 2026.4.5, 2026.7.1-2 e 2026.9.2. A chave real é de nível superior mcp.servers. E a entrada que escrevia era command: "clawops" via stdio, que gera dentro do contêiner do gateway, onde o clawops não está instalado e nada o instala.

No 1.x, nada validava a escrita, então o clawops armazenava uma chave que nada lia, reiniciava seu gateway e relatava: "A IA do gateway agora pode executar comandos do clawops." Não podia.

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"]

Ele delega para openclaw mcp add agora, que sonda o servidor antes de salvar, então "conectado" significa que o gateway conectou, não que um arquivo foi escrito.

Você tem que executar o servidor você mesmo. O clawops não está instalado no host do gateway:

clawops mcp serve --http 18790 --bind 0.0.0.0 --token "$(openssl rand -hex 16)"
clawops mcp wire --stack prod --token <same token>

Instalar o clawops no host do gateway é um acompanhamento deliberado, não parte da 2.0: isso coloca credenciais de implantação na máquina implantada, e a IA do gateway é acessível a partir de todos os canais aos quais está conectada. Veja docs/security/threat-model.md T11.

clawops mcp serve --http atende mais de um cliente e pergunta quem você é

Dois bugs, encontrados ao testar contra um gateway real em vez de um mock.

Ele construiu um transporte para todo o processo, então o primeiro cliente a se conectar o reivindicou e todos os seguintes. Um segundo editor, uma reconexão, a própria sonda do gateway, recebeu como resposta "Server already initialized". O modo HTTP é o modo multi-cliente.

Ele não tinha autenticação, enquanto expunha todas as ferramentas, incluindo clawops_destroy. Agora ele aceita um token de portador, compara-o em tempo constante e se recusa a vincular em qualquer lugar além de loopback sem um.

O firewall segue a implantação

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"]

Três controles de segurança estavam fazendo o oposto do que dizem.

clawops harden abriu a porta do gateway em toda implantação. O módulo ufw executou ufw allow 18789/tcp incondicionalmente. Como o gateway publica em 127.0.0.1, isso abriu uma porta em que nada estava escutando. Uma etapa de endurecimento que amplia o firewall além do que a implantação expõe. Agora ele lê os vínculos de porta do contêiner em execução e adiciona a regra apenas quando o gateway está realmente publicado, em qualquer porta em que esteja publicado.

A auditoria do grupo de segurança da AWS isentou as duas portas que existe para verificar. As portas 22 e 18789 estavam em uma lista "esperada", então um grupo abrindo SSH ou o gateway para 0.0.0.0/0 retornou como "Nenhuma regra de entrada aberta inesperada encontrada". Ele também nunca leu regras IPv6, então ::/0 era invisível.

O assistente de configuração padronizou o acesso SSH para 0.0.0.0/0. Pressionar Enter abriu o SSH para toda a internet, no caminho que a maioria dos usuários de primeira viagem percorre. Agora ele oferece seu próprio IP como um /32, e quando isso não pode ser detectado, ele não oferece padrão e exige uma resposta.

clawops plan não conseguia expressar nada disso, e apply nunca passou nada disso para o Pulumi. Ambos foram corrigidos na 2.0.1. Veja a lista no topo desta seção.

A porta do gateway vem do plano

"network": {
  "allowedSshCidrs": ["203.0.113.4/32"],
  "allowedGatewayCidrs": [],
  "publishGateway": "loopback",
  "gatewayPort": 9443
}

Um valor agora alcança as regras do grupo de segurança, a flag de publicação do contêiner, o padrão gateway.port e a URL do gateway. Era uma constante redeclarada em onze lugares, então alterá-la significava encontrar todos eles, e perder um produzia um contêiner publicando uma porta, um gateway escutando em outra e um firewall abrindo uma terceira.

Implantações locais usam clawops up --gateway-port 9443.

clawops doctor responde se funciona e diz isso no código de saída

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"]

Três mudanças:

Ele pergunta ao gateway. doctor costumava ler o campo de healthcheck do docker inspect, que a imagem do OpenClaw não define, então ele relatava "nenhum healthcheck configurado" e seguia em frente. Um contêiner em execução significa que o processo iniciou, não que ele atende. Agora ele testa /startupz e lê o corpo.

Ele sai com 1 quando algo falha. Apenas um Node.js antigo costumava fazer isso; uma chave SSH ilegível ou um gateway não suportado saía com 0, então uma etapa de CI executando clawops doctor lia uma implantação quebrada como sucesso. Avisos ainda saem com 0; uma máquina nova sem stacks está não configurada, não quebrada.

É uma ferramenta MCP. clawops_doctor retorna o mesmo relatório como dados estruturados, então um agente que encontra uma falha pode descobrir o porquê. Ele apenas relata; nunca executa openclaw doctor --fix. --json dá ao CLI o mesmo relatório.

clawops agents list para de inventar uma lista vazia

O comando terminava em || echo '[]', então um contêiner parado, um gateway ainda iniciando ou um erro de permissão do Docker todos produziam "Nenhum agente em execução.", uma resposta errada em vez de um erro. Agora ele falha e diz qual.

Comandos do dia dois funcionam na AWS

gateway restart, logs, monitor, backup, agents, config set e as verificações de contêiner do doctor estavam todas quebradas na AWS: o clawops conecta como ubuntu, mas o provisionamento só colocou clawops no grupo docker, então todo comando Docker falhava com permission denied. GCP and Azure connect as clawops, então apenas a AWS foi afetada.

Removido

clawops agents restart e a ferramenta MCP clawops_agents_restart. O OpenClaw 2.0 não tem reinício por agente, apenas gateway restart e daemon restart, ambos os quais interrompem todo agente no host. Use clawops gateway restart, ou fique no @clawops/cli@legacy.

clawops agents list e clawops agents logs não são afetados.


Marcos

MarcoStatusO que entrega
M0: Scaffold✅Ferramentas, CI, stubs, tipos gerados
M1: MVP GCP✅init / up / down / status / ssh / logs no GCP
M2: Gerenciamento Remoto✅tunnel, config, agents, gateway; pool de conexões SSH
M3: AWS + Azure✅Adaptadores AWS EC2 + Azure VM; stacks list
M4: VM Local✅Adaptador local (bootstrap SSH, sem Pulumi); doctor
M5: Camada MCP✅mcp serve (stdio), todas as operações CLI como ferramentas MCP, rastreamento de progresso
M6: Plan/Apply✅plan + apply; esquema de plano de implantação; transporte HTTP MCP; workflow_deploy_app
M7: Polimento v1.0✅Superfície completa de doctor; comando destroy; --dry-run entre comandos; guia de CI

Veja docs/roadmap.md para o roteiro público e trabalhos futuros.


Licença

MPL-2.0, veja LICENSE.