diff --git a/src/cli/agent-help.ts b/src/cli/agent-help.ts index 49eea4d..b5abb12 100644 --- a/src/cli/agent-help.ts +++ b/src/cli/agent-help.ts @@ -13,6 +13,11 @@ import { pluginUninstallMeta, } from './metadata/plugin.js'; import { updateMeta } from './metadata/self.js'; +import { + skillsListMeta, + skillsAddMeta, + skillsRemoveMeta, +} from './metadata/plugin-skills.js'; const allCommands: AgentCommandMeta[] = [ initMeta, @@ -27,6 +32,9 @@ const allCommands: AgentCommandMeta[] = [ marketplaceBrowseMeta, pluginListMeta, pluginValidateMeta, + skillsListMeta, + skillsAddMeta, + skillsRemoveMeta, updateMeta, ]; diff --git a/src/cli/commands/plugin-skills.ts b/src/cli/commands/plugin-skills.ts index 4b1616d..caf4b9a 100644 --- a/src/cli/commands/plugin-skills.ts +++ b/src/cli/commands/plugin-skills.ts @@ -170,7 +170,7 @@ const listCmd = command({ const allSkills = [...userSkills, ...dedupedProjectSkills]; jsonOutput({ success: true, - command: 'plugin skills list', + command: 'skills list', data: { scope: effectiveScope, skills: allSkills.map((s) => ({ @@ -220,7 +220,7 @@ const listCmd = command({ } catch (error) { if (error instanceof Error) { if (isJsonMode()) { - jsonOutput({ success: false, command: 'plugin skills list', error: error.message }); + jsonOutput({ success: false, command: 'skills list', error: error.message }); process.exit(1); } console.error(`Error: ${error.message}`); @@ -266,7 +266,7 @@ const removeCmd = command({ const skillNames = [...new Set(allSkills.map((s) => s.name))].join(', '); const error = `Skill '${skill}' not found in any installed plugin.\n\nAvailable skills: ${skillNames || 'none'}`; if (isJsonMode()) { - jsonOutput({ success: false, command: 'plugin skills remove', error }); + jsonOutput({ success: false, command: 'skills remove', error }); process.exit(1); } console.error(`Error: ${error}`); @@ -282,9 +282,9 @@ const removeCmd = command({ if (matches.length > 1) { if (!plugin) { const pluginList = matches.map((m) => ` - ${m.pluginName} (${m.pluginSource})`).join('\n'); - const error = `'${skill}' exists in multiple plugins:\n${pluginList}\n\nUse --plugin to specify: allagents plugin skills remove ${skill} --plugin `; + const error = `'${skill}' exists in multiple plugins:\n${pluginList}\n\nUse --plugin to specify: allagents skills remove ${skill} --plugin `; if (isJsonMode()) { - jsonOutput({ success: false, command: 'plugin skills remove', error }); + jsonOutput({ success: false, command: 'skills remove', error }); process.exit(1); } console.error(`Error: ${error}`); @@ -294,7 +294,7 @@ const removeCmd = command({ if (!filtered) { const error = `Plugin '${plugin}' not found. Installed plugins: ${matches.map((m) => m.pluginName).join(', ')}`; if (isJsonMode()) { - jsonOutput({ success: false, command: 'plugin skills remove', error }); + jsonOutput({ success: false, command: 'skills remove', error }); process.exit(1); } console.error(`Error: ${error}`); @@ -307,7 +307,7 @@ const removeCmd = command({ if (targetSkill.disabled) { const msg = `Skill '${skill}' is already disabled.`; if (isJsonMode()) { - jsonOutput({ success: false, command: 'plugin skills remove', error: msg }); + jsonOutput({ success: false, command: 'skills remove', error: msg }); process.exit(1); } console.log(msg); @@ -322,7 +322,7 @@ const removeCmd = command({ if (!result.success) { if (isJsonMode()) { - jsonOutput({ success: false, command: 'plugin skills remove', error: result.error ?? 'Unknown error' }); + jsonOutput({ success: false, command: 'skills remove', error: result.error ?? 'Unknown error' }); process.exit(1); } console.error(`Error: ${result.error}`); @@ -340,7 +340,7 @@ const removeCmd = command({ if (isJsonMode()) { jsonOutput({ success: syncResult.success, - command: 'plugin skills remove', + command: 'skills remove', data: { skill, plugin: targetSkill.pluginName, @@ -358,7 +358,7 @@ const removeCmd = command({ } catch (error) { if (error instanceof Error) { if (isJsonMode()) { - jsonOutput({ success: false, command: 'plugin skills remove', error: error.message }); + jsonOutput({ success: false, command: 'skills remove', error: error.message }); process.exit(1); } console.error(`Error: ${error.message}`); @@ -922,7 +922,7 @@ const addCmd = command({ if (skillArg) { const error = 'Cannot combine a skill argument with --list. Use --list alone to discover available skills.'; if (isJsonMode()) { - jsonOutput({ success: false, command: 'plugin skills add', error }); + jsonOutput({ success: false, command: 'skills add', error }); process.exit(1); } console.error(`Error: ${error}`); @@ -931,7 +931,7 @@ const addCmd = command({ if (!fromArg) { const error = '--list requires --from to specify a plugin source.'; if (isJsonMode()) { - jsonOutput({ success: false, command: 'plugin skills add', error }); + jsonOutput({ success: false, command: 'skills add', error }); process.exit(1); } console.error(`Error: ${error}`); @@ -940,7 +940,7 @@ const addCmd = command({ if (all) { const error = '--list and --all cannot be used together.'; if (isJsonMode()) { - jsonOutput({ success: false, command: 'plugin skills add', error }); + jsonOutput({ success: false, command: 'skills add', error }); process.exit(1); } console.error(`Error: ${error}`); @@ -950,7 +950,7 @@ const addCmd = command({ const discovered = await discoverSkillsFromSource(fromArg); if (!discovered.success) { if (isJsonMode()) { - jsonOutput({ success: false, command: 'plugin skills add', error: discovered.error }); + jsonOutput({ success: false, command: 'skills add', error: discovered.error }); process.exit(1); } console.error(`Error: ${discovered.error}`); @@ -960,7 +960,7 @@ const addCmd = command({ if (isJsonMode()) { jsonOutput({ success: true, - command: 'plugin skills add', + command: 'skills add', data: { source: fromArg, isMarketplace: discovered.isMarketplace, @@ -994,7 +994,7 @@ const addCmd = command({ if (!fromArg) { const error = '--all requires --from to specify a plugin source.'; if (isJsonMode()) { - jsonOutput({ success: false, command: 'plugin skills add', error }); + jsonOutput({ success: false, command: 'skills add', error }); process.exit(1); } console.error(`Error: ${error}`); @@ -1003,7 +1003,7 @@ const addCmd = command({ if (skillArg) { const error = 'Cannot combine a skill argument with --all. Use --all alone to install every skill.'; if (isJsonMode()) { - jsonOutput({ success: false, command: 'plugin skills add', error }); + jsonOutput({ success: false, command: 'skills add', error }); process.exit(1); } console.error(`Error: ${error}`); @@ -1021,7 +1021,7 @@ const addCmd = command({ if (!installResult.success) { if (isJsonMode()) { - jsonOutput({ success: false, command: 'plugin skills add', error: installResult.error }); + jsonOutput({ success: false, command: 'skills add', error: installResult.error }); process.exit(1); } console.error(`Error: ${installResult.error}`); @@ -1031,7 +1031,7 @@ const addCmd = command({ if (isJsonMode()) { jsonOutput({ success: true, - command: 'plugin skills add', + command: 'skills add', data: { source: fromArg, installed: installResult.installed, @@ -1061,7 +1061,7 @@ const addCmd = command({ if (!skillArg) { const error = 'A skill name is required. Use --list to discover available skills or --all to install everything.'; if (isJsonMode()) { - jsonOutput({ success: false, command: 'plugin skills add', error }); + jsonOutput({ success: false, command: 'skills add', error }); process.exit(1); } console.error(`Error: ${error}`); @@ -1078,7 +1078,7 @@ const addCmd = command({ const error = 'Cannot use --from when the skill argument is a GitHub URL. The URL is used as the plugin source automatically.'; if (isJsonMode()) { - jsonOutput({ success: false, command: 'plugin skills add', error }); + jsonOutput({ success: false, command: 'skills add', error }); process.exit(1); } console.error(`Error: ${error}`); @@ -1114,7 +1114,7 @@ const addCmd = command({ if (!installFromResult.success) { if (isJsonMode()) { - jsonOutput({ success: false, command: 'plugin skills add', error: installFromResult.error }); + jsonOutput({ success: false, command: 'skills add', error: installFromResult.error }); process.exit(1); } console.error(`Error: ${installFromResult.error}`); @@ -1124,7 +1124,7 @@ const addCmd = command({ if (isJsonMode()) { jsonOutput({ success: true, - command: 'plugin skills add', + command: 'skills add', data: { skill, plugin: installFromResult.pluginName, @@ -1142,7 +1142,7 @@ const addCmd = command({ const skillNames = [...new Set(allSkills.map((s) => s.name))].join(', '); const error = `Skill '${skill}' not found in any installed plugin.\n\nAvailable skills: ${skillNames || 'none'}`; if (isJsonMode()) { - jsonOutput({ success: false, command: 'plugin skills add', error }); + jsonOutput({ success: false, command: 'skills add', error }); process.exit(1); } console.error(`Error: ${error}`); @@ -1158,9 +1158,9 @@ const addCmd = command({ if (matches.length > 1) { if (!plugin) { const pluginList = matches.map((m) => ` - ${m.pluginName} (${m.pluginSource})`).join('\n'); - const error = `'${skill}' exists in multiple plugins:\n${pluginList}\n\nUse --plugin to specify: allagents plugin skills add ${skill} --plugin `; + const error = `'${skill}' exists in multiple plugins:\n${pluginList}\n\nUse --plugin to specify: allagents skills add ${skill} --plugin `; if (isJsonMode()) { - jsonOutput({ success: false, command: 'plugin skills add', error }); + jsonOutput({ success: false, command: 'skills add', error }); process.exit(1); } console.error(`Error: ${error}`); @@ -1170,7 +1170,7 @@ const addCmd = command({ if (!filtered) { const error = `Plugin '${plugin}' not found. Installed plugins: ${matches.map((m) => m.pluginName).join(', ')}`; if (isJsonMode()) { - jsonOutput({ success: false, command: 'plugin skills add', error }); + jsonOutput({ success: false, command: 'skills add', error }); process.exit(1); } console.error(`Error: ${error}`); @@ -1183,7 +1183,7 @@ const addCmd = command({ if (!targetSkill.disabled) { const msg = `Skill '${skill}' is already enabled.`; if (isJsonMode()) { - jsonOutput({ success: false, command: 'plugin skills add', error: msg }); + jsonOutput({ success: false, command: 'skills add', error: msg }); process.exit(1); } console.log(msg); @@ -1198,7 +1198,7 @@ const addCmd = command({ if (!result.success) { if (isJsonMode()) { - jsonOutput({ success: false, command: 'plugin skills add', error: result.error ?? 'Unknown error' }); + jsonOutput({ success: false, command: 'skills add', error: result.error ?? 'Unknown error' }); process.exit(1); } console.error(`Error: ${result.error}`); @@ -1216,7 +1216,7 @@ const addCmd = command({ if (isJsonMode()) { jsonOutput({ success: syncResult.success, - command: 'plugin skills add', + command: 'skills add', data: { skill, plugin: targetSkill.pluginName, @@ -1234,7 +1234,7 @@ const addCmd = command({ } catch (error) { if (error instanceof Error) { if (isJsonMode()) { - jsonOutput({ success: false, command: 'plugin skills add', error: error.message }); + jsonOutput({ success: false, command: 'skills add', error: error.message }); process.exit(1); } console.error(`Error: ${error.message}`); diff --git a/src/cli/metadata/plugin-skills.ts b/src/cli/metadata/plugin-skills.ts index e5658d0..cf8ec42 100644 --- a/src/cli/metadata/plugin-skills.ts +++ b/src/cli/metadata/plugin-skills.ts @@ -1,12 +1,12 @@ import type { AgentCommandMeta } from '../help.js'; export const skillsListMeta: AgentCommandMeta = { - command: 'plugin skills list', + command: 'skills list', description: 'List all skills from installed plugins', whenToUse: 'To see available skills and their enabled/disabled status', examples: [ - 'allagents plugin skills list', - 'allagents plugin skills list --scope user', + 'allagents skills list', + 'allagents skills list --scope user', ], expectedOutput: 'Lists skills grouped by plugin with enabled/disabled status', options: [ @@ -18,13 +18,13 @@ export const skillsListMeta: AgentCommandMeta = { }; export const skillsRemoveMeta: AgentCommandMeta = { - command: 'plugin skills remove', + command: 'skills remove', description: 'Disable a skill (exclude from sync)', whenToUse: 'To prevent a specific skill from being synced to your workspace', examples: [ - 'allagents plugin skills remove brainstorming', - 'allagents plugin skills remove brainstorming --plugin superpowers', - 'allagents plugin skills remove brainstorming --scope user', + 'allagents skills remove brainstorming', + 'allagents skills remove brainstorming --plugin superpowers', + 'allagents skills remove brainstorming --scope user', ], expectedOutput: 'Confirms skill was disabled and runs sync', positionals: [ @@ -42,7 +42,7 @@ export const skillsRemoveMeta: AgentCommandMeta = { }; export const skillsAddMeta: AgentCommandMeta = { - command: 'plugin skills add', + command: 'skills add', description: 'Add a skill from a plugin, or re-enable a previously disabled skill', whenToUse: 'To add a skill from a GitHub repo or marketplace plugin, or to re-enable a skill that was previously disabled', diff --git a/tests/unit/cli/agent-help.test.ts b/tests/unit/cli/agent-help.test.ts index 3737874..c2c7dea 100644 --- a/tests/unit/cli/agent-help.test.ts +++ b/tests/unit/cli/agent-help.test.ts @@ -13,6 +13,11 @@ import { pluginUninstallMeta, } from '../../../src/cli/metadata/plugin.js'; import { updateMeta } from '../../../src/cli/metadata/self.js'; +import { + skillsListMeta, + skillsAddMeta, + skillsRemoveMeta, +} from '../../../src/cli/metadata/plugin-skills.js'; import type { AgentCommandMeta } from '../../../src/cli/help.js'; const allCommands: AgentCommandMeta[] = [ @@ -28,6 +33,9 @@ const allCommands: AgentCommandMeta[] = [ marketplaceBrowseMeta, pluginListMeta, pluginValidateMeta, + skillsListMeta, + skillsAddMeta, + skillsRemoveMeta, updateMeta, ]; @@ -58,8 +66,8 @@ describe('extractAgentHelpFlag', () => { }); describe('agent command metadata', () => { - test('contains exactly 13 commands', () => { - expect(allCommands.length).toBe(13); + test('contains exactly 16 commands', () => { + expect(allCommands.length).toBe(16); }); test('all expected commands are present', () => { @@ -75,6 +83,9 @@ describe('agent command metadata', () => { 'plugin uninstall', 'plugin validate', 'self update', + 'skills add', + 'skills list', + 'skills remove', 'update', 'workspace init', 'workspace status',