Skip to content

macOS desktop has no local notifications for agent events #11866

Description

@Birzool

Summary

Agent activity notifications are mobile-only. When an agent needs input, needs an
approval, finishes, or fails, the desktop app raises nothing on the machine you are
sitting at. If your phone is in another room, there is no signal at all.

The settings UI is honest about this. The section reads:

Push notifications
Mobile push-notification and Live Activity registration.

So this is a missing capability, not a broken one. This issue asks for the desktop half.

What happens today

The awareness relay publishes thread state to the cloud, and the relay decides what to
deliver. On a setup with one linked iOS device, every publish returns:

agent activity publish completed
  ok: true,
  deliveries: {
    total: 1, queued: 1, successful: 0, failed: 0,
    kinds: [ 'live_activity_update' ],
    failedReasons: []
  }

RelayDeliveryKind includes push_notification, but it is only produced once the
mobile client has been granted notification permission. Nothing in this path ever
reaches the desktop.

The only new Notification(...).show() in the shipped bundle belongs to the app
updater.

Why this matters

Agents run for minutes. You switch to another window, and the moment the agent needs an
approval it stops and waits. Without a local signal you discover that by going back and
looking. The phone push solves it only while the phone is within reach, and it is the
wrong device to answer on, because answering means returning to the Mac anyway.

What I built as a workaround

A hook script on UserPromptSubmit, Notification, and Stop that raises a macOS
banner through terminal-notifier. It works, and the design decisions it forced may be
useful input for a native implementation:

Suppress when the app is frontmost. A banner about a thread you are already looking
at is pure duplication. The check has to avoid a TCC prompt, so lsappinfo front rather
than System Events. A native implementation can do better than mine: it knows which
thread is displayed, so it can suppress per thread instead of per app. That distinction
is invisible from outside the app. A hook can only see that T3 is frontmost, not which
thread is on screen.

One notification slot per thread. Grouping by a per-thread key means a newer state
for one thread replaces its own older banner, and never buries a banner from a different
thread.

A duration threshold for completions. Signalling every finished turn is noise. Only
turns longer than a threshold are worth a banner; short ones you are still watching.

The thread title in the banner. With several agents running, "an agent needs input"
is not actionable. The title has to say which thread.

Getting the thread title from outside took a detour worth mentioning:
projection_thread_sessions.provider_session_id is empty for every row, so the harness
session id has to be matched against provider_session_runtime.resume_cursor_json
instead. If exposing that mapping is intentional, a documented accessor would help
integrations; if it is not, the empty column may be a separate bug.

Proposal

Deliver the four events that already have preference flags for mobile
(notifyOnApproval, notifyOnInput, notifyOnCompletion, notifyOnFailure) as local
notifications on macOS, with:

  • a per-event toggle mirroring the mobile preference set,
  • suppression when the target thread is the focused thread in a visible window,
  • one notification group per thread,
  • click-through that selects the thread (Route t3code:// deep links into the existing thread route #11865 provides the mechanism, though an
    internal call is simpler for the app itself).

The client presence data already collected (focused, visible, recentlyInteracted,
appState) looks like it carries everything the suppression rule needs.

Environment

  • T3 Code (Alpha) 0.0.40, macOS 26 (Darwin 25.6), Apple Silicon.
  • One linked iOS device with notifications enabled; mobile push works.
  • Findings come from the shipped app.asar, boot-service.log, and the system
    notification log. I have not seen the source repository.

Offer

I can share the hook script if it is useful as a reference. It is about 330 lines of
Python and depends only on terminal-notifier.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions