Skip to content

feat: open external $EDITOR for composing long prompts via ctrl+x e chord #5

Description

@ezynda3

Feature Description

Add a new ctrl+x e leader key chord that opens the user's $EDITOR (or $VISUAL) in a temporary file, allowing them to compose or edit long, multi-line prompts in a full-featured text editor. When the editor is closed, the saved content replaces the input field text in the TUI.

Behavior:

  • ctrl+x e — opens $EDITOR with the current input field contents pre-populated in a temp file (e.g. /tmp/kit_prompt_*.md)
  • If the input field is empty, the editor opens with an empty file
  • If the input field already has text, that text is loaded into the editor so the user can continue editing
  • On editor exit (save & quit), the file contents are read back and inserted into the input textarea
  • On editor exit without saving (e.g. :cq in vim), the original input is preserved unchanged
  • The temp file is cleaned up after use
  • If $EDITOR is not set, show a brief status message (e.g. "Set $EDITOR to use external editor")

Motivation / Use Case

When composing complex, multi-line prompts — such as detailed architecture questions, multi-step instructions, or prompts with code blocks — the Kit input textarea is limiting:

  • No familiar editor keybindings — users lose access to vim/emacs motions, visual block mode, multi-cursor, etc.
  • Limited viewport — the textarea doesn't scroll well for very long prompts
  • No syntax highlighting — for prompts that embed code snippets, an editor with highlighting is much more productive
  • Muscle memory — power users already use ctrl+x e (or ctrl+x ctrl+e) in bash/zsh to edit the current command line in $EDITOR; this is a well-known UX pattern

This is especially valuable for Kit's target audience of developer power users who already live in their terminal editors.

Proposed Implementation

Approach

This can follow the same pattern that Crush uses:

  1. Use charmbracelet/x/editor — this package handles $EDITOR / $VISUAL lookup and command construction, and is already part of the Charm ecosystem
  2. Use tea.ExecProcess() — Bubble Tea's built-in mechanism to suspend the TUI, run an external process, and resume. This cleanly handles terminal state (raw mode teardown/restore, alternate screen, etc.)
  3. Wire into the existing ctrl+x leader key system — Kit already has ctrl+x as a leader prefix with ctrl+x s for steering. Adding e as another chord suffix is a natural extension

Sketch

In internal/ui/model.go, inside the if m.leaderKeyActive block:

case "e":
    // Ctrl+X e → open $EDITOR to compose prompt
    if m.state == stateReady || m.state == stateWorking {
        var currentText string
        if ic, ok := m.input.(*InputComponent); ok {
            currentText = ic.textarea.Value()
        }
        // Write current input to temp file
        tmpFile, err := os.CreateTemp("", "kit_prompt_*.md")
        if err == nil {
            tmpFile.WriteString(currentText)
            tmpFile.Close()
            editorCmd := editor.Command(tmpFile.Name())
            cmds = append(cmds, tea.ExecProcess(editorCmd, func(err error) tea.Msg {
                defer os.Remove(tmpFile.Name())
                if err != nil {
                    return nil
                }
                content, _ := os.ReadFile(tmpFile.Name())
                return externalEditorMsg{Text: string(content)}
            }))
        }
    }

Hint text update

The input hint should be updated to mention the new shortcut when space allows:

enter submit • ctrl+j newline • ctrl+x e editor • ctrl+v image

Dependencies

  • Add github.com/charmbracelet/x/editor to go.mod (lightweight, no transitive deps beyond what Kit already has)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request
    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions