Context Rich Notifications for Your Terminal
Notification routing in YEN is now context-aware end-to-end.
Hey folks!
This update fixes a problem that only shows up once your workflow gets real: Multiple tabs, multiple splits, and several long-running things happening at once.
Before this work, notification clicks could land in the wrong context or do nothing when route information was missing. That was unacceptable for a terminal-first app where context is everything.
In addition, the information in each notification was a little sparse and so increasing the visibility and flexibility for each type of notification was a definite opportunity for improvement. So, that’s what I did.
Now, when you click our new-and-improved, context-rich notification, YEN can take you back to the exact originating tab and split.
What you’ll see above are notifications spanning a number of different splits and views, like messages from our built-in chat and email and calendaring, or even a command that was just completed or updates from one of your cli dev tools. You get it all and can, of course, customize each type as you wish:
Fun times.
The Core Problem
In YEN, chat, mail, and calendar run as Go companion processes launched from terminal surfaces. When those processes emit desktop notifications, the app has to answer one question on click:
Which terminal surface did this come from?
If the answer is vague, users get context jumps. If the answer is wrong, users lose trust. So, I wanted to address that trust gap and now we have the following:
Every Surface Now Has a Stable Route Identity — Each terminal surface stamps a stable YEN_SURFACE_ID into its process environment. That identity is inherited correctly when creating new tabs and splits, so downstream notification emitters always know where they came from.
Notification Payloads Now Carry Route Metadata — The Go services still send the legacy title / body payload format for compatibility, but now also attach structured metadata like schema_version, service, and surface_id. That metadata flows through DistributedNotification userInfo and into macOS notification content userInfo in YEN.app.
Notification Response Handling Is Centrally Routed — YEN now uses one response-routing path for service notifications: Parse routes metadata to resolve the target surface by UUID and then focus the owning tab / window and split for default click and show actions, and finally a handle dismiss actions without stealing focus. If the notification is not service-managed, YEN falls back to the existing legacy handling path.
Safe Fallback Beats Wrong Routing — If a route is stale or missing, YEN does not jump to an arbitrary tab. Instead, it uses a safe fallback: Activate the app and bring the key or main window forward, without pretending it found a valid target.
Dedupe Is Surface-Aware — Service dedupe keys now include surface identity: surface_id + title + body which prevents one tab or split from suppressing identical notifications from another active context.
The fix was a real UX improvement opportunity that had to be entertained.
Why This Matters
This is not simply cosmetic. Notification routing is part of interaction integrity in a multi-context terminal. If click behavior is nondeterministic, users stop trusting notifications entirely.
The new behavior is deterministic:
Valid route metadata returns you to the exact origin context.
Invalid or stale metadata uses a documented safe fallback.
Cross-surface dedupe collisions are eliminated.
Notification clicks should feel boringly correct. In terminal workflows, boringly correct is exactly the point.
— 8




