@salestouch/cli 0.1.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,492 @@
1
+ import { box, cancel, confirm, intro, isCancel, log, multiselect, note, password, select, spinner, } from "@clack/prompts";
2
+ import pc from "picocolors";
3
+ import { readFlagBoolean } from "./core.js";
4
+ import { detectCliLocale } from "./locale.js";
5
+ import { resolveSetupAgents } from "./setup.js";
6
+ const SETUP_TRIGGER_FLAGS = [
7
+ "claude",
8
+ "cursor",
9
+ "codex",
10
+ "opencode",
11
+ "global",
12
+ "mcp",
13
+ "cli",
14
+ "skills",
15
+ "no-skills",
16
+ "local-mcp",
17
+ "login",
18
+ "api-key",
19
+ "access-token",
20
+ ];
21
+ const SETUP_STEPS_TOTAL = 5;
22
+ const ORANGE_OPEN = "\u001B[38;5;208m";
23
+ const ORANGE_CLOSE = "\u001B[39m";
24
+ function isFrench(locale) {
25
+ return locale === "fr";
26
+ }
27
+ function getSetupCancelMessage(locale) {
28
+ return isFrench(locale) ? "Configuration SalesTouch annulée." : "SalesTouch setup cancelled.";
29
+ }
30
+ function accent(text) {
31
+ return process.stdout.isTTY ? `${ORANGE_OPEN}${text}${ORANGE_CLOSE}` : text;
32
+ }
33
+ function reorderAgents(recommendedAgent) {
34
+ const allAgents = ["claude", "cursor", "codex", "opencode"];
35
+ return [recommendedAgent, ...allAgents.filter((agent) => agent !== recommendedAgent)];
36
+ }
37
+ function formatAgentList(agents, locale = detectCliLocale()) {
38
+ const labels = agents.map((agent) => getAgentLabel(agent));
39
+ if (labels.length <= 1) {
40
+ return labels[0] ?? "";
41
+ }
42
+ if (labels.length === 2) {
43
+ return isFrench(locale) ? `${labels[0]} et ${labels[1]}` : `${labels[0]} and ${labels[1]}`;
44
+ }
45
+ const head = labels.slice(0, -1).join(", ");
46
+ const tail = labels[labels.length - 1];
47
+ return isFrench(locale) ? `${head} et ${tail}` : `${head}, and ${tail}`;
48
+ }
49
+ function getAgentLabel(agent) {
50
+ switch (agent) {
51
+ case "claude":
52
+ return "Claude";
53
+ case "cursor":
54
+ return "Cursor";
55
+ case "codex":
56
+ return "Codex";
57
+ case "opencode":
58
+ return "OpenCode";
59
+ }
60
+ }
61
+ function getModeLabel(mode, mcpTarget, locale = detectCliLocale()) {
62
+ if (mode === "cli") {
63
+ return "CLI";
64
+ }
65
+ if (isFrench(locale)) {
66
+ return mcpTarget === "remote" ? "MCP distant" : "MCP local";
67
+ }
68
+ return mcpTarget === "remote" ? "Remote MCP" : "Local MCP";
69
+ }
70
+ function getScopeLabel(scope, locale = detectCliLocale()) {
71
+ if (isFrench(locale)) {
72
+ return scope === "global" ? "Global" : "Projet";
73
+ }
74
+ return scope === "global" ? "Global" : "Project";
75
+ }
76
+ function getScopePitch(scope, locale = detectCliLocale()) {
77
+ if (isFrench(locale)) {
78
+ return scope === "global"
79
+ ? "Installez-le une fois et gardez SalesTouch prêt partout où vous travaillez."
80
+ : "Gardez-le dans ce repo pour que la configuration voyage avec le projet.";
81
+ }
82
+ return scope === "global"
83
+ ? "Set it once and keep SalesTouch ready wherever you work."
84
+ : "Keep it in this repo so the setup travels with the project.";
85
+ }
86
+ function getAuthChoiceLabel(authChoice, existingAuth, locale = detectCliLocale()) {
87
+ if (authChoice === "reuse") {
88
+ if (isFrench(locale)) {
89
+ return existingAuth?.authMethod === "api_key"
90
+ ? "Utiliser la clé API existante"
91
+ : "Utiliser la connexion existante";
92
+ }
93
+ return existingAuth?.authMethod === "api_key" ? "Use existing API key" : "Use existing login";
94
+ }
95
+ if (authChoice === "login") {
96
+ return isFrench(locale) ? "Se connecter dans le navigateur" : "Sign in with browser";
97
+ }
98
+ return isFrench(locale) ? "Clé API" : "API key";
99
+ }
100
+ function canUseApiKeyForSelection(agent, mode, mcpTarget) {
101
+ return !(agent === "codex" && mode === "mcp" && mcpTarget === "remote");
102
+ }
103
+ function getStepTitle(step, title, locale = detectCliLocale()) {
104
+ return `${isFrench(locale) ? "Étape" : "Step"} ${step}/${SETUP_STEPS_TOTAL} · ${title}`;
105
+ }
106
+ function getAgentPitch(agent, locale = detectCliLocale()) {
107
+ if (isFrench(locale)) {
108
+ switch (agent) {
109
+ case "claude":
110
+ return "L'expérience SalesTouch la plus fluide aujourd'hui si vous voulez vitesse, contexte et finition.";
111
+ case "cursor":
112
+ return "Un très bon choix quand votre prospection vit à côté du code, de la doc et de l'exécution.";
113
+ case "codex":
114
+ return "Idéal pour les agents IA natifs au repo et les workflows pilotés par AGENTS.";
115
+ case "opencode":
116
+ return "Un workflow plus léger et plus ouvert, avec SalesTouch branché directement dans la boucle.";
117
+ }
118
+ }
119
+ switch (agent) {
120
+ case "claude":
121
+ return "The smoothest SalesTouch experience today if you want speed, context and polish.";
122
+ case "cursor":
123
+ return "A strong fit when prospecting sits next to your code, docs and execution.";
124
+ case "codex":
125
+ return "Ideal for repo-native AI agents and AGENTS-driven workflows.";
126
+ case "opencode":
127
+ return "A lighter open workflow with SalesTouch plugged straight into the loop.";
128
+ }
129
+ }
130
+ function getAgentSelectionPitch(agents, locale = detectCliLocale()) {
131
+ if (agents.length <= 1) {
132
+ return getAgentPitch(agents[0] ?? "codex", locale);
133
+ }
134
+ return isFrench(locale)
135
+ ? `SalesTouch va s'installer en une passe dans ${formatAgentList(agents, locale)}.`
136
+ : `SalesTouch will install across ${formatAgentList(agents, locale)} in one pass.`;
137
+ }
138
+ function getModePitch(mode, mcpTarget, locale = detectCliLocale()) {
139
+ if (isFrench(locale)) {
140
+ if (mode === "cli") {
141
+ return "Recommandé. Rapide, fiable et simple à faire confiance. SalesTouch donne à votre agent IA les bonnes commandes et les bons garde-fous.";
142
+ }
143
+ return mcpTarget === "remote"
144
+ ? "Donnez à votre agent IA le contexte, les tools et les resources SalesTouch en direct, sans lancer de serveur local."
145
+ : "Gardez le MCP sur votre machine si vous voulez un fallback 100% local.";
146
+ }
147
+ if (mode === "cli") {
148
+ return "Recommended. Fast, reliable, and easy to trust. SalesTouch gives your AI agent the right commands and guardrails.";
149
+ }
150
+ return mcpTarget === "remote"
151
+ ? "Give your AI agent live SalesTouch context, tools and resources without running a local server."
152
+ : "Keep the MCP on your machine when you want a fully local fallback.";
153
+ }
154
+ function getSkillsChoiceLabel(installSkills, locale = detectCliLocale()) {
155
+ if (isFrench(locale)) {
156
+ return installSkills ? "Oui, installer les skills" : "Non, sans les skills";
157
+ }
158
+ return installSkills ? "Yes, install the skills" : "No, skip the skills";
159
+ }
160
+ function getSkillsPitch(installSkills, mode, locale = detectCliLocale()) {
161
+ if (isFrench(locale)) {
162
+ return installSkills
163
+ ? mode === "mcp"
164
+ ? "Les skills SalesTouch seront installés en plus de la config MCP pour mieux guider votre agent."
165
+ : "Les skills SalesTouch seront installés avec la config CLI pour mieux guider votre agent."
166
+ : "La configuration sera installée sans les skills. Vous pourrez les réinstaller plus tard avec `salestouch skills reinstall`.";
167
+ }
168
+ return installSkills
169
+ ? mode === "mcp"
170
+ ? "SalesTouch skills will be installed alongside the MCP config to guide your agent."
171
+ : "SalesTouch skills will be installed alongside the CLI setup to guide your agent."
172
+ : "The setup will be installed without skills. You can reinstall them later with `salestouch skills reinstall`.";
173
+ }
174
+ function getAuthPitch(authChoice, locale = detectCliLocale()) {
175
+ if (isFrench(locale)) {
176
+ switch (authChoice) {
177
+ case "reuse":
178
+ return "Repartez tout de suite avec ce qui est déjà configuré.";
179
+ case "login":
180
+ return "Connectez-vous une fois dans le navigateur, puis laissez SalesTouch prêt pour les prochaines sessions.";
181
+ case "api_key":
182
+ return "Le bon choix pour l'automatisation ou quand vous voulez garder un contrôle total sur les credentials.";
183
+ }
184
+ }
185
+ switch (authChoice) {
186
+ case "reuse":
187
+ return "Pick up where you left off and reuse what is already configured.";
188
+ case "login":
189
+ return "Connect once in the browser, then let SalesTouch stay ready for future sessions.";
190
+ case "api_key":
191
+ return "Best for automation or for setups where you want full credential control.";
192
+ }
193
+ }
194
+ function getBrandHeader(locale = detectCliLocale()) {
195
+ return `${pc.bold(accent("SalesTouch"))} ${pc.bold(accent(isFrench(locale) ? "Configuration" : "Setup"))}`;
196
+ }
197
+ export function shouldRunSetupWizard(flags, isInteractive) {
198
+ if (!isInteractive || readFlagBoolean(flags, "json")) {
199
+ return false;
200
+ }
201
+ return !SETUP_TRIGGER_FLAGS.some((flag) => flags[flag] !== undefined);
202
+ }
203
+ export function buildSetupWizardAuthChoices(params) {
204
+ const { agent, agents = agent ? [agent] : [], mode, mcpTarget, existingAuth, locale = detectCliLocale(), } = params;
205
+ const choices = [];
206
+ const supportsApiKey = agents.every((candidate) => canUseApiKeyForSelection(candidate, mode, mcpTarget));
207
+ const canReuseExistingAuth = existingAuth !== null &&
208
+ (existingAuth.authMethod === "session" || supportsApiKey);
209
+ if (canReuseExistingAuth) {
210
+ choices.push({
211
+ label: getAuthChoiceLabel("reuse", existingAuth, locale),
212
+ value: "reuse",
213
+ hint: isFrench(locale)
214
+ ? "Continuez avec les identifiants déjà stockés dans la config CLI ou dans l'env"
215
+ : "Keep going with the credentials already stored in the CLI config or env",
216
+ });
217
+ }
218
+ choices.push({
219
+ label: getAuthChoiceLabel("login", null, locale),
220
+ value: "login",
221
+ hint: isFrench(locale)
222
+ ? "Lancez une fois le flow de connexion SalesTouch et gardez la session prête"
223
+ : "Run the SalesTouch login flow once and keep the session ready",
224
+ });
225
+ if (supportsApiKey) {
226
+ choices.push({
227
+ label: isFrench(locale) ? "Coller une clé API" : "Paste an API key",
228
+ value: "api_key",
229
+ hint: isFrench(locale)
230
+ ? "Utilisez une clé API SalesTouch pour l'automatisation ou un setup non interactif"
231
+ : "Use a SalesTouch API key for automation or non-interactive setup",
232
+ });
233
+ }
234
+ return choices;
235
+ }
236
+ export function applySetupWizardSelections(flags, selections) {
237
+ const nextFlags = {
238
+ ...flags,
239
+ [selections.mode]: true,
240
+ };
241
+ for (const agent of selections.agents) {
242
+ nextFlags[agent] = true;
243
+ }
244
+ if (selections.scope === "global") {
245
+ nextFlags.global = true;
246
+ }
247
+ if (selections.mode === "mcp" && selections.mcpTarget === "local") {
248
+ nextFlags["local-mcp"] = true;
249
+ }
250
+ if (!selections.installSkills) {
251
+ nextFlags["no-skills"] = true;
252
+ }
253
+ if (selections.authChoice === "login") {
254
+ nextFlags.login = true;
255
+ }
256
+ else if (selections.authChoice === "api_key" && selections.apiKey) {
257
+ nextFlags["api-key"] = selections.apiKey;
258
+ }
259
+ return nextFlags;
260
+ }
261
+ function unwrapPromptResult(value) {
262
+ if (isCancel(value)) {
263
+ cancel(getSetupCancelMessage(detectCliLocale()));
264
+ return null;
265
+ }
266
+ return value;
267
+ }
268
+ async function promptChoice(question, choices, defaultIndex = 0, locale = detectCliLocale()) {
269
+ const options = choices.map((choice, index) => ({
270
+ value: choice.value,
271
+ label: index === defaultIndex
272
+ ? `${choice.label} ${pc.dim(isFrench(locale) ? "(recommandé)" : "(recommended)")}`
273
+ : choice.label,
274
+ hint: choice.hint,
275
+ }));
276
+ return unwrapPromptResult(await select({
277
+ message: question,
278
+ initialValue: choices[defaultIndex]?.value,
279
+ options,
280
+ }));
281
+ }
282
+ async function promptMultiChoice(question, choices, initialValues) {
283
+ const options = choices.map((choice) => ({
284
+ value: choice.value,
285
+ label: choice.label,
286
+ hint: choice.hint,
287
+ }));
288
+ return unwrapPromptResult(await multiselect({
289
+ message: question,
290
+ options,
291
+ initialValues,
292
+ required: true,
293
+ }));
294
+ }
295
+ async function promptApiKey(question, locale = detectCliLocale(), defaultValue = "st_") {
296
+ return unwrapPromptResult(await password({
297
+ message: question,
298
+ mask: "*",
299
+ validate(value) {
300
+ if (!value || !value.trim()) {
301
+ return isFrench(locale) ? "Valeur requise." : "Value required.";
302
+ }
303
+ if (!value.trim().startsWith(defaultValue)) {
304
+ return isFrench(locale)
305
+ ? "Les clés API SalesTouch commencent par `st_`."
306
+ : "SalesTouch API keys start with `st_`.";
307
+ }
308
+ return undefined;
309
+ },
310
+ }));
311
+ }
312
+ function buildWizardSummary(params) {
313
+ const { agents, mode, scope, mcpTarget, installSkills, authChoice, existingAuth, locale = detectCliLocale(), } = params;
314
+ return [
315
+ `${pc.bold(isFrench(locale) ? "Agents IA" : "AI agents")} ${formatAgentList(agents, locale)}`,
316
+ `${pc.bold(isFrench(locale) ? "Installation" : "Install in")} ${getScopeLabel(scope, locale)}`,
317
+ `${pc.bold(isFrench(locale) ? "Connexion" : "Connection")} ${getModeLabel(mode, mcpTarget, locale)}`,
318
+ `${pc.bold(isFrench(locale) ? "Skills" : "Skills")} ${getSkillsChoiceLabel(installSkills, locale)}`,
319
+ `${pc.bold(isFrench(locale) ? "Accès" : "Sign-in")} ${getAuthChoiceLabel(authChoice, existingAuth, locale)}`,
320
+ ].join("\n");
321
+ }
322
+ export async function runInteractiveSetupWizard(params) {
323
+ const locale = detectCliLocale();
324
+ intro(getBrandHeader(locale));
325
+ box([
326
+ isFrench(locale)
327
+ ? `${pc.bold("Transformez votre agent IA préféré en équipe de recherche personnelle pour une prospection plus juste.")}`
328
+ : `${pc.bold("Turn your favorite AI agent into a personal research team for better prospecting.")}`,
329
+ isFrench(locale)
330
+ ? "Quelques choix, et SalesTouch s'occupe de la config, de la rule et, si vous le voulez, du pack de skills."
331
+ : "A few choices, and SalesTouch takes care of the config, the rule, and optionally the skill pack.",
332
+ "",
333
+ `${pc.dim(isFrench(locale) ? "Contrôles" : "Controls")} ${isFrench(locale) ? "flèches pour naviguer · Entrée pour confirmer · Ctrl+C pour annuler" : "arrows to move · Enter to confirm · Ctrl+C to cancel"}`,
334
+ ].join("\n"), isFrench(locale) ? "Créez des relations, pas du spam." : "Build relationships, not spam.", {
335
+ rounded: true,
336
+ contentPadding: 1,
337
+ titleAlign: "left",
338
+ });
339
+ const scope = await promptChoice(getStepTitle(1, isFrench(locale) ? "Choisissez où l'installer" : "Choose where to install", locale), [
340
+ {
341
+ label: isFrench(locale) ? "Ce repo" : "This repo",
342
+ value: "project",
343
+ hint: isFrench(locale)
344
+ ? "Gardez la configuration SalesTouch au plus près du projet sur lequel vous travaillez"
345
+ : "Keep the SalesTouch setup close to the project you are working on",
346
+ },
347
+ {
348
+ label: isFrench(locale) ? "Toute votre machine" : "Your whole machine",
349
+ value: "global",
350
+ hint: isFrench(locale)
351
+ ? "Installez une fois dans votre config perso et réutilisez partout"
352
+ : "Install once in your home config and reuse it everywhere",
353
+ },
354
+ ], 0, locale);
355
+ if (!scope) {
356
+ return null;
357
+ }
358
+ log.step(getScopePitch(scope, locale));
359
+ const detectionSpinner = spinner();
360
+ detectionSpinner.start(isFrench(locale)
361
+ ? "Recherche d'agents IA déjà disponibles sur cette machine"
362
+ : "Looking for AI agents already available on this machine");
363
+ const detectedAgents = await resolveSetupAgents([], scope);
364
+ detectionSpinner.stop(detectedAgents.length > 0
365
+ ? `${isFrench(locale) ? "Détecté" : "Found"} ${detectedAgents.map((agent) => getAgentLabel(agent)).join(", ")}`
366
+ : isFrench(locale)
367
+ ? "Aucun agent détecté. Codex est le point de départ le plus sûr."
368
+ : "No agent detected. Codex is the safest starting point.");
369
+ const recommendedAgent = detectedAgents[0] ?? "codex";
370
+ const orderedAgents = reorderAgents(recommendedAgent);
371
+ if (detectedAgents.length > 0) {
372
+ note(isFrench(locale)
373
+ ? `${getAgentLabel(recommendedAgent)} a été détecté dans votre environnement ${scope === "global" ? "global" : "de projet"}.`
374
+ : `Detected ${getAgentLabel(recommendedAgent)} from your current ${scope === "global" ? "home" : "project"} environment.`, isFrench(locale) ? "Meilleur match" : "Best match");
375
+ }
376
+ const suggestedAgents = detectedAgents.length > 0 ? detectedAgents : [recommendedAgent];
377
+ const agents = await promptMultiChoice(getStepTitle(2, isFrench(locale) ? "Choisissez vos agents IA" : "Choose your AI agents", locale), orderedAgents.map((candidate) => ({
378
+ label: getAgentLabel(candidate),
379
+ value: candidate,
380
+ hint: detectedAgents.includes(candidate)
381
+ ? isFrench(locale)
382
+ ? "Détecté sur cette machine"
383
+ : "Detected on this machine"
384
+ : isFrench(locale)
385
+ ? "Supporté, mais non détecté ici"
386
+ : "Supported, but not detected here",
387
+ })), suggestedAgents);
388
+ if (!agents || agents.length === 0) {
389
+ return null;
390
+ }
391
+ log.step(getAgentSelectionPitch(agents, locale));
392
+ const setupType = await promptChoice(getStepTitle(3, isFrench(locale) ? "Choisissez le style de setup" : "Choose the setup style", locale), [
393
+ {
394
+ label: isFrench(locale) ? "Mode Copilote · CLI" : "Copilot mode · CLI",
395
+ value: { mode: "cli", mcpTarget: "remote" },
396
+ hint: isFrench(locale)
397
+ ? "Le meilleur défaut. Commandes fiables, bons garde-fous, presque zéro friction."
398
+ : "Best default. Reliable commands, strong guardrails, and almost zero friction.",
399
+ },
400
+ {
401
+ label: isFrench(locale) ? "Mode Live · MCP distant" : "Live mode · Remote MCP",
402
+ value: { mode: "mcp", mcpTarget: "remote" },
403
+ hint: isFrench(locale)
404
+ ? "Laissez votre agent IA parler directement au serveur MCP hébergé par SalesTouch."
405
+ : "Let your AI agent talk directly to the hosted SalesTouch MCP server.",
406
+ },
407
+ {
408
+ label: isFrench(locale) ? "Mode Manuel · MCP local" : "Hands-on mode · Local MCP",
409
+ value: { mode: "mcp", mcpTarget: "local" },
410
+ hint: isFrench(locale)
411
+ ? "Lancez `pnpm salestouch mcp serve` vous-même si vous voulez un fallback local."
412
+ : "Run `pnpm salestouch mcp serve` yourself when you want a local fallback.",
413
+ },
414
+ ], 0, locale);
415
+ if (!setupType) {
416
+ return null;
417
+ }
418
+ note(getModePitch(setupType.mode, setupType.mcpTarget, locale), isFrench(locale) ? "Style choisi" : "Selected style");
419
+ const installSkills = await promptChoice(getStepTitle(4, isFrench(locale) ? "Choisissez si vous voulez les skills" : "Choose whether to install skills", locale), [
420
+ {
421
+ label: getSkillsChoiceLabel(true, locale),
422
+ value: true,
423
+ hint: isFrench(locale)
424
+ ? "Recommandé. Ajoute le pack SalesTouch dans vos agents IA."
425
+ : "Recommended. Adds the SalesTouch skill pack to your AI agents.",
426
+ },
427
+ {
428
+ label: getSkillsChoiceLabel(false, locale),
429
+ value: false,
430
+ hint: isFrench(locale)
431
+ ? "Installe seulement la config et les rules. Vous pourrez remettre les skills plus tard."
432
+ : "Install only the config and rules. You can bring the skills back later.",
433
+ },
434
+ ], 0, locale);
435
+ if (installSkills === null) {
436
+ return null;
437
+ }
438
+ log.step(getSkillsPitch(installSkills, setupType.mode, locale));
439
+ const authChoices = buildSetupWizardAuthChoices({
440
+ agents,
441
+ mode: setupType.mode,
442
+ mcpTarget: setupType.mcpTarget,
443
+ existingAuth: params.existingAuth,
444
+ locale,
445
+ });
446
+ const defaultAuthIndex = authChoices.findIndex((choice) => choice.value === "reuse");
447
+ const authChoice = await promptChoice(getStepTitle(5, isFrench(locale) ? "Choisissez comment vous connecter" : "Choose how to connect", locale), authChoices, defaultAuthIndex >= 0 ? defaultAuthIndex : 0, locale);
448
+ if (!authChoice) {
449
+ return null;
450
+ }
451
+ log.step(getAuthPitch(authChoice, locale));
452
+ let apiKey = null;
453
+ if (authChoice === "api_key") {
454
+ apiKey = await promptApiKey(isFrench(locale) ? "Collez votre clé API SalesTouch" : "Paste your SalesTouch API key", locale);
455
+ if (!apiKey) {
456
+ return null;
457
+ }
458
+ }
459
+ note(buildWizardSummary({
460
+ agents,
461
+ mode: setupType.mode,
462
+ scope,
463
+ mcpTarget: setupType.mcpTarget,
464
+ installSkills,
465
+ authChoice,
466
+ existingAuth: params.existingAuth,
467
+ locale,
468
+ }), isFrench(locale) ? "Votre setup" : "Your setup");
469
+ const shouldContinue = unwrapPromptResult(await confirm({
470
+ message: isFrench(locale) ? "C'est le bon setup ?" : "Does this look right?",
471
+ initialValue: true,
472
+ active: isFrench(locale) ? "Installer" : "Install it",
473
+ inactive: isFrench(locale) ? "Annuler" : "Cancel",
474
+ vertical: true,
475
+ }));
476
+ if (shouldContinue !== true) {
477
+ cancel(getSetupCancelMessage(locale));
478
+ return null;
479
+ }
480
+ log.step(isFrench(locale)
481
+ ? `Connexion de SalesTouch à ${formatAgentList(agents, locale)}.`
482
+ : `Bringing SalesTouch into ${formatAgentList(agents, locale)}.`);
483
+ return {
484
+ agents,
485
+ mode: setupType.mode,
486
+ scope,
487
+ mcpTarget: setupType.mcpTarget,
488
+ installSkills,
489
+ authChoice,
490
+ apiKey,
491
+ };
492
+ }
@@ -0,0 +1,51 @@
1
+ export type SetupAgent = "claude" | "cursor" | "codex" | "opencode";
2
+ export type SetupMode = "mcp" | "cli";
3
+ export type SetupScope = "project" | "global";
4
+ export type SetupMcpTarget = "remote" | "local";
5
+ export type SetupAuthMode = "oauth" | "api_key" | "local";
6
+ export type SetupManifest = {
7
+ version: 1;
8
+ cli_version: string;
9
+ generated_at: string;
10
+ scope: SetupScope;
11
+ mode: SetupMode;
12
+ mcp_target: SetupMcpTarget | null;
13
+ auth_mode: SetupAuthMode | null;
14
+ install_skills: boolean;
15
+ base_url: string;
16
+ mcp_url: string | null;
17
+ agents: SetupAgent[];
18
+ };
19
+ export type SetupResult = {
20
+ agent: SetupAgent;
21
+ mode: SetupMode;
22
+ scope: SetupScope;
23
+ mcpConfigPath?: string;
24
+ rulePath: string;
25
+ skillPath?: string;
26
+ manifestPath: string;
27
+ };
28
+ export type SkillInstallResult = {
29
+ agent: SetupAgent;
30
+ mode: SetupMode;
31
+ scope: SetupScope;
32
+ skillPath: string;
33
+ };
34
+ export declare function resolveSetupAgents(requestedAgents: SetupAgent[], scope: SetupScope): Promise<SetupAgent[]>;
35
+ export declare function readSetupManifest(scope: SetupScope): Promise<SetupManifest | null>;
36
+ export declare function runSetup(options: {
37
+ agents: SetupAgent[];
38
+ mode: SetupMode;
39
+ scope: SetupScope;
40
+ mcpTarget: SetupMcpTarget;
41
+ authMode: SetupAuthMode;
42
+ installSkills?: boolean;
43
+ baseUrl: string;
44
+ mcpUrl: string;
45
+ apiKey: string | null;
46
+ }): Promise<SetupResult[]>;
47
+ export declare function runSkillsInstall(options: {
48
+ agents: SetupAgent[];
49
+ mode: SetupMode;
50
+ scope: SetupScope;
51
+ }): Promise<SkillInstallResult[]>;