swytchcode 2.10.2 → 2.14.0-beta.1

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 (2) hide show
  1. package/bin/swytchcode.js +136 -15
  2. package/package.json +13 -8
package/bin/swytchcode.js CHANGED
@@ -87,7 +87,7 @@ function menuArrow(prompt, options) {
87
87
  resolve(options[n - 1].value);
88
88
  return;
89
89
  }
90
- writeln(`${c.red} Invalid choice. Please enter a number between 1 and ${options.length}.${c.reset}`);
90
+ writeln(`${c.red} invalid choice — enter a number between 1 and ${options.length}${c.reset}`);
91
91
  }
92
92
  }
93
93
 
@@ -165,11 +165,11 @@ function spinner(msg) {
165
165
  return {
166
166
  stop(doneMsg) {
167
167
  clearInterval(iv);
168
- process.stdout.write(`\r${c.green}✔${c.reset} ${doneMsg}\n`);
168
+ process.stdout.write(`\r${c.green}›${c.reset} ${doneMsg}\n`);
169
169
  },
170
170
  fail(failMsg) {
171
171
  clearInterval(iv);
172
- process.stdout.write(`\r${c.red}✖${c.reset} ${failMsg}\n`);
172
+ process.stdout.write(`\r${c.red}×${c.reset} ${failMsg}\n`);
173
173
  },
174
174
  };
175
175
  }
