#846·hunk

Allow the note composer save note command (Ctrl-S) to be remapped

Author: bpshaverCreated Aug 24, 2026Updated Aug 30, 2026
Labelsenhancement

What do you want to change?

Let the note composer's save key come from the [keybindings] table instead of being hardcoded to Ctrl-S. Something like a hunk.review.saveNote command id that the composer actually consults, shipping with ctrl+s as the default so nothing changes for anyone who doesn't touch it.

docs/keybindings.md currently says the opposite:

Keys that belong to a dialog, menu, or focused text input — Esc, Enter, Ctrl-S while writing a note — are part of those widgets rather than commands, and are not remappable.

But I don't see why.

Why?

Short version: under Zellij, Ctrl-S never makes it to Hunk at all. Zellij's stock keybindings grab it in every mode except Locked:

kdl
shared_except "scroll" "locked" {
    bind "Ctrl s" { SwitchToMode "Scroll"; }
}

I type up a note, hit Ctrl-S, and instead of saving, the pane drops into Zellij's scroll mode and my draft just sits there unsaved. Every other key I touch during a review is fine, and every other Hunk command I'd want to move is already remappable — the save chord is the one thing I can't route around from Hunk's side.

Repro:

  1. zellij with stock keybindings (no clear-defaults=true)
  2. hunk diff in a pane, c to start a note, type whatever
  3. Ctrl-S → Zellij switches to scroll mode, draft never saves

Setup: Hunk 0.18.1 (Homebrew), Zellij 0.44.3, iTerm2, zsh, macOS 26.3, TERM=xterm-256color.

How this is different from what's already been filed: #345 was this exact symptom under tmux, and #350 fixed it by widening isSaveDraftNoteKey to catch more encodings of Ctrl-S — raw \x13, CSI-u ESC[115;5u, tmux control mode. That trick can't save me here, unfortunately: Zellij eats the keystroke before Hunk's stdin ever sees it, so there's no encoding left to normalize. And #491 shipped user keybindings via #611, but that pass scoped focused-input keys out on purpose.

Could this be an extension? I went looking, and I don't think so. Per the routing precedence in docs/keybindings.md, focused text inputs sit above session extension keyboard modes, so an extension mode can't claim a chord while the composer has focus — and the composer's save handler isn't reachable through hunk.executeCommand either. Seems like it has to be a host change.

How? (optional)

Narrow version: register save as a real command spec in builtinCommandSpecs with defaultKeys: ["ctrl+s"], then have handleFocusedInputShortcut check the resolved chord for that id instead of calling isSaveDraftNoteKey. All the encoding-normalization work from #350 stays exactly where it is — it just becomes part of how ctrl+s gets matched rather than a special case that only saving knows about.

Focused inputs still resolve before the command table, so the rule survives; only the chord becomes configurable. Then the composer footer hint and the ? dialog would show the effective key for free, same way #614 wired up the rest of the surface.