@clawops/cli 1.7.1 → 1.7.3

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.
Files changed (41) hide show
  1. package/README.md +37 -92
  2. package/dist/{apply-BTZFFGAD.js → apply-PZ5IIU7Z.js} +5 -4
  3. package/dist/{aws-D7Y6LCGK.js → aws-L4RR2LSE.js} +1 -1
  4. package/dist/{azure-JQAMNVHN.js → azure-7OXQENQL.js} +1 -1
  5. package/dist/{bootstrap-RY4VOSDJ.js → bootstrap-HL4DNUNG.js} +13 -4
  6. package/dist/bootstrap.sh.tmpl +204 -0
  7. package/dist/chunk-2YOP6N7X.js +126 -0
  8. package/dist/{chunk-GJEF6UQA.js → chunk-3XK66DKK.js} +100 -16
  9. package/dist/{chunk-ISFHLA4G.js → chunk-5SPESD5N.js} +8 -6
  10. package/dist/{chunk-YTH4L2GN.js → chunk-6X45DDGH.js} +5 -4
  11. package/dist/{chunk-XKT42M34.js → chunk-C5X375RO.js} +14 -1
  12. package/dist/{chunk-LCKD7L7X.js → chunk-DQDAWNGB.js} +1 -1
  13. package/dist/{chunk-CG3Y7Y2R.js → chunk-FSUWPL7Q.js} +9 -9
  14. package/dist/{chunk-FQ4JXUCR.js → chunk-NESXDU5F.js} +7 -4
  15. package/dist/{chunk-ZFNPM2WG.js → chunk-O3F7OGH7.js} +40 -3
  16. package/dist/{chunk-3MFZ7E74.js → chunk-P5LKWRPL.js} +3 -3
  17. package/dist/chunk-PVUVI35Y.js +29 -0
  18. package/dist/cli.js +122 -68
  19. package/dist/{context-ALSJMTHE.js → context-5LCUG2QR.js} +1 -1
  20. package/dist/{gcp-6FT2A45S.js → gcp-UG6AWPIZ.js} +1 -1
  21. package/dist/{generate-SPT7PJKR.js → generate-6E7J6BTM.js} +4 -3
  22. package/dist/{harden-BDVYW567.js → harden-URPXLSVF.js} +2 -2
  23. package/dist/{mcp-wire-ZWIYMLEW.js → mcp-wire-SLL4TLSC.js} +1 -1
  24. package/dist/{package-OMPI6RMV.js → package-QE7V2JAT.js} +3 -2
  25. package/dist/{pool-JZGKPP6K.js → pool-QGFQRMGU.js} +2 -2
  26. package/dist/{remote-config-QF5TT7GU.js → remote-config-PFB66RPY.js} +3 -1
  27. package/dist/{server-RGLKKCCU.js → server-L22AJQZO.js} +19 -18
  28. package/dist/{ssh-E2AMBPZY.js → ssh-CNJNLM3E.js} +1 -1
  29. package/dist/{validate-T5M5EHSJ.js → validate-CFQ4FH2T.js} +2 -1
  30. package/dist/version-guard-MZAO4KHS.js +25 -0
  31. package/dist/versions-OEPAS2EL.js +24 -0
  32. package/package.json +3 -2
  33. package/spec/_gen-schemas.md +136 -0
  34. package/spec/deploy-plan.schema.json +193 -0
  35. package/spec/errors.yaml +175 -0
  36. package/spec/integrations.yaml +97 -0
  37. package/spec/invariants.yaml +81 -0
  38. package/spec/mcp-tools.yaml +532 -0
  39. package/spec/models.yaml +113 -0
  40. package/spec/openclaw-versions.yaml +67 -0
  41. package/spec/providers.schema.json +120 -0
package/dist/cli.js CHANGED
@@ -2,16 +2,19 @@
2
2
  import {
3
3
  monitor_default,
4
4
  validateOpenclawConfig
5
- } from "./chunk-CG3Y7Y2R.js";
5
+ } from "./chunk-FSUWPL7Q.js";
6
6
  import {
7
7
  MCP_APPS,
8
8
  buildMcpEntry,
9
9
  writeAppConfigs
10
10
  } from "./chunk-OIGTOLB3.js";
