Connect an agent to one phone.

Link your phone, save the connection in your client, and check it without sharing a key in chat.

Link a phone first.

  1. 01
    Sign in to the web app.

    Create your OnExit account, then open Phones.

  2. 02
    Link the phone you want an agent to reach.

    Use the QR flow or sign in on the iOS or Android app. Then test phone delivery before connecting an agent.

  3. 03
    Create a connection.

    Open Agents, name the connection and choose your phone, then select Connect agent. Every connection supports messages and alarms.

  4. 04
    Save, check, then try a message.

    Choose your client. Copy private configuration into its personal MCP settings, then copy the key-free check instructions into chat. Once your agent checks in, choose a first test. Follow the client steps below. Copy Agent instructions into your agent’s rules to keep updates and replies in the same conversation.

Home guides setup until a new agent has checked its connection to a linked phone. On the phone app, return after setup to refresh the connection. Once ready, Home shows your next item and a review count. Read full messages in Inbox and delivery details in Activity.

Your key stays in client settings.

Private configuration contains a key and is available during creation or rotation. Save it in personal client settings, not in chat or a project repository. Check instructions and test requests contain no key and remain available later. You can copy again during setup; Done, hide key clears the secret.

Test delivery before connecting an agent.

Once your phone is linked, choose Test phone delivery in Phones on the web, or on the phone app’s setup screen or Your phone tab. No agent key or MCP configuration is needed.

  1. Start with Message. Allow notifications and keep the phone app open for the first check.
  2. Select Send test message. For an alarm, choose Alarm and select Send test alarm only when you are ready for the phone to ring.
  3. The server schedules the test for about 10 seconds later. Delivery may take longer while the scheduler or phone catches up. Watch the test status and check Activity.

The test panel reports the server push mode, provider configuration, phone push registration and scheduler state. It keeps provider acceptance separate from a phone receipt. Only the phone can check its notification, alarm and battery settings; use the permission controls in the phone app.

Simulated push does not verify remote delivery.

If the server reports simulated push or an unconfigured provider, it cannot certify a real remote notification. An alarm may still schedule locally after the app syncs. iOS remote delivery requires configured APNs credentials; a simulator or preview is not a physical-device delivery test.

Checks refresh for up to 90 seconds while the test panel is open; Check delivery remains available afterward. Closing the panel stops checks without cancelling the scheduled test. Use the phone’s normal alarm controls to dismiss it. If a send is interrupted, Retry same test uses the original ID and does not schedule another copy. Another test explicitly creates a new test; new requests are limited to three per minute per account.

Phone tests appear in Inbox and Activity and do not consume the agent event allowance or mark an agent as connected. After delivery works, continue with agent setup. An agent test verifies the additional MCP/client path.

Set expectations once. Keep the conversation going.

In Agents, open a connection’s App setup and use the copy icon beside Agent instructions. The same prompt is available immediately after creating or rotating a key, and remains available after the key is hidden. Phone apps link to this same responsive setup page.

  1. Expand Customize instructions, choose your configured MCP or CLI integration, and edit the wording or default five-minute reply-check interval. Each version uses the matching tools or commands; it does not configure them for you.
  2. Copy the Markdown into AGENTS.md, CLAUDE.md, or the instructions/rules supported by your agent. Review it before saving. The generated prompt identifies your connection, phone and timezone and contains no API key. Edits stay only in this setup view and clear when it closes; they are not saved to your account or project automatically.
  3. The agent sends useful quiet updates, blockers and completion results in one thread per task, reads all new phone context, and continues in the same thread. Ringing, critical alerts and recurring reminders require your authorization. Each new agent message uses one event of quota; empty heartbeat messages are discouraged.

Check instructions still verify the connection without sending anything; the separate test request approves one quiet test. Agent instructions describe ongoing behavior after you add them to your rules. A running agent can check replies periodically, respecting retryAfterSeconds; a closed session needs a compatible automation to resume it. A verified webhook alone cannot wake an arbitrary agent chat. Read the thread and webhook behavior.

One thread. Messages from both sides.

Your agent starts a thread with send_message. Open Threads in the web app, or Inbox → Threads on your phone. Add context whenever you like—even several messages in a row, without waiting for the agent to ask anything.

  1. Connect your agent and ask it to send a message. Each thread belongs to that stable connection and its linked phone.
  2. Read the full thread and add your message. Text supports Markdown; code and line breaks stay readable. Your message is saved immediately, even if the agent is offline.
  3. The agent reads the same history with get_thread, or your verified receiver gets a webhook with the new message ID.
