Skip to content

Instantly share code, notes, and snippets.

@moritzWa
Created February 10, 2026 19:36
Show Gist options
  • Select an option

  • Save moritzWa/31045449d3707c0088fc3eac8a1c781b to your computer and use it in GitHub Desktop.

Select an option

Save moritzWa/31045449d3707c0088fc3eac8a1c781b to your computer and use it in GitHub Desktop.
Fix Shift+Enter for Claude Code multi-line input in Hyper terminal (xterm.js plugin)

Fix Shift+Enter for Claude Code (and other CLI tools) in Hyper Terminal

The Problem

Hyper terminal (powered by xterm.js) sends the same byte (\r, carriage return) for both Enter and Shift+Enter. This means Shift+Enter can't insert a newline in Claude Code's multi-line input - it just submits instead.

Other terminals like iTerm2, Kitty, Ghostty, and Alacritty either handle this natively or have simple config options. Hyper doesn't, but a small local plugin fixes it.

The Fix

Create a local Hyper plugin that intercepts Shift+Enter and sends \n (line feed, 0x0A) to the PTY instead of \r.

1. Create the plugin directory

mkdir -p ~/.hyper_plugins/local/hyper-shift-enter

2. Create the plugin file

Save this as ~/.hyper_plugins/local/hyper-shift-enter/index.js:

module.exports = {
  decorateTerm(Term, { React }) {
    return class extends React.Component {
      constructor(props) {
        super(props);
        this._onDecorated = this._onDecorated.bind(this);
      }

      _onDecorated(term) {
        if (this.props.onDecorated) this.props.onDecorated(term);
        if (!term || !term.term) return;

        const uid = this.props.uid;
        term.term.attachCustomKeyEventHandler((e) => {
          if (e.type === 'keydown' && e.key === 'Enter' && e.shiftKey) {
            e.preventDefault();
            // Send LF (0x0A) to PTY - this is what Claude Code expects for newline
            window.rpc.emit('data', { uid, data: '\n' });
            return false;
          }
          return true;
        });
      }

      render() {
        return React.createElement(Term, Object.assign({}, this.props, {
          onDecorated: this._onDecorated,
        }));
      }
    };
  },
};

3. Register the plugin in ~/.hyper.js

Add "hyper-shift-enter" to localPlugins:

localPlugins: ["hyper-shift-enter"],

4. Reload Hyper

Press Cmd+Shift+R (macOS) or restart Hyper.

How it works

  • xterm.js's attachCustomKeyEventHandler intercepts Shift+Enter before xterm processes it
  • Instead of the default \r (submit), it sends \n (line feed) to the shell PTY via Hyper's RPC
  • Claude Code (and other tools using raw terminal input) interprets \n as "insert newline" rather than "submit"

Also works for

  • Any CLI tool that distinguishes \n from \r for multi-line input
  • Bash line continuation (though for that you may prefer typing \ + Enter manually)

Related issues

Fixes for other terminals

  • Ghostty: keybind = shift+enter=text:\n in config
  • Alacritty: { key = "Return", mods = "Shift", chars = "\n" } in alacritty.toml
  • Kitty: Works out of the box (Kitty keyboard protocol)
  • iTerm2/WezTerm: Works out of the box (natively sends \n for Shift+Enter)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment