# @gamaraan/desktop-notify

A self-contained [pi](https://github.com/earendil-works/pi-coding-agent)
extension that surfaces completion, error, and model-requested notifications
through terminal protocols and best-effort native desktop toasts.

## Features

- Kitty OSC 99, OSC 9, and BEL terminal output.
- tmux passthrough, Zellij BEL fallback, and cmux surface routing.
- Linux `notify-send` → `gdbus`, macOS `/usr/bin/osascript`, native Windows
  `powershell.exe` WinRT toast, and WSL Windows-host routing with Linux fallback.
- Completion/error delivery at `agent_settled`, so retries and queued follow-ups
  produce one final notification.
- Side-effect-free programmatic client at `@gamaraan/desktop-notify/client`.
- Optional LLM-callable `notify` tool, disabled by default.
- No helper installation, shell lookup, raw stdin listener, or terminal probe.

Desktop delivery is deliberately best-effort. In-band output is emitted first;
missing binaries, locked-down desktops, unavailable session buses, and child
launch failures are silent.

## Install

```bash
pi install npm:@gamaraan/desktop-notify
```

From a checkout, add the package or `src/index.ts` to the pi extension list.
Restart pi after changing extension configuration.

## Configuration

Flags take precedence over environment variables, which take precedence over
built-in defaults:

| Flag | Environment | Default | Meaning |
| --- | --- | --- | --- |
| `--notify-completion on\|off` | `PI_NOTIFY_COMPLETION` | `on` | Final successful settlement |
| `--notify-error on\|off` | `PI_NOTIFY_ERROR` | `on` | Final error settlement |
| `--notify-tool on\|off` | `PI_NOTIFY_TOOL` | `off` | Register the model tool |

Global and desktop controls:

| Variable | Effect |
| --- | --- |
| `PI_NOTIFICATIONS=off\|0\|false` | Suppress all terminal and desktop output |
| `PI_NO_DESKTOP_NOTIFY=1` | Keep terminal output, suppress desktop fan-out |
| `PI_NOTIFY_PLATFORM=auto\|linux\|macos\|windows\|wsl\|off` | Select or disable desktop strategy |
| `PI_NOTIFY_OSC99_RICH=1` | Opt into structured Kitty OSC 99 metadata |

Every notification requires a TTY. Print, JSON, and RPC contexts are silent.
The extension never automatically produces a waiting-for-input notification;
ask-tool owns that future EventBus request.

## EventBus integration

Sibling extensions remain standalone and do not import this package. When both
are loaded, they may broadcast a string or documented object:

```ts
pi.events.emit("desktop-notify:request", {
  title: "Ask",
  body: "Waiting for input",
  type: "ask",
});
```

Without a listener this is a no-op. Keep the existing `ctx.ui.notify` behavior;
EventBus delivery is additive and best-effort. Do not use a dynamic-import
recipe or make desktop-notify a required dependency.

## Client API

```ts
import { notify, isAvailable } from "@gamaraan/desktop-notify/client";

if (isAvailable()) notify({ title: "Build", body: "Complete" });
```

The client imports no pi registration APIs. It validates plain objects, bounds
fields, and sanitizes terminal-bound text before dispatch.

## Native delivery limitations

- Linux needs a session D-Bus address or `$XDG_RUNTIME_DIR/bus` and either
  `notify-send` or `gdbus` on `PATH`.
- macOS uses only the built-in `/usr/bin/osascript`.
- Windows uses one static, base64-fed PowerShell WinRT command. Delivery can be
  unavailable on locked-down, Server Core, or hosts without an interactive
  notification identity; no third-party PowerShell module is installed.
- WSL prefers a resolved `powershell.exe` host path and otherwise tries Linux
  D-Bus. A mocked CI test proves routing, not native toast delivery.

Before a release, run the manual smoke checklist in `AGENTS.md` on available
Linux, macOS, Windows, and WSL hosts. Record OS, terminal, multiplexer, and
result in release notes.

## Development

```bash
bun install --frozen-lockfile
bun run typecheck
bun test
bun run verify:package
```

Tests use an injected runtime and never spawn real notifiers. See
[`AGENTS.md`](./AGENTS.md) for architecture, guardrails, parity notes, CI, and
future improvements. The detailed implementation blueprint is
[`IMPLEMENTATION_PLAN.md`](./IMPLEMENTATION_PLAN.md).

## License

MIT. See [LICENSE](./LICENSE). Notification behavior is ported from Oh My Pi,
which is itself a pi fork; their copyright notices are retained.