Periodic reads work without a receiver.

The agent reads get_thread( { threadId, after: 0, limit: 100}), follows nextCursor until null, then saves lastSequence for later checks. retryAfterSeconds is guidance for a running agent; it cannot wake a closed chat.

Threads, Inbox and Activity render Markdown on the web and in Android 1.18 and iPhone/iPad 1.18 builds: headings, bold, italics, strikethrough, nested lists, checklists, quotes, links, tables and fenced code blocks. Code and tables scroll within the message on small screens. Copying or reading through MCP/CLI preserves the original Markdown. Raw HTML does not execute; remote images use explicit links or local placeholders. Notification previews remain plain text.

MCP or REST message
{
  "clientMessageId": "f20e781c-62ec-47e0-8bfd-9859d8f24e3d",
  "text": "**Preview ready**\n\nAdd context anytime.",
  "title": "Website refresh"
}

Use this body for send_message or POST /v1/messages. Use a new UUID for each new message. Include threadId to continue; optionally include replyToMessageId from the same thread. After an uncertain send, retry the identical body and ID: it creates one message, one phone notification and one agent event charge. Human messages do not consume the agent allowance.

CLI
onexit threads --json
onexit thread <thread-id> --after 0 --limit 100 --json
onexit message "More context" --thread <thread-id> --json

Automatic delivery when you have a compatible receiver

In the web thread, expand Automatic delivery settings. Save your public HTTPS callback, copy its signing secret once into your receiver, then select Verify callback. Return the received challenge as JSON for the signed webhook.verify request. Settings apply to all threads for that connection. A pending callback keeps periodic reads active.

Webhook event
{
  "id": "<message-uuid>",
  "type": "message.created",
  "createdAt": "<ISO timestamp>",
  "data": {
    "threadId": "<thread-uuid>",
    "messageId": "<message-uuid>",
    "sequence": 3,
    "actor": "human"
  }
}

Every new human message after verification emits this event, including extra context added by opening the phone thread. Agent messages do not call their own receiver. No message text or API key is included. Verify OnExit-Signature as v1=HMAC-SHA256(secret, timestamp + "." + rawBody) using OnExit-Timestamp; reject stale timestamps and compare in constant time.

Store and deduplicate event IDs durably, return 2xx promptly, then fetch all new thread messages with the connection’s key. Events can be duplicated or arrive out of order. Transient failures retry up to eight attempts; periodic reads remain available after a failure. HTTPS on port 443 is required; private-network destinations and redirects are blocked.

Callback received does not mean agent continued.

Your receiver or a supported platform automation must resume the agent. Ordinary MCP installation alone does not provide an inbound webhook or wake-up capability for an arbitrary Codex, Claude, Cursor or ChatGPT chat. Thread text is context, never a substitute for platform permissions.

Read and list tools require the connection’s read scope; sending requires create. The server supplies the actor. Other agents cannot read this thread, even on the same phone. Rotation preserves threads; revocation stops agent access. Existing handoff tools keep working as before.

Install, sign in, and keep your phone connected.

In the web dashboard, choose Phones → Link phone. Scan the QR with the app, or sign in to the same account in the phone app. QR codes expire after five minutes and disappear when you close the window.

Android testers can use the APK download on their invitation page. Install updates over the existing app to preserve local settings. iPhone and iPad builds currently require the source project and Xcode; a public App Store download is not available yet.

After signing in again on the same phone, the app restores its registration and connected agents. Older installations may ask which existing phone to restore; choose “This is a new phone” only for a separate device. Your custom name and history stay with the restored phone.

Use the test icon beside a phone’s name before connecting any agent. A quiet message is the default; choose an alarm explicitly when testing ringing and permissions. Open Threads in the phone app to read or add context to a conversation.

Add it to your client.

Use the web app on the computer or device running your agent. In Agents, create a connection. Your one-time key is immediately visible and copyable. Expand App setup, choose your client, and copy the private configuration directly into personal client settings. Keep existing server entries when merging. Then reconnect or restart the client.

