@scalekit-inc/cli 0.1.1 → 0.2.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.
package/dist/index.js CHANGED
@@ -1,7 +1,248 @@
1
1
  // src/index.ts
2
2
  import cfonts from "cfonts";
3
+ import { Command as Command2 } from "commander";
4
+
5
+ // src/commands/setup.ts
6
+ import {
7
+ cancel,
8
+ confirm,
9
+ intro,
10
+ isCancel,
11
+ log,
12
+ multiselect,
13
+ outro
14
+ } from "@clack/prompts";
3
15
  import { Command } from "commander";
4
16
 
17
+ // src/stacks/claude.ts
18
+ import { execFileSync, spawn } from "child_process";
19
+ var CMDS = [
20
+ "claude plugin marketplace add scalekit-inc/claude-code-authstack",
21
+ "claude plugin install agent-auth@scalekit-auth-stack"
22
+ ];
23
+ var claudeStack = {
24
+ id: "claude",
25
+ name: "Claude Code",
26
+ description: "Scalekit auth plugins for Claude Code",
27
+ commands: CMDS,
28
+ detect() {
29
+ try {
30
+ execFileSync(
31
+ process.platform === "win32" ? "where" : "which",
32
+ ["claude"],
33
+ { stdio: "ignore" }
34
+ );
35
+ return true;
36
+ } catch {
37
+ return false;
38
+ }
39
+ },
40
+ async install() {
41
+ for (const cmd of CMDS) {
42
+ await new Promise((resolve, reject) => {
43
+ const child = spawn(cmd, { shell: true, stdio: "inherit" });
44
+ child.on("close", (code) => {
45
+ if (code === 0) resolve();
46
+ else reject(new Error(`"${cmd}" exited with code ${code}`));
47
+ });
48
+ child.on("error", reject);
49
+ });
50
+ }
51
+ }
52
+ };
53
+
54
+ // src/stacks/codex.ts
55
+ import { execFileSync as execFileSync2, spawn as spawn2 } from "child_process";
56
+ var INSTALL_URL = "https://raw.githubusercontent.com/scalekit-inc/codex-authstack/main/install.sh";
57
+ var INSTALL_CMD = `curl -fsSL ${INSTALL_URL} | bash`;
58
+ var codexStack = {
59
+ id: "codex",
60
+ name: "Codex",
61
+ description: "Scalekit auth plugins for Codex / OpenCode",
62
+ commands: [INSTALL_CMD],
63
+ detect() {
64
+ try {
65
+ execFileSync2(
66
+ process.platform === "win32" ? "where" : "which",
67
+ ["codex"],
68
+ { stdio: "ignore" }
69
+ );
70
+ return true;
71
+ } catch {
72
+ return false;
73
+ }
74
+ },
75
+ install() {
76
+ return new Promise((resolve, reject) => {
77
+ const child = spawn2(INSTALL_CMD, {
78
+ shell: true,
79
+ stdio: "inherit"
80
+ });
81
+ child.on("close", (code) => {
82
+ if (code === 0) resolve();
83
+ else reject(new Error(`Install exited with code ${code}`));
84
+ });
85
+ child.on("error", reject);
86
+ });
87
+ }
88
+ };
89
+
90
+ // src/stacks/cursor.ts
91
+ import { execFileSync as execFileSync3, spawn as spawn3 } from "child_process";
92
+ import { accessSync } from "fs";
93
+ import { homedir } from "os";
94
+ import { join } from "path";
95
+ var INSTALL_URL2 = "https://raw.githubusercontent.com/scalekit-inc/cursor-authstack/main/install.sh";
96
+ var INSTALL_CMD2 = `curl -fsSL ${INSTALL_URL2} | bash`;
97
+ var cursorStack = {
98
+ id: "cursor",
99
+ name: "Cursor",
100
+ description: "Scalekit auth plugins for Cursor editor",
101
+ commands: [INSTALL_CMD2],
102
+ detect() {
103
+ const configDir = process.platform === "win32" ? join(process.env.APPDATA || "", "Cursor") : join(homedir(), ".cursor");
104
+ try {
105
+ accessSync(configDir);
106
+ return true;
107
+ } catch {
108
+ }
109
+ try {
110
+ execFileSync3(
111
+ process.platform === "win32" ? "where" : "which",
112
+ ["cursor"],
113
+ { stdio: "ignore" }
114
+ );
115
+ return true;
116
+ } catch {
117
+ return false;
118
+ }
119
+ },
120
+ install() {
121
+ return new Promise((resolve, reject) => {
122
+ const child = spawn3(INSTALL_CMD2, {
123
+ shell: true,
124
+ stdio: "inherit"
125
+ });
126
+ child.on("close", (code) => {
127
+ if (code === 0) resolve();
128
+ else reject(new Error(`Install exited with code ${code}`));
129
+ });
130
+ child.on("error", reject);
131
+ });
132
+ }
133
+ };
134
+
135
+ // src/stacks/registry.ts
136
+ var stacks = [cursorStack, claudeStack, codexStack];
137
+ function findStack(id) {
138
+ return stacks.find((s) => s.id === id);
139
+ }
140
+
141
+ // src/commands/setup.ts
142
+ async function runStack(stack, dryRun) {
143
+ for (const cmd of stack.commands) {
144
+ log.info(dryRun ? `Would run: ${cmd}` : `$ ${cmd}`);
145
+ }
146
+ if (dryRun) return true;
147
+ try {
148
+ await stack.install();
149
+ return true;
150
+ } catch (err) {
151
+ log.error(
152
+ `${stack.name} failed: ${err instanceof Error ? err.message : err}`
153
+ );
154
+ return false;
155
+ }
156
+ }
157
+ async function interactiveSetup(opts) {
158
+ intro("ScaleKit Setup");
159
+ const detected = stacks.filter((s) => s.detect());
160
+ if (detected.length > 0) {
161
+ log.info(`Detected: ${detected.map((s) => s.name).join(", ")}`);
162
+ }
163
+ let toInstall;
164
+ if (opts.yes) {
165
+ toInstall = detected.length > 0 ? detected : stacks;
166
+ } else {
167
+ const selected = await multiselect({
168
+ message: "Which editors do you want to set up?",
169
+ options: stacks.map((s) => ({
170
+ value: s.id,
171
+ label: s.name,
172
+ hint: s.detect() ? "detected" : void 0
173
+ })),
174
+ required: true
175
+ });
176
+ if (isCancel(selected)) {
177
+ cancel("Setup cancelled.");
178
+ process.exit(0);
179
+ }
180
+ toInstall = stacks.filter((s) => selected.includes(s.id));
181
+ }
182
+ let succeeded = 0;
183
+ let failed = 0;
184
+ for (const stack of toInstall) {
185
+ log.step(`Setting up ${stack.name}...`);
186
+ if (await runStack(stack, !!opts.dryRun)) {
187
+ log.success(`${stack.name} \u2014 done`);
188
+ succeeded++;
189
+ } else {
190
+ failed++;
191
+ }
192
+ }
193
+ if (opts.dryRun) {
194
+ outro("Dry run complete \u2014 no commands were executed.");
195
+ } else if (failed === 0) {
196
+ outro(
197
+ `Setup complete! ${succeeded} stack${succeeded !== 1 ? "s" : ""} installed.`
198
+ );
199
+ } else {
200
+ outro(`Done. ${succeeded} succeeded, ${failed} failed.`);
201
+ }
202
+ }
203
+ async function directSetup(stackId, opts) {
204
+ const stack = findStack(stackId);
205
+ if (!stack) {
206
+ const ids = stacks.map((s) => s.id).join(", ");
207
+ log.error(`Unknown stack "${stackId}". Available: ${ids}`);
208
+ process.exit(1);
209
+ }
210
+ if (!opts.yes && !opts.dryRun) {
211
+ intro("ScaleKit Setup");
212
+ const ok2 = await confirm({
213
+ message: `Install ${stack.name} auth stack?`
214
+ });
215
+ if (isCancel(ok2) || !ok2) {
216
+ cancel("Setup cancelled.");
217
+ process.exit(0);
218
+ }
219
+ }
220
+ log.step(`Setting up ${stack.name}...`);
221
+ const ok = await runStack(stack, !!opts.dryRun);
222
+ if (opts.dryRun) {
223
+ outro("Dry run \u2014 no commands were executed.");
224
+ } else if (ok) {
225
+ outro(`${stack.name} auth stack installed.`);
226
+ } else {
227
+ process.exit(1);
228
+ }
229
+ }
230
+ var setupCommand = new Command("setup").description("set up ScaleKit auth stacks for your editors").argument("[stack]", "cursor, claude, or codex").option("-y, --yes", "skip confirmation prompts").option("--dry-run", "show commands without executing").addHelpText(
231
+ "after",
232
+ `
233
+ Examples:
234
+ $ scalekit setup interactive setup wizard
235
+ $ scalekit setup cursor set up Cursor directly
236
+ $ scalekit setup codex -y skip confirmation
237
+ $ scalekit setup --dry-run preview commands without running them`
238
+ ).action(async (stackId, opts) => {
239
+ if (stackId) {
240
+ await directSetup(stackId, opts);
241
+ } else {
242
+ await interactiveSetup(opts);
243
+ }
244
+ });
245
+
5
246
  // src/core/help.ts
