# pi-notify

Kitty-first completion notifications for Pi. This repository maintains a source import of
`@smoose/pi-notify@0.1.1` with local reliability and multi-window improvements.

## Behavior

- Waits for Pi's `agent_settled` event, so retries, automatic compaction, and queued follow-ups do not notify early.
- Uses Kitty OSC 99 with Base64 payloads, an ID unique to each Pi session, and explicit `a=focus`.
- Defaults to `o=always`: notifications remain visible while the originating Kitty window/pane has keyboard focus; clicking a notification returns to that exact source window.
- Measures the entire run across automatic retries and ignores runs shorter than three seconds by default.
- Emits terminal sequences only in interactive TUI mode, never into JSON, print, or RPC output.
- Uses macOS AppleScript outside Kitty and a sanitized OSC 777 fallback outside macOS.

The root `my-pi` bundle loads this local source directly. For the unmodified upstream package, use:

```bash
pi install npm:@smoose/pi-notify
```

Do not separately install upstream when using the bundle, or notifications will be duplicated.

## Commands

- `/notify on`: enable notifications for the current session.
- `/notify off`: disable notifications for the current session.
- `/notify test`: send a notification immediately; click it to verify exact Kitty-window focus.
- `/notify status`: show the active backend, visibility policy, and duration threshold.

Command overrides are session-local. Use environment variables for persistent defaults.

## Configuration

- `PI_NOTIFY_ENABLED`: `1`/`true` or `0`/`false`; default enabled.
- `PI_NOTIFY_TITLE`: title template; default `π - {project}`.
- `PI_NOTIFY_BODY`: body template; default `{message}`.
- `PI_NOTIFY_MESSAGE_SOURCE`: `assistant`, `user`, or privacy mode `none`; default `assistant`.
- `PI_NOTIFY_MESSAGE_MAX`: maximum message characters before ellipsis; default `80`, maximum `500`.
- `PI_NOTIFY_MIN_SECONDS`: minimum complete run duration; default `3`, range `0`–`3600`.
- `PI_NOTIFY_VISIBILITY`: Kitty policy `unfocused`, `invisible`, or `always`; default `always`.
- `PI_NOTIFY_ACTION`: Kitty click action `focus` or `none`; default `focus`.
- `PI_NOTIFY_SOUND_CMD`: optional shell command run after the notification. This is trusted local configuration and executes through a shell.

Visibility policies:

- `unfocused`: notify whenever the originating Kitty window/pane does not have keyboard focus.
- `invisible`: notify only when the originating window/pane is not visible.
- `always`: notify even while typing in the originating window.

Inside tmux, enable passthrough and restart the tmux server after changing the setting:

```tmux
set -g allow-passthrough all
```

The active tmux client type is checked so a stale `KITTY_WINDOW_ID` cannot force the Kitty backend for a non-Kitty client.

## Template variables

- `{project}`: current directory name.
- `{cwd}`: current working directory.
- `{model}`: active model as `provider/id`.
- `{model_short}`: active model ID.
- `{message}`: selected message, or `Ready for input` when source is `none` or text is unavailable.
- `{user_message}`: latest user text, truncated.
- `{assistant_message}`: latest settled assistant text, truncated.
- `{duration}` / `{duration_ms}`: complete duration including retries.
- `{status}`: `ready`, or `ready · N tool errors` when tools reported errors.
- `{status_icon}`: `✓` or `⚠`. This reports observed tool errors, not a definitive task-success verdict.
- `{tool_error_count}`: observed tool error count.

Example for multiple projects without exposing assistant text on the lock screen:

```bash
export PI_NOTIFY_TITLE='π {status_icon} · {project}'
export PI_NOTIFY_MESSAGE_SOURCE=none
export PI_NOTIFY_VISIBILITY=unfocused
```

Kitty must be allowed under **System Settings → Notifications**. Self-built or unsigned Kitty binaries may not be able to publish macOS notifications.
