fix(tui): `/skills` opens the Altimate skills browser, and its actions work
Issue for this PR
Closes #1328
Type of change
- Bug fix
What does this PR do?
Root cause was not the chord — it was which dialog /skills opened. Two commands registered slashName: "skills": the core prompt's prompt.skills (upstream's plain selector: Enter inserts /<skill>, no actions) and the Altimate plugin's altimate.skill.list. Autocomplete listed two /skills rows and Enter took the first, so users landed in the plain selector — which is exactly what the issue describes ("Enter inserts /<skill>", "ctrl+a does nothing"). The browser with Actions / New / Install was only reachable via <leader>k.
Changes:
- The core
prompt.skillskeeps its palette entry and loses its slash name; the Altimate browser owns/skills. - Enter uses the skill — inserts
/<skill>into the prompt viaapi.prompt.active(), as the docs say and the core selector did. The action picker isctrl+aand the Actions footer button. - Actions / New / Install are
DialogSelectactions with in-dialog bindings (ctrl+a/ctrl+e/ctrl+i) instead of a plugin-level keymap layer that the open dialog outranks (the model dialog bindsctrl+athe same way). They render as Tab-reachable footer buttons, so the picker no longer depends on a chord. New isctrl+ebecausectrl+nis every dialog's "next". The dialog actions have their own command names so the footer labels show the chords that actually work there. - Plugin
DialogSelectAPI gainsactionsandbindings, forwarded by the adapter. - Latent upstream bug fixed:
DialogSelectevaluated its action list eagerly, beforeselectedwas declared, so a function-valueddisabled(needed to keep the synthetic Install row out of the picker) threwCannot access 'selected' before initialization. Every existing caller passed a boolean, which never touchedselected. Evaluated lazily now. - Docs table updated (
ctrl+efor New, Tab for the footer buttons,/skillsopens the browser).
How did you verify your code works?
- vhs on a local build (
Set Width 1200 / Height 800, configured home): before — after/skills,Down,Ctrl+Athe frame is the unchanged plain selector. After — the footer readsActions ctrl+a · New ctrl+e · Install ctrl+i, andDown+Ctrl+AopensActions: dbt-pr-review(Show details / Test for a built-in).Enteron a row leaves/dbt-pr-reviewin the prompt at 0.7 s, 1.5 s and 3 s — no auto-submit. - New
packages/tui/test/ui/dialog-select-actions.test.tsx: mounts a realDialogSelectin the provider stack and presses keys —ctrl+afires the action for the highlighted row; follows the highlight afterDown;ctrl+efires the second action; no binding → nothing fires; the same with the plugin's global layer registering the same command name; the footer renders the buttons with their chords; and the function-valueddisabledcase that crashed before the lazy fix. packages/tui:test/ui,test/keymap,test/plugin,test/cli/tui— 84 pass.packages/opencode:test/altimate/plugin,test/cli/skill,test/cli/help— 91 pass. Typecheck clean in plugin/tui/opencode; upstream marker guard clean.
Screenshots / recordings
Final vhs frame after Down + Ctrl+A:
Actions: dbt-pr-review esc
Search
Show details View skill info, tools, and location
Test Validate the paired CLI tool works
Checklist
- I have tested my changes locally
- I have not included unrelated changes in this PR
🤖 Generated with Claude Code
https://claude.ai/code/session_012Q51zFUmPg1WwtS5CrGJE6
Summary by cubic
Makes /skills open the Altimate skills browser instead of the plain core selector, so Actions, New, and Install work while the dialog is open.
/skillshad two registrations (coreprompt.skillsand the Altimate browser), and Enter took the first, landing users in the action-less selector; the browser now owns the slash name.- Enter uses the skill, inserting
/<skill>into the prompt; the action picker isctrl+a. - Actions, New, and Install are dialog-level actions with in-dialog keybinds (
ctrl+a,ctrl+e,ctrl+g), rendered as Tab-reachable footer buttons — the picker no longer depends on a chord the open dialog overrides. New and Install are standalone, firing even when no row matches the filter. - Install is
ctrl+g(notctrl+i, which is Tab for most terminals) and stays dialog-local to avoid the session route'smessages_first. - The core
prompt.skillsnow hands off to the browser when it's registered and hides itself from the palette then. - The plugin
DialogSelectAPI gainsactionsandbindings, forwarded by the adapter. - Fixed a latent bug where
DialogSelectevaluated its action list beforeselectedwas declared, throwing on function-valueddisabledoptions.
Summary by CodeRabbit
-
New Features
- Added an improved skills browser with footer actions for browsing, creating, and installing skills.
- Added keyboard shortcuts for navigating between actions, creating skills, and installing skills.
- Selecting a skill now inserts it into the active prompt and closes the browser.
- Skill creation and installation retain the current search text.
- Added dialog action buttons and keybindings for supported workflows.
-
Bug Fixes
- Resolved conflicts between the
/skillscommand and skills browser autocomplete. - Fixed an error when displaying actions with selection-dependent disabled states.
- Resolved conflicts between the