Skip to content

feat: add slash command passthrough with autocomplete UI#68

Merged
realDuang merged 10 commits intomainfrom
feat/slash-command-passthrough
Apr 1, 2026
Merged

feat: add slash command passthrough with autocomplete UI#68
realDuang merged 10 commits intomainfrom
feat/slash-command-passthrough

Conversation

@realDuang
Copy link
Copy Markdown
Owner

@realDuang realDuang commented Mar 25, 2026

Summary

Add end-to-end slash command support across all three engines (Claude Code, GitHub Copilot, OpenCode). Users can type / in the prompt input to see an autocomplete menu of available commands and skills, then invoke them directly through the engine's native command API.

Changes

Gateway Protocol

  • Add command.list and command.invoke request types to the WebSocket gateway
  • Add commands.changed push notification for real-time command list updates
  • Add EngineCommand, CommandInvokeResult, and related types to unified.ts

Engine Adapters

  • Claude Code: Warm up via sdkQuery.supportedCommands() at session creation to discover built-in commands and user-installed skills; inject skill names into system prompt; handle local_command_output and slash command text in stream processing
  • Copilot: Fetch skills via rpc.skills.list() at session creation; handle command.execute, commands.changed, and session.skills_loaded events
  • OpenCode: Invoke commands via commandAsync() REST API; fall back to sendMessage for SSE-based response handling

Frontend

  • PromptInput: Add slash command autocomplete dropdown with keyboard navigation (↑/↓/Tab/Enter/Esc), fuzzy filtering by name/description, and automatic /command insertion on selection
  • Chat.tsx: Fetch commands on engine switch, handle commands.changed notifications, add handleCommandInvoke for optimistic UI with error rollback
  • GatewayClient/API: Add listCommands() and invokeCommand() client methods

Engine Capabilities

  • Add slashCommands: boolean to EngineCapabilities so the frontend conditionally shows the autocomplete UI

i18n

  • Add noCommandsFound key to en/zh/ru locales

Future: Cron types (stubs only)

  • Add CronCreateRequest, CronJobInfo, and related types to unified.ts
  • Gateway client methods are stubbed with rejection until backend handlers are implemented

Test Plan

  • Unit tests pass (bun run test:unit — 416 passed)
  • Type check passes (npm run typecheck)
  • CI pipeline green (7/7 checks)

realDuang and others added 3 commits March 25, 2026 14:38
Implement transparent slash command invocation across all three engines
(Claude Code, GitHub Copilot, OpenCode), allowing users to type engine-
native commands directly in the chat input.

- Types: Add EngineCommand, CommandListRequest, CommandInvokeRequest,
  CommandInvokeResult to unified type system; extend EngineCapabilities
  with slashCommands flag; add COMMAND_LIST/COMMAND_INVOKE request types
  and COMMANDS_CHANGED notification type

- Engine adapters: Add listCommands() and invokeCommand() to base
  EngineAdapter with safe defaults; implement per-engine discovery and
  invocation (Claude via embedded text, Copilot via skills API, OpenCode
  via command REST API with sendMessage fallback)

- Gateway: Route COMMAND_LIST and COMMAND_INVOKE through EngineManager;
  broadcast commands.changed events to all clients

- Client API: Add listCommands() and invokeCommand() RPC methods to
  gateway-client and gateway-api layers

- Frontend: Add autocomplete dropdown to PromptInput triggered on '/'
  with keyboard navigation (ArrowUp/Down/Tab/Enter/Escape); add command
  state management to Chat.tsx with availableCommands signal, engine-
  change fetch, and handleCommandInvoke handler with optimistic UI

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Claude Code:
- Fix init message field: use `slash_commands: string[]` (correct SDK
  type) instead of `msg.commands` which doesn't exist
- Enrich command names with descriptions from well-known commands list
  since the init message only provides names without metadata
- Extract getWellKnownCommands() for reuse between init and fallback

GitHub Copilot:
- Add command.execute event handler that acknowledges commands via
  session.rpc.commands.handlePendingCommand() — required by the SDK
  protocol to unblock the CLI after command dispatch
- Add command.completed event handler (logging)
- Add commands.changed event handler to dynamically refresh the cached
  command list when the CLI updates available commands
- Document the command flow in invokeCommand() comments

OpenCode:
- Remove unnecessary `(client.session as any).command()` cast — the SDK
  v2 types already expose `session.command()` with full type safety
