@silicaclaw/cli 1.0.0-beta.25 → 1.0.0-beta.29

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.
@@ -10,6 +10,37 @@ const __filename = fileURLToPath(import.meta.url);
10
10
  const __dirname = dirname(__filename);
11
11
  const ROOT_DIR = resolve(__dirname, "..");
12
12
 
13
+ const COLOR = {
14
+ reset: "\x1b[0m",
15
+ bold: "\x1b[1m",
16
+ dim: "\x1b[2m",
17
+ orange: "\x1b[38;5;208m",
18
+ green: "\x1b[32m",
19
+ yellow: "\x1b[33m",
20
+ };
21
+
22
+ function useColor() {
23
+ return Boolean(process.stdout.isTTY && !process.env.NO_COLOR);
24
+ }
25
+
26
+ function paint(text, ...styles) {
27
+ if (!useColor() || styles.length === 0) return text;
28
+ return `${styles.join("")}${text}${COLOR.reset}`;
29
+ }
30
+
31
+ function headline() {
32
+ console.log(`${paint("SilicaClaw", COLOR.bold, COLOR.orange)} ${paint(readVersion(), COLOR.dim)}`);
33
+ console.log(paint("Public identity and discovery for OpenClaw agents.", COLOR.dim));
34
+ }
35
+
36
+ function kv(label, value) {
37
+ console.log(`${paint(label.padEnd(14), COLOR.dim)} ${value}`);
38
+ }
39
+
40
+ function section(title) {
41
+ console.log(paint(title, COLOR.bold));
42
+ }
43
+
13
44
  function run(cmd, args, extra = {}) {
14
45
  const result = spawnSync(cmd, args, {
15
46
  cwd: ROOT_DIR,
@@ -18,7 +49,10 @@ function run(cmd, args, extra = {}) {
18
49
  ...extra,
19
50
  });
20
51
  if (result.error) {
21
- console.error(`[silicaclaw] failed to run ${cmd}: ${result.error.message}`);
52
+ headline();
53
+ console.log("");
54
+ console.error(`${paint("Command failed", COLOR.bold, COLOR.yellow)} ${cmd}`);
55
+ console.error(result.error.message);
22
56
  process.exit(1);
23
57
  }
24
58
  process.exit(result.status ?? 0);
@@ -89,14 +123,18 @@ function userEnvFile() {
89
123
  }
90
124
 
91
125
  function ensureLineInFile(filePath, block) {
92
- const current = existsSync(filePath) ? readFileSync(filePath, "utf8") : "";
93
- if (current.includes(block.trim())) {
94
- return false;
126
+ try {
127
+ const current = existsSync(filePath) ? readFileSync(filePath, "utf8") : "";
128
+ if (current.includes(block.trim())) {
129
+ return { changed: false, error: null };
130
+ }
131
+ const next = `${current.replace(/\s*$/, "")}\n\n${block}\n`;
132
+ mkdirSync(dirname(filePath), { recursive: true });
133
+ writeFileSync(filePath, next, "utf8");
134
+ return { changed: true, error: null };
135
+ } catch (error) {
136
+ return { changed: false, error: error instanceof Error ? error.message : String(error) };
95
137
  }
96
- const next = `${current.replace(/\s*$/, "")}\n\n${block}\n`;
97
- mkdirSync(dirname(filePath), { recursive: true });
98
- writeFileSync(filePath, next, "utf8");
99
- return true;
100
138
  }
101
139
 
102
140
  function shellInitTargets() {
@@ -159,21 +197,37 @@ function installPersistentCommand() {
159
197
  );
160
198
  const rcFiles = shellInitTargets();
161
199
  const updatedFiles = [];
200
+ const failedFiles = [];
162
201
  for (const filePath of rcFiles) {
163
- if (ensureLineInFile(filePath, rcBlock)) {
202
+ const result = ensureLineInFile(filePath, rcBlock);
203
+ if (result.changed) {
164
204
  updatedFiles.push(filePath);
165
205
  }
206
+ if (result.error) {
207
+ failedFiles.push({ filePath, error: result.error });
208
+ }
166
209
  }
167
210
 
168
- console.log("Installed persistent `silicaclaw` command.");
169
- console.log(`- shim: ${shimPath}`);
170
- console.log(`- env: ${envFile}`);
171
- console.log(`- shell init: ${rcFiles.join(", ")}`);
211
+ headline();
212
+ console.log("");
213
+ console.log(`${paint("Installed", COLOR.bold)} persistent command`);
214
+ kv("Command", "silicaclaw");
215
+ kv("Shim", shimPath);
216
+ kv("Env", envFile);
217
+ kv("Shell init", rcFiles.join(", "));
172
218
  console.log("");
173
- console.log("To activate in the current shell:");
174
- console.log(`source "${envFile}"`);
219
+ kv("Activate", `source "${envFile}"`);
175
220
  if (updatedFiles.length === 0) {
176
- console.log("Shell startup files were already configured.");
221
+ kv("Startup", "shell files already configured");
222
+ }
223
+ if (failedFiles.length > 0) {
224
+ console.log("");
225
+ console.log(paint("Shell files not updated automatically", COLOR.bold, COLOR.yellow));
226
+ for (const item of failedFiles) {
227
+ kv(item.filePath, item.error);
228
+ }
229
+ console.log("");
230
+ kv("Manual line", '[ -f "$HOME/.silicaclaw/env.sh" ] && . "$HOME/.silicaclaw/env.sh"');
177
231
  }
178
232
  }
179
233
 
@@ -197,49 +251,48 @@ function canWriteGlobalPrefix() {
197
251
 
198
252
  function showUpdateGuide(current, latest, beta) {
199
253
  const npxRuntime = isNpxRun();
200
- console.log("SilicaClaw update check");
201
- console.log(`current: ${current}`);
202
- console.log(`latest : ${latest || "-"}`);
203
- console.log(`beta : ${beta || "-"}`);
254
+ headline();
255
+ console.log("");
256
+ console.log(paint("Update check", COLOR.bold));
257
+ kv("Current", current);
258
+ kv("Latest", latest || "-");
259
+ kv("Beta", beta || "-");
204
260
  console.log("");
205
261
 
206
262
  const upToDate = Boolean(beta) && current === beta;
207
263
  if (upToDate) {
208
- console.log("You are already on the latest beta.");
264
+ console.log(`${paint("Ready", COLOR.bold)} you're already on the latest beta.`);
209
265
  } else {
210
- console.log("Update available.");
266
+ console.log(`${paint("Update available", COLOR.bold, COLOR.yellow)} install the latest beta and refresh your services.`);
211
267
  }
212
268
  console.log("");
213
- console.log("Quick next commands:");
214
- console.log("1) Start internet gateway");
215
- console.log(" silicaclaw start --mode=global-preview");
216
- console.log("2) Check gateway status");
217
- console.log(" silicaclaw status");
218
- console.log("3) Install persistent command (recommended once)");
219
- console.log(" npx -y @silicaclaw/cli@beta install");
220
- console.log("4) npx one-shot (no install)");
221
- console.log(" npx -y @silicaclaw/cli@beta start --mode=global-preview");
269
+ console.log(paint("Next commands", COLOR.bold));
270
+ kv("Start", "silicaclaw start --mode=global-preview");
271
+ kv("Status", "silicaclaw status");
272
+ kv("Install", "npx -y @silicaclaw/cli@beta install");
273
+ kv("One-shot", "npx -y @silicaclaw/cli@beta start --mode=global-preview");
222
274
  console.log("");
223
275
 
224
276
  const writableGlobal = canWriteGlobalPrefix();
225
277
  if (!npxRuntime && writableGlobal) {
226
- console.log("Optional global install:");
227
- console.log(" npm i -g @silicaclaw/cli@beta");
228
- console.log(" silicaclaw version");
278
+ console.log(paint("Optional global install", COLOR.bold));
279
+ kv("Install", "npm i -g @silicaclaw/cli@beta");
280
+ kv("Verify", "silicaclaw version");
229
281
  console.log("");
230
282
  } else if (!npxRuntime) {
231
- console.log("Global install skipped: npm global directory is not writable (likely EACCES).");
283
+ console.log(paint("Global install skipped", COLOR.bold, COLOR.yellow));
284
+ console.log("npm global directory is not writable on this machine.");
232
285
  console.log("");
233
286
  }
234
287
  if (npxRuntime) {
235
- console.log("Detected npx runtime.");
288
+ console.log(paint("Detected npx runtime", COLOR.bold));
236
289
  console.log("Run `npx -y @silicaclaw/cli@beta install` once to make `silicaclaw` available in new shells.");
237
290
  }
238
291
  }
239
292
 
240
293
  function getGatewayStatus() {
241
294
  try {
242
- const result = runCapture("node", [resolve(ROOT_DIR, "scripts", "silicaclaw-gateway.mjs"), "status"], {
295
+ const result = runCapture("node", [resolve(ROOT_DIR, "scripts", "silicaclaw-gateway.mjs"), "status", "--json"], {
243
296
  cwd: process.cwd(),
244
297
  });
245
298
  if ((result.status ?? 1) !== 0) return null;
@@ -301,13 +354,13 @@ function restartGatewayIfRunning() {
301
354
  const appDir = status?.app_dir ? String(status.app_dir) : "";
302
355
  const synced = syncCurrentPackageToAppDir(appDir);
303
356
  if (synced) {
304
- console.log(`Synced runtime files to app_dir: ${appDir}`);
357
+ kv("Synced", appDir);
305
358
  }
306
359
 
307
360
  const localRunning = Boolean(status?.local_console?.running);
308
361
  const signalingRunning = Boolean(status?.signaling?.running);
309
362
  if (!localRunning && !signalingRunning) {
310
- console.log("Gateway not running: no restart needed.");
363
+ kv("Runtime", "gateway not running; no refresh needed");
311
364
  return;
312
365
  }
313
366
 
@@ -320,14 +373,15 @@ function restartGatewayIfRunning() {
320
373
  args.push(`--room=${status.signaling.room}`);
321
374
  }
322
375
 
323
- console.log("Refreshing gateway services...");
376
+ console.log("");
377
+ console.log(paint("Refreshing background services", COLOR.bold));
324
378
  runInherit("node", args, { cwd: process.cwd() });
325
379
  }
326
380
 
327
381
  function tryGlobalUpgrade(beta) {
328
382
  const writableGlobal = canWriteGlobalPrefix();
329
383
  if (!writableGlobal) return false;
330
- console.log(`Installing @silicaclaw/cli@${beta} globally...`);
384
+ kv("Upgrade", `installing @silicaclaw/cli@${beta} globally`);
331
385
  const result = runInherit("npm", ["i", "-g", `@silicaclaw/cli@${beta}`]);
332
386
  return (result.status ?? 1) === 0;
333
387
  }
@@ -337,8 +391,12 @@ function update() {
337
391
  try {
338
392
  const result = runCapture("npm", ["view", "@silicaclaw/cli", "dist-tags", "--json"]);
339
393
  if ((result.status ?? 1) !== 0) {
340
- console.error("Failed to query npm dist-tags.");
394
+ headline();
395
+ console.log("");
396
+ console.error(paint("Update check failed", COLOR.bold, COLOR.yellow));
341
397
  if (result.stderr) console.error(result.stderr.trim());
398
+ console.log("");
399
+ kv("Try", "npm view @silicaclaw/cli dist-tags --json");
342
400
  process.exit(result.status ?? 1);
343
401
  }
344
402
  const text = String(result.stdout || "").trim();
@@ -351,73 +409,70 @@ function update() {
351
409
 
352
410
  if (hasNewBeta) {
353
411
  if (npxRuntime) {
354
- console.log(`New beta detected (${beta}). npx will use latest on next run.`);
412
+ kv("Update", `new beta detected (${beta}); npx will use it on the next run`);
355
413
  } else if (tryGlobalUpgrade(beta)) {
356
- console.log(`Global upgrade completed: ${beta}`);
414
+ kv("Upgrade", `global install updated to ${beta}`);
357
415
  } else {
358
- console.log("Skipped global upgrade (no write permission or upgrade failed).");
416
+ kv("Upgrade", "skipped global install");
359
417
  }
360
418
  }
361
419
 
362
420
  restartGatewayIfRunning();
363
421
  process.exit(0);
364
422
  } catch (error) {
365
- console.error(`Update check failed: ${error.message}`);
366
- console.log("Try manually:");
367
- console.log("npm view @silicaclaw/cli dist-tags --json");
423
+ headline();
424
+ console.log("");
425
+ console.error(paint("Update check failed", COLOR.bold, COLOR.yellow));
426
+ console.error(error.message);
427
+ console.log("");
428
+ kv("Try", "npm view @silicaclaw/cli dist-tags --json");
368
429
  process.exit(1);
369
430
  }
370
431
  }
371
432
 
372
433
  function help() {
373
- console.log(`
374
- SilicaClaw CLI
375
-
376
- Usage:
377
- silicaclaw onboard
378
- silicaclaw connect
379
- silicaclaw update
380
- silicaclaw install
381
- silicaclaw start [--mode=local|lan|global-preview]
382
- silicaclaw stop
383
- silicaclaw restart [--mode=local|lan|global-preview]
384
- silicaclaw status
385
- silicaclaw logs [local-console|signaling]
386
- silicaclaw gateway <start|stop|restart|status|logs>
387
- silicaclaw local-console
388
- silicaclaw explorer
389
- silicaclaw signaling
390
- silicaclaw doctor
391
- silicaclaw version
392
- silicaclaw help
393
-
394
- Commands:
395
- onboard Interactive step-by-step onboarding (recommended)
396
- connect Cross-network connect wizard (global-preview first)
397
- update Check latest npm version and show upgrade commands
398
- install Install persistent silicaclaw command for future shells
399
- start Start gateway-managed background services
400
- stop Stop gateway-managed background services
401
- restart Restart gateway-managed background services
402
- status Show gateway-managed service status
403
- logs Show gateway-managed service logs
404
- gateway Manage background services (start/stop/restart/status/logs)
405
- local-console Start local console (http://localhost:4310)
406
- explorer Start public explorer (http://localhost:4311)
407
- signaling Start WebRTC signaling preview server
408
- doctor Run project checks (npm run health)
409
- version Print SilicaClaw version
410
- help Show this help
411
- `.trim());
434
+ headline();
435
+ console.log("");
436
+ section("Core commands");
437
+ kv("Install", "npx -y @silicaclaw/cli@beta install");
438
+ kv("Start", "silicaclaw start --mode=global-preview");
439
+ kv("Status", "silicaclaw status");
440
+ kv("Stop", "silicaclaw stop");
441
+ kv("Update", "silicaclaw update");
442
+ console.log("");
443
+ section("Setup and network");
444
+ kv("Onboard", "silicaclaw onboard");
445
+ kv("Connect", "silicaclaw connect");
446
+ kv("Gateway", "silicaclaw gateway <start|stop|restart|status|logs>");
447
+ kv("Signaling", "silicaclaw signaling");
448
+ console.log("");
449
+ section("Local apps");
450
+ kv("Console", "silicaclaw local-console");
451
+ kv("Explorer", "silicaclaw explorer");
452
+ kv("Doctor", "silicaclaw doctor");
453
+ kv("Version", "silicaclaw version");
454
+ kv("Help", "silicaclaw help");
412
455
  }
413
456
 
414
457
  const cmd = String(process.argv[2] || "help").trim().toLowerCase();
415
458
 
416
459
  switch (cmd) {
417
460
  case "onboard":
461
+ headline();
462
+ console.log("");
463
+ section("Opening onboarding");
464
+ kv("Mode", "interactive setup");
465
+ kv("Focus", "install command, profile, internet relay");
466
+ console.log("");
418
467
  run("bash", [resolve(ROOT_DIR, "scripts", "quickstart.sh")]);
419
468
  break;
420
469
  case "connect":
470
+ headline();
471
+ console.log("");
472
+ section("Opening connect wizard");
473
+ kv("Mode", "global-preview first");
474
+ kv("Relay", "https://relay.silicaclaw.com");
475
+ console.log("");
421
476
  run("bash", [resolve(ROOT_DIR, "scripts", "quickstart.sh")], {
422
477
  env: {
423
478
  ...process.env,
@@ -459,12 +514,16 @@ switch (cmd) {
459
514
  run("npm", ["run", "webrtc-signaling"]);
460
515
  break;
461
516
  case "doctor":
517
+ headline();
518
+ console.log("");
519
+ section("Running health checks");
520
+ console.log("");
462
521
  run("npm", ["run", "health"]);
463
522
  break;
464
523
  case "version":
465
524
  case "-v":
466
525
  case "--version":
467
- console.log(readVersion());
526
+ headline();
468
527
  break;
469
528
  case "help":
470
529
  case "-h":