@synap-core/cli 0.9.5 → 1.0.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.
@@ -0,0 +1,487 @@
1
+ /**
2
+ * synap openclaw
3
+ *
4
+ * Everything you need to access, configure, and connect OpenClaw
5
+ * after installation. Subcommands:
6
+ *
7
+ * synap openclaw — overview: gateway status, AI key, next steps
8
+ * synap openclaw connect — show MCP client configs for Claude Desktop, Cursor, etc.
9
+ * synap openclaw configure — set AI provider key interactively
10
+ * synap openclaw logs — tail container logs
11
+ * synap openclaw restart — restart the container
12
+ */
13
+ import chalk from "chalk";
14
+ import { execSync } from "child_process";
15
+ import prompts from "prompts";
16
+ import fs from "node:fs";
17
+ import { log, banner } from "../utils/logger.js";
18
+ import { detectOpenClaw } from "../lib/openclaw.js";
19
+ import { findSynapDeployDir } from "../lib/pod.js";
20
+ // ─── Overview ────────────────────────────────────────────────────────────────
21
+ export async function openclawOverview() {
22
+ banner();
23
+ const oc = detectOpenClaw();
24
+ if (!oc.found) {
25
+ log.warn("OpenClaw is not running.");
26
+ log.blank();
27
+ log.dim("Start it: docker compose --profile openclaw up -d openclaw");
28
+ log.dim("Or run: synap init");
29
+ return;
30
+ }
31
+ // ── Gateway status ──────────────────────────────────────────────────────
32
+ log.heading("Gateway");
33
+ const gatewayPort = oc.gatewayPort ?? 18789;
34
+ if (oc.gatewayRunning) {
35
+ log.success(`Running on port ${gatewayPort}`);
36
+ log.info(`MCP endpoint: ${chalk.cyan(`http://localhost:${gatewayPort}/mcp`)}`);
37
+ }
38
+ else {
39
+ log.warn(`Port ${gatewayPort} not responding — OpenClaw may still be starting`);
40
+ log.dim("Give it a minute, then: synap openclaw");
41
+ }
42
+ if (oc.runtime === "docker") {
43
+ log.dim(`Container: ${oc.containerName ?? "openclaw"}`);
44
+ }
45
+ if (oc.version)
46
+ log.dim(`Version: ${oc.version}`);
47
+ // ── AI provider ─────────────────────────────────────────────────────────
48
+ log.heading("AI Provider");
49
+ const apiKeyStatus = getAiKeyStatus();
50
+ if (apiKeyStatus.configured) {
51
+ log.success(`${apiKeyStatus.provider} key configured`);
52
+ log.dim(`Model: ${apiKeyStatus.model ?? "default"}`);
53
+ }
54
+ else {
55
+ log.warn("No AI API key configured — OpenClaw cannot process requests");
56
+ log.blank();
57
+ if (oc.runtime === "docker") {
58
+ log.dim("Set your key: synap openclaw configure");
59
+ }
60
+ else {
61
+ log.dim("Set your key: openclaw configure (or: synap openclaw configure)");
62
+ }
63
+ log.blank();
64
+ log.dim("Supported: Anthropic (Claude), OpenAI, Google, or Synap IS");
65
+ }
66
+ // ── Skill ───────────────────────────────────────────────────────────────
67
+ log.heading("Synap Skill");
68
+ const skillInstalled = checkSkillInstalled(oc);
69
+ if (skillInstalled) {
70
+ log.success("synap skill installed");
71
+ }
72
+ else {
73
+ log.warn("Synap skill not installed");
74
+ const containerName = oc.containerName ?? "openclaw";
75
+ log.dim(oc.runtime === "docker"
76
+ ? `Install: docker exec ${containerName} openclaw skills install synap`
77
+ : "Install: openclaw skills install synap");
78
+ }
79
+ // ── Dashboard ────────────────────────────────────────────────────────────
80
+ log.heading("Dashboard");
81
+ if (oc.runtime === "docker") {
82
+ const containerName = oc.containerName ?? "openclaw";
83
+ log.info(`Web UI: ${chalk.cyan(`http://localhost:${oc.gatewayPort ?? 18789}`)}`);
84
+ log.dim("If on a remote server, tunnel first:");
85
+ log.dim(` ssh -N -L 18789:localhost:18789 user@your-server`);
86
+ log.dim(` Then open: http://localhost:18789`);
87
+ }
88
+ else {
89
+ log.info(`Web UI: ${chalk.cyan(`http://localhost:${oc.gatewayPort ?? 18789}`)}`);
90
+ log.dim("Open: openclaw dashboard — or just open the URL above");
91
+ }
92
+ // ── How to connect ───────────────────────────────────────────────────────
93
+ log.heading("AI Client (MCP)");
94
+ log.info("Connect Claude Desktop, Cursor, or Windsurf:");
95
+ log.blank();
96
+ log.dim(" Claude Desktop synap openclaw connect --client claude");
97
+ log.dim(" Cursor synap openclaw connect --client cursor");
98
+ log.dim(" Windsurf synap openclaw connect --client windsurf");
99
+ log.blank();
100
+ // ── Next steps ───────────────────────────────────────────────────────────
101
+ log.heading("Next Steps");
102
+ if (!apiKeyStatus.configured) {
103
+ log.info("1. Set your AI key: synap openclaw configure");
104
+ log.info("2. Connect a client: synap openclaw connect");
105
+ }
106
+ else if (!skillInstalled) {
107
+ const containerName = oc.containerName ?? "openclaw";
108
+ log.info(oc.runtime === "docker"
109
+ ? `1. Install skill: docker exec ${containerName} openclaw skills install synap`
110
+ : "1. Install skill: openclaw skills install synap");
111
+ log.info("2. Connect a client: synap openclaw connect");
112
+ }
113
+ else if (!oc.gatewayRunning) {
114
+ log.info("1. Wait for gateway (it may still be starting)");
115
+ log.info("2. Connect a client: synap openclaw connect");
116
+ }
117
+ else {
118
+ log.success("Everything looks good.");
119
+ log.info("Connect an AI client: synap openclaw connect");
120
+ }
121
+ log.blank();
122
+ }
123
+ // ─── Connect: show MCP client configs ────────────────────────────────────────
124
+ export async function openclawConnect(opts) {
125
+ const oc = detectOpenClaw();
126
+ const gatewayPort = oc.gatewayPort ?? 18789;
127
+ const isDocker = oc.runtime === "docker";
128
+ // OpenClaw MCP is stdio-based — clients run `openclaw mcp serve` as a local process
129
+ // which connects to the gateway over WebSocket.
130
+ // For Docker/remote setups the gateway is at ws://localhost:<port> after SSH tunnel.
131
+ const client = opts.client?.toLowerCase();
132
+ if (!client || client === "claude") {
133
+ printMcpConfig("Claude Desktop", gatewayPort, isDocker, "claude");
134
+ }
135
+ if (!client || client === "cursor") {
136
+ printMcpConfig("Cursor", gatewayPort, isDocker, "cursor");
137
+ }
138
+ if (!client || client === "windsurf") {
139
+ printMcpConfig("Windsurf", gatewayPort, isDocker, "windsurf");
140
+ }
141
+ if (client && !["claude", "cursor", "windsurf"].includes(client)) {
142
+ log.warn(`Unknown client "${client}". Showing generic config.`);
143
+ printMcpConfig("MCP Client", gatewayPort, isDocker, "generic");
144
+ }
145
+ if (isDocker) {
146
+ log.blank();
147
+ log.info("Remote server? Tunnel the gateway port first:");
148
+ log.dim(" ssh -N -L 18789:localhost:18789 user@your-server");
149
+ log.dim(" Then use the configs above (they point to localhost:18789)");
150
+ log.blank();
151
+ log.dim("openclaw must be installed locally: npm i -g openclaw");
152
+ }
153
+ }
154
+ function printMcpConfig(label, gatewayPort, isRemote, client) {
155
+ log.heading(label);
156
+ // MCP config: stdio command that connects to the local (or tunneled) gateway
157
+ const args = isRemote
158
+ ? ["mcp", "serve", "--url", `ws://localhost:${gatewayPort}`]
159
+ : ["mcp", "serve"];
160
+ const config = JSON.stringify({ mcpServers: { openclaw: { command: "openclaw", args } } }, null, 2);
161
+ const paths = {
162
+ claude: "macOS: ~/Library/Application Support/Claude/claude_desktop_config.json",
163
+ cursor: "~/.cursor/mcp.json",
164
+ windsurf: "~/.windsurf/mcp.json",
165
+ generic: "<your MCP client config file>",
166
+ };
167
+ log.dim(`Config file: ${paths[client]}`);
168
+ log.blank();
169
+ console.log(chalk.cyan(config));
170
+ log.blank();
171
+ if (client === "claude") {
172
+ log.dim("After saving: quit and reopen Claude Desktop");
173
+ log.dim('Ask: "What tools do you have?" — OpenClaw tools should appear');
174
+ }
175
+ if (client === "cursor") {
176
+ log.dim("After saving: Cmd+Shift+P → MCP: Restart Servers");
177
+ }
178
+ log.blank();
179
+ }
180
+ // ─── Dashboard ───────────────────────────────────────────────────────────────
181
+ export function openclawDashboard() {
182
+ const oc = detectOpenClaw();
183
+ const port = oc.gatewayPort ?? 18789;
184
+ const url = `http://localhost:${port}`;
185
+ if (oc.runtime === "docker") {
186
+ // On a remote server the browser can't open — give SSH tunnel instructions
187
+ const isRemoteServer = !process.env.DISPLAY && process.platform === "linux";
188
+ if (isRemoteServer) {
189
+ log.info(`OpenClaw dashboard: ${chalk.cyan(url)}`);
190
+ log.blank();
191
+ log.info("You're on a remote server. Tunnel the port to your laptop:");
192
+ log.blank();
193
+ console.log(chalk.cyan(` ssh -N -L ${port}:localhost:${port} user@$(hostname)`));
194
+ log.blank();
195
+ log.dim(`Then open ${url} in your browser.`);
196
+ }
197
+ else {
198
+ // Local Docker — just open it
199
+ log.info(`Opening ${chalk.cyan(url)} ...`);
200
+ try {
201
+ const open = process.platform === "darwin" ? "open" : "xdg-open";
202
+ execSync(`${open} ${url}`, { stdio: "ignore" });
203
+ }
204
+ catch {
205
+ log.dim(`Open manually: ${url}`);
206
+ }
207
+ }
208
+ }
209
+ else {
210
+ // Local install — use openclaw's own command
211
+ log.info(`Opening dashboard...`);
212
+ try {
213
+ execSync("openclaw dashboard", { stdio: "inherit", timeout: 5000 });
214
+ }
215
+ catch {
216
+ // Fallback: open URL directly
217
+ try {
218
+ const open = process.platform === "darwin" ? "open" : "xdg-open";
219
+ execSync(`${open} ${url}`, { stdio: "ignore" });
220
+ }
221
+ catch {
222
+ log.info(`Dashboard: ${chalk.cyan(url)}`);
223
+ }
224
+ }
225
+ }
226
+ }
227
+ // ─── Configure: set AI provider key ──────────────────────────────────────────
228
+ export async function openclawConfigure() {
229
+ banner();
230
+ log.heading("Configure AI Provider");
231
+ const deployDir = findSynapDeployDir();
232
+ // Show current status
233
+ const current = getAiKeyStatus();
234
+ if (current.configured) {
235
+ log.success(`Currently using: ${current.provider}`);
236
+ log.dim(`Model: ${current.model ?? "default"}`);
237
+ log.blank();
238
+ }
239
+ const { provider } = await prompts({
240
+ type: "select",
241
+ name: "provider",
242
+ message: "Which AI provider?",
243
+ choices: [
244
+ {
245
+ title: "Anthropic (Claude)",
246
+ description: "claude-sonnet-4-6 — best quality, recommended",
247
+ value: "anthropic",
248
+ },
249
+ {
250
+ title: "OpenAI (GPT-4o)",
251
+ value: "openai",
252
+ },
253
+ {
254
+ title: "Google (Gemini)",
255
+ value: "google",
256
+ },
257
+ {
258
+ title: "Synap IS (via pod)",
259
+ description: "Uses your pod AI — no external key needed",
260
+ value: "synap",
261
+ },
262
+ ],
263
+ });
264
+ if (!provider)
265
+ return;
266
+ if (provider === "synap") {
267
+ log.blank();
268
+ log.info("Synap IS uses your pod's AI subscription.");
269
+ log.dim("Make sure IS is provisioned: synap finish");
270
+ log.dim("Then OpenClaw will use your pod URL as the AI endpoint.");
271
+ return;
272
+ }
273
+ const envKey = provider === "anthropic"
274
+ ? "ANTHROPIC_API_KEY"
275
+ : provider === "openai"
276
+ ? "OPENAI_API_KEY"
277
+ : "GEMINI_API_KEY";
278
+ const modelDefault = provider === "anthropic"
279
+ ? "anthropic/claude-sonnet-4-6"
280
+ : provider === "openai"
281
+ ? "openai/gpt-4o"
282
+ : "google/gemini-2.0-flash";
283
+ const { apiKey } = await prompts({
284
+ type: "password",
285
+ name: "apiKey",
286
+ message: `${envKey}:`,
287
+ });
288
+ if (!apiKey)
289
+ return;
290
+ const { model } = await prompts({
291
+ type: "text",
292
+ name: "model",
293
+ message: "Model (leave blank for default):",
294
+ initial: modelDefault,
295
+ });
296
+ if (deployDir) {
297
+ // Write to .env file
298
+ const envFile = `${deployDir}/.env`;
299
+ writeEnvVar(envFile, envKey, apiKey);
300
+ if (model && model !== modelDefault) {
301
+ writeEnvVar(envFile, "OPENCLAW_MODEL", model);
302
+ }
303
+ else {
304
+ writeEnvVar(envFile, "OPENCLAW_MODEL", modelDefault);
305
+ }
306
+ log.blank();
307
+ log.success(`${envKey} written to ${deployDir}/.env`);
308
+ // Restart container to pick up new env vars
309
+ const oc = detectOpenClaw();
310
+ const containerName = oc.containerName ?? "openclaw";
311
+ const { doRestart } = await prompts({
312
+ type: "confirm",
313
+ name: "doRestart",
314
+ message: `Restart ${containerName} to apply?`,
315
+ initial: true,
316
+ });
317
+ if (doRestart) {
318
+ try {
319
+ log.info(`Restarting ${containerName}...`);
320
+ execSync(`docker restart ${containerName}`, { stdio: "pipe", timeout: 30000 });
321
+ log.success("Restarted. Give it 30s to come back up.");
322
+ log.dim(`Check: synap openclaw`);
323
+ }
324
+ catch {
325
+ log.warn("Restart failed — restart manually:");
326
+ log.dim(` docker restart ${containerName}`);
327
+ }
328
+ }
329
+ }
330
+ else {
331
+ // No deploy dir — show env export instructions
332
+ log.blank();
333
+ log.warn("Could not find deploy directory. Set the key manually:");
334
+ log.blank();
335
+ console.log(chalk.cyan(` export ${envKey}="${apiKey}"`));
336
+ if (model) {
337
+ console.log(chalk.cyan(` export OPENCLAW_MODEL="${model}"`));
338
+ }
339
+ log.blank();
340
+ log.dim("Or add to your pod .env file, then: docker restart openclaw");
341
+ }
342
+ log.blank();
343
+ }
344
+ // ─── Logs: tail container output ─────────────────────────────────────────────
345
+ export function openclawLogs(opts) {
346
+ const oc = detectOpenClaw();
347
+ if (oc.runtime !== "docker") {
348
+ log.warn("Log tailing only available for Docker runtime.");
349
+ log.dim("OpenClaw logs: check your process manager or journald");
350
+ return;
351
+ }
352
+ const containerName = oc.containerName ?? "openclaw";
353
+ const lines = opts.lines ?? 50;
354
+ const flag = opts.follow ? "-f" : `--tail ${lines}`;
355
+ try {
356
+ log.dim(`docker logs ${containerName} ${flag}`);
357
+ log.blank();
358
+ execSync(`docker logs ${containerName} ${flag}`, { stdio: "inherit", timeout: opts.follow ? 0 : 30000 });
359
+ }
360
+ catch {
361
+ log.error(`Could not get logs for container "${containerName}"`);
362
+ log.dim(`Try: docker logs ${containerName} --tail 50`);
363
+ }
364
+ }
365
+ // ─── Restart ─────────────────────────────────────────────────────────────────
366
+ export async function openclawRestart() {
367
+ const oc = detectOpenClaw();
368
+ if (oc.runtime !== "docker") {
369
+ log.warn("Restart only available for Docker runtime.");
370
+ return;
371
+ }
372
+ const containerName = oc.containerName ?? "openclaw";
373
+ const { confirm } = await prompts({
374
+ type: "confirm",
375
+ name: "confirm",
376
+ message: `Restart ${containerName}?`,
377
+ initial: true,
378
+ });
379
+ if (!confirm)
380
+ return;
381
+ try {
382
+ execSync(`docker restart ${containerName}`, { stdio: "pipe", timeout: 30000 });
383
+ log.success(`${containerName} restarted — give it ~30s to come back up`);
384
+ log.dim("Check: synap openclaw");
385
+ }
386
+ catch {
387
+ log.error("Restart failed");
388
+ log.dim(`Try: docker restart ${containerName}`);
389
+ }
390
+ }
391
+ function getAiKeyStatus() {
392
+ // Check deploy dir .env first (most accurate for Docker deployments)
393
+ const deployDir = findSynapDeployDir();
394
+ if (deployDir) {
395
+ const envFile = `${deployDir}/.env`;
396
+ try {
397
+ const envContent = fs.readFileSync(envFile, "utf-8");
398
+ const vars = parseEnvFile(envContent);
399
+ if (vars.ANTHROPIC_API_KEY) {
400
+ return { configured: true, provider: "Anthropic", model: vars.OPENCLAW_MODEL };
401
+ }
402
+ if (vars.OPENAI_API_KEY) {
403
+ return { configured: true, provider: "OpenAI", model: vars.OPENCLAW_MODEL };
404
+ }
405
+ if (vars.GEMINI_API_KEY) {
406
+ return { configured: true, provider: "Google", model: vars.OPENCLAW_MODEL };
407
+ }
408
+ }
409
+ catch {
410
+ // unreadable
411
+ }
412
+ }
413
+ // Fallback: check live container env (via docker inspect)
414
+ const oc = detectOpenClaw();
415
+ if (oc.runtime === "docker") {
416
+ try {
417
+ const containerName = oc.containerName ?? "openclaw";
418
+ const raw = execSync(`docker inspect --format '{{range .Config.Env}}{{.}}\\n{{end}}' ${containerName} 2>/dev/null`, { encoding: "utf-8", timeout: 5000 });
419
+ const envLines = raw.split("\\n").filter(Boolean);
420
+ const env = {};
421
+ for (const line of envLines) {
422
+ const idx = line.indexOf("=");
423
+ if (idx > 0)
424
+ env[line.slice(0, idx)] = line.slice(idx + 1);
425
+ }
426
+ if (env.ANTHROPIC_API_KEY)
427
+ return { configured: true, provider: "Anthropic", model: env.OPENCLAW_MODEL };
428
+ if (env.OPENAI_API_KEY)
429
+ return { configured: true, provider: "OpenAI", model: env.OPENCLAW_MODEL };
430
+ if (env.GEMINI_API_KEY)
431
+ return { configured: true, provider: "Google", model: env.OPENCLAW_MODEL };
432
+ }
433
+ catch {
434
+ // docker not available
435
+ }
436
+ }
437
+ return { configured: false };
438
+ }
439
+ function checkSkillInstalled(oc) {
440
+ if (!oc.found)
441
+ return false;
442
+ if (oc.runtime === "docker") {
443
+ try {
444
+ const containerName = oc.containerName ?? "openclaw";
445
+ const out = execSync(`docker exec ${containerName} openclaw skills list 2>/dev/null`, { encoding: "utf-8", timeout: 10000 });
446
+ return /synap/i.test(out);
447
+ }
448
+ catch {
449
+ return false;
450
+ }
451
+ }
452
+ // Local install — check skills directory
453
+ return false;
454
+ }
455
+ function writeEnvVar(envFile, key, value) {
456
+ let content = "";
457
+ try {
458
+ content = fs.existsSync(envFile) ? fs.readFileSync(envFile, "utf-8") : "";
459
+ }
460
+ catch {
461
+ // start fresh
462
+ }
463
+ const regex = new RegExp(`^${key}=.*`, "m");
464
+ const line = `${key}=${value}`;
465
+ content = regex.test(content)
466
+ ? content.replace(regex, line)
467
+ : content.endsWith("\n") || content === ""
468
+ ? content + line + "\n"
469
+ : content + "\n" + line + "\n";
470
+ fs.writeFileSync(envFile, content, { mode: 0o600 });
471
+ }
472
+ function parseEnvFile(content) {
473
+ const result = {};
474
+ for (const line of content.split("\n")) {
475
+ const trimmed = line.trim();
476
+ if (!trimmed || trimmed.startsWith("#"))
477
+ continue;
478
+ const idx = trimmed.indexOf("=");
479
+ if (idx > 0) {
480
+ const key = trimmed.slice(0, idx);
481
+ const val = trimmed.slice(idx + 1).replace(/^["']|["']$/g, "");
482
+ result[key] = val;
483
+ }
484
+ }
485
+ return result;
486
+ }
487
+ //# sourceMappingURL=openclaw.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openclaw.js","sourceRoot":"","sources":["../../src/commands/openclaw.ts"],"names":[],"mappings":"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"}
@@ -103,23 +103,39 @@ export async function status() {
103
103
  // Hoist creds so all sections can use it
104
104
  const creds = getStoredToken();
105
105
  // Auth status
106
+ // Strategy: show what we know locally first (email from stored creds),
107
+ // then validate with the server. If the server is unreachable, trust the
108
+ // local token as long as it hasn't locally expired. Only prompt to re-login
109
+ // when the server explicitly rejects it (401) or the local expiry has passed.
106
110
  log.heading("Account");
107
111
  let loggedIn = false;
108
112
  if (creds) {
109
- const authStatus = await isLoggedIn();
110
- if (authStatus.valid) {
111
- loggedIn = true;
112
- log.success(`Logged in as ${authStatus.email}`);
113
- log.dim(`User ID: ${authStatus.userId}`);
114
- log.dim(`Token expires: ${new Date(creds.expiresAt).toLocaleDateString()}`);
115
- }
116
- else if (isTokenLocallyExpired(creds)) {
117
- log.warn("Session expired run: synap login");
118
- log.dim("On a server? Use: synap login --token <token>");
113
+ // Always show local identity immediately — don't wait for server
114
+ log.success(`Logged in as ${chalk.bold(creds.email)}`);
115
+ log.dim(`User ID: ${creds.userId}`);
116
+ if (isTokenLocallyExpired(creds)) {
117
+ // Local expiry passed — validate against server to confirm
118
+ const authStatus = await isLoggedIn();
119
+ if (authStatus.valid) {
120
+ loggedIn = true;
121
+ log.dim(`Token refreshed (valid until ${new Date(creds.expiresAt).toLocaleDateString()})`);
122
+ }
123
+ else {
124
+ log.warn("Session expired — run: synap login");
125
+ log.dim("On a server without a browser? Use: synap login --token <token>");
126
+ }
119
127
  }
120
128
  else {
121
- log.warn("Could not reach Synap (network error?)");
122
- log.dim("Run: synap status (when online)");
129
+ // Token is locally fresh — validate in background but don't block on failure
130
+ loggedIn = true;
131
+ const authStatus = await isLoggedIn().catch(() => ({ valid: false }));
132
+ if (authStatus.valid) {
133
+ log.dim(`Token valid until ${new Date(creds.expiresAt).toLocaleDateString()}`);
134
+ }
135
+ else {
136
+ // CP unreachable but token is fresh — trust it, just note it
137
+ log.dim(`Token fresh (CP unreachable — cached credentials in use)`);
138
+ }
123
139
  }
124
140
  }
125
141
  else {
@@ -175,28 +191,41 @@ export async function status() {
175
191
  }
176
192
  }
177
193
  else if (localConfig?.podId && creds) {
178
- // No Docker container visible — check CP remote status
179
- log.dim("No local container checking CP provisioning state...");
180
- const remoteStatus = await getOpenClawRemoteStatus(creds.token, localConfig.podId);
181
- if (!remoteStatus || remoteStatus.status === "not_provisioned") {
182
- log.dim("Not provisioned. Run: synap init");
194
+ // No Docker container visible here — check CP for remote provisioning state
195
+ const remoteStatus = await getOpenClawRemoteStatus(creds.token, localConfig.podId).catch(() => null);
196
+ if (remoteStatus === null) {
197
+ // CP unreachable show what we know locally
198
+ log.dim(`Pod ID: ${localConfig.podId}`);
199
+ log.dim("CP unreachable — cannot check remote OpenClaw state");
200
+ log.dim("If on the pod server, run: docker ps | grep openclaw");
201
+ }
202
+ else if (remoteStatus.status === "not_provisioned") {
203
+ log.dim("Not provisioned on pod server. Run: synap init");
183
204
  }
184
205
  else if (remoteStatus.status === "provisioning") {
185
- log.info(`CP state: ${chalk.yellow("provisioning")} — may still be starting`);
186
- log.dim("Check Docker logs: docker logs synap-backend-openclaw-1 --tail 30");
206
+ log.info(`Pod server: ${chalk.yellow("provisioning")} — still starting up`);
207
+ log.dim("Check: docker logs openclaw --tail 30");
208
+ log.dim("Once ready: synap finish");
187
209
  }
188
210
  else if (remoteStatus.status === "running") {
189
- log.success(`CP state: ${chalk.green("running")}`);
190
- log.dim("But no local container found — run from the server where the pod is hosted");
211
+ log.success(`Pod server: ${chalk.green("running")}`);
212
+ if (remoteStatus.url)
213
+ log.dim(`URL: ${remoteStatus.url}`);
214
+ log.dim("Run synap finish to install the skill");
191
215
  }
192
216
  else if (remoteStatus.status === "error") {
193
- log.warn(`CP state: ${chalk.red("error")} — provisioning failed`);
217
+ log.warn(`Pod server: ${chalk.red("error")} — provisioning failed`);
194
218
  log.dim("Re-run: synap init");
195
219
  }
196
220
  }
197
221
  else {
198
- log.dim("Not detected (no container, no local install)");
199
- log.dim("Run synap init to set it up");
222
+ log.dim("Not detected locally");
223
+ if (!localConfig) {
224
+ log.dim("Run synap init to connect to a pod");
225
+ }
226
+ else {
227
+ log.dim("Run synap init to set up OpenClaw");
228
+ }
200
229
  }
201
230
  }
202
231
  // Pod status