diff --git a/apps/desktop/src/lib/desktop-slash-commands.test.ts b/apps/desktop/src/lib/desktop-slash-commands.test.ts index efb16453479a5..b2684e58fd0c1 100644 --- a/apps/desktop/src/lib/desktop-slash-commands.test.ts +++ b/apps/desktop/src/lib/desktop-slash-commands.test.ts @@ -35,7 +35,6 @@ describe('desktop slash command curation', () => { expect(isDesktopSlashSuggestion('/redraw')).toBe(false) expect(isDesktopSlashSuggestion('/approve')).toBe(false) expect(isDesktopSlashSuggestion('/model')).toBe(false) - expect(isDesktopSlashSuggestion('/skills')).toBe(false) expect(isDesktopSlashSuggestion('/voice')).toBe(false) expect(isDesktopSlashSuggestion('/curator')).toBe(false) }) @@ -131,6 +130,7 @@ describe('desktop slash command curation', () => { '/queue', '/retry', '/rollback', + '/skills', '/tools', '/undo', '/version' @@ -161,6 +161,16 @@ describe('desktop slash command curation', () => { expect(desktopSlashUnavailableMessage('/journey')).toBeNull() }) + it('exposes /skills on the desktop with exec surface for pending/approve/reject/diff/approval subcommands', () => { + expect(resolveDesktopCommand('/skills')?.surface).toEqual({ kind: 'exec' }) + expect(isDesktopSlashCommand('/skills')).toBe(true) + expect(isDesktopSlashSuggestion('/skills')).toBe(true) + expect(desktopSlashUnavailableMessage('/skills')).toBeNull() + // args:true keeps typed subcommands (pending, approve, reject, diff, approval) + // from being committed as a sealed directive chip. + expect(resolveDesktopCommand('/skills')?.args).toBe(true) + }) + it('allows aliases to execute without cluttering the popover', () => { expect(isDesktopSlashSuggestion('/reset')).toBe(false) expect(isDesktopSlashCommand('/reset')).toBe(true) @@ -254,8 +264,8 @@ describe('desktop slash command curation', () => { it('explains known commands that desktop owns elsewhere', () => { expect(desktopSlashUnavailableMessage('/model sonnet')).toContain('model picker') - expect(desktopSlashUnavailableMessage('/skills')).toContain('desktop sidebar') expect(desktopSlashUnavailableMessage('/clear')).toContain('terminal interface') + expect(desktopSlashUnavailableMessage('/pets')).toContain('desktop sidebar') }) it('flags /model as a picker-owned command so the desktop opens the overlay', () => { diff --git a/apps/desktop/src/lib/desktop-slash-commands.ts b/apps/desktop/src/lib/desktop-slash-commands.ts index 399479242f62b..04a7e5e2ab348 100644 --- a/apps/desktop/src/lib/desktop-slash-commands.ts +++ b/apps/desktop/src/lib/desktop-slash-commands.ts @@ -242,6 +242,12 @@ const DESKTOP_COMMAND_SPECS: readonly DesktopCommandSpec[] = [ { name: '/undo', description: 'Remove the last user/assistant exchange', surface: exec() }, { name: '/usage', description: 'Show token usage for this session', surface: exec() }, { name: '/version', description: 'Show Hermes Agent version', surface: exec() }, + { + name: '/skills', + description: 'Search, install, inspect, or manage skills (pending, approve, reject, diff, approval)', + surface: exec(), + args: true + }, // No desktop surface, but carry an alias (underscore spelling variants). { name: '/reload-mcp', aliases: ['/reload_mcp'], surface: unavailable('advanced') }, @@ -285,7 +291,7 @@ const NO_DESKTOP_SURFACE: Record = '/verbose' ], messaging: ['/approve', '/deny'], - settings: ['/skills', '/pets'], + settings: ['/pets'], advanced: ['/curator', '/fast', '/insights', '/kanban', '/reasoning', '/voice'] }