Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,35 @@

All notable changes to cmux are documented here.

## Ivrix [1.1.3] - 2026-07-31

Typing ergonomics for a Hebrew keyboard: a shortcut for the direction toggle,
and shell quotes that survive the Hebrew layout.

### Added
- **A keyboard shortcut for the text direction.** Flipping between left-to-right
and right-to-left meant reaching for the titlebar button. `Ctrl+Cmd+H` now does
it, and so does View > Toggle Text Direction. Rebind it in Settings > Keyboard
Shortcuts or as `shortcuts.bindings.toggleTextDirection` in `cmux.json`. The
titlebar button's tooltip names the shortcut, and follows a rebind.
- **ASCII quotes when typing on a Hebrew layout.** A Hebrew layout puts geresh
and gershayim (`׳` `״`) on the apostrophe and quote keys, so `echo "hi"` typed
in Hebrew reached the shell as `echo ״hi״` and the shell never saw a quote at
all. Those two characters are now sent as ASCII `'` and `"`. Only for keys you
actually press: pasted text, dictation, and anything inserted programmatically
are untouched. Turn it off in Settings > Terminal to type acronyms such as
צה״ל, which need the real gershayim.

### Changed
- **Selection editing now asks whether input is marked, not which screen is up.**
Selecting text at a prompt and typing over it was refused outright whenever an
application had taken over the screen. That was a proxy for the real
requirement, which is `OSC 133` marking saying which cells are the edit buffer;
without it there is nothing to count arrow keys and deletes against. It now
checks for the marking directly. An application that emits no marks is refused
exactly as before, so nothing changes today: Claude Code, for one, takes the
screen and emits no marks, and its composer stays copy-only until it does.

## Ivrix [1.1.2] - 2026-07-29

Right-to-left fixes for selecting and moving around inside full-screen
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ public struct TerminalCatalogSection: SettingCatalogSection {
userDefaultsKey: HebrewFontFace.settingsPath
)

/// Rewrite Hebrew geresh/gershayim to ASCII `'`/`"` while typing.
public let hebrewAsciiQuotes = DefaultsKey<Bool>(
id: "terminal.hebrewAsciiQuotes",
defaultValue: true,
userDefaultsKey: "terminal.hebrewAsciiQuotes"
)

public let copyOnSelect = DefaultsKey<Bool>(
id: "terminal.copyOnSelect",
defaultValue: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ extension ShortcutAction {
case .attachTextBoxFile: return ShortcutStroke(key: "a", command: true, shift: true, option: true)
case .sendCtrlFToTerminal: return nil
case .clearScreenKeepScrollback: return ShortcutStroke(key: "k", command: true, shift: true)
case .toggleTextDirection: return ShortcutStroke(key: "h", command: true, control: true)
case .toggleRightSidebar: return ShortcutStroke(key: "b", command: true, option: true)
case .fileExplorerOpenSelection: return ShortcutStroke(key: "\r")
case .fileExplorerOpenSelectionFinderAlias: return ShortcutStroke(key: "↓", command: true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ public enum ShortcutAction: String, CaseIterable, Sendable, Hashable, SettingCod
case sendCtrlFToTerminal
/// Clears the focused terminal's visible screen while preserving scrollback.
case clearScreenKeepScrollback
/// Ivrix: flips the terminal print direction between LTR and RTL, the same
/// state the titlebar direction control writes.
case toggleTextDirection

// MARK: Panes
case focusLeft
Expand Down Expand Up @@ -194,7 +197,7 @@ extension ShortcutAction {
.newWorkspaceGroup, .groupSelectedWorkspaces, .toggleFocusedWorkspaceGroupCollapsed,
.reopenClosedBrowserPanel, .newSurface, .toggleTerminalCopyMode,
.focusTextBoxInput, .cycleTextBoxSubmitAction, .attachTextBoxFile, .sendCtrlFToTerminal,
.clearScreenKeepScrollback:
.clearScreenKeepScrollback, .toggleTextDirection:
return .navigation
case .focusLeft, .focusRight, .focusUp, .focusDown, .splitRight, .splitDown,
.toggleSplitZoom, .equalizeSplits, .splitBrowserRight, .splitBrowserDown,
Expand Down Expand Up @@ -399,6 +402,8 @@ extension ShortcutAction {
return String(localized: "shortcut.sendCtrlFToTerminal.label", defaultValue: "Send Ctrl-F to Terminal")
case .clearScreenKeepScrollback:
return String(localized: "shortcut.clearScreenKeepScrollback.label", defaultValue: "Clear Screen (Keep Scrollback)")
case .toggleTextDirection:
return String(localized: "shortcut.toggleTextDirection.label", defaultValue: "Toggle Text Direction (LTR/RTL)")
case .focusLeft: return "Focus Pane Left"
case .focusRight: return "Focus Pane Right"
case .focusUp: return "Focus Pane Up"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ extension Array where Element == CuratedSettingEntry {
synonyms: "terminal.scrollSpeed scroll speed multiplier wheel mouse trackpad sensitivity faster slower"
),
.init(section: .terminal, id: "copy-on-select", title: "Copy on Selection", synonyms: "terminal.copyOnSelect copy on selection select clipboard mouse double click triple click iterm"),
.init(section: .terminal, id: "hebrew-ascii-quotes", title: "ASCII Quotes on Hebrew Layout", synonyms: "terminal.hebrewAsciiQuotes hebrew ascii quotes geresh gershayim apostrophe quote punctuation rtl ivrix shell quoting layout"),
.init(section: .terminal, id: "agent-auto-resume", title: "Resume Agent Sessions on Reopen", synonyms: "terminal.autoResumeAgentSessions auto resume restore reopen relaunch quit sessions agents claude code codex opencode rovo dev rovodev toggle"),
.init(section: .terminal, id: "agent-hibernation", title: "Agent Hibernation", synonyms: "terminal.agentHibernation.enabled idle hibernate suspend background agents claude code codex opencode live terminals"),
.init(section: .terminal, id: "agent-hibernation-idle", title: "Hibernate After Idle Seconds", synonyms: "terminal.agentHibernation.idleSeconds idle seconds timeout delay hibernate suspend"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public struct TerminalSection: View {
@State private var scrollBar: DefaultsValueModel<Bool>
@State private var copyOnSelect: DefaultsValueModel<Bool>
@State private var hebrewFont: DefaultsValueModel<HebrewFontFace>
@State private var hebrewAsciiQuotes: DefaultsValueModel<Bool>
@State private var autoResume: DefaultsValueModel<Bool>
@State private var hibernation: DefaultsValueModel<Bool>
@State private var idleSeconds: DefaultsValueModel<Double>
Expand Down Expand Up @@ -51,6 +52,7 @@ public struct TerminalSection: View {
_scrollBar = State(initialValue: DefaultsValueModel(store: defaultsStore, key: catalog.terminal.showScrollBar))
_copyOnSelect = State(initialValue: DefaultsValueModel(store: defaultsStore, key: catalog.terminal.copyOnSelect))
_hebrewFont = State(initialValue: DefaultsValueModel(store: defaultsStore, key: catalog.terminal.hebrewFont))
_hebrewAsciiQuotes = State(initialValue: DefaultsValueModel(store: defaultsStore, key: catalog.terminal.hebrewAsciiQuotes))
_autoResume = State(initialValue: DefaultsValueModel(store: defaultsStore, key: catalog.terminal.autoResumeAgentSessions))
_hibernation = State(initialValue: DefaultsValueModel(store: defaultsStore, key: catalog.terminal.agentHibernationEnabled))
_idleSeconds = State(initialValue: DefaultsValueModel(store: defaultsStore, key: catalog.terminal.agentHibernationIdleSeconds))
Expand Down Expand Up @@ -80,6 +82,7 @@ public struct TerminalSection: View {
scrollBar,
copyOnSelect,
hebrewFont,
hebrewAsciiQuotes,
autoResume,
hibernation,
idleSeconds,
Expand Down Expand Up @@ -339,6 +342,25 @@ public struct TerminalSection: View {
.accessibilityIdentifier("SettingsHebrewFontPicker")
}
SettingsCardDivider()
SettingsCardRow(
configurationReview: .json("terminal.hebrewAsciiQuotes"),
String(localized: "settings.terminal.hebrewAsciiQuotes", defaultValue: "ASCII Quotes on Hebrew Layout"),
subtitle: hebrewAsciiQuotes.current
? String(
localized: "settings.terminal.hebrewAsciiQuotes.subtitleOn",
defaultValue: "Typing geresh or gershayim (׳ ״) on a Hebrew layout sends ASCII ' and \" instead, so shell quoting works."
)
: String(
localized: "settings.terminal.hebrewAsciiQuotes.subtitleOff",
defaultValue: "Hebrew punctuation is sent as typed. Needed for acronyms such as צה״ל; shell quoting will not work from a Hebrew layout."
)
) {
Toggle("", isOn: Binding(get: { hebrewAsciiQuotes.current }, set: { hebrewAsciiQuotes.set($0) }))
.labelsHidden()
.controlSize(.small)
.accessibilityIdentifier("SettingsTerminalHebrewAsciiQuotesToggle")
}
SettingsCardDivider()
SettingsCardRow(
configurationReview: .json("terminal.scrollSpeed"),
String(localized: "settings.terminal.scrollSpeed", defaultValue: "Scroll Speed"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ struct SettingsRowAnchorResolutionTests {
"terminal.rendererRealization.maxWarmRenderers",
"terminal.autoResumeAgentSessions",
"terminal.copyOnSelect",
"terminal.hebrewAsciiQuotes",
"terminal.resumeCommands",
"terminal.sessionContentAlignment",
"terminal.sessionContentMaxWidth",
Expand Down
Loading