Skip to content

Commit 16a2d1c

Browse files
committed
Add adjustable terminal scrollback buffer size; bump to 1.2.5
New Settings → General control (numeric field + stepper) sets the scrollback buffer, persisted via SettingsManager (clamped 500–50,000, default 1,000) and applied live to every terminal through TerminalManager.setBufferSize.
1 parent 2ba2a84 commit 16a2d1c

5 files changed

Lines changed: 82 additions & 2 deletions

File tree

Notchy.xcodeproj/project.pbxproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@
290290
"@executable_path/../Frameworks",
291291
);
292292
MACOSX_DEPLOYMENT_TARGET = 15.6;
293-
MARKETING_VERSION = 1.2.4;
293+
MARKETING_VERSION = 1.2.5;
294294
PRODUCT_BUNDLE_IDENTIFIER = li.luy.notchy;
295295
PRODUCT_NAME = "$(TARGET_NAME)";
296296
REGISTER_APP_GROUPS = YES;
@@ -330,7 +330,7 @@
330330
"@executable_path/../Frameworks",
331331
);
332332
MACOSX_DEPLOYMENT_TARGET = 15.6;
333-
MARKETING_VERSION = 1.2.4;
333+
MARKETING_VERSION = 1.2.5;
334334
PRODUCT_BUNDLE_IDENTIFIER = li.luy.notchy;
335335
PRODUCT_NAME = "$(TARGET_NAME)";
336336
REGISTER_APP_GROUPS = YES;

Notchy/SettingsManager.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,23 @@ class SettingsManager {
4747
didSet { UserDefaults.standard.set(Double(terminalFontSize), forKey: "terminalFontSize") }
4848
}
4949

50+
static let minBufferSize = 500
51+
static let maxBufferSize = 50000
52+
static let defaultBufferSize = 1000
53+
54+
/// Scrollback buffer size in lines, applied to every terminal's normal
55+
/// buffer. Clamped to [minBufferSize, maxBufferSize].
56+
var terminalBufferSize: Int {
57+
didSet {
58+
let clamped = max(Self.minBufferSize, min(Self.maxBufferSize, terminalBufferSize))
59+
if clamped != terminalBufferSize {
60+
terminalBufferSize = clamped
61+
return
62+
}
63+
UserDefaults.standard.set(terminalBufferSize, forKey: "terminalBufferSize")
64+
}
65+
}
66+
5067
init() {
5168
let defaults = UserDefaults.standard
5269
if defaults.object(forKey: "replaceNotch") == nil { defaults.set(true, forKey: "replaceNotch") }
@@ -58,6 +75,7 @@ class SettingsManager {
5875
if defaults.object(forKey: "preferredAgent") == nil { defaults.set(AgentKind.claude.rawValue, forKey: "preferredAgent") }
5976
if defaults.object(forKey: "selectionCopyEnabled") == nil { defaults.set(true, forKey: "selectionCopyEnabled") }
6077
if defaults.object(forKey: "externalDisplayTrigger") == nil { defaults.set(false, forKey: "externalDisplayTrigger") }
78+
if defaults.object(forKey: "terminalBufferSize") == nil { defaults.set(Self.defaultBufferSize, forKey: "terminalBufferSize") }
6179

6280
showNotch = defaults.bool(forKey: "replaceNotch")
6381
soundsEnabled = defaults.bool(forKey: "soundsEnabled")
@@ -70,5 +88,9 @@ class SettingsManager {
7088
externalDisplayTrigger = defaults.bool(forKey: "externalDisplayTrigger")
7189
let storedFontSize = defaults.double(forKey: "terminalFontSize")
7290
terminalFontSize = storedFontSize > 0 ? CGFloat(storedFontSize) : 13
91+
let storedBufferSize = defaults.integer(forKey: "terminalBufferSize")
92+
terminalBufferSize = storedBufferSize > 0
93+
? max(Self.minBufferSize, min(Self.maxBufferSize, storedBufferSize))
94+
: Self.defaultBufferSize
7395
}
7496
}

Notchy/SettingsWindow.swift

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,58 @@ struct GeneralTab: View {
8484
.font(.caption)
8585
.foregroundStyle(.secondary)
8686
}
87+
BufferSizeRow()
8788
}
8889
}
8990
.formStyle(.grouped)
9091
.scrollContentBackground(.hidden)
9192
}
9293
}
9394

95+
/// Scrollback buffer size control: a numeric field (committed on Enter/blur)
96+
/// plus a stepper. Edits are clamped to the SettingsManager bounds and applied
97+
/// to every live terminal via TerminalManager.
98+
struct BufferSizeRow: View {
99+
@Bindable private var settings = SettingsManager.shared
100+
@State private var draft: String = String(SettingsManager.shared.terminalBufferSize)
101+
102+
private func commit() {
103+
let parsed = Int(draft.trimmingCharacters(in: .whitespaces)) ?? settings.terminalBufferSize
104+
TerminalManager.shared.setBufferSize(parsed)
105+
// Reflect the clamped, persisted value back into the field.
106+
draft = String(settings.terminalBufferSize)
107+
}
108+
109+
private func step(_ delta: Int) {
110+
TerminalManager.shared.setBufferSize(settings.terminalBufferSize + delta)
111+
draft = String(settings.terminalBufferSize)
112+
}
113+
114+
var body: some View {
115+
VStack(alignment: .leading, spacing: 2) {
116+
HStack {
117+
Text("Scrollback buffer")
118+
Spacer()
119+
TextField("", text: $draft)
120+
.multilineTextAlignment(.trailing)
121+
.frame(width: 70)
122+
.onSubmit { commit() }
123+
Stepper("") {
124+
step(500)
125+
} onDecrement: {
126+
step(-500)
127+
}
128+
.labelsHidden()
129+
Text("lines")
130+
.foregroundStyle(.secondary)
131+
}
132+
Text("Lines kept in terminal history (\(SettingsManager.minBufferSize)\(SettingsManager.maxBufferSize))")
133+
.font(.caption)
134+
.foregroundStyle(.secondary)
135+
}
136+
}
137+
}
138+
94139
struct IntegrationsTab: View {
95140
@Bindable private var settings = SettingsManager.shared
96141

Notchy/TerminalManager.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,17 @@ class TerminalManager: NSObject, LocalProcessTerminalViewDelegate {
572572
}
573573
}
574574

575+
/// Apply a new scrollback buffer size to every live terminal and persist it.
576+
/// Clamped to [minBufferSize, maxBufferSize].
577+
func setBufferSize(_ size: Int) {
578+
let newSize = max(SettingsManager.minBufferSize, min(SettingsManager.maxBufferSize, size))
579+
guard newSize != SettingsManager.shared.terminalBufferSize else { return }
580+
SettingsManager.shared.terminalBufferSize = newSize
581+
for terminal in terminals.values {
582+
terminal.changeScrollback(newSize)
583+
}
584+
}
585+
575586
func terminal(for sessionId: UUID, workingDirectory: String, launchAgent: Bool = true) -> LocalProcessTerminalView {
576587
if let existing = terminals[sessionId] {
577588
return existing
@@ -584,6 +595,7 @@ class TerminalManager: NSObject, LocalProcessTerminalViewDelegate {
584595
terminal.font = makeTerminalFont(size: SettingsManager.shared.terminalFontSize)
585596
terminal.nativeBackgroundColor = NSColor(white: 0.05, alpha: 1.0)
586597
terminal.nativeForegroundColor = NSColor(white: 0.95, alpha: 1.0)
598+
terminal.changeScrollback(SettingsManager.shared.terminalBufferSize)
587599

588600
let shell = ProcessInfo.processInfo.environment["SHELL"] ?? "/bin/zsh"
589601
let environment = buildEnvironment()

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ A macOS menu bar app that puts Claude Code or Codex right in your MacBook's notc
1515
- **Pin tabs to persist** — right-click a `+` tab → **Pin Tab** to keep it across app restarts; Notchy remembers the tab's working directory and re-runs agent auto-launch on relaunch
1616
- **Shadow tabs** — right-click an Xcode or pinned tab → **Shadow Tab** to spawn a plain shell sibling cd'd into the same directory, for ad-hoc git/build commands without disturbing the agent
1717
- **Zoom terminal font** — Cmd+= (or Cmd++) and Cmd+− adjust the font size across all open terminals, Cmd+0 resets to default; the size is persisted across launches
18+
- **Adjustable scrollback** — set the terminal history buffer in Settings → General → Terminal (default 1,000 lines, up to 50,000)
1819
- **Live status in the notch** — animated pill shows whether the agent is working, waiting, or done
1920
- **Git checkpoints** — Cmd+S to snapshot your project before the agent makes changes
2021

0 commit comments

Comments
 (0)