11
- import "./chunk-ZFNPM2WG.js";
12
- import "./chunk-3MFZ7E74.js";
13
- import "./chunk-LCKD7L7X.js";
14
- import "./chunk-GJEF6UQA.js";
11
+ import "./chunk-DQDAWNGB.js";
12
+ import "./chunk-O3F7OGH7.js";
13
+ import "./chunk-P5LKWRPL.js";
14
+ import {
15
+ resolveSpecDir
16
+ } from "./chunk-PVUVI35Y.js";
17
+ import "./chunk-3XK66DKK.js";
15
18
  import {
16
19
  REPO_URL,
17
20
  chalk,
@@ -202,14 +205,16 @@ var up_default = defineCommand2({
202
205
  "instance-type": { type: "string", description: "Instance size alias (micro|small|medium|large|gpu)" },
203
206
  "dry-run": { type: "boolean", description: "Preview without applying" },
204
207
  "no-wait": { type: "boolean", description: "Return immediately without waiting for healthy state" },
205
- "openclaw-version": { type: "string", description: "semver or 'stable'/'dev'" },
208
+ "openclaw-version": { type: "string", description: "OpenClaw release (e.g. 2026.7.1-2). Moving tags are resolved and range-checked" },
206
209
  stack: { type: "string", description: "Target stack name" },
207
210
  config: { type: "string", description: "Path to openclaw config overlay JSON (local provider only)" }
208
211
  },
209
212
  async run({ args }) {
210
- const { buildContext } = await import("./context-ALSJMTHE.js");
213
+ const { buildContext } = await import("./context-5LCUG2QR.js");
214
+ const { guardOpenclawVersion, defaultOpenclawVersion } = await import("./version-guard-MZAO4KHS.js");
211
215
  const ctx = buildContext(args);
212
- const openclawVersion = typeof args["openclaw-version"] === "string" ? args["openclaw-version"] : "stable";
216
+ const requestedVersion = typeof args["openclaw-version"] === "string" ? args["openclaw-version"] : await defaultOpenclawVersion();
217
+ const openclawVersion = await guardOpenclawVersion(requestedVersion);
213
218
  if (ctx.adapter.name === "local") {
214
219
  const stackConfig = ctx.config.stacks[ctx.stackName];
215
220
  if (!stackConfig?.localOpts) {
@@ -218,7 +223,7 @@ var up_default = defineCommand2({
218
223
  );
219
224
  }
220
225
  const { localOpts } = stackConfig;
221
- const { localBootstrap } = await import("./bootstrap-RY4VOSDJ.js");
226
+ const { localBootstrap } = await import("./bootstrap-HL4DNUNG.js");
222
227
  const abortController = new AbortController();
223
228
  process3.on("SIGINT", () => abortController.abort());
224
229
  process3.on("SIGTERM", () => abortController.abort());
@@ -311,9 +316,9 @@ var up_default = defineCommand2({
311
316
  }
312
317
  });
313
318
  async function applyLocalConfigOverlay(opts) {
314
- const { connect } = await import("./ssh-E2AMBPZY.js");
319
+ const { connect } = await import("./ssh-CNJNLM3E.js");
315
320
  const { resolveSecrets } = await import("./secrets-SVZWNAPK.js");
316
- const { readRemoteConfig, atomicWriteConfig, restartGateway, deepMerge } = await import("./remote-config-QF5TT7GU.js");
321
+ const { readRemoteConfig, atomicWriteConfig, restartGateway, deepMerge } = await import("./remote-config-PFB66RPY.js");
317
322
  let overlay;
318
323
  try {
319
324
  overlay = JSON.parse(readFileSync(opts.configPath, "utf-8"));
@@ -353,7 +358,7 @@ var down_default = defineCommand3({
353
358
  "dry-run": { type: "boolean", description: "Show what would be destroyed without destroying" }
354
359
  },
355
360
  async run({ args }) {
356
- const { buildContext } = await import("./context-ALSJMTHE.js");
361
+ const { buildContext } = await import("./context-5LCUG2QR.js");
357
362
  const ctx = buildContext(args);
358
363
  if (args["dry-run"]) {
359
364
  info(`Dry run \u2014 would destroy stack "${ctx.stackName}"`);
@@ -417,7 +422,7 @@ var status_default = defineCommand4({
417
422
  json: { type: "boolean", description: "Emit JSON" }
418
423
  },
419
424
  async run({ args }) {
420
- const { buildContext } = await import("./context-ALSJMTHE.js");
425
+ const { buildContext } = await import("./context-5LCUG2QR.js");
421
426
  const ctx = buildContext(args);
422
427
  if (ctx.adapter.name === "local") {
423
428
  const state = ctx.localState;
@@ -489,8 +494,8 @@ var plan_default = defineCommand5({
489
494
  out: { type: "string", description: "Write plan JSON to this absolute path (default: stdout)" }
490
495
  },
491
496
  async run({ args }) {
492
- const { buildContext } = await import("./context-ALSJMTHE.js");
493
- const { generatePlan } = await import("./generate-SPT7PJKR.js");
497
+ const { buildContext } = await import("./context-5LCUG2QR.js");
498
+ const { generatePlan } = await import("./generate-6E7J6BTM.js");
494
499
  const ctx = buildContext(args);
495
500
  if (ctx.adapter.name === "local") {
496
501
  throw new UsageError(
@@ -579,8 +584,8 @@ var apply_default = defineCommand6({
579
584
  "dry-run": { type: "boolean", description: "Validate plan and show diff without applying" }
580
585
  },
581
586
  async run({ args }) {
582
- const { validatePlan } = await import("./validate-T5M5EHSJ.js");
583
- const { applyPlan } = await import("./apply-BTZFFGAD.js");
587
+ const { validatePlan } = await import("./validate-CFQ4FH2T.js");
588
+ const { applyPlan } = await import("./apply-PZ5IIU7Z.js");
584
589
  const planPath = args._?.[0];
585
590
  if (!planPath) {
586
591
  throw new UsageError("Usage: clawops apply <plan.json>");
@@ -696,7 +701,7 @@ var destroy_default = defineCommand7({
696
701
  "dry-run": { type: "boolean", description: "Show what would be destroyed without destroying" }
697
702
  },
698
703
  async run({ args }) {
699
- const { buildContext } = await import("./context-ALSJMTHE.js");
704
+ const { buildContext } = await import("./context-5LCUG2QR.js");
700
705
  const ctx = buildContext(args);
701
706
  if (ctx.adapter.name === "local") {
702
707
  throw new UsageError(
@@ -763,8 +768,8 @@ var ssh_default = defineCommand8({
763
768
  command: { type: "string", description: "Remote command to run (instead of interactive shell)" }
764
769
  },
765
770
  async run({ args }) {
766
- const { buildContext } = await import("./context-ALSJMTHE.js");
767
- const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
771
+ const { buildContext } = await import("./context-5LCUG2QR.js");
772
+ const { acquireSession, drainPool } = await import("./pool-QGFQRMGU.js");
768
773
  const ctx = buildContext(args);
769
774
  let conn;
770
775
  if (ctx.adapter.name === "local") {
@@ -850,9 +855,9 @@ var tunnel_default = defineCommand9({
850
855
  "no-open": { type: "boolean", description: "Do not open browser after tunnel is ready" }
851
856
  },
852
857
  async run({ args }) {
853
- const { buildContext } = await import("./context-ALSJMTHE.js");
858
+ const { buildContext } = await import("./context-5LCUG2QR.js");
854
859
  const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
855
- const { acquireSession } = await import("./pool-JZGKPP6K.js");
860
+ const { acquireSession } = await import("./pool-QGFQRMGU.js");
856
861
  const ctx = buildContext(args);
857
862
  const stack = await ctx.getStack();
858
863
  const outputMap = await stack.outputs();
@@ -918,9 +923,9 @@ var logs_default = defineCommand10({
918
923
  since: { type: "string", description: "Show logs since duration (e.g. 5m, 1h)" }
919
924
  },
920
925
  async run({ args }) {
921
- const { buildContext } = await import("./context-ALSJMTHE.js");
926
+ const { buildContext } = await import("./context-5LCUG2QR.js");
922
927
  const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
923
- const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
928
+ const { acquireSession, drainPool } = await import("./pool-QGFQRMGU.js");
924
929
  const ctx = buildContext(args);
925
930
  const stack = await ctx.getStack();
926
931
  const outputMap = await stack.outputs();
@@ -994,7 +999,7 @@ function dockerRunCmd(image) {
994
999
  return [
995
1000
  "docker stop openclaw 2>/dev/null || true",
996
1001
  "docker rm openclaw 2>/dev/null || true",
997
- `docker run -d --name openclaw --restart unless-stopped -p 18789:18789 -v ${OPENCLAW_CONFIG}:/app/config.json:ro ${image}`
1002
+ `docker run -d --name openclaw --restart unless-stopped -p 18789:18789 -e OPENCLAW_CONFIG_PATH=/app/config.json --add-host=host.docker.internal:host-gateway -v ${OPENCLAW_CONFIG}:/app/config.json:ro ${image}`
998
1003
  ].join(" && ");
999
1004
  }
1000
1005
  function getPath(obj, dotKey) {
@@ -1035,9 +1040,9 @@ var config_default = defineCommand11({
1035
1040
  "dry-run": { type: "boolean", description: "Show what would change without writing" }
1036
1041
  },
1037
1042
  async run({ args }) {
1038
- const { buildContext } = await import("./context-ALSJMTHE.js");
1043
+ const { buildContext } = await import("./context-5LCUG2QR.js");
1039
1044
  const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
1040
- const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
1045
+ const { acquireSession, drainPool } = await import("./pool-QGFQRMGU.js");
1041
1046
  const [action, key, value] = args._ ?? [];
1042
1047
  if (!action || !["get", "set", "unset", "validate"].includes(action)) {
1043
1048
  failure("Usage: clawops config <get [key] | set key value | unset key | validate>");
@@ -1161,9 +1166,9 @@ var agents_default = defineCommand12({
1161
1166
  json: { type: "boolean", description: "Emit JSON (for list)" }
1162
1167
  },
1163
1168
  async run({ args }) {
1164
- const { buildContext } = await import("./context-ALSJMTHE.js");
1169
+ const { buildContext } = await import("./context-5LCUG2QR.js");
1165
1170
  const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
1166
- const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
1171
+ const { acquireSession, drainPool } = await import("./pool-QGFQRMGU.js");
1167
1172
  const [action, name] = args._ ?? [];
1168
1173
  if (!action || !["list", "restart", "logs"].includes(action)) {
1169
1174
  failure("Usage: clawops agents <list | restart [name] | logs <name>>");
@@ -1252,7 +1257,7 @@ import { defineCommand as defineCommand13 } from "citty";
1252
1257
  import process15 from "process";
1253
1258
  var OPENCLAW_CONFIG2 = "/home/clawops/openclaw.json";
1254
1259
  function dockerRunCmd2(version) {
1255
- return `docker stop openclaw 2>/dev/null || true && docker rm openclaw 2>/dev/null || true && docker run -d --name openclaw --restart unless-stopped -p 18789:18789 -v ${OPENCLAW_CONFIG2}:/app/config.json:ro ghcr.io/openclaw/openclaw:${version}`;
1260
+ return `docker stop openclaw 2>/dev/null || true && docker rm openclaw 2>/dev/null || true && docker run -d --name openclaw --restart unless-stopped -p 18789:18789 -e OPENCLAW_CONFIG_PATH=/app/config.json --add-host=host.docker.internal:host-gateway -v ${OPENCLAW_CONFIG2}:/app/config.json:ro ghcr.io/openclaw/openclaw:${version}`;
1256
1261
  }
1257
1262
  var gateway_default = defineCommand13({
1258
1263
  meta: {
@@ -1265,9 +1270,9 @@ var gateway_default = defineCommand13({
1265
1270
  json: { type: "boolean", description: "Emit JSON (for status)" }
1266
1271
  },
1267
1272
  async run({ args }) {
1268
- const { buildContext } = await import("./context-ALSJMTHE.js");
1273
+ const { buildContext } = await import("./context-5LCUG2QR.js");
1269
1274
  const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
1270
- const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
1275
+ const { acquireSession, drainPool } = await import("./pool-QGFQRMGU.js");
1271
1276
  const [action, versionArg] = args._ ?? [];
1272
1277
  if (!action || !["status", "restart", "update"].includes(action)) {
1273
1278
  failure("Usage: clawops gateway <status | restart | update [version]>");
@@ -1378,8 +1383,8 @@ var backup_default = defineCommand14({
1378
1383
  yes: { type: "boolean", description: "[restore] Skip confirmation prompt" }
1379
1384
  },
1380
1385
  async run({ args }) {
1381
- const { buildContext } = await import("./context-ALSJMTHE.js");
1382
- const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
1386
+ const { buildContext } = await import("./context-5LCUG2QR.js");
1387
+ const { acquireSession, drainPool } = await import("./pool-QGFQRMGU.js");
1383
1388
  const action = args.action;
1384
1389
  if (action !== "create" && action !== "restore") {
1385
1390
  throw new UsageError(`Unknown action: ${action}. Use "create" or "restore"`);
@@ -1551,7 +1556,7 @@ var stacks_default = defineCommand15({
1551
1556
  let isDeployed = false;
1552
1557
  if (!args.force) {
1553
1558
  try {
1554
- const { buildContext } = await import("./context-ALSJMTHE.js");
1559
+ const { buildContext } = await import("./context-5LCUG2QR.js");
1555
1560
  const ctx = buildContext({ stack: name });
1556
1561
  if (ctx.adapter.name === "local") {
1557
1562
  isDeployed = !!ctx.localState;
@@ -1672,9 +1677,9 @@ var doctor_default = defineCommand16({
1672
1677
  info("Credential checks skipped \u2014 no config");
1673
1678
  } else {
1674
1679
  const { getProvider } = await import("./providers-2OABPW2E.js");
1675
- await import("./aws-D7Y6LCGK.js");
1676
- await import("./gcp-6FT2A45S.js");
1677
- await import("./azure-JQAMNVHN.js");
1680
+ await import("./aws-L4RR2LSE.js");
1681
+ await import("./gcp-UG6AWPIZ.js");
1682
+ await import("./azure-7OXQENQL.js");
1678
1683
  await import("./local-DXBEVZ5C.js");
1679
1684
  const checkedProviders = /* @__PURE__ */ new Set();
1680
1685
  for (const [stackName, stackCfg] of Object.entries(config.stacks)) {
@@ -1703,15 +1708,27 @@ var doctor_default = defineCommand16({
1703
1708
  warn("No stacks configured \u2014 run `clawops init`");
1704
1709
  }
1705
1710
  }
1711
+ process18.stdout.write("\nOpenClaw\n");
1712
+ try {
1713
+ const yaml = await import("./js-yaml-PTEEG4FO.js");
1714
+ const { loadVersionSpec, describeRange } = await import("./versions-OEPAS2EL.js");
1715
+ const support = loadVersionSpec(yaml).support;
1716
+ success(`Supported range ${describeRange(support)} (recommended ${support.recommended})`);
1717
+ if (!support.max) {
1718
+ warn("No upper bound declared \u2014 this line would accept any OpenClaw release");
1719
+ }
1720
+ } catch (e) {
1721
+ failure(`Version matrix ${e.message}`);
1722
+ }
1706
1723
  if (args.stack) {
1707
1724
  process18.stdout.write("\nRemote health\n");
1708
1725
  if (!config) {
1709
1726
  info("Remote health skipped \u2014 no config");
1710
1727
  } else {
1711
1728
  try {
1712
- const { buildContext } = await import("./context-ALSJMTHE.js");
1729
+ const { buildContext } = await import("./context-5LCUG2QR.js");
1713
1730
  const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
1714
- const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
1731
+ const { acquireSession, drainPool } = await import("./pool-QGFQRMGU.js");
1715
1732
  const ctx = buildContext({ stack: args.stack });
1716
1733
  const stack = await ctx.getStack();
1717
1734
  const outputMap = await stack.outputs();
@@ -1746,6 +1763,34 @@ var doctor_default = defineCommand16({
1746
1763
  } else {
1747
1764
  failure(`Container ${containerStatus || "unknown"}`);
1748
1765
  }
1766
+ const imageResult = await session.exec(
1767
+ `docker inspect openclaw --format '{{.Config.Image}}' 2>/dev/null || echo ''`,
1768
+ ac.signal
1769
+ );
1770
+ const image = imageResult.stdout.trim();
1771
+ const deployedVersion = image.includes(":") ? image.slice(image.lastIndexOf(":") + 1) : "";
1772
+ if (deployedVersion) {
1773
+ const yaml = await import("./js-yaml-PTEEG4FO.js");
1774
+ const { loadVersionSpec, checkVersion, isMovingTag } = await import("./versions-OEPAS2EL.js");
1775
+ const support = loadVersionSpec(yaml).support;
1776
+ if (isMovingTag(deployedVersion)) {
1777
+ warn(
1778
+ `Deployed ${image} (moving tag \u2014 pin an explicit version; "${deployedVersion}" now resolves to OpenClaw 2.0)`
1779
+ );
1780
+ } else {
1781
+ const check = checkVersion(deployedVersion, support);
1782
+ if (check.ok) {
1783
+ success(`Deployed OpenClaw ${deployedVersion}`);
1784
+ } else {
1785
+ failure(`Deployed OpenClaw ${deployedVersion} is not supported by this clawops line`);
1786
+ if (check.error.reason === "too-new") {
1787
+ warn(
1788
+ " This gateway is running OpenClaw 2.0 or later. Session state may already have been lost: 2.0 stores sessions and credentials in SQLite under a directory this clawops line does not mount, so every container restart discards them. Upgrade to clawops 2.x before making changes."
1789
+ );
1790
+ }
1791
+ }
1792
+ }
1793
+ }
1749
1794
  const healthResult = await session.exec(
1750
1795
  `docker inspect openclaw --format '{{.State.Health.Status}}' 2>/dev/null || echo 'none'`,
1751
1796
  ac.signal
@@ -1798,8 +1843,8 @@ var doctor_default = defineCommand16({
1798
1843
  if (args.stack && config) {
1799
1844
  process18.stdout.write("\nHardening\n");
1800
1845
  try {
1801
- const { MODULE_CATALOG, resolveModules, withRemoteExec } = await import("./harden-BDVYW567.js");
1802
- const { buildContext } = await import("./context-ALSJMTHE.js");
1846
+ const { MODULE_CATALOG, resolveModules, withRemoteExec } = await import("./harden-URPXLSVF.js");
1847
+ const { buildContext } = await import("./context-5LCUG2QR.js");
1803
1848
  const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
1804
1849
  const ctx = buildContext({ stack: args.stack });
1805
1850
  const stackObj = await ctx.getStack();
@@ -1862,7 +1907,7 @@ var serveCmd = defineCommand17({
1862
1907
  inspector: { type: "boolean", description: "Enable MCP inspector" }
1863
1908
  },
1864
1909
  async run({ args }) {
1865
- const { serveMcp } = await import("./server-RGLKKCCU.js");
1910
+ const { serveMcp } = await import("./server-L22AJQZO.js");
1866
1911
  await serveMcp({
1867
1912
  port: args.http ? Number(args.http) : void 0,
1868
1913
  bind: args.bind,
@@ -1937,10 +1982,10 @@ var wireCmd = defineCommand17({
1937
1982
  force: { type: "boolean", description: "Apply even if gateway version is below minimum" }
1938
1983
  },
1939
1984
  async run({ args }) {
1940
- const { buildContext } = await import("./context-ALSJMTHE.js");
1941
- const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
1985
+ const { buildContext } = await import("./context-5LCUG2QR.js");
1986
+ const { acquireSession, drainPool } = await import("./pool-QGFQRMGU.js");
1942
1987
  const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
1943
- const { wireGatewayMcp } = await import("./mcp-wire-ZWIYMLEW.js");
1988
+ const { wireGatewayMcp } = await import("./mcp-wire-SLL4TLSC.js");
1944
1989
  const ac = new AbortController();
1945
1990
  process19.on("SIGINT", () => {
1946
1991
  ac.abort();
@@ -2027,7 +2072,6 @@ import { randomBytes } from "crypto";
2027
2072
  import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, existsSync as existsSync2, mkdirSync as mkdirSync3 } from "fs";
2028
2073
  import { execSync, spawnSync, spawn as spawn2 } from "child_process";
2029
2074
  import path3 from "path";
2030
- import { fileURLToPath } from "url";
2031
2075
  var setup_default = defineCommand18({
2032
2076
  meta: {
2033
2077
  name: "setup",
@@ -2220,10 +2264,14 @@ var setup_default = defineCommand18({
2220
2264
  const { baseUrl } = await inquirer.prompt([{
2221
2265
  type: "input",
2222
2266
  name: "baseUrl",
2223
- message: "Ollama address: (the URL where Ollama is running \u2014 usually http://localhost:11434)",
2224
- default: modelProvider.baseUrlDefault ?? "http://localhost:11434"
2267
+ message: "Ollama address: (OpenClaw runs in a container, so use host.docker.internal rather than localhost to reach Ollama on the host)",
2268
+ default: modelProvider.baseUrlDefault ?? "http://host.docker.internal:11434"
2225
2269
  }]);
2226
- modelConfig["baseUrl"] = baseUrl;
2270
+ const rewritten = rewriteLocalhostForContainer(baseUrl);
2271
+ if (rewritten !== baseUrl) {
2272
+ info(` Using ${rewritten} \u2014 inside the container, localhost is the container itself.`);
2273
+ }
2274
+ modelConfig["baseUrl"] = rewritten;
2227
2275
  }
2228
2276
  const builtModelConfig = {
2229
2277
  provider: modelProviderId,
@@ -2458,7 +2506,7 @@ var setup_default = defineCommand18({
2458
2506
  default: false
2459
2507
  }]);
2460
2508
  if (applyNow) {
2461
- const { applyPlan } = await import("./apply-BTZFFGAD.js");
2509
+ const { applyPlan } = await import("./apply-PZ5IIU7Z.js");
2462
2510
  const plan = JSON.parse(readFileSync3(outputPath, "utf-8"));
2463
2511
  try {
2464
2512
  await applyPlan(plan, {
@@ -2487,9 +2535,9 @@ To deploy later: clawops apply ${outputPath}`);
2487
2535
  });
2488
2536
  async function runLocalDeploy(opts) {
2489
2537
  const { setConfig: setConfig2, getConfig: getConfig2, getConfigDir: getConfigDir2 } = await import("./store-SDUR52Z5.js");
2490
- const { localBootstrap } = await import("./bootstrap-RY4VOSDJ.js");
2491
- const { connect } = await import("./ssh-E2AMBPZY.js");
2492
- const { readRemoteConfig, atomicWriteConfig, restartGateway, deepMerge } = await import("./remote-config-QF5TT7GU.js");
2538
+ const { localBootstrap } = await import("./bootstrap-HL4DNUNG.js");
2539
+ const { connect } = await import("./ssh-CNJNLM3E.js");
2540
+ const { readRemoteConfig, atomicWriteConfig, restartGateway, deepMerge } = await import("./remote-config-PFB66RPY.js");
2493
2541
  const { resolveSecrets } = await import("./secrets-SVZWNAPK.js");
2494
2542
  const knownHostsPath = path3.join(getConfigDir2(), "known_hosts");
2495
2543
  const existing = getConfig2();
@@ -2570,7 +2618,7 @@ async function runLocalDeploy(opts) {
2570
2618
  spin2.fail("Configuration failed");
2571
2619
  throw err;
2572
2620
  }
2573
- const { drainPool } = await import("./pool-JZGKPP6K.js");
2621
+ const { drainPool } = await import("./pool-QGFQRMGU.js");
2574
2622
  drainPool();
2575
2623
  const tokenPath = path3.join(os.homedir(), ".clawops", "secrets", `GATEWAY_TOKEN_${opts.stackName}`);
2576
2624
  const dashboardUrl = `${state.gatewayUrl}?token=${opts.gatewayToken}`;
@@ -2708,7 +2756,7 @@ var DOCKER_CHECK_CMD = [
2708
2756
  "echo NOT_RUNNING"
2709
2757
  ].join("; ");
2710
2758
  async function checkDockerPreflight(opts) {
2711
- const { acquireSession } = await import("./pool-JZGKPP6K.js");
2759
+ const { acquireSession } = await import("./pool-QGFQRMGU.js");
2712
2760
  const { ProviderError } = await import("./errors-OK47MQFD.js");
2713
2761
  const spin = spinner("Checking Docker on target host...");
2714
2762
  const timeoutSignal = AbortSignal.timeout(DOCKER_PREFLIGHT_TIMEOUT_MS);
@@ -2755,7 +2803,7 @@ async function checkDockerPreflight(opts) {
2755
2803
  var DOCKER_POLL_MS = 3e3;
2756
2804
  var DOCKER_TIMEOUT_MS = 9e4;
2757
2805
  async function startRemoteDocker(opts, spin) {
2758
- const { acquireSession } = await import("./pool-JZGKPP6K.js");
2806
+ const { acquireSession } = await import("./pool-QGFQRMGU.js");
2759
2807
  const { ProviderError } = await import("./errors-OK47MQFD.js");
2760
2808
  spin.text = "Starting Docker on the remote server...";
2761
2809
  const { session, release } = await acquireSession({
@@ -2959,9 +3007,9 @@ async function maybeWireGatewayMcp(opts) {
2959
3007
  process20.stdout.write("\n");
2960
3008
  const { wireGateway } = await inquirerPromptWire(opts.inquirer);
2961
3009
  if (!wireGateway) return;
2962
- const { connect } = await import("./ssh-E2AMBPZY.js");
3010
+ const { connect } = await import("./ssh-CNJNLM3E.js");
2963
3011
  const { getConfigDir: getConfigDir2 } = await import("./store-SDUR52Z5.js");
2964
- const { wireGatewayMcp } = await import("./mcp-wire-ZWIYMLEW.js");
3012
+ const { wireGatewayMcp } = await import("./mcp-wire-SLL4TLSC.js");
2965
3013
  const knownHostsPath = path3.join(getConfigDir2(), "known_hosts");
2966
3014
  const spin = spinner("Wiring gateway MCP client...");
2967
3015
  const session = await connect({
@@ -3005,7 +3053,7 @@ async function inquirerPromptWire(inquirer) {
3005
3053
  }]);
3006
3054
  }
3007
3055
  function loadCatalogs(yaml) {
3008
- const specDir = path3.join(path3.dirname(fileURLToPath(import.meta.url)), "../../../spec");
3056
+ const specDir = resolveSpecDir();
3009
3057
  try {
3010
3058
  const modelsRaw = yaml.load(readFileSync3(path3.join(specDir, "models.yaml"), "utf-8"));
3011
3059
  const integrationsRaw = yaml.load(readFileSync3(path3.join(specDir, "integrations.yaml"), "utf-8"));
@@ -3017,6 +3065,12 @@ function loadCatalogs(yaml) {
3017
3065
  throw new Error(`Cannot load wizard catalogs from spec/: ${err.message}`);
3018
3066
  }
3019
3067
  }
3068
+ function rewriteLocalhostForContainer(url) {
3069
+ return url.replace(
3070
+ /^(https?:\/\/)(localhost|127\.0\.0\.1|\[::1\])(?=[:/]|$)/i,
3071
+ "$1host.docker.internal"
3072
+ );
3073
+ }
3020
3074
  function defaultRegion(provider) {
3021
3075
  if (provider === "aws") return "us-east-1";
3022
3076
  if (provider === "gcp") return "us-central1";
@@ -3053,7 +3107,7 @@ function instanceChoices(provider) {
3053
3107
  return table[provider] ?? [];
3054
3108
  }
3055
3109
  async function maybeHarden(opts) {
3056
- const { MODULE_CATALOG, resolveModules, runHardening, formatHardenSummary } = await import("./harden-BDVYW567.js");
3110
+ const { MODULE_CATALOG, resolveModules, runHardening, formatHardenSummary } = await import("./harden-URPXLSVF.js");
3057
3111
  const { getConfig: getConfig2 } = await import("./store-SDUR52Z5.js");
3058
3112
  const config = getConfig2();
3059
3113
  if (!config) return;
@@ -3077,7 +3131,7 @@ async function maybeHarden(opts) {
3077
3131
  const modules = availableModules.filter((m) => selectedIds.includes(m.id));
3078
3132
  process20.stdout.write("\nApplying hardening modules...\n\n");
3079
3133
  try {
3080
- const { buildContext } = await import("./context-ALSJMTHE.js");
3134
+ const { buildContext } = await import("./context-5LCUG2QR.js");
3081
3135
  const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
3082
3136
  const ctx = buildContext({ stack: opts.stackName });
3083
3137
  const stackObj = await ctx.getStack();
@@ -3286,10 +3340,10 @@ var rotateCmd = defineCommand19({
3286
3340
  }
3287
3341
  info(`Re-applying config overlay to stack "${targetStack}"\u2026`);
3288
3342
  try {
3289
- const { buildContext } = await import("./context-ALSJMTHE.js");
3290
- const { readRemoteConfig, atomicWriteConfig, restartGateway, deepMerge } = await import("./remote-config-QF5TT7GU.js");
3343
+ const { buildContext } = await import("./context-5LCUG2QR.js");
3344
+ const { readRemoteConfig, atomicWriteConfig, restartGateway, deepMerge } = await import("./remote-config-PFB66RPY.js");
3291
3345
  const { resolveSecrets } = await import("./secrets-SVZWNAPK.js");
3292
- const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
3346
+ const { acquireSession, drainPool } = await import("./pool-QGFQRMGU.js");
3293
3347
  const { localStateToConnectionInfo } = await import("./state-PRBIIN7I.js");
3294
3348
  const ctx = buildContext({ stack: targetStack });
3295
3349
  let conn;
@@ -3473,7 +3527,7 @@ import { accessSync as accessSync2, constants as constants2 } from "fs";
3473
3527
  import { execSync as execSync2 } from "child_process";
3474
3528
  var ISSUES_URL = `${REPO_URL}/issues/new`;
3475
3529
  var BODY_CAP = 2e3;
3476
- var VERSION = true ? "1.7.1" : "dev";
3530
+ var VERSION = true ? "1.7.3" : "dev";
3477
3531
  async function collectContext() {
3478
3532
  const nodeVersion = process22.version;
3479
3533
  const os3 = `${process22.platform} ${process22.arch}`;
@@ -3590,8 +3644,8 @@ var harden_default = defineCommand22({
3590
3644
  json: { type: "boolean", description: "Emit structured JSON output" }
3591
3645
  },
3592
3646
  async run({ args }) {
3593
- const { MODULE_CATALOG, resolveModules, runHardening, formatHardenSummary } = await import("./harden-BDVYW567.js");
3594
- const { buildContext } = await import("./context-ALSJMTHE.js");
3647
+ const { MODULE_CATALOG, resolveModules, runHardening, formatHardenSummary } = await import("./harden-URPXLSVF.js");
3648
+ const { buildContext } = await import("./context-5LCUG2QR.js");
3595
3649
  const { getConfig: getConfig2 } = await import("./store-SDUR52Z5.js");
3596
3650
  if (args.list) {
3597
3651
  process23.stdout.write("\nAvailable hardening modules:\n\n");
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  buildContext
4
- } from "./chunk-3MFZ7E74.js";
4
+ } from "./chunk-P5LKWRPL.js";
5
5
  import "./chunk-A2I76FTA.js";
6
6
  import "./chunk-CX5SL5HP.js";
7
7
  import "./chunk-KGXPLI7W.js";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  makeStartupScript
4
- } from "./chunk-XKT42M34.js";
4
+ } from "./chunk-C5X375RO.js";
5
5
 
6
6
  // src/providers/gcp/index.ts
7
7
  import process2 from "process";
@@ -2,9 +2,10 @@
2
2
  import {
3
3
  generatePlan,
4
4
  planId
5
- } from "./chunk-FQ4JXUCR.js";
6
- import "./chunk-YTH4L2GN.js";
7
- import "./chunk-3MFZ7E74.js";
5
+ } from "./chunk-NESXDU5F.js";
6
+ import "./chunk-6X45DDGH.js";
7
+ import "./chunk-P5LKWRPL.js";
8
+ import "./chunk-PVUVI35Y.js";
8
9
  import "./chunk-A2I76FTA.js";
9
10
  import "./chunk-CX5SL5HP.js";
10
11
  import "./chunk-KGXPLI7W.js";
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  acquireSession,
4
4
  drainPool
5
- } from "./chunk-LCKD7L7X.js";
6
- import "./chunk-GJEF6UQA.js";
5
+ } from "./chunk-DQDAWNGB.js";
6
+ import "./chunk-3XK66DKK.js";
7
7
  import "./chunk-KGXPLI7W.js";
8
8
 
9
9
  // src/harden/types.ts
@@ -4,7 +4,7 @@ import {
4
4
  deepMerge,
5
5
  readRemoteConfig,
6
6
  restartGateway
7
- } from "./chunk-ZFNPM2WG.js";
7
+ } from "./chunk-O3F7OGH7.js";
8
8
 
9
9
  // src/cli/mcp-wire.ts
10
10
  var GATEWAY_MCP_MIN_VERSION = "2026.4";
@@ -2,7 +2,7 @@
2
2
 
3
3
  // package.json
4
4
  var name = "@clawops/cli";
5
- var version = "1.7.1";
5
+ var version = "1.7.3";
6
6
  var description = "Deploy and manage self-hosted OpenClaw instances across clouds";
7
7
  var type = "module";
8
8
  var bin = {
@@ -12,7 +12,8 @@ var exports = {
12
12
  ".": "./dist/index.js"
13
13
  };
14
14
  var files = [
15
- "dist"
15
+ "dist",
16
+ "spec"
16
17
  ];
17
18
  var repository = {
18
19
  type: "git",
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  acquireSession,
4
4
  drainPool
5
- } from "./chunk-LCKD7L7X.js";
6
- import "./chunk-GJEF6UQA.js";
5
+ } from "./chunk-DQDAWNGB.js";
6
+ import "./chunk-3XK66DKK.js";
7
7
  import "./chunk-KGXPLI7W.js";
8
8
  export {
9
9
  acquireSession,
@@ -6,9 +6,10 @@ import {
6
6
  OPENCLAW_TMP,
7
7
  atomicWriteConfig,
8
8
  deepMerge,
9
+ normaliseGatewayPort,
9
10
  readRemoteConfig,
10
11
  restartGateway
11
- } from "./chunk-ZFNPM2WG.js";
12
+ } from "./chunk-O3F7OGH7.js";
12
13
  export {
13
14
  OPENCLAW_CONFIG,
14
15
  OPENCLAW_CONFIG_LINUX,
@@ -16,6 +17,7 @@ export {
16
17
  OPENCLAW_TMP,
17
18
  atomicWriteConfig,
18
19
  deepMerge,
20
+ normaliseGatewayPort,
19
21
  readRemoteConfig,
20
22
  restartGateway
21
23
  };