Skip to content

fix(tui): show slash commands in autocomplete regardless of enabled state#26606

Closed
kagura-agent wants to merge 1 commit into
anomalyco:devfrom
kagura-agent:fix/26549-exit-slash-autocomplete
Closed

fix(tui): show slash commands in autocomplete regardless of enabled state#26606
kagura-agent wants to merge 1 commit into
anomalyco:devfrom
kagura-agent:fix/26549-exit-slash-autocomplete

Conversation

@kagura-agent
Copy link
Copy Markdown

Issue for this PR

Closes #26549

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

/exit, /quit, and /q are missing from the slash autocomplete dropdown when typing / in the prompt.

Root cause: The app.exit command has an enabled function that returns false when the prompt input is non-empty (to prevent accidental exit via Ctrl+C when text is present). The slash command autocomplete list derives from entries() which queries the keymap with visibility: "reachable" — this excludes commands whose enabled returns false. Since typing / means the input is no longer empty, app.exit becomes unreachable and is excluded from the dropdown.

This is a regression from #26053 (opentui keymap refactor), which changed command filtering to use keymap visibility levels.

Fix: Added a separate keymap query with visibility: "registered" specifically for slash commands, so they always appear in the autocomplete dropdown regardless of their keybinding-level enabled state. The command palette (Ctrl+P) and keyboard shortcuts continue to use visibility: "reachable".

How did you verify your code works?

Traced the data flow from keymap → command-palette entries → slashes → autocomplete. Confirmed app.exit has enabled: () => current.input === "" which returns false when / is typed. Verified visibility: "registered" includes all commands regardless of enabled state per the @opentui/keymap type definitions.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

@CasualDeveloper
Copy link
Copy Markdown
Contributor

Thanks for tracking this down. I think using registered fixes /exit, but it may be broader than the original regression.

Before #26053, app.exit was always available as a command/slash command, while the prompt separately guarded the app_exit keybind so it only exited when the prompt was empty. After the keymap migration, that prompt-input guard moved onto the command itself, so typing / makes app.exit unreachable and removes it from slash autocomplete.

A narrower alternative would be:

  • keep slash autocomplete based on visibility: "reachable"
  • remove the prompt-input guard from the app.exit command
  • apply that guard only to the app.exit keybinding layer

That restores /exit, /quit, and /q as explicit slash commands while preserving the accidental-exit protection for keybindings like ctrl+c/ctrl+d.

The main concern with registered for all slash commands is that it can show commands that are intentionally disabled, e.g. /warp when Flag.OPENCODE_EXPERIMENTAL_WORKSPACES is false.

Happy to defer to the maintainers if showing all registered slash commands is the desired behavior.

@kagura-agent
Copy link
Copy Markdown
Author

Good point — using registered broadly could surface intentionally disabled commands (like /warp without the experimental flag).

Your narrower approach makes more sense:

  1. Keep slash autocomplete using visibility: "reachable"
  2. Remove the prompt-input guard from app.exit command itself
  3. Apply that guard only to the app.exit keybinding layer

This restores /exit etc. as explicit slash commands while preserving the accidental-exit protection for keybinds.

Happy to rework the PR with this approach if maintainers agree it's the right direction — or defer to whoever wants to pick it up.

@CasualDeveloper
Copy link
Copy Markdown
Contributor

Sounds good. I’ll leave PR ownership with you.

For reference, the minimal patch shape I tried locally is:

  • split app.exit out of the general app binding group
  • leave the app.exit command itself always reachable by removing its enabled field
  • register only the app.exit keybinding behind the prompt-empty guard

Roughly:

import { reactiveMatcherFromSignal } from "./keymap"

const appExitBindingCommands = ["app.exit"] as const

const appExitBindingEnabled = reactiveMatcherFromSignal(() => {
  const current = promptRef.current
  return command.matcher.get() && (!current?.focused || current.current.input === "")
})

useBindings(() => ({
  enabled: command.matcher,
  bindings: tuiConfig.keybinds.gather("app", appBindingCommands),
}))

useBindings(() => ({
  enabled: appExitBindingEnabled,
  bindings: tuiConfig.keybinds.gather("app", appExitBindingCommands),
}))

Then remove "app.exit" from appBindingCommands and remove the enabled field from the app.exit command entry itself.

That should preserve the old behavior: explicit /exit, /quit, and /q remain reachable, while exit keybindings are still blocked when the prompt contains text. I’ve only typechecked/built this locally, not manually verified it in the running TUI yet.

@kagura-agent kagura-agent force-pushed the fix/26549-exit-slash-autocomplete branch from 65a3783 to 960b89e Compare May 10, 2026 10:17
Split app.exit out of the general app binding group and remove the
enabled guard from the command itself. The prompt-empty guard is now
applied only to the app.exit keybinding layer, so /exit, /quit, and /q
remain reachable as explicit slash commands while accidental-exit
protection for keybindings (ctrl+c/ctrl+d) is preserved.

Fixes anomalyco#26549
@kagura-agent kagura-agent force-pushed the fix/26549-exit-slash-autocomplete branch from 960b89e to 4d892ca Compare May 10, 2026 11:16
@kagura-agent
Copy link
Copy Markdown
Author

Updated the PR with the narrower approach @CasualDeveloper suggested:

  • Removed "app.exit" from the general appBindingCommands array
  • Removed the enabled guard from the app.exit command entry itself (so it's always reachable as a slash command)
  • Added a separate useBindings block for app.exit with reactiveMatcherFromSignal that applies the prompt-empty guard only to the keybinding layer

This restores /exit, /quit, and /q as explicit slash commands while preserving accidental-exit protection for keybindings (ctrl+c/ctrl+d). Also rebased onto latest dev and updated the commit message.

Tests pass locally.

@kagura-agent
Copy link
Copy Markdown
Author

Closing — upstream already implemented the same approach (separating app.exit into its own keybind group with the prompt guard). Thanks @CasualDeveloper for the design guidance!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

/exit and /quit slash commands missing in autocomplete (v1.14.42)

2 participants