@agimon-ai/po-notification
Desktop notifications and an animated shell-tab title for Po sessions.
Package details
Install @agimon-ai/po-notification from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@agimon-ai/po-notification- Package
@agimon-ai/po-notification- Version
0.0.0-alpha.40- Published
- Oct 21, 2026
- Downloads
- 3,933/mo · 3,933/wk
- Author
- agiflow-ai
- License
- BUSL-1.1
- Types
- extension
- Size
- 139.7 KB
- Dependencies
- 2 dependencies · 1 peer
Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@agimon-ai/po-notification
Native push delivery, notification text helpers, and shell-tab title utilities for Po sessions.
Long agent runs are worth walking away from. This package supplies the native push sender and /notify command. Hosts own notification
routing through the shared po/notification service and live session entries.
What it does
| Surface | Behavior |
|---|---|
| Shell tab title | π - <session or first prompt> - <repository>, with a braille spinner while the agent works |
| Notification API | caller-authored notices through the shared po/notification Cordis service |
| Mid-run | server-derived native push for each dialog during a run, parent sessions only |
| At rest | server-derived native push for settled parent runs with no queued follow-up; requires host execution state, skipped for sandbox sessions |
The package exports shell-title controllers and a system-notification helper (cmux notify, then
osascript on macOS), but does not install a terminal router or shell-title lifecycle itself.
The /notify command calls the active headless client's notification API, which appends a versioned
po-notification session entry for live clients and the native push subscriber.
Service usage
Callers should discover the optional service through Cordis and request delivery without depending on a particular host:
import { PO_NOTIFICATION_SERVICE, readPoNotificationService } from '@agimon-ai/po-core/notification';
ctx.inject([PO_NOTIFICATION_SERVICE], (notificationContext) => {
void readPoNotificationService(notificationContext)?.request({
body: 'Deployment needs approval',
level: 'warning',
});
});
body is required. title, subtitle, and level are optional, and level accepts info,
warning, or error. Entry normalization defaults title and subtitle to empty strings and level to
info. A host must provide the optional service. This package does not wrap Pi's ui.notify API.
Browser delivery
po-web shows full notification text only for entries received by a currently open page. Every connected
page receives live notification entries for every attached session, not only the focused session. Permission
is requested only from an explicit settings action.
Browser Web Push is not supported. Closed-app delivery uses the paired native iOS or Android app,
with explicit notification permission and native push enrollment. The server subscribes once to live
notification entries across all sessions, even with no client sockets connected. It also derives
"Input needed" (Po needs your input) and "Run finished" (Po finished) pushes from live hub events,
without adding transcript entries. It never reads history
for push, and has no durable outbox or replay. Enrollment is persisted on the trusted device record;
revocation, token rotation and remote disable are rechecked before queued work is dispatched.
Native push server credentials
Add these four variables to the server user's ~/.zshrc (use absolute paths):
export PO_APNS_KEY_FILE="$HOME/.po-secrets/AuthKey.p8"
export PO_APNS_KEY_ID="ABCDEFGHIJ"
export PO_APNS_TEAM_ID="KLMNOPQRST"
export PO_FCM_SERVICE_ACCOUNT_FILE="$HOME/.po-secrets/firebase-service-account.json"
Restrict the directory to the server user (chmod 700) and credential files to owner read/write
(chmod 600). Never commit, paste into logs, or distribute these files with the app. Start Po from a
shell that inherited these variables. GUI or service launches may not read ~/.zshrc; configure their
launch environment explicitly. Restart the server after changing credentials or variables: files and
key material are validated once at startup. Missing or invalid credentials disable only that provider,
with a redacted diagnostic. No provider credentials are read from a session's environment.
For Apple, provision the company ai.po.app App ID with Push Notifications, sign the native app with the
matching entitlement and provisioning profile, and create an APNs signing key in the Apple Developer
team. The server topic is fixed to ai.po.app. The native build-only variable
PO_NATIVE_APNS_ENVIRONMENT selects development or production to match the signed entitlement;
it is not a server credential. At runtime the native app reads the provisioning profile through
expo-application, falling back to production for App Store/TestFlight installs without a profile,
and registers its token with that environment for server routing. iOS push enrollment
refuses a different application ID, including the previous ai.agimon.po development app. Rebuild and
pair the company iOS app with its matching profile; old iOS installs are a separate app identity.
For Firebase, register Android package ai.agimon.po, enable the FCM HTTP v1 API, and grant a service
account permission to send FCM messages. The server reads client_email, private_key, and
project_id from its service-account JSON, not from a separate project environment variable.
The native build-only PO_NATIVE_ANDROID_GOOGLE_SERVICES_FILE points to the matching Android
google-services.json. This client configuration is not the server service-account private key.
Rebuild and reinstall the app when changing native build configuration.
Provider rejections produce redacted Native push <provider>: <outcome> <status> <reason> notices;
status and allowlisted APNs reason are included when available, never tokens, text, or keys.
Privacy: native push carries the full notification title, subtitle and body, subject to provider payload limits. Apple or Google and the device lock screen can receive that text, including sensitive agent output. This is not generic-copy-only delivery. Do not enable it for content you cannot share with those providers or display on the lock screen.
Delivery is bounded, best effort, and timeout-limited, not guaranteed. FCM uses TTL 0 and APNs uses expiration 0, so providers are asked not to retain notifications for offline delivery. This is an offline-retention ceiling, not a guarantee that every background or terminated app receives a notice. Excess pending work is dropped. Invalid endpoints are conditionally cleared without deleting a rotated token. Physical-device verification remains blocked until signed Apple/Firebase builds, credentials, and paired devices are available; source tests do not establish real-device delivery.
Forgetting a paired host first requires successful remote device revocation. If the host is unreachable or revocation fails, Po keeps local keys so you can reconnect and retry. A confirmed revocation is checkpointed so interrupted local key deletion can finish after a restart. Revocation cannot recall notifications already submitted to Apple or Google.
The shell title
The title is animated from a worker thread, so a busy agent turn never stalls the spinner. The worker is unreferenced, so a pending frame cannot hold the process open. If worker threads are unavailable, or the worker fails or exits, the last command replays on the main thread.
Titles are only written to an attached terminal: rpc sessions and headless ones get none, so
escape sequences never end up in machine-read output.
Quiet by design
- Server-derived pushes are silent for child sessions.
- Dialogs notify only during a run, once per dialog id. A new run resets deduplication.
- A finished push requires the host to report idle with no pending follow-up messages.
- Missing execution-state readers, including sandbox mirrors, skip completion pushes and log one redacted notice per session. Dialog pushes still work.
Installation
Po depends on this package and activates it as fixed host core, so a Po install already has
it. It is not selectable from .po/modes.yaml.
The server loader uses /extensions/server, built from src/extensions. The root export contains
reusable notification helpers and types. The session command delegates to the host client; this package
has no Pi entry, notification wrapper, or automatically installed shell-title controller.
License
Business Source License 1.1: free for personal use, organisations under USD 1M revenue, non-profits and education. See LICENSE and https://agimon.ai/licensing.