[Bug] Ghostty terminal-setup uses naive string search for keybind detection

Resolved 💬 8 comments Opened Oct 27, 2025 by dmmalam Closed Feb 7, 2026

Bug Description
# Bug Report: Ghostty terminal-setup uses naive string search and doesn't support modern key codes

## Problem 1: Naive String Search for Existing Keybinds

### Description
The /terminal-setup command performs a naive Y.includes("shift+enter") check that:

  • Matches comments and documentation, not just actual keybindings
  • Fails to detect keybindings Claude Code itself previously added
  • Creates false positives when users have default Ghostty documentation

### Evidence
From the Claude binary:
```javascript
if(Y.includes("shift+enter"))return 'Found existing Ghostty Shift+Enter key binding. Remove it to continue.'

How This Failed

  1. Claude Code successfully added keybind = shift+enter=text:\x1b\r via /terminal-setup
  2. User later added/moved documentation comments containing "shift + enter"
  3. Re-running /terminal-setup falsely detected the comment (not the actual keybind)
  4. User was blocked from proceeding despite having the correct keybind already

Impact

  • False positives from documentation/comments
  • Cannot detect legitimately conflicting keybinds vs comments
  • Catch-22: Can't add keybind because any mention of the string triggers the check
  • Breaks unexpectedly when users edit their config files

Workaround

Remove or reword any comments containing "shift+enter" (e.g., change to "shift+return"). However, this is problematic if you legitimately need multiple shift+enter bindings or want to
document what you changed and why.

Suggested Fix for Detection

Parse the config properly and only detect active (uncommented) keybinds:

const lines = Y.split('\n');
const hasActiveBinding = lines.some(line => {
const trimmed = line.trim();
// Skip comments and empty lines
if (!trimmed || trimmed.startsWith('#')) return false;
// Match actual keybind directives
return /keybind\s=\s.*shift\+enter/i.test(trimmed);
});

if (hasActiveBinding) {
// Optionally: warn but allow user to proceed with --force flag
console.warn('Detected existing shift+enter binding. This may conflict.');
if (!flags.force) {
console.log('Re-run with --force to override.');
return;
}
}

Problem 2: Ghostty Uses Modern Terminal Standards

Root Cause

Ghostty sends [27;2;13~ (modifyOtherKeys standard) for Shift+Enter by default, but Claude Code only recognizes the older \x1b\r (ESC + CR) sequence.

Current Solution (Suboptimal)

Requires manually configuring Ghostty to send the legacy sequence via:
keybind = shift+enter=text:\x1b\r

Better Solution: Support Modern Key Codes

Claude Code should recognize both:

  • Legacy: \x1b\r (ESC + CR) - for older terminals
  • Modern: [27;2;13~ - for terminals following modifyOtherKeys standard

This would make Shift+Enter work out of the box in Ghostty and other modern terminals without requiring any configuration.

Implementation Suggestion

Update the input parser to recognize both sequences:
// Legacy sequence
if (input === '\x1b\r') {
insertNewline();
}
// Modern modifyOtherKeys sequence for Shift+Enter
if (input === '\x1b[27;2;13~') {
insertNewline();
}

Benefits

  • Works out of the box in modern terminals (Ghostty, WezTerm, etc.)
  • No configuration required
  • Backwards compatible with terminals sending legacy sequences
  • Aligns with modern terminal standards

Related Issues

  • #5757 - Reports the [27;2;13~ sequence not being recognized
  • #1282 - Feature request for Ghostty support
  • #6344 - Crash during terminal-setup

Reproduction

  1. Run /terminal-setup successfully (Claude adds the keybind)
  2. Add a comment like # Note: changed shift + enter to shift + return
  3. Re-run /terminal-setup
  4. Get false positive: "Found existing Ghostty Shift+Enter key binding"

Priority

Medium-High: Affects all Ghostty users and creates confusing false positives

You can copy this and use the built-in bug reporter to submit it!

Environment Info

  • Platform: darwin
  • Terminal: ghostty
  • Version: 2.0.27
  • Feedback ID: 93791566-b3ee-4234-9474-aa0ea7c1c3a3

Errors

[{"error":"Error: Plugin path not found: /Users/dmmalam/.claude/plugins/marketplaces/plugins/pr-review-toolkit\n    at hTI (/$bunfs/root/claude:700:4853)\n    at hTI (/$bunfs/root/claude:700:10866)\n    at bTI (/$bunfs/root/claude:700:4397)\n    at async <anonymous> (/$bunfs/root/claude:700:11813)\n    at async CO (/$bunfs/root/claude:724:25941)\n    at async <anonymous> (/$bunfs/root/claude:3755:312)\n    at async parseAsync (/$bunfs/root/claude:26:4180)\n    at async r85 (/$bunfs/root/claude:3800:1619)\n    at async l85 (/$bunfs/root/claude:3745:1545)\n    at async s85 (/$bunfs/root/claude:3800:9962)","timestamp":"2025-10-27T19:47:

Note: Error logs were truncated.

View original on GitHub ↗

This issue has 8 comments on GitHub. Read the full discussion on GitHub ↗