Notifications while Pincer is closed (iOS)
On iOS, Pincer can only post notifications while it’s running and connected. To get notified about replies, approvals and questions while it’s closed, pick a mode in Settings → Notifications → While Pincer is closed:
| Mode | Server needed | How fast |
|---|---|---|
| Background refresh | No | Delayed. iOS decides when Pincer checks. |
| Push relay | Yes: a self-hosted relay and an APNs key | Instant. |
| Off | No | You’re notified only while Pincer is open. |
Background refresh is the default until you enter a relay URL. If you already have a relay set up, Pincer keeps using Push relay.
On macOS you don’t need any of this. Mac notifications arrive while Pincer is running and connected, and this setting only exists on iOS.
Background refresh
Section titled “Background refresh”In Settings → Notifications, Background refresh shows a note while Low Power Mode is on. The note updates when the power mode changes; it does not change your notification preferences.
No server, no Apple Developer key. Turn it on and Pincer does the rest:
- iOS wakes Pincer now and then, even when it’s closed.
- Pincer briefly connects to each saved gateway.
- It posts a notification for each new reply, approval and question since the last check.
- It disconnects.
It’s not instant
Section titled “It’s not instant”iOS decides when, usually 15 minutes to a few hours apart, depending on how often you use Pincer and your battery. It pauses in Low Power Mode, and stops after you swipe Pincer away in the app switcher until you open it again.
- Background App Refresh has to be on for Pincer, under Settings → General → Background App Refresh in iOS. If it’s off, Settings → Notifications in Pincer shows a warning with a button that opens iOS Settings. If your device restricts it, Settings says “Background App Refresh is restricted on this device”.
- Each gateway has to be reachable from your phone when iOS checks, for example with Tailscale connected. A gateway Pincer can’t reach is skipped until the next check.
If you need notifications right away, use a push relay.
What you’re notified about
Section titled “What you’re notified about”- Replies to your chats that finished and are unread. You get up to 10 per gateway per check, the newest first. If more chats have replies, one silent summary reports how many remain. The summary does not open an individual chat; those chats stay unread in the chat list.
- Approvals that are still waiting.
- Questions an agent is waiting on you to answer.
Approvals and questions always notify, even for hidden automation and slash-command chats. Replies skip subagents, archived chats, and hidden automation and slash-command chats. To include automation or slash-command chats, turn on Show Automations or Show Slash Commands in the chat list’s Organize menu.
A check that finds several new items plays one sound, for the first notification; the rest arrive silently. After each check the app icon’s badge shows your unread chats, as it does while Pincer is open. If a gateway couldn’t be reached, the badge stays as it was.
The first check after you set it up only records a starting point, so you don’t get a flood of old chats.
Unlike push, these notifications include the message preview, the same as the ones Pincer posts while it’s open.
Turning off Notify about replies and approvals stops background refresh too.
Checking it works
Section titled “Checking it works”Under While Pincer is closed, the Last checked row shows the live relative age of Pincer’s last check and how it went, such as “Up to date”, “3 new” or “Couldn’t reach Home”. Use it to troubleshoot: “Couldn’t reach Home” means the gateway wasn’t reachable, “Stopped early” means iOS cut a check short, and Not yet means iOS hasn’t run a check.
Notifications look and group the same as the others in Pincer, one thread per chat. Tap one to open the chat. You can answer an approval from its notification. See Answering from a notification.
A reply you already got while Pincer was open isn’t notified again.
Push relay
Section titled “Push relay”Push relay gives instant notifications, but you have to run a small server.
Why a relay
Section titled “Why a relay”iOS gives a suspended app no network, so Pincer can’t keep its connection to the gateway open. Only Apple’s push service (APNs) can wake it, and only a server holding the APNs key of the team that signed the app can send those pushes.
Your gateway sends notifications as standard Web Push instead. The relay is a small server that turns one into the other:
Gateway ──Web Push (encrypted)──▶ relay ──APNs──▶ iPhone ──▶ Pincer decrypts itThe gateway pushes when a reply finishes, an exec approval is waiting, an agent asks a question, or a task fails.
What the relay and Apple can see
Section titled “What the relay and Apple can see”- Not the content. Each notification is end-to-end encrypted (RFC 8291) to a key that exists only on your device. A notification service extension decrypts it on the phone, so neither the relay nor Apple can read it.
- Not much, even decrypted. The gateway sends only a generic title, such as “OpenClaw agent finished”, and which chat or approval it’s about. It never sends message content. Pincer loads the content when you open the notification.
- Not your device token. The relay seals the APNs token into an opaque id, so the gateway never sees it.
- Nothing stored. The relay keeps no database.
The encryption keys are separate for each gateway and stored in the Keychain as this device only. Removing a gateway from Pincer unsubscribes it and deletes its keys.
Set up the relay
Section titled “Set up the relay”The relay is a Node server with no dependencies. The easiest place to run it is the gateway machine. You’ll need:
- Node.js 20 or newer;
- Tailscale on that machine, for HTTPS;
- access to the Apple Developer account that signs your copy of Pincer.
-
Create an APNs key. At developer.apple.com → Keys, click +:
- Key Name:
Pincer Push Relay; - enable Apple Push Notifications service (APNs), then Configure;
- Environment: Sandbox & Production;
- Key restriction: Team Scoped (All Topics), or Topic Specific with
chat.pincer.ios.
Download
AuthKey_XXXXXXXXXX.p8. You can only download it once, so keep a copy. Note the Key ID and your Team ID. - Key Name:
-
Install the relay. On the gateway machine, from a checkout of the Pincer repo:
Terminal window cd push-relaycp ~/Downloads/AuthKey_XXXXXXXXXX.p8 AuthKey.p8./install-service.shThe first run creates
.envwith a randomRELAY_SECRET. SetAPNS_KEY_IDandAPNS_TEAM_IDin it, then run./install-service.shagain. It installs a launchd service on macOS, or a systemd--userservice on Linux, and checks that the relay answers onhttp://127.0.0.1:8787. -
Publish it over HTTPS:
Terminal window ./install-service.sh --serve# or by hand:tailscale serve --bg --https=8443 http://127.0.0.1:8787The URL looks like
https://gateway-host.your-tailnet.ts.net:8443. Iftailscale servecomplains about HTTPS, turn on MagicDNS and HTTPS Certificates in the Tailscale admin console. The relay has to be reachable from both your iPhone and the gateway. -
Turn it on in Pincer. See the next section.
Other HTTPS front ends, such as Caddy or a Cloudflare Tunnel, work too. The push relay README has every option.
Turn it on in Pincer
Section titled “Turn it on in Pincer”On your iPhone or iPad:
- Go to Settings → Notifications.
- Keep Notify about replies and approvals on, and allow notifications when iOS asks.
- Set While Pincer is closed to Push relay.
- Enter the relay’s URL under Push relay, then tap return.
Each gateway gets a row with its push status. It should show Push on within a few seconds.
To test it, send a message, then close Pincer from the app switcher before the reply finishes. You should get an “OpenClaw agent finished” notification that opens the chat.
The relay URL has to start with https://. Plain http:// only works for localhost, 127.0.0.1 and ::1. Turning off Notify about replies and approvals, or choosing another mode, turns push off.
Status
Section titled “Status”| Status | What it means |
|---|---|
| Push on | Subscribed. The gateway pushes through the relay. |
| Waiting for APNs | iOS hasn’t given Pincer a device token yet. Check that notifications are allowed for Pincer in iOS Settings. |
| Relay must be https:// | The URL isn’t https://. |
| Gateway has no Web Push | The gateway doesn’t support push.web.subscribe. Update OpenClaw. |
| Push off | Notifications are off, the mode isn’t Push relay, or there’s no relay URL yet. |
| Not connected | Pincer subscribes each time it connects. Open the gateway. |
| Anything else | An error, such as “Push relay refused registration (…)”. Usually the phone can’t reach the relay. |
To check the relay from your phone, open https://…:8443/healthz in Safari. It should show {"ok":true}.
Approving from a push
Section titled “Approving from a push”Approval pushes have the same actions as Pincer’s own notifications: Allow once, Always allow and Deny. A push doesn’t know whether Always allow is permitted, so it always offers it. If it isn’t, you get a follow-up saying “Always allow isn’t available for this command.” with Allow once and Deny. See Answering from a notification.
If a push can’t be decrypted, for example because you removed the gateway, iOS shows a generic “New notification” alert instead.
No double alerts
Section titled “No double alerts”Once push is working for a gateway, you won’t get the same notification twice:
- while Pincer is in the background, it stops posting its own notifications for that gateway and leaves it to push, except when catching up on what the gateway didn’t push;
- while Pincer is open and connected to that gateway, pushes from it are hidden.
Catching up
Section titled “Catching up”When a push arrives, iOS also wakes Pincer briefly so it can catch up, the same way background refresh does:
- the app icon’s badge updates to show your unread chats;
- replies, approvals and questions the gateway didn’t push get their own notification, with the message preview.
Anything already pushed, by this push or one still in Notification Center, isn’t notified again.
iOS decides whether to wake Pincer, and may skip it to save battery. It doesn’t wake Pincer after you swipe it away in the app switcher, until you open it again. The pushes themselves still arrive either way.
Catching up needs an up-to-date relay. To update it, pull the latest Pincer repo on the relay machine and run ./install-service.sh again. An older relay still delivers pushes, but doesn’t wake Pincer.
Managing the relay
Section titled “Managing the relay”./install-service.sh --print # show the service definition./install-service.sh # reinstall after editing .env or upgrading Node./install-service.sh --uninstallOn Linux, run sudo loginctl enable-linger $USER so the relay keeps running while you’re logged out.
Logs are in ~/Library/Logs/pincer-push-relay.log on macOS, or journalctl --user -u pincer-push-relay on Linux. The relay logs one line per push:
InvalidProviderTokenor403: the Key ID, Team ID or.p8don’t match, or the key doesn’t allow this environment or bundle id.BadDeviceToken: the token is stale. Reopen Pincer.DeviceTokenNotForTopic: the key is Topic Specific for a different bundle id.- No
pushlines at all: the gateway can’t reach the relay.
More fixes are in Troubleshooting.