@@ -208,7 +208,7 @@ function apiPost(urlStr, body) {
208
208
  function spawnBin(binPath, args, extraEnv = {}) {
209
209
  const env = { ...process.env, ...extraEnv };
210
210
  let result;
211
- if (process.stdin.isTTY) {
211
+ if (process.stdin.isTTY || (args.length > 0 && args[0] === 'mcp')) {
212
212
  result = spawnSync(binPath, args, { stdio: 'inherit', env });
213
213
  } else {
214
214
  let stdinData;
@@ -427,6 +427,134 @@ async function runDemoSelection() {
427
427
  }
428
428
  }
429
429
 
430
+ // ─── Welcome card (mirrors internal/output/banner.go) ───────────────────────
431
+ const CARD_WORDMARK = [
432
+ '███████╗██╗ ██╗██╗ ██╗████████╗ ██████╗██╗ ██╗ ██████╗ ██████╗ ██████╗ ███████╗',
433
+ '██╔════╝██║ ██║╚██╗ ██╔╝╚══██╔══╝██╔════╝██║ ██║██╔════╝██╔═══██╗██╔══██╗██╔════╝',
434
+ '███████╗██║ █╗ ██║ ╚████╔╝ ██║ ██║ ███████║██║ ██║ ██║██║ ██║█████╗',
435
+ '╚════██║██║███╗██║ ╚██╔╝ ██║ ██║ ██╔══██║██║ ██║ ██║██║ ██║██╔══╝',
436
+ '███████║╚███╔███╔╝ ██║ ██║ ╚██████╗██║ ██║╚██████╗╚██████╔╝██████╔╝███████╗',
437
+ '╚══════╝ ╚══╝╚══╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝',
438
+ ];
439
+ const CARD_MARK = [
440
+ ' ▄▄▄█████████▄▄',
441
+ ' ▄▄███▀▀▀ ▀▀▀███▄',
442
+ ' ▄███▀',
443
+ ' ███ ▄████████▀',
444
+ ' ██▀ █████████',
445
+ ' ██▀ ▄████████▀',
446
+ '███ ▄████████▀',
447
+ '██ █████████',
448
+ '██ ▄██████████████▀',
449
+ '██ ▄██████████████▀',
450
+ '▀██ ██████▀▄█████▀',
451
+ ' ██▄ ▄████▀',
452
+ ' ██▄ ▄████▀',
453
+ ' ▀██▄ ▄██▀ ▄',
454
+ ' ▀▀▀ ▄█▀▀ ▄▄███',
455
+ ' ▄▀ ▄▄▄▄▄▄▄▄▄████▀▀',
456
+ ' ▀ ▀▀████████▀▀',
457
+ ];
458
+ const CARD_TAGLINE = 'Your agent calls an API. We make sure it goes through.';
459
+
460
+ function rep(ch, n) { return n > 0 ? ch.repeat(n) : ''; }
461
+ function vlen(s) { return [...s].length; }
462
+ function padRows(rows) {
463
+ const w = Math.max(...rows.map(vlen));
464
+ return { rows: rows.map(r => r + rep(' ', w - vlen(r))), w };
465
+ }
466
+
467
+ // welcomeCard renders the framed welcome card (logo mark left + wordmark right,
468
+ // wordmark vertically centered), stepping down to a plain wordmark or the compact
469
+ // banner based on width / UTF-8 / truecolor / TTY / NO_COLOR. Mirrors the Go banner.
470
+ function welcomeCard(cliVersion) {
471
+ const isTTY = !!process.stdout.isTTY;
472
+ const width = process.stdout.columns || 0;
473
+ const ct = process.env.COLORTERM || '';
474
+ const truecolor = ct === 'truecolor' || ct === '24bit';
475
+ const noColor = !!process.env.NO_COLOR || !!process.env.CI;
476
+ const useColor = !noColor && isTTY;
477
+ const utf8 = process.platform === 'win32'
478
+ ? (!!process.env.WT_SESSION || process.env.TERM_PROGRAM === 'vscode' || process.env.ConEmuANSI === 'ON')
479
+ : /utf-?8/i.test(process.env.LC_ALL || process.env.LC_CTYPE || process.env.LANG || '');
480
+
481
+ const orange = s => !useColor ? s : (truecolor ? `\x1b[38;2;245;148;30m${s}\x1b[0m` : `\x1b[38;5;214m${s}\x1b[0m`);
482
+ const frame = s => !useColor ? s : (truecolor ? `\x1b[38;2;122;78;24m${s}\x1b[0m` : `\x1b[38;5;214m${s}\x1b[0m`);
483
+ const dim = s => !useColor ? s : `\x1b[2m${s}\x1b[0m`;
484
+ const green = s => !useColor ? s : `\x1b[32m${s}\x1b[0m`;
485
+
486
+ const { rows: wm, w: wmW } = padRows(CARD_WORDMARK);
487
+ const { rows: mk, w: mkW } = padRows(CARD_MARK);
488
+ const gutter = 4, margin = 2;
489
+ const innerW = margin + mkW + gutter + wmW + margin;
490
+ const cardW = innerW + 2;
491
+
492
+ if (!isTTY || noColor) { compactCard(cliVersion, false); return; }
493
+ if (!utf8 || width < 87) { compactCard(cliVersion, useColor); return; }
494
+ if (!truecolor || width < cardW + 2) { wordmarkCard({ orange, dim, green, wm }); return; }
495
+
496
+ const boxRow = (colored, vis) => frame('│') + colored + rep(' ', Math.max(0, innerW - vis)) + frame('│');
497
+ writeln();
498
+ const title = ' Welcome to Swytchcode ';
499
+ writeln(frame('┌─' + title + rep('─', innerW - 1 - vlen(title)) + '┐'));
500
+ writeln(boxRow('', 0));
501
+ // Logo (left) + wordmark (right); wordmark vertically centered.
502
+ const nRows = Math.max(mk.length, wm.length);
503
+ const wmOff = Math.max(0, Math.floor((mk.length - wm.length) / 2));
504
+ for (let i = 0; i < nRows; i++) {
505
+ const left = i < mk.length ? orange(mk[i]) : rep(' ', mkW);
506
+ const wi = i - wmOff;
507
+ const right = (wi >= 0 && wi < wm.length) ? orange(wm[wi]) : rep(' ', wmW);
508
+ writeln(boxRow(rep(' ', margin) + left + rep(' ', gutter) + right, margin + mkW + gutter + wmW));
509
+ }
510
+ writeln(boxRow('', 0));
511
+ // Tagline centered across the inner width.
512
+ const lead = margin + Math.floor((innerW - 2 * margin - vlen(CARD_TAGLINE)) / 2);
513
+ writeln(boxRow(rep(' ', lead) + dim(CARD_TAGLINE), lead + vlen(CARD_TAGLINE)));
514
+ writeln(boxRow('', 0));
515
+ writeln(frame('└' + rep('─', innerW) + '┘'));
516
+ cardBelow({ orange, dim, green });
517
+ }
518
+
519
+ function compactCard(cliVersion, useColor) {
520
+ const orange = s => useColor ? `\x1b[38;5;214m${s}\x1b[0m` : s;
521
+ const dim = s => useColor ? `\x1b[2m${s}\x1b[0m` : s;
522
+ writeln();
523
+ writeln(` ${orange('swytchcode')} ${dim('v' + cliVersion)}`);
524
+ writeln(` ${CARD_TAGLINE}`);
525
+ writeln();
526
+ writeln(` ${dim('docs')} docs.swytchcode.com`);
527
+ writeln(` ${dim('chat')} discord.gg/zuSXSv5GWs`);
528
+ writeln();
529
+ }
530
+
531
+ function wordmarkCard({ orange, dim, green, wm }) {
532
+ writeln();
533
+ for (const row of wm) writeln(` ${orange(row)}`);
534
+ writeln(`\n ${dim(CARD_TAGLINE)}`);
535
+ cardBelow({ orange, dim, green });
536
+ }
537
+
538
+ // cardBelow prints the description, sign-in line, cwd, and get-started hints.
539
+ function cardBelow({ orange, dim, green }) {
540
+ writeln();
541
+ writeln('Swytchcode sits between your agent and any API — auth, retries, idempotency, and schema');
542
+ writeln(`validation, handled. Run a command below, or ${orange('swytchcode --help')} for the full list.`);
543
+ writeln();
544
+ writeln(`${orange('●')} ${dim('not signed in — run ')}${orange('swytchcode login')}`);
545
+ const cwd = process.cwd().replace(/\\/g, '/');
546
+ const home = (require('os').homedir() || '').replace(/\\/g, '/');
547
+ writeln(dim(home && cwd.startsWith(home) ? '~' + cwd.slice(home.length) : cwd));
548
+ writeln(`\n${dim('get started')}`);
549
+ const rows = [
550
+ ['swytchcode init', 'set up this project'],
551
+ ['swytchcode get <project>', 'fetch integration bundles'],
552
+ ['swytchcode exec <canonical_id>', 'run a tool'],
553
+ ];
554
+ for (const [cmd, desc] of rows) writeln(` ${green('›')} ${cmd.padEnd(32)} ${dim(desc)}`);
555
+ writeln();
556
+ }
557
+
430
558
  async function runOnboarding() {
431
559
  let cliVersion = '0.0.0';
432
560
  try {
@@ -445,14 +573,7 @@ async function runOnboarding() {
445
573
  // Clear screen for a clean experience
446
574
  process.stdout.write('\x1Bc');
447
575
 
448
- writeln();
449
- const vPad = ' '.repeat(Math.max(0, 34 - cliVersion.length));
450
- writeln(` ${c.yellow}==========================================${c.reset}`);
451
- writeln(` ${c.yellow}|${c.reset} ${c.yellow}⚡ ${c.bold}Welcome to Swytchcode${c.reset} ${c.yellow}|${c.reset}`);
452
- writeln(` ${c.yellow}|${c.reset} ${c.dim}v${cliVersion}${c.reset}${vPad}${c.yellow}|${c.reset}`);
453
- writeln(` ${c.yellow}|${c.reset} ${c.dim}Execution authority layer${c.reset} ${c.yellow}|${c.reset}`);
454
- writeln(` ${c.yellow}==========================================${c.reset}`);
455
- writeln();
576
+ welcomeCard(cliVersion);
456
577
 
457
578
  // ── Step 1: Demo ──────────────────────────────────────────────────────────
458
579
  writeln(`${c.bold} Step 1 of 4 — See it in action${c.reset}`);
@@ -489,7 +610,7 @@ async function runOnboardingSteps2to4() {
489
610
  const installSpin = spinner('Running npm install swytchcode ...');
490
611
  try {
491
612
  execSync('npm install swytchcode', { stdio: 'pipe' });
492
- installSpin.stop('Installed successfully');
613
+ installSpin.stop('installed');
493
614
  } catch (e) {
494
615
  if (e.signal === 'SIGINT') {
495
616
  installSpin.stop('Cancelled');
@@ -529,7 +650,7 @@ async function runOnboardingSteps2to4() {
529
650
  writeln(` ${c.yellow}Login window closed or failed.${c.reset}`);
530
651
  writeln(` ${c.dim}You can log in later with:${c.reset} ${c.cyan}swytchcode login${c.reset}`);
531
652
  } else {
532
- writeln(` ${c.green}✔ Logged in successfully.${c.reset}`);
653
+ writeln(` ${c.green}›${c.reset} logged in`);
533
654
  }
534
655
  } else if (authChoice === 'register') {
535
656
  writeln(` ${c.dim}Opening browser to create your account ...${c.reset}`);
@@ -540,7 +661,7 @@ async function runOnboardingSteps2to4() {
540
661
  writeln(` ${c.yellow}Browser window closed or failed.${c.reset}`);
541
662
  writeln(` ${c.dim}Create your account at:${c.reset} ${c.cyan}https://swytchcode.com/signup${c.reset}`);
542
663
  } else {
543
- writeln(` ${c.green}✔ Account connected successfully.${c.reset}`);
664
+ writeln(` ${c.green}›${c.reset} account connected`);
544
665
  }
545
666
  } else {
546
667
  writeln(` ${c.dim}No problem — you can connect your account any time with:${c.reset}`);
package/package.json CHANGED
@@ -1,6 +1,10 @@
1
1
  {
2
2
  "name": "swytchcode",
3
- "version": "2.10.2",
3
+ "version": "2.14.0-beta.1",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "git+https://gitlab.com/swytchcode/cli.git"
7
+ },
4
8
  "description": "Execution authority layer for API integrations",
5
9
  "keywords": [
6
10
  "api",
@@ -13,7 +17,8 @@
13
17
  "homepage": "https://cli.swytchcode.com",
14
18
  "license": "MIT",
15
19
  "bin": {
16
- "swytchcode": "./bin/swytchcode.js"
20
+ "swytchcode": "./bin/swytchcode.js",
21
+ "swy": "./bin/swytchcode.js"
17
22
  },
18
23
  "engines": {
19
24
  "node": ">=14"
@@ -23,11 +28,11 @@
23
28
  "README.md"
24
29
  ],
25
30
  "optionalDependencies": {
26
- "swytchcode-cli-darwin-arm64": "2.10.2",
27
- "swytchcode-cli-darwin-x64": "2.10.2",
28
- "swytchcode-cli-linux-arm64": "2.10.2",
29
- "swytchcode-cli-linux-x64": "2.10.2",
30
- "swytchcode-cli-win32-arm64": "2.10.2",
31
- "swytchcode-cli-win32-x64": "2.10.2"
31
+ "swytchcode-cli-darwin-arm64": "2.14.0-beta.1",
32
+ "swytchcode-cli-darwin-x64": "2.14.0-beta.1",
33
+ "swytchcode-cli-linux-arm64": "2.14.0-beta.1",
34
+ "swytchcode-cli-linux-x64": "2.14.0-beta.1",
35
+ "swytchcode-cli-win32-arm64": "2.14.0-beta.1",
36
+ "swytchcode-cli-win32-x64": "2.14.0-beta.1"
32
37
  }
33
38
  }