2025, Nov 13 13:00

Make macOS notifications clickable in Python: why pync open fails for local paths and how to fix it

Fix macOS notifications in Python when pync open won't launch local paths. Use execute with macOS open and terminal-notifier to make reliable, clickable alerts.

Making macOS notifications actionable from Python is straightforward until you try to open a local path from the notification. A common setup on macOS uses pync as a thin wrapper over terminal-notifier, and that’s where a subtle gotcha shows up: the open keyword that looks like it should open a file or directory simply doesn’t trigger when pointed at a local path, even if everything else in the script runs.

Problem snapshot

The following example dispatches a notification that should open a Desktop subdirectory on click. A second notification with a URL works fine, which makes the behavior even more confusing at first glance.

import os
import platform

user_desktop = os.path.join(os.path.expanduser("~"), "Desktop")
path_to_view = os.path.join(user_desktop, "my Schedules")

if platform.system() == "Darwin":  # macOS
    from pync import Notifier

    print("dispatching notification")
    Notifier.notify(
        "Your files are ready. Click to view.",
        title="my Schedule Generator",
        sound=True,  # Optional sound
        open=path_to_view  # Expected to make the notification clickable
    )
    print("attempted to open path")

Notifier.notify("website link", open="http://github.com/", title="titling")

The print outputs appear, and the URL-based notification opens as expected. The clickable notification that targets the local path, however, never shows up.

What’s really happening

The behavior ties back to pync itself. According to the pync documentation on PyPI, examples that rely on the open keyword look valid, but when tried in practice they do not work. pync hasn’t been updated since 2018, which probably suggests that it’s incompatible with current macOS versions. That explains why a URL opens fine while a local path passed via open silently fails.

There’s another prerequisite worth confirming: pync depends on the terminal-notifier tool. Without it, notifications won’t function as intended. The project referenced is terminal-notifier, available at https://github.com/julienXX/terminal-notifier.

The workable approach

To make a notification open a target from a click, switch from the open keyword to the execute keyword. That lets terminal-notifier run a command on click. Using the macOS open command is enough to launch the file or path you want.

from pync import Notifier

# the file to be opened
TARGET_ITEM = __file__
Notifier.notify("Check this out", execute=f'open "{TARGET_ITEM}"')

This pattern avoids the non-working open keyword and delegates the action to the system’s open command via execute.

Applying it to the original flow

If your goal is to make a Desktop path clickable, keep your path construction logic and swap in execute to call open with the same path. The remainder of the script can stay intact, including the URL-based notification, which already behaves correctly.

import os
import platform

home_desk = os.path.join(os.path.expanduser("~"), "Desktop")
click_target = os.path.join(home_desk, "my Schedules")

if platform.system() == "Darwin":  # macOS
    from pync import Notifier

    print("dispatching notification")
    Notifier.notify(
        "Your files are ready. Click to view.",
        title="my Schedule Generator",
        sound=True,
        execute=f'open "{click_target}"'
    )
    print("attempted to open path")

Notifier.notify("website link", open="http://github.com/", title="titling")

Why this detail matters

Notification actions are part of many productivity and automation flows. Relying on an argument that appears documented but doesn’t work on current systems leads to brittle UX and debugging churn. Knowing that pync’s open keyword is unreliable and that execute is the safe route helps you ship behavior that consistently opens what users expect.

Takeaways

If a pync notification does nothing when it should open a local path, the issue is not your if branch or path construction. The open keyword itself is the culprit. Prefer execute with the macOS open command to achieve the same outcome. Verify that terminal-notifier is installed, keep the URL-based notifications as they are, and your clickable notifications will behave predictably.