npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

pi-notifi

v1.0.0

Published

Pi extension that sends focus-aware desktop notifications when pi finishes a task.

Readme

pi-notifi

A focus-aware desktop notification package for pi. It sends a notification when an interactive pi task finishes, but skips the notification if the tmux window containing that pi agent is already visible in Hyprland.

Notifications include a Focus action that jumps back to the originating pi agent by restoring the saved Hyprland/Ghostty/tmux target.

This package is intentionally developed for an Arch + Hyprland + Ghostty + tmux + dunst workflow. If your setup differs, copy/fork it and adapt the small focus script.

Requirements

  • Linux with Hyprland
  • Ghostty
  • tmux
  • dunst or another notification daemon compatible with notify-send actions
  • notify-send from libnotify
  • dunstctl if using the example keybinds
  • jq

On Arch:

sudo pacman -S libnotify dunst jq

Your pi shell should be running inside tmux, and that tmux client should be inside a Hyprland-managed Ghostty window.

Install

From npm, once published:

pi install npm:pi-notifi

From git:

pi install git:github.com/<you>/pi-notifi

For a one-off test without installing:

pi -e git:github.com/<you>/pi-notifi

For local development from this checkout:

pi -e /absolute/path/to/pi-notifi

The package manifest loads:

index.ts

No manual symlink is required. The extension invokes the packaged focus helper at:

scripts/notifi-focus

My dunst / Hyprland setup

Hyprland binds:

bind = SUPER, X, exec, dunstctl close
bind = SUPER, N, exec, dunstctl action

Dunst mouse behavior:

mouse_left_click = do_action, close_current
mouse_right_click = close_current

Behavior:

  • SUPER X / right click: close the current notification without action.
  • SUPER N / left click: invoke the notification action. Dunst closes actioned notifications automatically.
  • For notifi notifications, the action jumps to the Ghostty/tmux location that produced that specific notification.

Commands

Inside pi:

/notifi status
/notifi test
/notifi on|enable
/notifi off|disable

on / off are persisted into the current pi session.

Configuration

Configuration is read from the first valid JSON file that exists:

  1. <project>/.pi/notifi.json
  2. ~/.pi/agent/notifi.json
  3. ~/.pi/agent/extensions/notifi.json

Example:

{
  "disabled": false,
  "defaults": {
    "urgency": "normal",
    "expireTime": 0
  },
  "events": {
    "finished": {
      "body": "Task Finished"
    },
    "error": {
      "body": "Task Failed",
      "urgency": "critical"
    },
    "aborted": {
      "disabled": true,
      "body": "Task Aborted"
    }
  }
}

Top-level fields:

| Field | Default | Description | | ---------- | ------- | ------------------------------ | | disabled | false | Disable all notifi events | | defaults | {} | Shared defaults for all events | | events | {} | Per-event notification config |

Supported events:

| Event | Default disabled | Default focus-aware | Default body | Default urgency | | ---------- | ---------------- | ------------------- | --------------- | --------------- | | finished | false | true | Task Finished | normal | | error | false | false | Task Failed | critical | | aborted | true | false | Task Aborted | normal |

Each event, and defaults, supports:

| Field | Default | Description | | ------------ | --------------------------------------- | ------------------------------------------------------------------- | | disabled | event-specific | Disable notifications for this event | | focusAware | event-specific | If true, suppress this event when the pi tmux window is visible | | title | <tmux-session>:<window-index> or pi | Notification title | | body | event-specific | Notification body | | urgency | event-specific | notify-send urgency: low, normal, or critical | | expireTime | 0 | notify-send expire time in ms; 0 requests persist until dismissed |

Environment variables with the old PI_NOTIFI_* names override JSON for quick one-off changes. Invalid JSON config files are ignored so a bad config does not break notification delivery.

Behavior

For focus-aware events, notification is suppressed only when all of these are true:

  1. pi is running inside tmux.
  2. notifi identifies the tmux session/window containing the pi pane.
  3. an attached tmux client is currently viewing that same tmux window.
  4. that tmux client maps through its process tree to a Hyprland window.
  5. that Hyprland window is on a workspace visible on a monitor.

Pane focus does not matter for notification suppression. If the pi pane is anywhere in the visible tmux window, no notification is sent. Notification actions still try to focus the original pi pane after switching to the saved tmux session/window.

If the tmux window is not visible, notifi sends a persistent notification with a Focus action:

<title: tmux-session:window-index>
<body: Task Finished | Task Failed | Task Aborted>
<action: Focus>

Only finished is focus-aware by default. error and aborted are not focus-aware by default, so enabled error/abort notifications fire even when the pi tmux window is visible. Aborted tasks still do not notify by default because the aborted event is disabled by default. Headless/print-mode pi runs do not notify.

Action target cache

Each notification gets a unique UUID target id. The extension writes that notification's jump target to:

${XDG_CACHE_HOME:-~/.cache}/notifi/targets/<target-id>.json

Each notification action captures its own target id, so multiple concurrent pi agents and long-lived notifications do not overwrite each other.

scripts/notifi-focus <target-id>:

  1. validates the target id
  2. reads the target file
  3. deletes the consumed target file
  4. prunes target files older than 24 hours
  5. switches Hyprland to the saved Ghostty workspace/window when possible
  6. switches tmux to the saved session/window
  7. focuses the original pi pane if it still exists

If no existing Ghostty/tmux client can be mapped back to Hyprland but the tmux session/window still exists, the action opens Ghostty attached to that tmux session/window. If the tmux session/window no longer exists, it exits successfully and does nothing.

Target files for notifications dismissed without action are cleaned up the next time a notifi action is consumed.

Edge cases

  • If multiple Ghostty windows are attached to tmux, notifi prefers one already viewing the target window, then one in the target session, then any usable tmux client it can map back to Hyprland.
  • If no saved/reusable Ghostty/Hyprland window exists, notifi falls back to opening Ghostty attached to the saved tmux session/window.
  • If the saved tmux session or window no longer exists, the action exits successfully and does nothing.
  • If the saved tmux pane no longer exists, the action still switches to the saved tmux window and skips pane focus.
  • If the target file is missing, malformed, or older than 24 hours when pruning runs, the action exits successfully and/or removes stale metadata.