Return to Agents and copy check instructions into the conversation. They identify the phone, timezone and existing server without including the key. The checks send nothing. Check connection confirms the agent’s ping; copying a key or configuration does not verify installation.

This setup uses remote MCP with bearer headers. OAuth-only clients need a different connection method and are not supported by this key flow. No local server or package installation is required.

Client steps and configuration examples

The MCP server exposes a small set of tools: ping the API, get the current time, send a handoff, list handoffs and devices, cancel a handoff, and acknowledge one that arrived. Every connection supports both messages and alarms. Tools: ping, get_current_time, send_handoff, list_handoffs, list_devices, cancel_handoff, ack_handoff. Shared threads add send_message, get_thread and list_threads; see Threads and messages. The hosted server runs at the URL below, so you do not need Node, Python, a local onexit binary, or a repository checkout.

For a bounded list, pass limit (1–100) and reuse the returned nextCursor as after with the same filters until it is empty. MCP returns { items, nextCursor } when paging options are set; calls without them keep the legacy list response.

Cursor

  1. Open Cursor Settings → Tools & MCP and add a global MCP server, or open ~/.cursor/mcp.json.
  2. Merge the private configuration copied from Agents into mcpServers. Use the unique server name it provides.
  3. Save and enable/reconnect the server. Open an agent chat, then paste the key-free check instructions from Agents.

These are placeholders. Use the generated configuration for your connection. Keep credentials in personal settings. Advanced users can use Bearer ${env:ONEXIT_API_KEY} if the variable is available to the running Cursor process. Official Cursor guide.

Cursor · ~/.cursor/mcp.json
{
  "mcpServers": {
    "onexit-mcp": {
      "url": "https://api.onexit.app/mcp",
      "headers": {
        "Authorization": "Bearer aa_...",
        "X-OnExit-Timezone": "Asia/Kolkata"
      }
    }
  }
}

Use the generated configuration from Agents for your own URL, key, and timezone. Merge the server entry into your existing configuration; keep other servers in place. Each new connection has a unique server name.

Codex

  1. Open MCP servers in Settings. The underlying personal configuration is ~/.codex/config.toml.
  2. Merge the generated [mcp_servers.…] entry into that file. Preserve existing servers and settings.
  3. Save and restart/reconnect the client. Paste the key-free check instructions into the conversation.

Advanced users can replace the Authorization header with bearer_token_env_var = "ONEXIT_API_KEY" and set that variable in the client process environment. Do not add a second Authorization source. Official Codex guide.

Codex · ~/.codex/config.toml
[mcp_servers.onexit-mcp]
url = "https://api.onexit.app/mcp"
http_headers = { Authorization = "Bearer aa_...", "X-OnExit-Timezone" = "Asia/Kolkata" }

Reconnect the server, then call ping, list_devices, and get_current_time. Check the intended phone and timezone before sending. Configuration formats: Cursor MCP and Codex MCP.

Reopen setup or replace a lost key?

Expand Connection setup on the agent’s row to reopen the key-free instructions. If you lost the private configuration, choose Rotate key on that same connection. Update safely keeps the old key working for up to 15 minutes. Save the replacement configuration in your client, reconnect, and paste the key-free check instructions into chat. After ping succeeds, select Check connection and Retire old key. Your phone, scheduled handoffs, threads, and history stay with the same connection.

If a key may be exposed, choose Replace immediately. Revoke connection stops all keys for that connection. Secrets cannot be retrieved after you finish, leave, or reload; generating another replacement stops the previous replacement and keeps any existing retirement deadline. Copying alone does not confirm installation.

From a working connection to your phone.

  1. 01
    Check before sending.

    In Agents, let the agent run the check instructions. Wait for “Agent checked successfully.” If it still reports the old key, reconnect the client after updating its settings.

  2. 02
    Choose one test.

    Copy test request appears after verification. Paste it into the agent to approve one quiet message in a new thread. Open Threads on the phone and reply or add context anytime. Copying alone sends nothing.

  3. 03
    Keep the linked phone nearby.

    Allow notifications and keep the app open for this first check. Open Threads to read the conversation and Activity to see phone-reported delivery. iOS remote push depends on the configured APNs service; a simulator or mock provider does not certify delivery.

Accepted does not mean received.

