@clawops/cli 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +97 -0
- package/dist/{apply-DLNE2JYZ.js → apply-5RREMN3L.js} +3 -3
- package/dist/{aws-KQBWY43W.js → aws-FRE2JVAZ.js} +9 -4
- package/dist/{azure-4EJFVJZL.js → azure-PVC3AQVC.js} +11 -4
- package/dist/chunk-JYQZJMD3.js +764 -0
- package/dist/{chunk-JDN6PLH2.js → chunk-T5EX55GP.js} +3 -3
- package/dist/{chunk-ZDPBBYYV.js → chunk-UAA6YOOP.js} +2 -2
- package/dist/{chunk-UDNZUSKA.js → chunk-ZFNPM2WG.js} +1 -1
- package/dist/{chunk-JCUZU5BH.js → chunk-ZONXY3C6.js} +2 -2
- package/dist/cli.js +63 -50
- package/dist/{context-M2RMDHX6.js → context-PSGEX2D7.js} +1 -1
- package/dist/{gcp-SKURG3L6.js → gcp-BXDTC6EK.js} +60 -17
- package/dist/{generate-U7PJ5LRG.js → generate-Z7DBMANX.js} +2 -2
- package/dist/{package-AFUTH62F.js → package-WAJRGBBM.js} +2 -1
- package/dist/{remote-config-JQ77SRC2.js → remote-config-QF5TT7GU.js} +1 -1
- package/dist/{server-I62UES5V.js → server-IWLZJ4EU.js} +92 -19
- package/package.json +2 -1
- package/dist/chunk-LVIIYY27.js +0 -266
package/README.md
CHANGED
|
@@ -9,6 +9,31 @@ and Cursor drive them through typed MCP tools with explicit safety controls.
|
|
|
9
9
|
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
+
## What's new in v1.4.0
|
|
13
|
+
|
|
14
|
+
**`clawops monitor`** — live dashboard for any deployed stack. Shows gateway health, container
|
|
15
|
+
status, CPU/memory, disk usage, and a rolling log tail. Refreshes on an interval with `[r]`,
|
|
16
|
+
toggles logs with `[l]`, and quits with `[q]`.
|
|
17
|
+
|
|
18
|
+
Run without `--stack` to get an **interactive stack picker** first — probes all registered stacks
|
|
19
|
+
in parallel, shows only running ones by default, and lets you toggle to a full list (`[a]`) where
|
|
20
|
+
not-deployed stacks can be deleted from the registry with `[d]`. Press `[s]` inside the dashboard
|
|
21
|
+
to go back to the picker.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
clawops monitor # interactive stack selection → dashboard
|
|
25
|
+
clawops monitor --stack prod # jump straight to a named stack
|
|
26
|
+
clawops monitor --stack prod | cat # one-shot snapshot for CI
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**`clawops_monitor` MCP tool** — same snapshot as a single structured JSON call, so Claude Code
|
|
30
|
+
and Cursor can check stack health without opening a terminal.
|
|
31
|
+
|
|
32
|
+
**`clawops stacks delete` guard** — now blocks deletion of a still-deployed stack and requires
|
|
33
|
+
`--force` to remove from the registry without tearing down cloud resources first.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
12
37
|
## Who this is for
|
|
13
38
|
|
|
14
39
|
- **OpenClaw users** who want the simplest path to self-hosting across cloud or local VMs, with
|
|
@@ -393,6 +418,78 @@ Key design decisions:
|
|
|
393
418
|
|
|
394
419
|
See [`docs/architecture.md`](docs/architecture.md) for a full narrative, and [`docs/decisions/`](docs/decisions/) for ADRs.
|
|
395
420
|
|
|
421
|
+
### Cloud provider stacks
|
|
422
|
+
|
|
423
|
+
Each cloud provider is an inline Pulumi program that creates the resources below. All three share the same outputs (`publicIp`, `gatewayUrl`, `sshHost`, `sshPort`, `sshUser`) consumed by the SSH and config-overlay layers.
|
|
424
|
+
|
|
425
|
+
#### AWS
|
|
426
|
+
|
|
427
|
+
```mermaid
|
|
428
|
+
flowchart LR
|
|
429
|
+
subgraph NET["Networking"]
|
|
430
|
+
VPC["VPC (10.0.0.0/16)"]
|
|
431
|
+
IGW[Internet Gateway]
|
|
432
|
+
SUBNET["Subnet (10.0.1.0/24)"]
|
|
433
|
+
RT[Route Table]
|
|
434
|
+
SG["Security Group (ports 22, 18789)"]
|
|
435
|
+
end
|
|
436
|
+
subgraph IAM["IAM"]
|
|
437
|
+
ROLE[IAM Role]
|
|
438
|
+
SSM[SSM Policy Attachment]
|
|
439
|
+
BED["Bedrock Policy Attachment (optional)"]
|
|
440
|
+
IP[Instance Profile]
|
|
441
|
+
end
|
|
442
|
+
subgraph COMPUTE["Compute"]
|
|
443
|
+
KP[EC2 Key Pair]
|
|
444
|
+
EC2["EC2 Instance (Ubuntu 22.04, IMDSv2)"]
|
|
445
|
+
EIP[Elastic IP]
|
|
446
|
+
end
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
[Detailed diagram →](docs/providers/aws.md#stack-diagram)
|
|
450
|
+
|
|
451
|
+
#### GCP
|
|
452
|
+
|
|
453
|
+
```mermaid
|
|
454
|
+
flowchart LR
|
|
455
|
+
subgraph NET["Networking"]
|
|
456
|
+
NW[VPC Network]
|
|
457
|
+
SN["Subnetwork (10.0.0.0/24)"]
|
|
458
|
+
FW1["Firewall: SSH port 22 (conditional)"]
|
|
459
|
+
FW2["Firewall: Gateway port 18789 (conditional)"]
|
|
460
|
+
ADDR[Static External IP]
|
|
461
|
+
end
|
|
462
|
+
subgraph COMPUTE["Compute"]
|
|
463
|
+
VM["Compute Instance (Debian 12, 20 GB)"]
|
|
464
|
+
end
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
[Detailed diagram →](docs/providers/gcp.md#stack-diagram)
|
|
468
|
+
|
|
469
|
+
#### Azure
|
|
470
|
+
|
|
471
|
+
```mermaid
|
|
472
|
+
flowchart LR
|
|
473
|
+
RG[Resource Group]
|
|
474
|
+
subgraph NET["Networking"]
|
|
475
|
+
VNET["Virtual Network (10.0.0.0/16)"]
|
|
476
|
+
SUBNET["Subnet (10.0.1.0/24)"]
|
|
477
|
+
NSG["Network Security Group (ports 22, 18789)"]
|
|
478
|
+
PIP["Public IP Address (Static)"]
|
|
479
|
+
NIC[Network Interface]
|
|
480
|
+
end
|
|
481
|
+
subgraph COMPUTE["Compute"]
|
|
482
|
+
VM["VM (Ubuntu 22.04, managed identity)"]
|
|
483
|
+
end
|
|
484
|
+
subgraph KV["Key Vault (optional)"]
|
|
485
|
+
VAULT["Key Vault (RBAC, name max 24 chars)"]
|
|
486
|
+
RA["Role Assignment (Secrets User)"]
|
|
487
|
+
SECRET["Secret: gateway-token"]
|
|
488
|
+
end
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
[Detailed diagram →](docs/providers/azure.md#stack-diagram)
|
|
492
|
+
|
|
396
493
|
---
|
|
397
494
|
|
|
398
495
|
## Development
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
applyPlan
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ZONXY3C6.js";
|
|
5
5
|
import "./chunk-YTH4L2GN.js";
|
|
6
6
|
import "./chunk-6ZFIFDBJ.js";
|
|
7
7
|
import "./chunk-BOPSG2LI.js";
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-T5EX55GP.js";
|
|
9
|
+
import "./chunk-ZFNPM2WG.js";
|
|
10
10
|
import "./chunk-A2I76FTA.js";
|
|
11
11
|
import "./chunk-CX5SL5HP.js";
|
|
12
12
|
import "./chunk-KGXPLI7W.js";
|
|
@@ -142,6 +142,12 @@ var awsProgram = async () => {
|
|
|
142
142
|
iamInstanceProfile: instanceProfile.name,
|
|
143
143
|
keyName: keyPair.keyName,
|
|
144
144
|
userData: makeStartupScript(openclawVersion, bedrockEnabled),
|
|
145
|
+
// IMDSv2 with hopLimit=2 so Docker containers on this host can reach IMDS
|
|
146
|
+
// and obtain the instance role credentials (required for Bedrock access).
|
|
147
|
+
metadataOptions: {
|
|
148
|
+
httpTokens: "required",
|
|
149
|
+
httpPutResponseHopLimit: 2
|
|
150
|
+
},
|
|
145
151
|
tags: { Name: "clawops" }
|
|
146
152
|
});
|
|
147
153
|
const eip = new aws.ec2.Eip("clawops-eip", {
|
|
@@ -164,8 +170,7 @@ var awsProgram = async () => {
|
|
|
164
170
|
};
|
|
165
171
|
};
|
|
166
172
|
function makeStartupScript(openclawVersion, bedrockEnabled) {
|
|
167
|
-
const
|
|
168
|
-
const bedrockEnvFlag = bedrockEnabled ? " --env-file /etc/openclaw.env \\\\\n" : "";
|
|
173
|
+
const bedrockEnvFlag = bedrockEnabled ? " -e AWS_DEFAULT_REGION=$(curl -sf http://169.254.169.254/latest/meta-data/placement/region || echo us-east-1) \\\n" : "";
|
|
169
174
|
return `#!/bin/bash
|
|
170
175
|
set -euo pipefail
|
|
171
176
|
|
|
@@ -175,7 +180,7 @@ mkdir -p /home/clawops/.ssh
|
|
|
175
180
|
chmod 700 /home/clawops/.ssh
|
|
176
181
|
chown clawops:clawops /home/clawops/.ssh
|
|
177
182
|
|
|
178
|
-
# Install Docker if not present (
|
|
183
|
+
# Install Docker if not present (AWS AMI is ubuntu-22.04)
|
|
179
184
|
if ! command -v docker &>/dev/null; then
|
|
180
185
|
export DEBIAN_FRONTEND=noninteractive
|
|
181
186
|
apt-get update -q
|
|
@@ -193,7 +198,7 @@ if ! command -v docker &>/dev/null; then
|
|
|
193
198
|
fi
|
|
194
199
|
|
|
195
200
|
usermod -aG docker clawops
|
|
196
|
-
|
|
201
|
+
|
|
197
202
|
# Pull OpenClaw image
|
|
198
203
|
OPENCLAW_VERSION="${openclawVersion}"
|
|
199
204
|
docker pull ghcr.io/openclaw/openclaw:\${OPENCLAW_VERSION}
|
|
@@ -4,12 +4,14 @@
|
|
|
4
4
|
import process2 from "process";
|
|
5
5
|
|
|
6
6
|
// src/providers/azure/program.ts
|
|
7
|
+
import { createHash } from "crypto";
|
|
7
8
|
var GATEWAY_PORT = 18789;
|
|
8
9
|
var SSH_PORT = 22;
|
|
9
10
|
var azureProgram = async () => {
|
|
10
|
-
const [pulumi, azure, { resolveIngressCidrs, detectEgressIp }] = await Promise.all([
|
|
11
|
+
const [pulumi, azure, random, { resolveIngressCidrs, detectEgressIp }] = await Promise.all([
|
|
11
12
|
import("@pulumi/pulumi"),
|
|
12
13
|
import("@pulumi/azure-native"),
|
|
14
|
+
import("@pulumi/random"),
|
|
13
15
|
import("./firewall-YYDOWDDP.js")
|
|
14
16
|
]);
|
|
15
17
|
const cfg = new pulumi.Config();
|
|
@@ -138,8 +140,9 @@ var azureProgram = async () => {
|
|
|
138
140
|
}
|
|
139
141
|
});
|
|
140
142
|
if (keyVaultEnabled) {
|
|
141
|
-
const
|
|
142
|
-
const
|
|
143
|
+
const safeName = stackName.replace(/[^a-zA-Z0-9-]/g, "-");
|
|
144
|
+
const rawKvName = `clawops-${safeName}-kv`;
|
|
145
|
+
const kvName = rawKvName.length > 24 ? `cl-${createHash("sha256").update(stackName).digest("hex").slice(0, 20)}` : rawKvName;
|
|
143
146
|
const kv = new azure.keyvault.Vault("clawops-kv", {
|
|
144
147
|
resourceGroupName: rg.name,
|
|
145
148
|
location: rg.location,
|
|
@@ -157,11 +160,15 @@ var azureProgram = async () => {
|
|
|
157
160
|
principalId: pulumi.output(vm.identity).apply((i) => i?.principalId ?? ""),
|
|
158
161
|
principalType: "ServicePrincipal"
|
|
159
162
|
});
|
|
163
|
+
const gatewayToken = new random.RandomPassword("clawops-kv-gateway-token", {
|
|
164
|
+
length: 32,
|
|
165
|
+
special: false
|
|
166
|
+
});
|
|
160
167
|
new azure.keyvault.Secret("clawops-gateway-token", {
|
|
161
168
|
resourceGroupName: rg.name,
|
|
162
169
|
vaultName: kv.name,
|
|
163
170
|
secretName: "gateway-token",
|
|
164
|
-
properties: { value:
|
|
171
|
+
properties: { value: gatewayToken.result }
|
|
165
172
|
});
|
|
166
173
|
}
|
|
167
174
|
const resolvedIp = pulumi.output(publicIp.ipAddress).apply((ip) => ip ?? "");
|