- Remove `cmd: any` cast in fetchCommands() since SDK types flow through

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Mar 25, 2026

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 20.65% (🎯 15%) 2246 / 10876
🔵 Statements 20.27% (🎯 15%) 2368 / 11679
🔵 Functions 21.08% (🎯 15%) 415 / 1968
🔵 Branches 17.43% (🎯 15%) 1132 / 6491
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
electron/main/engines/engine-adapter.ts 0% 0% 0% 0% 176-312
electron/main/engines/mock-adapter.ts 55.5% 47.94% 60.86% 56.41% 251-381, 390-435, 471-473, 482, 522, 592-607, 621, 652-653, 661, 669
electron/main/engines/claude/index.ts 0% 0% 0% 0% 107-2594
electron/main/engines/copilot/index.ts 0% 0% 0% 0% 93-1354
electron/main/engines/opencode/index.ts 0% 0% 0% 0% 60-1337
electron/main/gateway/engine-manager.ts 65.58% 50.71% 71.95% 68.21% 152, 159-163, 229, 250, 252, 263, 265, 283, 300, 319-323, 327, 375, 389, 406, 414-418, 449-453, 458, 472, 481, 483-526, 553-562, 566, 581, 620, 647-658, 696-700, 723-725, 747-754, 797, 808, 832, 882, 887, 895-899, 913, 916, 920, 971-1024, 1037, 1053, 1086, 1101, 1114-1120, 1181-1334
electron/main/gateway/ws-server.ts 0% 0% 0% 0% 52-639
src/lib/gateway-api.ts 3.5% 0% 0% 3.53% 72-472
src/lib/gateway-client.ts 7.57% 0% 0% 7.97% 127-616
src/locales/en.ts 0% 100% 100% 0% 601-1192
src/locales/ru.ts 0% 100% 100% 0% 3-599
src/locales/zh.ts 0% 100% 100% 0% 3-596
src/types/unified.ts 100% 100% 100% 100%
Generated in workflow #259 for commit a659c34 by the Vitest Coverage Report Action

realDuang and others added 3 commits March 25, 2026 20:30
Claude Code fixes:
- Handle local_command_output system messages so /help, /cost etc.
  actually display their output instead of silently dropping it
- Extract user-installed skills from init message's skills[] array
  alongside built-in slash_commands[]
- Improve listCommands() to check session state before falling back
  to the well-known commands list

Copilot fixes:
- Await fetchSkills() in createSession() instead of fire-and-forget,
  ensuring cachedCommands is populated before frontend requests
- Retry fetchSkills in listCommands() when cache is empty
- Add session.skills_loaded event handler for real-time skill updates
- Format handlePendingCommand() call correctly

Frontend (Chat.tsx):
- Pass sessionId to gateway.listCommands() so adapters can look up
  the correct engine session for command discovery
- Re-fetch commands when active session changes (not just engine type)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1. Claude /help and other slash commands producing no output:
   - Handle string content in handleAssistantMessage (SDK wraps
     slash command output as plain string, not content block array)
   - Handle text content in handleUserMessage (synthetic user messages
     from CLI with XML-stripped slash command output)
   - Use result.result text as fallback in handleResultMessage when
     buffer is empty (for local-jsx commands like /help)
   - Keep local_command_output handler for future-proofing

2. Claude skills not showing: Added debug logging to init message
   handler to trace slash_commands and skills arrays from SDK.

3. Copilot slash commands completely non-functional:
   - Root cause: listCommands called before engine session is active
     (lazy creation). activeSessions lookup returns undefined.
   - Fix: activate session via ensureActiveSession in listCommands
     when no active session found but directory is known.
   - Enhanced fetchSkills with comprehensive debug logging.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Use SDK's supportedCommands() API via sdkQuery for Claude warmup,
  replacing init-message parsing (gets full name + description)
- Trigger warmup in createSession() and await it in listCommands()
  so commands are available before user sends first message
- Inject cached user skill names into system prompt via append
- Pass directory from conversationStore to Copilot listCommands()
  so sessions can resume after app restart
- Create engine session eagerly in engine-manager createSession()
  instead of lazily on first sendMessage
- Track only engineType (not sessionId) in Chat.tsx createEffect
  to avoid re-fetching commands on every session switch

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@realDuang realDuang marked this pull request as ready for review March 26, 2026 12:00
Copilot AI review requested due to automatic review settings March 26, 2026 12:00
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-pass “slash command / skills” passthrough support end-to-end (types → gateway RPC → engine adapters → chat UI), plus some initial scaffolding for cron/scheduled tasks.

