@qcts33/pi-ios-notify0.4.0
Send iOS push notifications via Bark when pi completes agent turns
Untested on omp
This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.
Reports 0
No reports yet.
Readme
pi-ios-notify ๐ฑ
Send iOS push notifications via Bark when pi completes agent turns. Get notified right on your iPhone when long-running tasks finish, errors occur, or after each individual turn โ without watching the terminal.
Notifications are off until you run /ios-notify on in the session you want to hear from. Every other session โ including the pi child process of a subagent โ stays silent. See Activation.
Package: @qcts33/pi-ios-notify
Repository: forgejo.horse-carat.ts.net/qcts33/pi-extensions (tailnet-only), package packages/pi-ios-notify
How it works
pi (your Mac)
โ
โ agent completes a turn โ extension fires
โ
โผ
pi-ios-notify extension
โ
โ POST https://api.day.app/YOUR_KEY
โ { title: "โ
pi Complete", body: "โฆ" }
โ
โผ
Bark server โ Apple Push Notification service โ Your iPhone ๐ฑ
Prerequisites
- Bark iOS app โ Free on the App Store
- A computer running pi (macOS, Linux, or Windows)
- Pi 1.x (floor 1.0.0, tested on 1.2.0) โ the extension uses native
fetchandExtensionAPI. Below the floor a session shows one warning at session start; the rest of the extension still runs.
Installation
via npm
pi install npm:@qcts33/pi-ios-notify
from a local checkout
pi install /path/to/pi-extensions/packages/pi-ios-notify
Quick test (no install)
pi -e /path/to/pi-extensions/packages/pi-ios-notify
The upstream package @aslamplr/pi-ios-notify still exists on npm. Installing it gets upstream's 0.1.1,
without the changes listed under Fork provenance.
Setup
1. Get your Bark device key
- Install Bark on your iPhone
- Open the app โ you'll see your device key URL, like:
https://api.day.app/YOUR_DEVICE_KEY_HERE - Copy the
YOUR_DEVICE_KEY_HEREpart (the UUID string)
2. Configure the extension
Inside pi, run:
/ios-notify setup
Paste your Bark device key when prompted.
3. Test it
/ios-notify test
You should receive a "๐ Test" notification on your iPhone within a second or two.
Activation
Notifications are off by default and every session starts off. Only a session you activate sends:
/ios-notify on
The state lives in the running pi process and is never written to disk, so each of these starts you inactive again: /reload, --resume, /new, a fork, a session switch, a restart. Run /ios-notify on again after any of them. While the session is active the footer shows ๐ฑ, and /ios-notify off clears it.
/ios-notify test ignores the gate: it sends whenever you ask it to.
The events toggles below choose which events an active session may send. They never make an inactive session send.
Commands
| Command | Description |
|---|---|
/ios-notify on |
Activate notifications for the current session |
/ios-notify off |
Deactivate notifications for the current session |
/ios-notify setup |
Enter your Bark device key |
/ios-notify test |
Send a test notification |
/ios-notify status |
Show current configuration |
/ios-notify events <type> <true|false> |
Enable/disable notification types (agent-end, agent-settled, prompt-tools, turn-end, error) |
/ios-notify prompt-tools list |
List configured prompt tool names and labels |
/ios-notify prompt-tools add <name> [label] |
Add a tool name to watch with optional label |
/ios-notify prompt-tools remove <name> |
Remove a tool from the watch list |
/ios-notify prompt-tools clear |
Remove all prompt tools |
/ios-notify sound <name> |
Set notification sound |
| `/ios-notify icon <url | pi |
/ios-notify url <value> |
Set optional URL to open when notification is tapped (URL scheme, e.g. ssh://user@host) |
/ios-notify debug <on|off> |
Enable/disable debug logging |
/ios-notify hostname <true|false> |
Append hostname to notifications |
/ios-notify body-content <prompt|output> |
Set whether the Complete notification shows the agent's last output or your prompt |
Notification events
An active session sends the events switched on here. These toggles do not make an inactive session send; see Activation.
| Event | Default | Description |
|---|---|---|
agent-end |
โ on | Notify when agent finishes a response |
agent-settled |
โ off | Notify only when the agent is truly idle (no auto retry/compaction/continuation). More accurate than agent-end; recommended with agent-end disabled |
prompt-tools |
โ on | Notify mid-turn when a configured tool calls for user input |
turn-end |
โ off | Notify after each individual LLM turn (can be noisy!) |
error |
โ on | Notify when a tool execution fails |
Note: Enabling both
agent-endandagent-settledsends duplicate completion notifications โ one peragent_endrun plus one when the agent fully settles. For a single, accurate completion signal, useagent-end=false+agent-settled=true.
Toggle with:
/ios-notify events agent-end false
/ios-notify events agent-settled true
/ios-notify events prompt-tools false
/ios-notify events turn-end true
/ios-notify events error false
Notification body content
The "โ Complete" notification body can show either the agent's last output or your original prompt:
output(default) โ the agent's final natural-language reply, truncated to 120 characters. The notification itself tells you what the agent concluded.promptโ the prompt you typed, with the turn count (legacy behavior).
If the agent's final turn produced no text (e.g. it ended on pure tool calls or thinking blocks), output mode falls back to showing your prompt so the notification body is never empty. Thinking content is never captured.
Toggle with:
/ios-notify body-content output
/ios-notify body-content prompt
Check the current value with /ios-notify status.
Prompt tools
Prompt tools are tools registered by extensions that may ask for user input mid-turn (e.g. ask_user from pi-ask-user, safe_shell_approve from pi-safe-shell). When the LLM calls one of these tools, you get notified immediately.
Configure which tools to watch:
/ios-notify prompt-tools list
/ios-notify prompt-tools add my_custom_tool "My Label"
/ios-notify prompt-tools remove ask_user
The label is shown as the notification title suffix. Default configured tools:
| Tool | Label | Source |
|---|---|---|
ask_user |
Asking | pi-ask-user extension |
ask-user |
Asking | pi-ask-user extension |
safe_shell_approve |
Permission | pi-safe-shell extension |
Cross-extension notifications
Any extension can send a push notification by emitting an event on pi's shared event bus:
pi.events.emit("pi-ios-notify:notify", {
title: "๐ Approval needed",
body: "bash: rm -rf node_modules",
source: "safe-shell", // optional
});
pi-ios-notify listens for pi-ios-notify:notify and forwards the title and body to Bark. The emitter controls the notification content entirely. Requires an active session (see Activation) and the prompt-tools event toggle to be enabled.
See the companion extension @aslamplr/pi-safe-shell for a usage example โ it emits pi-ios-notify:notify before blocking on user approval prompts.
Custom icon
/ios-notify icon https://example.com/my-icon.png
Use default to reset to Bark's default icon, or pi to use the pi logo:
/ios-notify icon pi
/ios-notify icon default
Notification URL
Set a URL that opens when the notification is tapped. Supports any URL scheme:
/ios-notify url ssh://user@myserver # opens Termius/Blink (SSH)
/ios-notify url https://my-dashboard.com # opens Safari
/ios-notify url pi://settings # custom scheme
/ios-notify url "" # clear (no-op on tap)
Debug mode
Enable debug logging to see why notifications are or aren't firing:
/ios-notify debug on
Debug output appears as informative notifications in pi's UI, each prefixed with ๐. Each event handler logs its name, the session gate, config state and throttle flags:
๐ tool_call active=true name=ask_user inPromptTools=true promptTools=true throttled=false
๐ agent_end active=true agentEnd=true
When nothing reaches the phone, the logged active= says whether the activation gate or the event's own toggle stopped it.
Turn off with:
/ios-notify debug off
Notification sounds
Bark supports various iOS notification sounds. Change with:
/ios-notify sound birdsong
Common sounds: default, minuet, alarm, anticipate, birdsong, bloom, calypso, chime, descant, electronic, fanfare, horn, ladder, mazurka, nightingale, piano, rocket, sirius, strums, suspense, telegraph, tiptoes, tritone, tuberose, twinkle.
Configuration file
The extension stores its config at ~/.pi/ios-notify.json. You can edit it directly:
{
"barkKey": "YOUR_DEVICE_KEY",
"barkServer": "https://api.day.app",
"events": {
"agentEnd": true,
"agentSettled": false,
"promptTools": true,
"turnEnd": false,
"error": true
},
"promptTools": {
"ask_user": "Asking",
"ask-user": "Asking",
"safe_shell_approve": "Permission"
},
"sound": "default",
"title": "pi",
"bodyContent": "output",
"icon": "",
"showHostname": false,
"url": "",
"debug": false
}
Add more tools directly in the config:
{
"promptTools": {
"ask_user": "Asking",
"safe_shell_approve": "Permission",
"my_custom_tool": "Waiting"
}
}
Custom Bark server
If you self-host Bark, set the server:
{
"barkServer": "https://bark.yourdomain.com",
"barkKey": "YOUR_KEY"
}
What notifications look like
| Event | Notification |
|---|---|
| Agent completes response | โ
pi Complete โ "refactor the auth module to use JWT" (3 turns) |
| Prompt tool called mid-turn | ๐ฌ pi Asking โ ask_user |
| Prompt tool called mid-turn | ๐ฌ pi Permission โ safe_shell_approve |
| Cross-extension event emit | ๐ฌ pi {emitter's title} โ {emitter's body} |
| Each turn | ๐ pi Turn โ Turn 3 finished |
| Tool error | โ ๏ธ pi Error โ Error in bash: command not found: foobar (includes error detail) |
Privacy
- Only the Bark device key and notification content are sent to the Bark server
- The notification body โ your prompt, or the agent's last text truncated to 120 characters โ is the only conversation content that leaves the machine
- Bark stores notification content encrypted on their server
- You can optionally set up end-to-end encryption in the Bark app
Project structure
pi-ios-notify/
โโโ index.ts # Extension entry point (no compilation needed)
โโโ utils.ts # Pure utility functions
โโโ test/ # Vitest suite for the pure utilities
โโโ defaults.json # Default icons/images
โโโ package.json # Package manifest with pi.extensions entry
โโโ README.md # This file
Standard npm package layout โ the pi.extensions field in package.json tells pi where to find entry points.
Development
This package is a workspace member of the pi-extensions monorepo. Everything runs from the repo root through npm workspaces:
npm install # once, at the repo root
npm test # vitest for this package, node --test for the others
npm run verify # lint + typecheck + tests + pack check
Load for testing:
pi -e /path/to/pi-extensions/packages/pi-ios-notify
Reload changes:
/reload
Tests
npm test
Runs vitest on the extracted utility functions (test/utils.test.ts):
formatPromptโ truncation, edge casespluralizeโ singular, plural, auto-pluralizeonOffโ boolean to on/offparseBoolโ all truthy/falsy strings, edge cases
โ๏ธ No Warranty
THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. The authors make no representations that this extension will deliver notifications reliably or in a timely manner. You are responsible for testing notification delivery and configuring appropriate settings.
License
MIT โ see LICENSE, which carries upstream's copyright notice as well as this fork's.
Fork provenance
This package is qcts33's fork of aslamplr/pi-ios-notify,
taken from upstream 0.1.1 and published under the @qcts33 scope. On top of upstream's 0.1.1 it adds:
- an
agent-settledevent, driven by pi'sagent_settledevent, as a more accurate completion signal thanagent-end - a
body-contentsetting that puts the agent's last output in the notification body instead of your prompt - a 5-second fetch timeout and fire-and-forget delivery, so a slow Bark server cannot stall the agent loop
- notifications only in a session the user activated with
/ios-notify on; every other session, including the childpiprocess of a subagent, starts silent
Upstream is kept as a read-only remote: upstream fixes are cherry-picked into this fork, and this fork's changes are not upstreamed automatically.
Credits
- Bark โ the wonderful free iOS push notification app
- aslamplr/pi-ios-notify โ the upstream extension this fork descends from
- Inspired by doublezz10/opencode_ios_notifications, Stephanvs/opencode-ntfy, and blanboom/bark-notification-for-claude-codex-opencode