Push notifications¶
vmux includes an optional backend that can send APNs alerts when a pane first
enters needs_input and, optionally, error. It can also notify compatible
native clients when Agent Context verifies a new human decision. It is not
needed for the PWA or normal pane control.
No public native client is available
The native iOS companion under ios/ is in development. It is not on the
App Store or publicly available. APNs setup therefore remains for client
implementers who control their own app signing and bundle id.
Data path¶
The vmux host talks directly to Apple's APNs service over HTTP/2. There is no
vmux relay. A compatible client registers its device token at
POST /api/push/register, and vmux stores it locally in vmux-push.json.
Pane alerts use generic copy and omit names, targets, questions, and option labels. Common confirmation categories carry only the opaque pane id and the minimal input-key mapping needed by a registered action.
Agent decision notifications always use generic alert copy and opaque routing
identifiers. Decision titles, descriptions, prompts, options, transcript
content, and terminal input keys stay on the vmux server. The legacy
contextual device-registration field is accepted and stored for compatibility
but does not change notification content.
Scheduled Review digests are always generic. The payload contains only a
review_due event and the opaque server-instance identifier; queue contents
remain on the vmux server until the client fetches GET /api/review.
Install the optional backend¶
From a source checkout:
The published extra is installable as vmux-agent[push].
APNs requirements¶
You need:
- an Apple Developer team
- an APNs
.p8signing key, Key ID, and Team ID - a compatible app signed by that same team
- an
apns_topicexactly matching that app's bundle id
APNs credentials are team-scoped. A key from one team cannot push to an app signed by another.
Configure¶
Keep the key outside the repository:
push:
apns_key_path: /absolute/path/to/AuthKey_ABC123DEFG.p8
apns_key_id: ABC123DEFG
apns_team_id: XYZ1234567
apns_topic: com.example.vmux-client
environment: sandbox
on_error: false
cooldown: 30
Use sandbox for a development build and production for TestFlight or App
Store provisioning. Key paths and identifiers are YAML-only and do not appear
in API responses.
Client registration¶
A compatible authenticated client sends:
POST /api/push/register
Authorization: Bearer <vmux-token>
Content-Type: application/json
{"token":"<apns-device-token-hex>","name":"My iPhone","platform":"ios","contextual":true}
It unregisters with:
at POST /api/push/unregister.
contextual defaults to true for older-client compatibility and can be changed
by re-registering the same token, but it no longer changes notification copy.
Notifications use pane categories
vmux.confirm2, vmux.confirm3, and vmux.generic, plus
vmux.agent-decision for a foreground route to the verified Review item and
vmux.agent-review for a scheduled digest route. A client may register matching
notification actions; clients without them still receive ordinary alerts.
Agent decision notifications never contain a terminal input key and never
bypass live server revalidation.
An Agent Context notification uses this routing envelope. Treat every value as an opaque cache key and fetch the current decision after opening it:
{
"aps": {
"category": "vmux.agent-decision",
"thread-id": "vmux-agents"
},
"vmux": {
"type": "decision",
"server_instance_id": "...",
"agent_id": "...",
"decision_id": "...",
"revision": 3
}
}
The client must ignore the route when server_instance_id does not match its
active server. Alert text is fixed and generic. The payload never includes
decision titles, descriptions, prompts, source-log paths, working directories,
transcript messages, decision options, commands, tool output, or a terminal
input key.
A scheduled digest uses this privacy-minimized envelope and is sent to every registered iOS device:
{
"aps": {
"alert": {"title": "vmux", "body": "Your agent review is ready."},
"category": "vmux.agent-review",
"thread-id": "vmux-agents"
},
"vmux": {
"type": "review_due",
"server_instance_id": "..."
}
}
Alert timing¶
vmux alerts only on an observed transition into a watched state. A pane already
waiting when vmux starts does not immediately re-alert. push.cooldown, 30
seconds by default, suppresses repeats for the same pane.
An agent decision alert is scheduled once when a structured request becomes a new verified pending decision. The client fetches current state after a tap, so a resolved or changed prompt cannot be answered from stale notification data.
Review batching is disabled by default. When enabled with
PATCH /api/review/settings, normal/low structured decisions and ordinary
needs_input transitions are accumulated until the persisted due time. A due
window is claimed atomically so restarts do not duplicate a digest. Empty
windows advance without sending; a completed review resets the next due time.
Explicit runtime-provided high/critical decisions always bypass batching.
Pane errors bypass it only when urgent_pane_errors is enabled. vmux never
infers urgency from prompt wording.
Troubleshoot¶
Query GET /api/config and inspect _info.push:
configuredmeans the requiredapns_*fields are present.availablemeans the optional Python dependencies imported.devicesmust be at least one.
Common failures are the wrong APNs environment, a topic that differs from the bundle id, a device token from another environment, an unreadable key path, or a service account that cannot access the key.