Skip to content

ghostel backend: buffer keymap is lost after leaving copy/emacs/line mode, so C-g sends literal Ctrl-G instead of escape #147

Description

@deg

Versions: claude-code.el 0.4.5 (rev 03199df, :vc install), ghostel 20260714.2158 (module v0.44.0) from MELPA, Emacs 30.2, macOS (Apple Silicon).

Note: the diagnosis and this text are by Claude (AI agent), not human-reviewed.

Repro:

  1. (setq claude-code-terminal-backend 'ghostel) and start Claude (M-x claude-code).
  2. In the Claude buffer, enter any ghostel read-only mode — easiest is a mouse click or scroll, which auto-engages copy mode (or C-c C-t explicitly).
  3. Press C-g to leave copy mode ("leaving read-only mode").
  4. Press C-g again, expecting it to send <escape> (interrupt Claude).

Expected: C-gclaude-code--ghostel-send-escape, as bound by the ghostel claude-code--term-setup-keymap method.

Actual: C-gghostel-send-C-g, which delivers a literal Ctrl-G to the Claude TUI — Claude Code interprets that as "open prompt in external editor", so an editor window pops up instead of the agent being interrupted. The <return>/S-<return> bindings from claude-code-newline-keybinding-style are lost at the same time.

Cause: the ghostel claude-code--term-setup-keymap method installs its keymap with use-local-map at buffer creation. But ghostel's input-mode switchers (ghostel-semi-char-mode, ghostel-char-mode, the read-only exits) each call use-local-map with ghostel's own maps, so the first round-trip through any input mode permanently discards claude-code's map. Since mouse selection and scrolling auto-enter copy mode, this happens in normal use without the user ever invoking a mode switch.

Possible fix: attach the claude-code bindings through a buffer-local minor mode (minor-mode keymaps take precedence over the local map and survive use-local-map), rather than replacing the local map. That would make the bindings robust against ghostel's mode switching without needing ghostel-side changes.

Workaround I'm using: an :after advice on ghostel-semi-char-mode that re-runs (claude-code--term-setup-keymap 'ghostel) in claude-code--buffer-p buffers.

Happy to provide more detail. Thanks for the package — the named-instances-per-project model is exactly what I wanted.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions