Problem
Remote clients (desktop apps, web UIs) connecting via Gateway WebSocket have no way to discover available slash commands and skills at runtime.
The Telegram plugin solves this by calling listSkillCommandsForAgents() + listNativeCommandSpecsForConfig() directly — it runs in-process and can read the workspace filesystem. A remote WebSocket client cannot do this.
Gateway currently exposes skills.status (installation/requirements report) and skills.bins, but neither returns the command-oriented view a client needs to build a / autocomplete menu.
Proposed solution
Add a commands.list RPC method to Gateway that returns the merged command list a client needs:
// Params
{ agentId?: string }
// Result
{
commands: Array<{
name: string // e.g. "help", "model", "github"
description: string
category: string // "session" | "options" | "management" | "tools" | "skill"
acceptsArgs?: boolean
args?: Array<{ name: string; required?: boolean; choices?: string[] }>
source: "native" | "skill" | "plugin"
}>
}
The implementation is straightforward — the building blocks already exist:
listNativeCommandSpecsForConfig() in src/auto-reply/commands-registry.ts — native commands
listSkillCommandsForAgents() in src/auto-reply/skill-commands.ts — workspace skills
getPluginCommandSpecs() in src/plugins/command-registry-state.ts — plugin commands
The new handler just calls these three, normalizes the output into a flat list, and returns it. Same pattern Telegram uses in registerTelegramNativeCommands() (extensions/telegram/src/bot-native-commands.ts:385), minus the Telegram-specific menu sync.
Why this matters
Without this RPC, every remote client must hardcode a stale command list and cannot show workspace skills at all. This is the only missing piece — the server-side discovery logic is already generic and tested.
Problem
Remote clients (desktop apps, web UIs) connecting via Gateway WebSocket have no way to discover available slash commands and skills at runtime.
The Telegram plugin solves this by calling
listSkillCommandsForAgents()+listNativeCommandSpecsForConfig()directly — it runs in-process and can read the workspace filesystem. A remote WebSocket client cannot do this.Gateway currently exposes
skills.status(installation/requirements report) andskills.bins, but neither returns the command-oriented view a client needs to build a/autocomplete menu.Proposed solution
Add a
commands.listRPC method to Gateway that returns the merged command list a client needs:The implementation is straightforward — the building blocks already exist:
listNativeCommandSpecsForConfig()insrc/auto-reply/commands-registry.ts— native commandslistSkillCommandsForAgents()insrc/auto-reply/skill-commands.ts— workspace skillsgetPluginCommandSpecs()insrc/plugins/command-registry-state.ts— plugin commandsThe new handler just calls these three, normalizes the output into a flat list, and returns it. Same pattern Telegram uses in
registerTelegramNativeCommands()(extensions/telegram/src/bot-native-commands.ts:385), minus the Telegram-specific menu sync.Why this matters
Without this RPC, every remote client must hardcode a stale command list and cannot show workspace skills at all. This is the only missing piece — the server-side discovery logic is already generic and tested.