diff --git a/apps/skillkit/src/cli.ts b/apps/skillkit/src/cli.ts index b0cfface..2e317931 100644 --- a/apps/skillkit/src/cli.ts +++ b/apps/skillkit/src/cli.ts @@ -3,6 +3,8 @@ import { readFileSync } from 'node:fs'; import { fileURLToPath } from 'node:url'; import { dirname, join } from 'node:path'; import { Cli, Builtins } from 'clipanion'; +import { setVersion, setAgentCount } from '@skillkit/cli'; +import { getAdapterCount } from '@skillkit/agents'; import { InstallCommand, SyncCommand, @@ -130,6 +132,9 @@ const packageJsonPath = join(__dirname, '../package.json'); const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8')); const version = packageJson.version || '1.2.0'; +setVersion(version); +setAgentCount(getAdapterCount()); + const cli = new Cli({ binaryLabel: 'skillkit', binaryName: 'skillkit', diff --git a/packages/agents/src/index.ts b/packages/agents/src/index.ts index c36169b6..fcf1879e 100644 --- a/packages/agents/src/index.ts +++ b/packages/agents/src/index.ts @@ -107,6 +107,10 @@ export function getAllAdapters(): AgentAdapterWithType[] { })); } +export function getAdapterCount(): number { + return Object.keys(adapters).length; +} + export async function detectAgent(): Promise { const checkOrder: AgentType[] = [ 'claude-code', diff --git a/packages/cli/src/commands/install.ts b/packages/cli/src/commands/install.ts index 9aadb42a..594477c2 100644 --- a/packages/cli/src/commands/install.ts +++ b/packages/cli/src/commands/install.ts @@ -40,7 +40,7 @@ import { isCancel, spinner, quickAgentSelect, - skillMultiselect, + quickSkillSelect, selectInstallMethod, confirm, outro, @@ -273,13 +273,10 @@ export class InstallCommand extends Command { } else if (this.all || this.yes) { skillsToInstall = discoveredSkills; } else if (isInteractive && discoveredSkills.length > 1) { - // Interactive skill selection step(`Source: ${colors.cyan(this.source)}`); - const skillResult = await skillMultiselect({ - message: "Select skills to install", + const skillResult = await quickSkillSelect({ skills: discoveredSkills.map((s) => ({ name: s.name })), - initialValues: discoveredSkills.map((s) => s.name), }); if (isCancel(skillResult)) { @@ -287,8 +284,9 @@ export class InstallCommand extends Command { return 0; } + const selected = (skillResult as { skills: string[] }).skills; skillsToInstall = discoveredSkills.filter((s) => - (skillResult as string[]).includes(s.name), + selected.includes(s.name), ); } diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 306d7c52..7639007e 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -4,5 +4,8 @@ export * from './commands/index.js'; // Export helper functions export * from './helpers.js'; +// Export onboarding utilities +export { setVersion, setAgentCount } from './onboarding/index.js'; + // Re-export commonly used types from core export type { AgentType, Skill, SkillMetadata, SkillkitConfig } from '@skillkit/core'; diff --git a/packages/cli/src/onboarding/index.ts b/packages/cli/src/onboarding/index.ts index 9139ec9c..79158e4c 100644 --- a/packages/cli/src/onboarding/index.ts +++ b/packages/cli/src/onboarding/index.ts @@ -42,6 +42,7 @@ export { select, agentMultiselect, quickAgentSelect, + quickSkillSelect, skillMultiselect, groupMultiselect, stepTrail, @@ -87,8 +88,8 @@ import { getLastAgents, } from './preferences.js'; -let VERSION = '1.7.6'; -let AGENT_COUNT = 44; +let VERSION = 'dev'; +let AGENT_COUNT = 0; export function setVersion(version: string): void { VERSION = version; @@ -161,18 +162,22 @@ export async function runInstallFlow(options: InstallFlowOptions): Promise s.name); - const skillResult = await prompts.skillMultiselect({ - message: 'Select skills to install', - skills: discoveredSkills.map(s => ({ name: s.name })), - initialValues: skillNames, - }); + let selectedSkills: string[]; - if (prompts.isCancel(skillResult)) { - prompts.cancel('Installation cancelled'); - return { selectedSkills: [], selectedAgents: [], installMethod: 'symlink', cancelled: true }; + if (discoveredSkills.length > 1) { + const skillResult = await prompts.quickSkillSelect({ + skills: discoveredSkills.map(s => ({ name: s.name })), + }); + + if (prompts.isCancel(skillResult)) { + prompts.cancel('Installation cancelled'); + return { selectedSkills: [], selectedAgents: [], installMethod: 'symlink', cancelled: true }; + } + + selectedSkills = (skillResult as { skills: string[] }).skills; + } else { + selectedSkills = discoveredSkills.map(s => s.name); } if (detectedAgents.length > 1) { @@ -190,7 +195,7 @@ export async function runInstallFlow(options: InstallFlowOptions): Promise { + const { skills } = options; + + const result = await clack.select({ + message: options.message || `Found ${skills.length} skills — how would you like to install?`, + options: [ + { value: 'all' as const, label: 'Install all skills', hint: `${skills.length} skills` }, + { value: 'select' as const, label: 'Select specific skills', hint: 'Choose manually' }, + ], + }); + + if (clack.isCancel(result)) { + return result; + } + + const method = result as 'all' | 'select'; + + if (method === 'all') { + return { skills: skills.map(s => s.name), method }; + } + + const selected = await skillMultiselect({ + message: 'Select skills to install', + skills, + initialValues: [], + }); + + if (clack.isCancel(selected)) { + return selected; + } + + return { skills: selected as string[], method }; +} + export async function groupMultiselect(options: { message: string; options: Record>;