The agent can confirm that the API saved the message. Only the phone can report receiving or presenting it. If nothing arrives, check the target phone, permissions and Activity before trying again. Retry an uncertain thread send with the same clientMessageId and identical text to avoid duplicates.

Send from the command line.

The CLI is currently available to beta testers building from the repository. It is not a public npm install. For setup without a checkout, use the hosted MCP setup above. With the source-built CLI on your PATH, sign in and confirm the phone before sending.

terminal
onexit login --api-url https://api.onexit.app
onexit ping
onexit doctor
onexit devices
onexit send "in 10 seconds" "Review the fix" --message "Tests pass. The pull request is ready for your review."
onexit list
After a phone and a key.

MCP and CLI both send, list, cancel, and acknowledge handoffs, and both can ping the API. CLI also has test, plus session-only devices and keys. Rename, unlink, pairing, history, billing, and the account display name stay in the web console. An agent key cannot mint keys or change billing.

onexit list keeps its legacy output with no options. Add --limit, --after, and optional --status or --order to page through a large handoff list; continue with the returned cursor until there is no next page.

Call it from a script.

Replace the example fireAt with a future ISO 8601 UTC time and use your own agent key. The key’s pinned device is selected for you, so an automated workflow cannot fan out to every phone on the account.

request
curl -X POST https://api.onexit.app/v1/alarms \
  -H "Authorization: Bearer aa_..." \
  -H "Content-Type: application/json" \
  -d '{
    "fireAt": "REPLACE_WITH_FUTURE_ISO_UTC",
    "label": "Review the deploy",
    "message": "The canary has run for ten minutes. Check errors before expanding."
  }'

How messages and alarms arrive.

Push tells the app there is a new handoff to fetch. Once an alarm has reached the phone, the operating system schedules it locally, so it can still ring after the network disappears. Use message mode for progress updates and review requests. Use alarm mode for a scheduled check or a task you need to act on promptly. You choose the mode for each scheduled handoff: MCP send_handoff accepts deliveryMode: "alarm" | "notify"; CLI uses send --mode alarm|notify. Thread send_message always sends a quiet notification. Only ring when the person requests it.

Say what changed and what to do next.

Use a short title for the result or blocker. Put the context and next action in the message.

  1. 01
    Review the fix · Message

    Tests pass. The pull request is ready for your review.

  2. 02
    Access needed · Message

    Staging needs a database permission. Check the agent thread to continue.

  3. 03
    Check the rollout · Alarm at 09:30

    The canary has run for ten minutes. Check errors before expanding.

  4. 04
    Scan still running · Message

    The first batch is complete. Three matches found; the remaining batches are still running.

These are examples. An agent can report a result, ask you to return to its thread, or schedule a check. Agree on which updates and alarms it should send.

Plans and monthly usage.

Every plan includes the same handoff to your chosen phone and unlimited phones for your account. Billing is per person. A monthly allowance covers each message or alarm an agent creates; alarms you create yourself do not count, and there is no per-handoff charge.

  1. 01
    Free · Try it with an agent

    No card required.

    $0 per month · 100 included handoffs per month

  2. 02
    Pro · Daily agent updates

    For daily updates from your agents.

    $5 per month · 5,000 included handoffs per month

  3. 03
    Ultra · More agents, more updates

    For frequent updates from multiple agents.

    $20 per month · 50,000 included handoffs per month

Manage billing on the web.

Open Plan & usage in the web app to change your plan, update your payment method, view invoices, or cancel. The phone apps show usage and link to the same page. If paid plans are unavailable, the web app shows a contact option.

Accepted is not the same as received.

Start with the MCP ping and list_devices tools. Ask your agent for a test only when you are ready to receive it. Check the key’s phone and delivery mode, connectivity, and notification permissions. An alarm can ring offline only after the phone has scheduled it locally.

A 401 means reconnect your key; 403 means the operation is not allowed; 429 means a rate or usage limit. After a network timeout, list recent handoffs before sending again—the first request may have succeeded.

In Activity, Provider accepted means the push service accepted a request. A separate phone report can show that a phone received, scheduled, or presented it. Provider acceptance does not confirm phone receipt, and a phone report does not confirm that you saw or heard it.

For agent-readable setup, tools, and failure handling, use llms.txt or the full agent reference.

Connect your agent.

Link a phone. Choose messages or alarms.
Save your client settings, then check the connection.

Get connected