← Back to PRs

#20900: fix(tui): surface plugin commands in autocomplete via hello-ok snapshot

by jyrkihuhta open 2026-02-19 12:02 View on GitHub →
app: macos app: web-ui gateway size: XS
## Summary - Plugin commands registered via `api.registerCommand()` never appear in TUI autocomplete because plugins load in the gateway process, not the TUI process — `listPluginCommands()` always returns empty in the TUI - Adds `pluginCommands` (optional `{name, description}[]`) to the `SnapshotSchema` sent in the hello-ok handshake - Gateway populates the field from `listPluginCommands()` when building the snapshot - TUI reads `client.hello.snapshot.pluginCommands` and refreshes autocomplete on connect ## Files changed | File | Change | |------|--------| | `src/gateway/protocol/schema/snapshot.ts` | Add `pluginCommands` optional array to `SnapshotSchema` | | `src/gateway/server/health-state.ts` | Populate `pluginCommands` in `buildGatewaySnapshot()` | | `src/tui/commands.ts` | Accept `pluginCommands` in `SlashCommandOptions`, append to command list | | `src/tui/tui.ts` | Pass snapshot plugin commands to autocomplete, refresh on connect | ## Test plan - [x] `pnpm vitest run src/tui/` — 14 files, 101 tests pass - [x] `pnpm vitest run src/gateway/` — 45 files, 440 tests pass (6 pre-existing failures from missing `https-proxy-agent`) - [x] Deployed to production gateway with a custom plugin (`/reflexes`), confirmed autocomplete works in TUI after connect ## AI disclosure This PR was AI-assisted (Claude). The code has been tested locally and deployed to a production instance. I understand what the code does and have verified the fix end-to-end. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- greptile_comment --> <h3>Greptile Summary</h3> Plugin commands registered via `api.registerCommand()` in plugins now correctly appear in TUI autocomplete. The fix addresses the issue where plugins load in the gateway process but the TUI runs in a separate process, so `listPluginCommands()` always returned empty in the TUI. The implementation adds an optional `pluginCommands` field to the `SnapshotSchema` (sent in the hello-ok handshake), populates it from `listPluginCommands()` in the gateway's `buildGatewaySnapshot()`, and reads it in the TUI to refresh autocomplete on connect. - `src/gateway/protocol/schema/snapshot.ts:70-77` - adds optional `pluginCommands` array with `name` and `description` fields to the snapshot schema - `src/gateway/server/health-state.ts:7,46` - imports and calls `listPluginCommands()` to populate snapshot field - `src/tui/commands.ts:21,139-144` - accepts `pluginCommands` in options, appends to command list with deduplication - `src/tui/tui.ts:396,782` - passes snapshot plugin commands to autocomplete and refreshes on connect <h3>Confidence Score: 5/5</h3> - This PR is safe to merge with minimal risk - The implementation is clean, well-structured, and follows TypeScript best practices. The changes are minimal and scoped to the specific issue. The optional field addition to the schema maintains backward compatibility. The code properly handles null/undefined cases with optional chaining and nullish coalescing. All tests pass (101 TUI tests, 440 gateway tests), and the author verified the fix end-to-end in production with a custom plugin. - No files require special attention <sub>Last reviewed commit: ef65166</sub> <!-- greptile_other_comments_section --> <sub>(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!</sub> <!-- /greptile_comment -->

Most Similar PRs