swytchcode
Advanced tools
+81
-46
@@ -189,5 +189,6 @@ #!/usr/bin/env node | ||
| // ─── Binary resolution (shared by normal pass-through AND onboarding) ──────── | ||
| function spawnBin(binPath, args) { | ||
| function spawnBin(binPath, args, extraEnv = {}) { | ||
| const env = { ...process.env, ...extraEnv }; | ||
| if (process.stdin.isTTY) { | ||
| return spawnSync(binPath, args, { stdio: 'inherit' }); | ||
| return spawnSync(binPath, args, { stdio: 'inherit', env }); | ||
| } | ||
@@ -200,2 +201,3 @@ let stdinData; | ||
| input: stdinData, | ||
| env, | ||
| }); | ||
@@ -271,3 +273,5 @@ } | ||
| const userArgs = process.argv.slice(2); | ||
| // Capture original arg BEFORE mutation | ||
| const originalArg = process.argv[2] || ''; | ||
| const isCanonicalDemoArg = /^[\w]+\.[\w.]+$/.test(originalArg) && !originalArg.startsWith('-'); | ||
| // Legacy support: npx swytchcode <canonical_id> → npx swytchcode exec <canonical_id> | ||
@@ -277,13 +281,36 @@ if (userArgs.length > 0 && /^[\w]+\.[\w.]+$/.test(userArgs[0]) && !userArgs[0].startsWith('-')) { | ||
| } | ||
| async function runOnboardingDirectDemo(canonicalId) { | ||
| writeln(); | ||
| writeln(` ${c.yellow}⚡ Running ${c.bold}${canonicalId}${c.reset}${c.yellow} live...${c.reset}`); | ||
| writeln(); | ||
| const demoResult = spawnBin(binPath, ['exec', canonicalId], { SWYTCHCODE_ONBOARDING: '1' }); | ||
| writeln(); | ||
| if (demoResult.status === 0) { | ||
| writeln(` ${c.dim}That was a real API call through Swytchcode.${c.reset}`); | ||
| writeln(); | ||
| } else { | ||
| writeln(` ${c.yellow}⚠ ${c.bold}${canonicalId}${c.reset}${c.yellow} isn't a valid demo tool.${c.reset}`); | ||
| writeln(` ${c.dim}Let's run a working demo instead.${c.reset}`); | ||
| writeln(); | ||
| await runDemoSelection(); | ||
| } | ||
| await runOnboardingSteps2to4(); | ||
| } | ||
| // ─── Normal pass-through (not npx, or npx with args) ──────────────────────── | ||
| if (!isNpx || userArgs.length > 0) { | ||
| // ─── Normal pass-through (not npx, or npx with non-demo args) ─────────────── | ||
| if (!isNpx || (userArgs.length > 0 && !isCanonicalDemoArg)) { | ||
| const result = spawnBin(binPath, userArgs); | ||
| if (result.error) { | ||
| err(`swytchcode: failed to launch binary: ${result.error.message}`); | ||
| process.exit(1); | ||
| } | ||
| process.exit(exitCode(result)); | ||
| } | ||
| // ─── NPX with canonical ID: run demo directly then show onboarding ─────────── | ||
| if (isNpx && isCanonicalDemoArg) { | ||
| runOnboardingDirectDemo(originalArg).catch(e => { | ||
| err(`\nswytchcode: onboarding error (${e.message}) — falling back to CLI.\n`); | ||
| const result = spawnBin(binPath, userArgs); | ||
| process.exit(exitCode(result)); | ||
| }); | ||
| } else { | ||
| // ─── NPX ONBOARDING FLOW ───────────────────────────────────────────────────── | ||
@@ -318,2 +345,45 @@ // Only reached when: isNpx === true AND no args passed (bare `npx swytchcode`) | ||
| } | ||
| } | ||
| async function runDemoSelection() { | ||
| let demoTools = []; | ||
| try { | ||
| const res = await apiGet(`${API_BASE}/demo/tools`); | ||
| if (res.status === 200 && Array.isArray(res.body.tools)) { | ||
| demoTools = res.body.tools; | ||
| } | ||
| } catch (_) {} | ||
| if (demoTools.length === 0) { | ||
| writeln(`${c.yellow} Demo unavailable right now — skipping to setup.${c.reset}`); | ||
| writeln(); | ||
| return; | ||
| } | ||
| const friendlyName = { | ||
| 'stripe.create_payment': 'Stripe — Create a payment ($20.00)', | ||
| }; | ||
| const demoOptions = demoTools.map(t => ({ | ||
| label: friendlyName[t] || t, | ||
| value: t, | ||
| })); | ||
| demoOptions.push({ label: 'Skip demo', value: '__skip__' }); | ||
| const chosen = await menuArrow('Choose a demo to run:', demoOptions); | ||
| if (chosen !== '__skip__') { | ||
| writeln(); | ||
| writeln(` ${c.gray}$ swytchcode demo stripe${c.reset}`); | ||
| spawnSync(binPath, ['demo', 'stripe'], { | ||
| stdio: 'inherit', | ||
| env: { ...process.env, SWYTCHCODE_ONBOARDING: '1' } | ||
| }); | ||
| writeln(); | ||
| writeln(` ${c.dim}That was a real API call. No credentials, no setup.${c.reset}`); | ||
| writeln(` ${c.dim}With Swytchcode, every API integration works exactly like this.${c.reset}`); | ||
| } | ||
| } | ||
| async function runOnboarding() { | ||
@@ -350,41 +420,7 @@ let cliVersion = '0.0.0'; | ||
| writeln(); | ||
| await runDemoSelection(); | ||
| await runOnboardingSteps2to4(); | ||
| } | ||
| // Fetch available demo tools | ||
| let demoTools = []; | ||
| try { | ||
| const res = await apiGet(`${API_BASE}/demo/tools`); | ||
| if (res.status === 200 && Array.isArray(res.body.tools)) { | ||
| demoTools = res.body.tools; | ||
| } | ||
| } catch (_) { | ||
| // silently fall through — skip demo if API is unreachable | ||
| } | ||
| if (demoTools.length === 0) { | ||
| writeln(`${c.yellow} Demo unavailable right now — skipping to setup.${c.reset}`); | ||
| writeln(); | ||
| } else { | ||
| // Map tool IDs to friendly names | ||
| const friendlyName = { | ||
| 'stripe.create_payment': 'Stripe — Create a payment ($20.00)', | ||
| }; | ||
| const demoOptions = demoTools.map(t => ({ | ||
| label: friendlyName[t] || t, | ||
| value: t, | ||
| })); | ||
| demoOptions.push({ label: 'Skip demo', value: '__skip__' }); | ||
| const chosen = await menuArrow('Choose a demo to run:', demoOptions); | ||
| if (chosen !== '__skip__') { | ||
| writeln(); | ||
| writeln(` ${c.gray}$ swytchcode demo stripe${c.reset}`); | ||
| spawnSync(binPath, ['demo', 'stripe'], { stdio: 'inherit' }); | ||
| writeln(); | ||
| writeln(` ${c.dim}That was a real API call. No credentials, no setup.${c.reset}`); | ||
| writeln(` ${c.dim}With Swytchcode, every API integration works exactly like this.${c.reset}`); | ||
| } | ||
| } | ||
| async function runOnboardingSteps2to4() { | ||
| // ── Step 2: Install ─────────────────────────────────────────────────────── | ||
@@ -514,3 +550,2 @@ writeln(); | ||
| runOnboarding().catch(e => { | ||
| // If onboarding crashes for any reason, fall back to normal binary pass-through | ||
| err(`\nswytchcode: onboarding error (${e.message}) — falling back to CLI.\n`); | ||
@@ -517,0 +552,0 @@ const result = spawnBin(binPath, userArgs); |
+7
-7
| { | ||
| "name": "swytchcode", | ||
| "version": "2.5.2", | ||
| "version": "2.6.0", | ||
| "description": "Execution authority layer for API integrations", | ||
@@ -26,9 +26,9 @@ "keywords": [ | ||
| "optionalDependencies": { | ||
| "swytchcode-cli-darwin-arm64": "2.5.2", | ||
| "swytchcode-cli-darwin-x64": "2.5.2", | ||
| "swytchcode-cli-linux-arm64": "2.5.2", | ||
| "swytchcode-cli-linux-x64": "2.5.2", | ||
| "swytchcode-cli-win32-arm64": "2.5.2", | ||
| "swytchcode-cli-win32-x64": "2.5.2" | ||
| "swytchcode-cli-darwin-arm64": "2.6.0", | ||
| "swytchcode-cli-darwin-x64": "2.6.0", | ||
| "swytchcode-cli-linux-arm64": "2.6.0", | ||
| "swytchcode-cli-linux-x64": "2.6.0", | ||
| "swytchcode-cli-win32-arm64": "2.6.0", | ||
| "swytchcode-cli-win32-x64": "2.6.0" | ||
| } | ||
| } |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 1 instance in 1 package
23309
5.82%492
7.42%8
14.29%