Skip to content

Add settings for "notifying" on "activity"#20014

Open
carlos-zamora wants to merge 14 commits intomainfrom
dev/cazamor/toast/activity
Open

Add settings for "notifying" on "activity"#20014
carlos-zamora wants to merge 14 commits intomainfrom
dev/cazamor/toast/activity

Conversation

@carlos-zamora
Copy link
Copy Markdown
Member

@carlos-zamora carlos-zamora commented Mar 25, 2026

This PR implements the proposal in this comment. It adds 3 settings:

  • notifyOnInactiveOutput: send a "notification"(below) of some kind when an inactive tab has new output.
  • notifyOnNextPrompt: Similarly, but when we get a new prompt start (requires shell integration)
  • autoDetectRunningCommand: attempt to automatically detect the progress state of this profile

For the notifyOn* settings, they take any combination of the following flags:

  • tab: flash the taskbar
  • audible: emit an audible bell (This will use the sounds from bellSounds, if specified)
  • taskbar: display an icon in the tab (ala terminal activity indicator/alert when in background #7955 (comment) ) (basically, similar to the bell icon)
  • notification: send a desktop "toast" (read: notification). Clicking that notification will focus the tab that sent it

For the autoDetectRunningCommand setting, we support:

  • disabled: don't do this
  • automatic: (requires shell integration) if we got a FTCS_COMMAND_EXECUTED  (133;C), then any output, set our progress state to indeterminate

Validated using this config:

"defaults":
{
	"autoDetectRunningCommand": "automatic",
	"autoMarkPrompts": true, // Needed even when your OMP config has shell integration enabled
	"rightClickContextMenu": true,
	"showMarksOnScrollbar": true
},
"list":
[
	{
		"commandline": "pwsh -nologo",
		"name": "Inactive Output",
		"notifyOnInactiveOutput":
		[
			"taskbar",
			"audible",
			"tab",
			"notification"
		]
	},
	{
		"commandline": "pwsh -nologo",
		"name": "Next Prompt",
		"notifyOnNextPrompt":
		[
			"taskbar",
			"audible",
			"tab",
			"notification"
		]
	},

Heavily based on #19935
Co-authored by @zadjii-msft

@carlos-zamora carlos-zamora force-pushed the dev/cazamor/toast/base branch from 4357c17 to aeb531f Compare March 25, 2026 17:29
## Summary of the Pull Request
Targets #20010 

Manually assign an AUMID to our process when we're running unpackaged.
Main difference from #19937 is what AUMID we use. Before, it was per
branding, but the `WindowEmperor` already appends an exe path hash for
unpackaged instances to prevent crosstalk. Here, we're just using the
same pattern: `Microsoft.WindowsTerminal.<hash>`.

Heavily based on #19937
Co-authored by @zadjii-msft
@carlos-zamora carlos-zamora force-pushed the dev/cazamor/toast/activity branch from 47c0ae7 to 09c47c6 Compare March 25, 2026 21:51
@carlos-zamora carlos-zamora force-pushed the dev/cazamor/toast/activity branch from 09c47c6 to 98a4ccb Compare March 27, 2026 02:27
@carlos-zamora carlos-zamora marked this pull request as ready for review March 27, 2026 02:27
@carlos-zamora
Copy link
Copy Markdown
Member Author

Tested this out, it's pretty cool.
Reviewed it myself and using GHCP, everything looks good.

The only thing I can think of is the possibility of adding the experimental. prefix to these settings, but even then, I don't think that necessarily does anything. Like, when would it exit experimental?

So yeah, marked this as ready for review. Enjoy y'all! 😊

Comment thread src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw Outdated
Comment thread src/cascadia/TerminalSettingsEditor/Profiles_Advanced.xaml Outdated
@carlos-zamora carlos-zamora force-pushed the dev/cazamor/toast/activity branch from 90fdd9b to fbb886e Compare April 17, 2026 02:05
"description": "Sets the sound played when the application emits a BEL. When set to an array, the terminal will pick one of those sounds at random.",
"$ref": "#/$defs/BellSound"
},
"notifyOnInactiveOutput": {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about a setting for duration? Ghostty has this as well. I may only want to see this after, say, 10s and not a command that maybe takes a second and I quickly flip away intending to come back in a few seconds. A longer job is more likely something we'll "walk away from" for a longer period instead of just flipping windows back and forth a bit.

If someone really wanted to be alerted for every command when the window is inactive, they can set this to 0 (or maybe that's the default).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... ghostty calls these settings activity-monitor and activity-monitor-threshold. So, we could name this notifyOnInactiveOutputThreshold and also have it take an int representing seconds (default of 0). Then just place them next to each other in the settings UI.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having a higher default (IIRC, Ghostty's is 30s when enabled) might solve the other issue you mentioned, but you could also debounce notifications. If they come in within Xs (maybe also configurable), don't notify. Frankly, given the goal is to notify you some task is done - and this would seem to be a long-running task, IMO, since any quick task you're probably coming back to frequently - the "threshold" having a higher default like 30s would probably be sufficient - at least as a start.

@carlos-zamora
Copy link
Copy Markdown
Member Author

I was just using this feature with Copilot, and it was sending a ton of notifications as it was thinking.
At first, I was thinking that we should only let the session send one notification of this type, but now I'm not sure if that's the right approach. I'm particularly thinking of situations where the attached CLI app may send a bit of output, then wait, then send more. I guess in a situation like that, we definitely want a notification on the second one, and maybe on the first?

Thoughts? CC @DHowett @zadjii-msft

@zadjii-msft
Copy link
Copy Markdown
Member

IMO:

I think we need to send one notification when the tab gets activity and then no more until that pane is focused.
If it emits some text, and you don't focus it, and then five minutes later it emits some more text, we don't send a second notification. That pane is already in the "there was inactive activity" state. We don't need to send another notification until the user activates it (to dismiss that state)

Like, consider how the in-tab indicator would work. It's like the bell icon. "this tab did a thing" stays until the user activates it to dismiss that state.

lhecker
lhecker previously approved these changes Apr 22, 2026
Comment thread src/cascadia/TerminalApp/IPaneContent.idl Outdated
}
},
{
"type": "string",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the setting always used an array, I think that'd be fine too. That's just [two] extra characters after all.

page->Dispatcher().RunAsync(winrt::Windows::UI::Core::CoreDispatcherPriority::Normal, [weakPage{ page->get_weak() }, weakTab, weakContent]() {
if (const auto p{ weakPage.get() })
page->Dispatcher().RunAsync(winrt::Windows::UI::Core::CoreDispatcherPriority::Normal, [weakThis, weakTab, weakContent]() {
if (const auto p{ weakThis.get() })
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neat.

Comment thread src/cascadia/TerminalApp/TerminalPaneContent.cpp Outdated
Comment thread src/cascadia/TerminalApp/TerminalPaneContent.cpp Outdated
Comment thread src/cascadia/TerminalControl/IControlSettings.idl
Comment thread src/cascadia/TerminalSettingsEditor/ProfileViewModel.cpp Outdated
@carlos-zamora carlos-zamora force-pushed the dev/cazamor/toast/activity branch from fbb886e to 6c2b796 Compare April 30, 2026 00:23
Base automatically changed from dev/cazamor/toast/base to main April 30, 2026 00:24
@carlos-zamora carlos-zamora dismissed lhecker’s stale review April 30, 2026 00:24

The base branch was changed.

@microsoft-github-policy-service microsoft-github-policy-service Bot added Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. Area-Extensibility A feature that would ideally be fulfilled by us having an extension model. Area-UserInterface Issues pertaining to the user interface of the Console or Terminal Product-Terminal The new Windows Terminal. labels Apr 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area-Extensibility A feature that would ideally be fulfilled by us having an extension model. Area-UserInterface Issues pertaining to the user interface of the Console or Terminal Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. Product-Terminal The new Windows Terminal. zBugBash-Consider

Projects

None yet

4 participants