detached 9e796e1

fix(daemon): exclude hidden commands from palette codes

commit
9e796e191705c6c8ffe4f56430e27ed81e709293
author
brice · · 2026-07-23 21:43 UTC
parent
4165239
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
2 files · +32 -2
M internal/usecase/daemon/config.go +2 -2
@@ -113,7 +113,7 @@ func configWarningsError(warnings []domain.Warning) error {
113113 }
114114
115115 func (d *Daemon) buildCodeOverrides(configured map[string]string) (map[string]string, []domain.Warning) {
116- commands := command.Registry()
116+ commands := command.PaletteRegistry()
117117 bySlug := make(map[string]command.Command, len(commands))
118118 for _, cmd := range commands {
119119 bySlug[cmd.Slug] = cmd
@@ -294,7 +294,7 @@ func commandWithOverrides(cmd command.Command, overrides map[string]string) comm
294294 func (d *Daemon) commandByEffectiveCode(code string) (command.Command, bool) {
295295 code = strings.ToUpper(strings.TrimSpace(code))
296296 overrides := d.codeOverrideSnapshot()
297- for _, cmd := range command.Registry() {
297+ for _, cmd := range command.PaletteRegistry() {
298298 cmd = commandWithOverrides(cmd, overrides)
299299 if cmd.Code == code {
300300 return cmd, true
@@ -113,7 +113,7 @@ func configWarningsError(warnings []domain.Warning) error {
113 }113 }
114 114
115 func (d *Daemon) buildCodeOverrides(configured map[string]string) (map[string]string, []domain.Warning) {115 func (d *Daemon) buildCodeOverrides(configured map[string]string) (map[string]string, []domain.Warning) {
116- commands := command.Registry()116+ commands := command.PaletteRegistry()
117 bySlug := make(map[string]command.Command, len(commands))117 bySlug := make(map[string]command.Command, len(commands))
118 for _, cmd := range commands {118 for _, cmd := range commands {
119 bySlug[cmd.Slug] = cmd119 bySlug[cmd.Slug] = cmd
@@ -294,7 +294,7 @@ func commandWithOverrides(cmd command.Command, overrides map[string]string) comm
294 func (d *Daemon) commandByEffectiveCode(code string) (command.Command, bool) {294 func (d *Daemon) commandByEffectiveCode(code string) (command.Command, bool) {
295 code = strings.ToUpper(strings.TrimSpace(code))295 code = strings.ToUpper(strings.TrimSpace(code))
296 overrides := d.codeOverrideSnapshot()296 overrides := d.codeOverrideSnapshot()
297- for _, cmd := range command.Registry() {297+ for _, cmd := range command.PaletteRegistry() {
298 cmd = commandWithOverrides(cmd, overrides)298 cmd = commandWithOverrides(cmd, overrides)
299 if cmd.Code == code {299 if cmd.Code == code {
300 return cmd, true300 return cmd, true
M internal/usecase/daemon/palette_test.go +30 -0
@@ -574,6 +574,36 @@ func TestPaletteReopensWithSuccessfulCommandFirst(t *testing.T) {
574574 require.Equal(t, "NXT", cmd.Code)
575575 }
576576
577+func TestPaletteCodeOverridesRejectAPIOnlyCommands(t *testing.T) {
578+ d := newTestDaemon(t, nil, stubClock{})
579+
580+ overrides, warnings := d.buildCodeOverrides(map[string]string{
581+ "new-tab": "TAB",
582+ "toast": "API",
583+ })
584+
585+ require.Equal(t, map[string]string{"new-tab": "TAB"}, overrides)
586+ require.Len(t, warnings, 1)
587+ require.Contains(t, warnings[0].Msg, `unknown command code slug "toast"`)
588+}
589+
590+func TestCommandByEffectiveCodeExcludesAPIOnlyCommands(t *testing.T) {
591+ d := newTestDaemon(t, nil, stubClock{})
592+ overrides := map[string]string{
593+ "new-tab": "TAB",
594+ "toast": "API",
595+ }
596+ d.codeOverrides.Store(&overrides)
597+
598+ cmd, ok := d.commandByEffectiveCode("tab")
599+ require.True(t, ok)
600+ require.Equal(t, "new-tab", cmd.Slug)
601+ require.Equal(t, "TAB", cmd.Code)
602+
603+ _, ok = d.commandByEffectiveCode("API")
604+ require.False(t, ok)
605+}
606+
577607 func TestPaletteRecentCommandsNewestFirstThenRegistryOrder(t *testing.T) {
578608 d := &Daemon{}
579609 d.recordPaletteUse("SSP")
@@ -574,6 +574,36 @@ func TestPaletteReopensWithSuccessfulCommandFirst(t *testing.T) {
574 require.Equal(t, "NXT", cmd.Code)574 require.Equal(t, "NXT", cmd.Code)
575 }575 }
576 576
577+func TestPaletteCodeOverridesRejectAPIOnlyCommands(t *testing.T) {
578+ d := newTestDaemon(t, nil, stubClock{})
579+
580+ overrides, warnings := d.buildCodeOverrides(map[string]string{
581+ "new-tab": "TAB",
582+ "toast": "API",
583+ })
584+
585+ require.Equal(t, map[string]string{"new-tab": "TAB"}, overrides)
586+ require.Len(t, warnings, 1)
587+ require.Contains(t, warnings[0].Msg, `unknown command code slug "toast"`)
588+}
589+
590+func TestCommandByEffectiveCodeExcludesAPIOnlyCommands(t *testing.T) {
591+ d := newTestDaemon(t, nil, stubClock{})
592+ overrides := map[string]string{
593+ "new-tab": "TAB",
594+ "toast": "API",
595+ }
596+ d.codeOverrides.Store(&overrides)
597+
598+ cmd, ok := d.commandByEffectiveCode("tab")
599+ require.True(t, ok)
600+ require.Equal(t, "new-tab", cmd.Slug)
601+ require.Equal(t, "TAB", cmd.Code)
602+
603+ _, ok = d.commandByEffectiveCode("API")
604+ require.False(t, ok)
605+}
606+
577 func TestPaletteRecentCommandsNewestFirstThenRegistryOrder(t *testing.T) {607 func TestPaletteRecentCommandsNewestFirstThenRegistryOrder(t *testing.T) {
578 d := &Daemon{}608 d := &Daemon{}
579 d.recordPaletteUse("SSP")609 d.recordPaletteUse("SSP")

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 12

Tags 11

↑↓ moveenter openesc close