Problem
The active-tab suppression check is at tab granularity, not pane granularity. If you split a tab into 4 panes — each running a different agent — and you're focused on pane A, pane B's OSC 9;2 produces no system notification, because activeTabId === tab.id.
You're not looking at pane B. The whole point of multi-pane is independent agents. This breaks the "Claude is asking me a question" guarantee for everyone running >1 pane per tab.
Current code
src/terminal-manager.ts line ~775 (post-#547):
tab.onOscNotification = (text) => {
if (tab.muted) return;
if (this.activeTabId === tab.id && !document.hidden) return; // ← too coarse
this.notifications.notifyAgentAttention(text, tab.title, tab.id);
};
The signal needs to be: "is the user currently looking at the pane that emitted the OSC?" not "is the user currently on this tab?"
Proposal
Plumb the source pane through the OSC notification path. Tab.handleOscNotification already receives the originating Pane (src/tab.ts:195). Forward it through onOscNotification instead of dropping it:
// Tab
onOscNotification: ((text: string, pane: Pane) => void) | null = null;
private handleOscNotification(pane: Pane, text: string) {
if (this.muted) return;
const showGrace = Date.now() - this.lastShownAt < 3000;
if (!this.isVisible && !this.transitioning && !showGrace) {
this.state.needsAttention = true;
this.onStateChange?.();
}
this.onOscNotification?.(text, pane);
}
// TerminalManager
tab.onOscNotification = (text, pane) => {
if (tab.muted) return;
const isFocusedPaneOnActiveTab =
this.activeTabId === tab.id && tab.getFocusedPane() === pane && !document.hidden;
if (isFocusedPaneOnActiveTab) return;
this.notifications.notifyAgentAttention(text, tab.title, tab.id);
};
Acceptance
- 4-pane tab, you're looking at pane A. Pane B OSCs → banner fires.
- 4-pane tab, you're looking at pane A. Pane A OSCs → no banner.
- 1-pane tab (the common case) → behavior unchanged.
Files
| File |
Change |
src/tab.ts |
onOscNotification signature gains a Pane argument |
src/pane.ts |
(no change — already passes this up via existing onOscNotification |
src/terminal-manager.ts |
Check tab.getFocusedPane() === pane instead of tab equality |
Notes
- Today's behavior is correct for the 1-pane case, which is most users today. This bug bites people running multiple agents per tab via splits.
- The "click → tab" flow doesn't change. Click still resolves to a tab, not a pane (focusing the right pane within the tab is a future enhancement).
Problem
The active-tab suppression check is at tab granularity, not pane granularity. If you split a tab into 4 panes — each running a different agent — and you're focused on pane A, pane B's OSC 9;2 produces no system notification, because
activeTabId === tab.id.You're not looking at pane B. The whole point of multi-pane is independent agents. This breaks the "Claude is asking me a question" guarantee for everyone running >1 pane per tab.
Current code
src/terminal-manager.tsline ~775 (post-#547):The signal needs to be: "is the user currently looking at the pane that emitted the OSC?" not "is the user currently on this tab?"
Proposal
Plumb the source pane through the OSC notification path.
Tab.handleOscNotificationalready receives the originatingPane(src/tab.ts:195). Forward it throughonOscNotificationinstead of dropping it:Acceptance
Files
src/tab.tsonOscNotificationsignature gains aPaneargumentsrc/pane.tsthisup via existingonOscNotificationsrc/terminal-manager.tstab.getFocusedPane() === paneinstead of tab equalityNotes