Changes:

  • Extend unified types + gateway protocol with command list/invoke request/notifications (and new slashCommands capability flag).
  • Add UI support for slash-command autocomplete in PromptInput and a command-invoke path in Chat.
  • Implement adapter-level command discovery/invocation for Copilot/Claude/OpenCode and wire gateway routing/broadcast.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
src/types/unified.ts Adds slashCommands capability, command/cron request+notification constants, and command/cron payload types.
src/pages/Chat.tsx Fetches/updates available commands per engine; adds onCommandInvoke path with optimistic message.
src/components/PromptInput.tsx Adds slash-command parsing, autocomplete dropdown, and routes /... sends to onCommandInvoke.
src/locales/en.ts Adds prompt.noCommandsFound key to locale schema and English strings.
src/locales/ru.ts Adds Russian string for noCommandsFound.
src/locales/zh.ts Adds Chinese string for noCommandsFound.
src/lib/gateway-client.ts Adds RPC helpers for command.* and cron.* request types; adds events for new notifications.
src/lib/gateway-api.ts Exposes listCommands / invokeCommand and binds commands.changed notification handler.
electron/main/gateway/ws-server.ts Routes command.list / command.invoke requests and broadcasts commands.changed.
electron/main/gateway/engine-manager.ts Eagerly creates engine session on conversation creation; adds list/invoke command APIs.
electron/main/engines/engine-adapter.ts Adds default listCommands / invokeCommand API surface + commands.changed event typing.
electron/main/engines/opencode/index.ts Adds OpenCode command listing and invocation stub.
electron/main/engines/mock-adapter.ts Sets slashCommands: false capability.
electron/main/engines/copilot/index.ts Adds skill discovery/caching and command event handling + invoke passthrough.
electron/main/engines/claude/index.ts Adds command warmup/listing + command passthrough; injects skill names into system prompt append.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread electron/main/engines/claude/index.ts Outdated
Comment thread electron/main/engines/opencode/index.ts Outdated
Comment thread src/lib/gateway-client.ts Outdated
Comment thread electron/main/engines/copilot/index.ts Outdated
Comment thread electron/main/engines/claude/index.ts Outdated
Comment thread src/components/PromptInput.tsx Outdated
Comment thread electron/main/gateway/engine-manager.ts Outdated
Comment thread electron/main/engines/copilot/index.ts Outdated
Comment thread electron/main/engines/claude/index.ts Outdated
@realDuang realDuang changed the title [WIP] slash command passthrough feat: slash command passthrough Mar 27, 2026
realDuang and others added 3 commits March 27, 2026 15:43
…ssthrough

# Conflicts:
#	electron/main/gateway/ws-server.ts
#	src/lib/gateway-api.ts
#	src/lib/gateway-client.ts
#	src/pages/Chat.tsx
#	src/types/unified.ts
- Downgrade verbose debug logs from info to debug level (Claude SDK messages,
  system messages, Copilot session events, fetchSkills)
- Remove JSON.stringify of full message payloads in logs to prevent leaking
  user data; log only type/subtype
- Fix OpenCode invokeCommand to return handledAsCommand:false so gateway
  falls back to sendMessage correctly
- Guard Cron RPC client methods with clear rejection until backend handlers
  are implemented
- Add zero-length guard for modulo in command menu keyboard navigation
  to prevent NaN
- Clean up orphaned conversation if engine session creation fails in
  EngineManager.createSession
- Reduce local_command_output logging to debug level, remove content preview

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@realDuang realDuang changed the title feat: slash command passthrough feat: add slash command passthrough with autocomplete UI Mar 31, 2026
@realDuang realDuang self-assigned this Mar 31, 2026
@realDuang realDuang added the enhancement New feature or request label Mar 31, 2026
…ee, file explorer, slash commands)

- Add 'Developer Workflow Tools' section to all 5 README languages
  - Scheduled Tasks (interval/daily/weekly automation)
  - Git Worktree Parallel Sessions (isolated branches with merge/squash/rebase)
  - File Explorer & Git Monitoring (real-time change tracking, inline diff)
  - Slash Commands & Engine Skills (unified autocomplete for all engines)
- Add Token usage tracking to 'And More' section
- Website: add 4 new feature cards, remove 'Modern Tech Stack' card
- Website: add i18n translations (en/zh) for new feature cards

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@realDuang realDuang merged commit 734564d into main Apr 1, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants