feat(tui): register /skills slash command to open Skills Hub

Intercept bare /skills locally and flip overlay.skillsHub, so the
overlay opens instantly without waiting on slash.exec. /skills <args>
still forwards to slash.exec and paginates any output. Tests cover
both branches.
This commit is contained in:
Brooklyn Nicholson 2026-04-18 09:29:39 -05:00
parent ef284e021a
commit 949b8f5521
2 changed files with 43 additions and 1 deletions

View file

@ -17,6 +17,26 @@ describe('createSlashHandler', () => {
expect(getOverlayState().picker).toBe(true)
})
it('opens the skills hub locally for bare /skills', () => {
const ctx = buildCtx()
expect(createSlashHandler(ctx)('/skills')).toBe(true)
expect(getOverlayState().skillsHub).toBe(true)
expect(ctx.gateway.rpc).not.toHaveBeenCalled()
expect(ctx.gateway.gw.request).not.toHaveBeenCalled()
})
it('falls through /skills with args to slash.exec without opening overlay', () => {
const ctx = buildCtx()
expect(createSlashHandler(ctx)('/skills install foo')).toBe(true)
expect(getOverlayState().skillsHub).toBe(false)
expect(ctx.gateway.rpc).toHaveBeenCalledWith('slash.exec', {
command: 'skills install foo',
session_id: null
})
})
it('cycles details mode and persists it', async () => {
const ctx = buildCtx()

View file

@ -1,7 +1,29 @@
import type { ToolsConfigureResponse } from '../../../gatewayTypes.js'
import type { SlashExecResponse, ToolsConfigureResponse } from '../../../gatewayTypes.js'
import { patchOverlayState } from '../../overlayStore.js'
import type { SlashCommand } from '../types.js'
export const opsCommands: SlashCommand[] = [
{
help: 'browse, inspect, and install skills',
name: 'skills',
run: (arg, ctx) => {
if (!arg.trim()) {
return patchOverlayState({ skillsHub: true })
}
ctx.gateway
.rpc<SlashExecResponse>('slash.exec', { command: `skills ${arg}`, session_id: ctx.sid })
.then(
ctx.guarded<SlashExecResponse>(r => {
if (r.output) {
ctx.transcript.page(r.output, 'Skills')
}
})
)
.catch(ctx.guardedErr)
}
},
{
help: 'enable or disable tools (client-side history reset on change)',
name: 'tools',