6
247
  import pc from "picocolors";
7
248
  function formatHeader(cmd) {
@@ -58,11 +299,12 @@ function showBanner() {
58
299
  space: true
59
300
  });
60
301
  }
61
- var program = new Command();
302
+ var program = new Command2();
62
303
  program.name("scalekit").description("Auth stack for the agentic era").version("0.1.0").option("--plain", "disable colors and styling (also respects NO_COLOR env)").configureHelp(scalekitHelp()).addHelpCommand(false);
304
+ program.addCommand(setupCommand);
63
305
  program.action(() => {
64
306
  showBanner();
65
307
  program.help();
66
308
  });
67
- program.parse();
309
+ await program.parseAsync();
68
310
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/core/help.ts"],"sourcesContent":["import cfonts from \"cfonts\";\nimport { Command } from \"commander\";\nimport { scalekitHelp } from \"./core/help.js\";\n\nfunction showBanner() {\n\tif (process.env.NO_COLOR || process.argv.includes(\"--plain\")) {\n\t\treturn;\n\t}\n\n\tcfonts.say(\"ScaleKit\", {\n\t\tfont: \"chrome\",\n\t\talign: \"left\",\n\t\tcolors: [\"cyan\", \"white\", \"blue\"],\n\t\tletterSpacing: 1,\n\t\tspace: true,\n\t});\n}\n\nconst program = new Command();\n\nprogram\n\t.name(\"scalekit\")\n\t.description(\"Auth stack for the agentic era\")\n\t.version(\"0.1.0\")\n\t.option(\"--plain\", \"disable colors and styling (also respects NO_COLOR env)\")\n\t.configureHelp(scalekitHelp())\n\t.addHelpCommand(false);\n\nprogram.action(() => {\n\tshowBanner();\n\tprogram.help();\n});\n\nprogram.parse();\n","import type { Command, Help } from \"commander\";\nimport pc from \"picocolors\";\n\nfunction formatHeader(cmd: Command): string {\n\tconst desc = cmd.description();\n\tconst title = desc ? `${cmd.name()} — ${desc}` : cmd.name();\n\treturn pc.bold(pc.cyan(title));\n}\n\nfunction formatUsage(cmd: Command): string {\n\treturn [pc.bold(\"USAGE\"), ` $ ${cmd.name()} ${cmd.usage()}`].join(\"\\n\");\n}\n\nfunction formatCommands(cmd: Command, helper: Help): string | null {\n\tconst commands = helper.visibleCommands(cmd);\n\tif (commands.length === 0) return null;\n\n\tconst pad = Math.max(...commands.map((c) => c.name().length)) + 2;\n\tconst lines = commands.map(\n\t\t(sub) => ` ${pc.bold(sub.name().padEnd(pad))}${pc.dim(sub.description())}`,\n\t);\n\n\treturn [pc.bold(\"COMMANDS\"), ...lines].join(\"\\n\");\n}\n\nfunction formatOptions(cmd: Command, helper: Help): string | null {\n\tconst options = helper.visibleOptions(cmd);\n\tif (options.length === 0) return null;\n\n\tconst pad = Math.max(...options.map((o) => helper.optionTerm(o).length)) + 2;\n\tconst lines = options.map(\n\t\t(opt) =>\n\t\t\t` ${pc.yellow(helper.optionTerm(opt).padEnd(pad))}${pc.dim(opt.description)}`,\n\t);\n\n\treturn [pc.bold(\"OPTIONS\"), ...lines].join(\"\\n\");\n}\n\nexport function scalekitHelp() {\n\treturn {\n\t\tformatHelp(cmd: Command, helper: Help): string {\n\t\t\tconst sections = [\n\t\t\t\tformatHeader(cmd),\n\t\t\t\tformatUsage(cmd),\n\t\t\t\tformatCommands(cmd, helper),\n\t\t\t\tformatOptions(cmd, helper),\n\t\t\t].filter(Boolean);\n\n\t\t\treturn `${sections.join(\"\\n\\n\")}\\n`;\n\t\t},\n\t};\n}\n"],"mappings":";AAAA,OAAO,YAAY;AACnB,SAAS,eAAe;;;ACAxB,OAAO,QAAQ;AAEf,SAAS,aAAa,KAAsB;AAC3C,QAAM,OAAO,IAAI,YAAY;AAC7B,QAAM,QAAQ,OAAO,GAAG,IAAI,KAAK,CAAC,WAAM,IAAI,KAAK,IAAI,KAAK;AAC1D,SAAO,GAAG,KAAK,GAAG,KAAK,KAAK,CAAC;AAC9B;AAEA,SAAS,YAAY,KAAsB;AAC1C,SAAO,CAAC,GAAG,KAAK,OAAO,GAAG,OAAO,IAAI,KAAK,CAAC,IAAI,IAAI,MAAM,CAAC,EAAE,EAAE,KAAK,IAAI;AACxE;AAEA,SAAS,eAAe,KAAc,QAA6B;AAClE,QAAM,WAAW,OAAO,gBAAgB,GAAG;AAC3C,MAAI,SAAS,WAAW,EAAG,QAAO;AAElC,QAAM,MAAM,KAAK,IAAI,GAAG,SAAS,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI;AAChE,QAAM,QAAQ,SAAS;AAAA,IACtB,CAAC,QAAQ,KAAK,GAAG,KAAK,IAAI,KAAK,EAAE,OAAO,GAAG,CAAC,CAAC,GAAG,GAAG,IAAI,IAAI,YAAY,CAAC,CAAC;AAAA,EAC1E;AAEA,SAAO,CAAC,GAAG,KAAK,UAAU,GAAG,GAAG,KAAK,EAAE,KAAK,IAAI;AACjD;AAEA,SAAS,cAAc,KAAc,QAA6B;AACjE,QAAM,UAAU,OAAO,eAAe,GAAG;AACzC,MAAI,QAAQ,WAAW,EAAG,QAAO;AAEjC,QAAM,MAAM,KAAK,IAAI,GAAG,QAAQ,IAAI,CAAC,MAAM,OAAO,WAAW,CAAC,EAAE,MAAM,CAAC,IAAI;AAC3E,QAAM,QAAQ,QAAQ;AAAA,IACrB,CAAC,QACA,KAAK,GAAG,OAAO,OAAO,WAAW,GAAG,EAAE,OAAO,GAAG,CAAC,CAAC,GAAG,GAAG,IAAI,IAAI,WAAW,CAAC;AAAA,EAC9E;AAEA,SAAO,CAAC,GAAG,KAAK,SAAS,GAAG,GAAG,KAAK,EAAE,KAAK,IAAI;AAChD;AAEO,SAAS,eAAe;AAC9B,SAAO;AAAA,IACN,WAAW,KAAc,QAAsB;AAC9C,YAAM,WAAW;AAAA,QAChB,aAAa,GAAG;AAAA,QAChB,YAAY,GAAG;AAAA,QACf,eAAe,KAAK,MAAM;AAAA,QAC1B,cAAc,KAAK,MAAM;AAAA,MAC1B,EAAE,OAAO,OAAO;AAEhB,aAAO,GAAG,SAAS,KAAK,MAAM,CAAC;AAAA;AAAA,IAChC;AAAA,EACD;AACD;;;AD/CA,SAAS,aAAa;AACrB,MAAI,QAAQ,IAAI,YAAY,QAAQ,KAAK,SAAS,SAAS,GAAG;AAC7D;AAAA,EACD;AAEA,SAAO,IAAI,YAAY;AAAA,IACtB,MAAM;AAAA,IACN,OAAO;AAAA,IACP,QAAQ,CAAC,QAAQ,SAAS,MAAM;AAAA,IAChC,eAAe;AAAA,IACf,OAAO;AAAA,EACR,CAAC;AACF;AAEA,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACE,KAAK,UAAU,EACf,YAAY,gCAAgC,EAC5C,QAAQ,OAAO,EACf,OAAO,WAAW,yDAAyD,EAC3E,cAAc,aAAa,CAAC,EAC5B,eAAe,KAAK;AAEtB,QAAQ,OAAO,MAAM;AACpB,aAAW;AACX,UAAQ,KAAK;AACd,CAAC;AAED,QAAQ,MAAM;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/setup.ts","../src/stacks/claude.ts","../src/stacks/codex.ts","../src/stacks/cursor.ts","../src/stacks/registry.ts","../src/core/help.ts"],"sourcesContent":["import cfonts from \"cfonts\";\nimport { Command } from \"commander\";\nimport { setupCommand } from \"./commands/setup.js\";\nimport { scalekitHelp } from \"./core/help.js\";\n\nfunction showBanner() {\n\tif (process.env.NO_COLOR || process.argv.includes(\"--plain\")) {\n\t\treturn;\n\t}\n\n\tcfonts.say(\"ScaleKit\", {\n\t\tfont: \"chrome\",\n\t\talign: \"left\",\n\t\tcolors: [\"cyan\", \"white\", \"blue\"],\n\t\tletterSpacing: 1,\n\t\tspace: true,\n\t});\n}\n\nconst program = new Command();\n\nprogram\n\t.name(\"scalekit\")\n\t.description(\"Auth stack for the agentic era\")\n\t.version(\"0.1.0\")\n\t.option(\"--plain\", \"disable colors and styling (also respects NO_COLOR env)\")\n\t.configureHelp(scalekitHelp())\n\t.addHelpCommand(false);\n\nprogram.addCommand(setupCommand);\n\nprogram.action(() => {\n\tshowBanner();\n\tprogram.help();\n});\n\nawait program.parseAsync();\n","import {\n\tcancel,\n\tconfirm,\n\tintro,\n\tisCancel,\n\tlog,\n\tmultiselect,\n\toutro,\n} from \"@clack/prompts\";\nimport { Command } from \"commander\";\nimport { findStack, type Stack, stacks } from \"../stacks/registry.js\";\n\ninterface SetupOpts {\n\tyes?: boolean;\n\tdryRun?: boolean;\n}\n\nasync function runStack(stack: Stack, dryRun: boolean): Promise<boolean> {\n\tfor (const cmd of stack.commands) {\n\t\tlog.info(dryRun ? `Would run: ${cmd}` : `$ ${cmd}`);\n\t}\n\tif (dryRun) return true;\n\n\ttry {\n\t\tawait stack.install();\n\t\treturn true;\n\t} catch (err) {\n\t\tlog.error(\n\t\t\t`${stack.name} failed: ${err instanceof Error ? err.message : err}`,\n\t\t);\n\t\treturn false;\n\t}\n}\n\nasync function interactiveSetup(opts: SetupOpts) {\n\tintro(\"ScaleKit Setup\");\n\n\tconst detected = stacks.filter((s) => s.detect());\n\n\tif (detected.length > 0) {\n\t\tlog.info(`Detected: ${detected.map((s) => s.name).join(\", \")}`);\n\t}\n\n\tlet toInstall: Stack[];\n\n\tif (opts.yes) {\n\t\ttoInstall = detected.length > 0 ? detected : stacks;\n\t} else {\n\t\tconst selected = await multiselect({\n\t\t\tmessage: \"Which editors do you want to set up?\",\n\t\t\toptions: stacks.map((s) => ({\n\t\t\t\tvalue: s.id,\n\t\t\t\tlabel: s.name,\n\t\t\t\thint: s.detect() ? \"detected\" : undefined,\n\t\t\t})),\n\t\t\trequired: true,\n\t\t});\n\n\t\tif (isCancel(selected)) {\n\t\t\tcancel(\"Setup cancelled.\");\n\t\t\tprocess.exit(0);\n\t\t}\n\n\t\ttoInstall = stacks.filter((s) => selected.includes(s.id));\n\t}\n\n\tlet succeeded = 0;\n\tlet failed = 0;\n\n\tfor (const stack of toInstall) {\n\t\tlog.step(`Setting up ${stack.name}...`);\n\t\tif (await runStack(stack, !!opts.dryRun)) {\n\t\t\tlog.success(`${stack.name} — done`);\n\t\t\tsucceeded++;\n\t\t} else {\n\t\t\tfailed++;\n\t\t}\n\t}\n\n\tif (opts.dryRun) {\n\t\toutro(\"Dry run complete — no commands were executed.\");\n\t} else if (failed === 0) {\n\t\toutro(\n\t\t\t`Setup complete! ${succeeded} stack${succeeded !== 1 ? \"s\" : \"\"} installed.`,\n\t\t);\n\t} else {\n\t\toutro(`Done. ${succeeded} succeeded, ${failed} failed.`);\n\t}\n}\n\nasync function directSetup(stackId: string, opts: SetupOpts) {\n\tconst stack = findStack(stackId);\n\tif (!stack) {\n\t\tconst ids = stacks.map((s) => s.id).join(\", \");\n\t\tlog.error(`Unknown stack \"${stackId}\". Available: ${ids}`);\n\t\tprocess.exit(1);\n\t}\n\n\tif (!opts.yes && !opts.dryRun) {\n\t\tintro(\"ScaleKit Setup\");\n\t\tconst ok = await confirm({\n\t\t\tmessage: `Install ${stack.name} auth stack?`,\n\t\t});\n\t\tif (isCancel(ok) || !ok) {\n\t\t\tcancel(\"Setup cancelled.\");\n\t\t\tprocess.exit(0);\n\t\t}\n\t}\n\n\tlog.step(`Setting up ${stack.name}...`);\n\tconst ok = await runStack(stack, !!opts.dryRun);\n\n\tif (opts.dryRun) {\n\t\toutro(\"Dry run — no commands were executed.\");\n\t} else if (ok) {\n\t\toutro(`${stack.name} auth stack installed.`);\n\t} else {\n\t\tprocess.exit(1);\n\t}\n}\n\nexport const setupCommand = new Command(\"setup\")\n\t.description(\"set up ScaleKit auth stacks for your editors\")\n\t.argument(\"[stack]\", \"cursor, claude, or codex\")\n\t.option(\"-y, --yes\", \"skip confirmation prompts\")\n\t.option(\"--dry-run\", \"show commands without executing\")\n\t.addHelpText(\n\t\t\"after\",\n\t\t`\nExamples:\n $ scalekit setup interactive setup wizard\n $ scalekit setup cursor set up Cursor directly\n $ scalekit setup codex -y skip confirmation\n $ scalekit setup --dry-run preview commands without running them`,\n\t)\n\t.action(async (stackId: string | undefined, opts: SetupOpts) => {\n\t\tif (stackId) {\n\t\t\tawait directSetup(stackId, opts);\n\t\t} else {\n\t\t\tawait interactiveSetup(opts);\n\t\t}\n\t});\n","import { execFileSync, spawn } from \"node:child_process\";\nimport type { Stack } from \"./registry.js\";\n\nconst CMDS = [\n\t\"claude plugin marketplace add scalekit-inc/claude-code-authstack\",\n\t\"claude plugin install agent-auth@scalekit-auth-stack\",\n];\n\nexport const claudeStack: Stack = {\n\tid: \"claude\",\n\tname: \"Claude Code\",\n\tdescription: \"Scalekit auth plugins for Claude Code\",\n\tcommands: CMDS,\n\n\tdetect() {\n\t\ttry {\n\t\t\texecFileSync(\n\t\t\t\tprocess.platform === \"win32\" ? \"where\" : \"which\",\n\t\t\t\t[\"claude\"],\n\t\t\t\t{ stdio: \"ignore\" },\n\t\t\t);\n\t\t\treturn true;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t},\n\n\tasync install() {\n\t\tfor (const cmd of CMDS) {\n\t\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\t\tconst child = spawn(cmd, { shell: true, stdio: \"inherit\" });\n\t\t\t\tchild.on(\"close\", (code) => {\n\t\t\t\t\tif (code === 0) resolve();\n\t\t\t\t\telse reject(new Error(`\"${cmd}\" exited with code ${code}`));\n\t\t\t\t});\n\t\t\t\tchild.on(\"error\", reject);\n\t\t\t});\n\t\t}\n\t},\n};\n","import { execFileSync, spawn } from \"node:child_process\";\nimport type { Stack } from \"./registry.js\";\n\nconst INSTALL_URL =\n\t\"https://raw.githubusercontent.com/scalekit-inc/codex-authstack/main/install.sh\";\nconst INSTALL_CMD = `curl -fsSL ${INSTALL_URL} | bash`;\n\nexport const codexStack: Stack = {\n\tid: \"codex\",\n\tname: \"Codex\",\n\tdescription: \"Scalekit auth plugins for Codex / OpenCode\",\n\tcommands: [INSTALL_CMD],\n\n\tdetect() {\n\t\ttry {\n\t\t\texecFileSync(\n\t\t\t\tprocess.platform === \"win32\" ? \"where\" : \"which\",\n\t\t\t\t[\"codex\"],\n\t\t\t\t{ stdio: \"ignore\" },\n\t\t\t);\n\t\t\treturn true;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t},\n\n\tinstall() {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst child = spawn(INSTALL_CMD, {\n\t\t\t\tshell: true,\n\t\t\t\tstdio: \"inherit\",\n\t\t\t});\n\t\t\tchild.on(\"close\", (code) => {\n\t\t\t\tif (code === 0) resolve();\n\t\t\t\telse reject(new Error(`Install exited with code ${code}`));\n\t\t\t});\n\t\t\tchild.on(\"error\", reject);\n\t\t});\n\t},\n};\n","import { execFileSync, spawn } from \"node:child_process\";\nimport { accessSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Stack } from \"./registry.js\";\n\nconst INSTALL_URL =\n\t\"https://raw.githubusercontent.com/scalekit-inc/cursor-authstack/main/install.sh\";\nconst INSTALL_CMD = `curl -fsSL ${INSTALL_URL} | bash`;\n\nexport const cursorStack: Stack = {\n\tid: \"cursor\",\n\tname: \"Cursor\",\n\tdescription: \"Scalekit auth plugins for Cursor editor\",\n\tcommands: [INSTALL_CMD],\n\n\tdetect() {\n\t\tconst configDir =\n\t\t\tprocess.platform === \"win32\"\n\t\t\t\t? join(process.env.APPDATA || \"\", \"Cursor\")\n\t\t\t\t: join(homedir(), \".cursor\");\n\t\ttry {\n\t\t\taccessSync(configDir);\n\t\t\treturn true;\n\t\t} catch {\n\t\t\t// not found via config dir, check PATH\n\t\t}\n\t\ttry {\n\t\t\texecFileSync(\n\t\t\t\tprocess.platform === \"win32\" ? \"where\" : \"which\",\n\t\t\t\t[\"cursor\"],\n\t\t\t\t{ stdio: \"ignore\" },\n\t\t\t);\n\t\t\treturn true;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t},\n\n\tinstall() {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst child = spawn(INSTALL_CMD, {\n\t\t\t\tshell: true,\n\t\t\t\tstdio: \"inherit\",\n\t\t\t});\n\t\t\tchild.on(\"close\", (code) => {\n\t\t\t\tif (code === 0) resolve();\n\t\t\t\telse reject(new Error(`Install exited with code ${code}`));\n\t\t\t});\n\t\t\tchild.on(\"error\", reject);\n\t\t});\n\t},\n};\n","import { claudeStack } from \"./claude.js\";\nimport { codexStack } from \"./codex.js\";\nimport { cursorStack } from \"./cursor.js\";\n\nexport interface Stack {\n\tid: string;\n\tname: string;\n\tdescription: string;\n\tcommands: string[];\n\tdetect: () => boolean;\n\tinstall: () => Promise<void>;\n}\n\nexport const stacks: Stack[] = [cursorStack, claudeStack, codexStack];\n\nexport function findStack(id: string): Stack | undefined {\n\treturn stacks.find((s) => s.id === id);\n}\n","import type { Command, Help } from \"commander\";\nimport pc from \"picocolors\";\n\nfunction formatHeader(cmd: Command): string {\n\tconst desc = cmd.description();\n\tconst title = desc ? `${cmd.name()} — ${desc}` : cmd.name();\n\treturn pc.bold(pc.cyan(title));\n}\n\nfunction formatUsage(cmd: Command): string {\n\treturn [pc.bold(\"USAGE\"), ` $ ${cmd.name()} ${cmd.usage()}`].join(\"\\n\");\n}\n\nfunction formatCommands(cmd: Command, helper: Help): string | null {\n\tconst commands = helper.visibleCommands(cmd);\n\tif (commands.length === 0) return null;\n\n\tconst pad = Math.max(...commands.map((c) => c.name().length)) + 2;\n\tconst lines = commands.map(\n\t\t(sub) => ` ${pc.bold(sub.name().padEnd(pad))}${pc.dim(sub.description())}`,\n\t);\n\n\treturn [pc.bold(\"COMMANDS\"), ...lines].join(\"\\n\");\n}\n\nfunction formatOptions(cmd: Command, helper: Help): string | null {\n\tconst options = helper.visibleOptions(cmd);\n\tif (options.length === 0) return null;\n\n\tconst pad = Math.max(...options.map((o) => helper.optionTerm(o).length)) + 2;\n\tconst lines = options.map(\n\t\t(opt) =>\n\t\t\t` ${pc.yellow(helper.optionTerm(opt).padEnd(pad))}${pc.dim(opt.description)}`,\n\t);\n\n\treturn [pc.bold(\"OPTIONS\"), ...lines].join(\"\\n\");\n}\n\nexport function scalekitHelp() {\n\treturn {\n\t\tformatHelp(cmd: Command, helper: Help): string {\n\t\t\tconst sections = [\n\t\t\t\tformatHeader(cmd),\n\t\t\t\tformatUsage(cmd),\n\t\t\t\tformatCommands(cmd, helper),\n\t\t\t\tformatOptions(cmd, helper),\n\t\t\t].filter(Boolean);\n\n\t\t\treturn `${sections.join(\"\\n\\n\")}\\n`;\n\t\t},\n\t};\n}\n"],"mappings":"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","names":["Command","execFileSync","spawn","execFileSync","spawn","INSTALL_URL","INSTALL_CMD","ok","Command"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scalekit-inc/cli",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Scalekit CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -24,6 +24,7 @@
24
24
  },
25
25
  "license": "MIT",
26
26
  "dependencies": {
27
+ "@clack/prompts": "^1.4.0",
27
28
  "cfonts": "^3.3.1",
28
29
  "commander": "^14.0.3",
29
30
  "picocolors": "^1.1.1"