# The macOS app, in depth

URnetwork on the Mac is built from the same Xcode project as the iPhone and
iPad app: one codebase, one engine, two window shapes. You use it like a VPN
(connect, and your traffic appears from somewhere else), but it exits through
real home connections shared by other members, not through datacenters. This
tour covers the Mac-shaped parts in full and walks the shared features with
enough depth to use them; where the behavior is identical to iOS, the
[iOS tour](/docs/tour-ios) has the exhaustive version. For install and first
connect, see [getting started on macOS](/docs/getting-started-macos); for
what member-run exits change, the [overview](/docs/overview).

## How the app is built

Two processes, like every serious VPN on Apple platforms:

- **The app** (bundle `network.ur`) is the window and menu-bar extra.
- **The tunnel extension** (`network.ur.extension`) is an
  `NEPacketTunnelProvider` network extension that macOS starts and
  supervises. Your traffic moves through this process, which means your
  protection never depends on the window being open.

The app talks to the tunnel over a local device RPC (a private control
channel between the two processes), so it can attach to a tunnel that is
already running. Quit and reopen the app mid-session, or crash it, and it
adopts the live tunnel rather than restarting it. This is also why macOS
asks you to approve a VPN configuration on first connect: the extension is a
system-managed component, and the OS requires consent.

The app requires macOS 13.5 or later, and everything is open source at
[github.com/urnetwork](https://github.com/urnetwork), so claims like "the
data path logs nothing" can be checked in code rather than taken on trust.
No independent audit covers the protocol or the operator's server code,
where the privacy claims live. Two 2025 third-party assessments cover other
surfaces: a penetration test of the web application and API, and a Leviathan
Security Group MASA AL2 assessment of the Android app, which passed. Neither
covers the Mac app. The [threat model](/docs/threat-model) records both and
their limits.

## The window: a sidebar with four sections

The main window is a split view. The sidebar has the same four sections as
the iOS tabs (**Connect**, **Account**, **Leaderboard**, **Support**), with
the selected section filling the rest of the window.

### Connect

The big globe is the connect button. The status line under it reads
**Connected to N providers**, and clicking that line opens **Provider
Locations**: a spinnable globe over the list of providers actually carrying
you right now. Expect several at once, commonly three to eight. Your client
runs two sets side by side (a quality set for HTTPS, a speed set for
everything else) and pins each site to one provider, so the picture is
plural by design while any single site still sees one stable address. Slow
or vanished providers are replaced automatically; one going offline
mid-stream costs at most a brief stall while that site moves to another in
your set, and if a whole session drags, reconnect to draw a fresh set. The
[overview](/docs/overview) explains the path each connection takes, why it
stops at four legs, and what each party along it can and cannot see.

Below the globe sits the details drawer: your selected location, **Connect
options** (connection mode, Fixed IP, Strong Anonymization, Post Quantum
Encryption), the Remote / Blocked / Local stats cards that open client
contracts, split rules and the DNS panel, and the **Block ads and trackers**
toggle. Provide mode is not here. It lives in Account → Settings.

| Setting | Default | Effect | Main cost |
|---|---|---|---|
| Connection mode | Auto | Auto runs both provider sets and routes each packet to the fitting one | Web or Streaming commit to a single set |
| Fixed IP | Off | Narrows the window to one provider, so every site sees one steady address | Gives up the plural exit |
| Strong Anonymization | On | Forbids a direct client-to-provider path, so a provider never sees your real IP | Slower than the direct path |
| Post Quantum Encryption | On | Seals the session end to end to the provider, so the operator carries ciphertext | Skips providers it cannot seal with |
| Block ads and trackers | Off | Filters ads and trackers out of everything the tunnel carries | Filtering is tunnel-wide, not per-app |

- Turning Strong Anonymization off is direct mode: faster, and that provider
  then sees your real address.
- The seal is fail-closed. While Post Quantum Encryption is on, the client
  will not send or accept application data in the clear: a provider it
  cannot establish a sealed session with is skipped, not used unsealed. The
  cost is availability, not confidentiality — you lose that provider, not
  your encryption. Every current provider build speaks the responder side,
  so that is uncommon. Switch the setting off and traffic can take the
  standard path again. No app yet shows a per-connection sealed-or-not
  verdict.

A provider is another member's real connection; the platform is the operator
in between, matching you to them. A provider sees where the traffic it
carries goes, the view your ISP has of you today, but not what is inside,
because nearly every site seals its own contents with HTTPS. By default it
never learns your real IP, which stays with the platform. The platform, in
turn, keeps almost nothing: your address is held as a keyed one-way hash
(scrambled with one secret key, not reversible) of its surrounding address
block rather than the address itself, and the transfer ledger records byte
counts between client ids, never the sites you visit. A geographic lookup
does file an approximate city against each connection, so the coarse where
is known; the what never is. With both defaults on, a provider never learns
who you are and the operator cannot read what you send, so no single party
holds both your identity and your activity.

| Mode | Operator sees | Provider sees | Default and availability |
|---|---|---|---|
| **Relayed sealed** | your account and source connection, which providers you are on, and ciphertext with its timing and volume | destinations it egresses and a device/contract id, **not** your real IP | the shipped default: Post Quantum Encryption, on in the connect drawer |
| **Relayed standard** | your account and source connection, which providers you are on, and the destinations and packet bytes inside | destinations it egresses and a device/contract id, **not** your real IP | only with **Post Quantum Encryption** switched off |
| **Direct** | less relay involvement | **your real IP** and the destinations it egresses | opt-in: switch off **Strong Anonymization** |

Limit: nothing verifies that the providers offered to you are independent of
each other or of the operator, and the operator can run providers itself.
The [threat model](/docs/threat-model) works these rows against named
adversaries, including a hostile operator, and is explicit about where each
one fails.

Click the location card and the provider list opens. On the Mac it slides in
as a panel beside the connect view rather than a sheet, and the toolbar's
**Show Provider List** button toggles it too. Browsing it lists countries,
each with a live count of providers online; type a place name into **Search
providers** and a **Cities** section appears in the results. City-level
targeting is something you search for, not scroll to. Every location is a
member's device physically there: the platform geolocates the connection it
observes, and an address that looks like a datacenter or a VPN is demoted
rather than trusted. "Best available" optimizes for speed near you; a
specific location makes you appear there.

### Account

Identity and plan live here:

- **Plan.** Free is a real daily data allowance; UR Pro is a large monthly
  one at $5/month or $40/year. Current numbers at
  [ur.io/products](https://ur.io/products).
- **Your providing activity.** Where sharing is set up, with what yours has
  carried itemized. Settings links it as "Uses the UR Protocol";
  [ur.xyz](https://ur.xyz) documents how the rewards for participating work.
- **Balance codes.** One-time data top-ups: a gift card for data, no
  subscription attached.
- **Blocked locations.** Countries you never want to exit through.
- **Provider identities.** The providers your client currently holds a
  verified sealed session with.
- **The post-quantum identity panel.** Covered below.
- **Settings.** Where provide mode, the kill switch, blocked locations,
  start-at-login, your seedphrase and sign-in methods, and account deletion
  all live.

The Settings toggles at a glance:

| Setting | Default | Effect | Main cost |
|---|---|---|---|
| Provide mode | Never | Shares your Mac's spare bandwidth publicly, or with your own devices only | Every byte carried counts against an ISP data cap |
| Kill switch | Off | Refuses local fallback, so traffic stops rather than leaking when no provider is reachable | No traffic when providers fail |
| Launch URnetwork on system startup | Off | Starts the app at login through macOS's own login-items service | An entry in System Settings → Login Items |

Starting without an email is a first-class path here. **Create Instant
Account** on the login screen makes a real, permanent network in one click,
secured by a seedphrase the platform generates and shows once, immediately
after creation. Save it: it is the only way back in, the operator keeps only
hashed forms of it, and with it saved the account outlives this Mac. Account
is then where you can add any other sign-in method (Apple, Google, email or
phone, Solana, Bittensor) to that same network, keeping balance and history.
An email or phone is your sign-in and recovery path, nothing more, and the
seedphrase and wallet paths, with on-chain USDC payment, let an account
carry no email, name, or card at all. An **auth code** generated on any
already-signed-in device is the fastest way to bring your Mac onto an
existing account.

### Leaderboard

Top providers by data moved, never anything about anyone's browsing. Provide
from your Mac and you can appear here, publicly by network name or
privately, unnamed. If you do not provide, you are simply not on it.

### Support

Plans, help, feedback, and community links, with the ability to attach
client logs to a report: the normal path when something breaks. Outside the
app, feedback.ur.io works from any browser; security findings go to
security@ur.io under the disclosure policy at ur.io/vdp.

## The menu-bar extra

URnetwork also lives in the menu bar, and it is the fastest way to use the
app day to day:

- **Status at a glance.** Connected and Providing, each with a check or
  cross.
- **Connect / Disconnect.** One click, no window needed.
- **Show.** Bring the main window back.
- **Quit URnetwork.** Disconnects and exits.

Close the window and the app keeps running in the menu bar; the tunnel keeps
running regardless, because it is a separate system-managed process. ⌘Q is
deliberately not a quit either: it hides the window and drops the app out of
the Dock into the menu bar. **Quit URnetwork** here is the real exit, and it
takes the tunnel down with it.

## Shared with iOS: the deep features

These work identically to the iOS app; the [iOS tour](/docs/tour-ios) covers
each in full detail.

### Custom DNS

A complete DNS panel under Connect. DNS is the internet's phone book (it
turns a name like netflix.com into the address your Mac connects to) and a
classic place for snooping and blocking by local and regional firewalls. You
do not need to touch the
panel: the default, encrypted DNS over HTTPS resolved through the tunnel, is
already the most secure setting. From there you can switch any combination
of **DoH (remote/local)** and **unencrypted DNS (remote/local)**, edit the
resolver lists yourself, and use **local DNS fallback**, which races a local
resolver while the tunnel starts so lookups never stall during the handshake
(off means DNS resolves only through the tunnel). The screen offers
per-country recommended settings, because some national networks interfere
with lookups enough to break the strictest configuration, with one-tap apply
and one-tap restore to the secure defaults, plus suggested servers marked in
your connected country's color.

### Split rules

Route specific traffic outside the tunnel or pin it in place, at the domain
and IP level. Tap live traffic to route it locally, the fix when an office
intranet, printer, or NAS vanishes behind the tunnel. Or hold a site to a
single provider for a stable address, which keeps address-sensitive sites
like banks calm; that provider then sees your visits to that one site, still
without your identity or content. Rules catch the whole co-associated
network cluster, so CDN and subdomain traffic moves together. As on iOS,
**there is no per-app split tunneling here**. Android and Windows have it,
but Apple platforms do not give VPN apps a supported per-app hook, so rules
on the Mac are network-level.

### Provide mode

Sharing your Mac's spare bandwidth (a desktop on a good uplink is exactly
the device the network wants) is set in Account → Settings → Connections,
where **Provide mode** is a four-way choice rather than a switch:

| Mode | What it carries |
|---|---|
| **Never** | Nothing. The default: you are purely a user |
| **Auto** | Public traffic while you are connected; only your own devices when you are not |
| **Always** | Public traffic, connected or not |
| **Network** | Only ever your own devices |

Public traffic is metered under signed contracts (cryptographic agreements
that count bytes between client identities, which is how usage is settled
without recording destinations), and providers participate in the UR
protocol; [ur.xyz](https://ur.xyz) documents how the rewards for that
participation work.

Safety is engineered on your own machine. The connect engine's open-source
inspection layer runs on your Mac at egress and blocks file-sharing
(BitTorrent-class) and attack-pattern traffic before it leaves your
connection. What a match produces: the packet is dropped, and a file-sharing
signature additionally raises an abuse flag to the operator carrying only
the sending device's id and a boolean (no destination, no domain, no
contents), for which the operator ships no handler today. Attack-pattern and
opaque-tunnel drops raise nothing at all. The same filter is why URnetwork
is deliberately not a torrenting tool for users. Limit: no shared-exit
design makes the risk exactly zero, which is why the audience is yours to
choose, and every byte you carry counts against an ISP data cap, so on a
metered plan provide selectively or not at all.

### The post-quantum identity panel

The setting itself is **Post Quantum Encryption**, a toggle in the connect
drawer under Connect options, and it ships **on**: sealed is the state a
fresh install starts in, not a choice you have to make. Account then shows
your client's post-quantum session identity with a share sheet for
out-of-band comparison, the same idea as comparing safety numbers in a
messaging app: reading the fingerprint over another channel proves the
sealed session ends where you think it does. What the setting covers: your
client seals traffic directly to a provider using a TLS 1.3 session
negotiated with **X25519MLKEM768** (hybrid classical + ML-KEM), so the
operator in the middle carries bytes it cannot read, and recordings made
today are designed to stay sealed even against a future quantum computer
(the "harvest now, decrypt later" threat). It is fail-closed: while the
setting is on the client will not send or accept application data in the
clear, so a provider it cannot establish a sealed session with is skipped
rather than used unsealed — you lose that provider, not your encryption.
Every current provider build speaks the responder side, so that is uncommon;
switch the setting off and traffic can take the standard platform path
again. No app yet shows a per-connection sealed-or-not verdict. Identity
signatures remain Ed25519, and "post-quantum" means this session key
exchange, nothing broader.

## Troubleshooting

### The VPN configuration approval

First connect triggers a system dialog asking to allow a VPN configuration.
If it was declined, the tunnel can never start. Approve it on the next
attempt, or look in **System Settings → VPN** (also visible under Network),
where the URnetwork configuration should be listed and enabled.

### Multiple VPN profiles, and how the app manages them

Reinstalls and upgrades can leave macOS holding more than one URnetwork VPN
profile. The app expects this: on connect it enumerates every profile, and
when starting one fails it resets that profile and retries, then moves on to
the next. If a tunnel is already running it adopts it over the device RPC
instead of restarting. Broken profiles are reset or removed with a cap on
removals, and every profile operation is deadline-bounded so a wedged system
daemon cannot hang the app. It is automatic, described here so the entries
in System Settings make sense.

### "Failed to load VPN profiles" (error 12)

If connecting fails with **"Failed to load VPN profiles"** (error code 12),
the system's VPN preference store is refusing to enumerate profiles, a state
the app cannot repair from inside. Fix it by hand:

1. Open System Settings and find the VPN configurations (System Settings →
   VPN, or the equivalent of General → VPN & Device Management on your macOS
   version).
2. Remove the URnetwork configuration(s).
3. Reconnect from the app and approve the fresh configuration.

Removing the configuration deletes plumbing, not data: your account,
settings, and split rules are untouched, and the next connect recreates it
(showing the one-time approval dialog again).

### Starting at login

**Launch URnetwork on system startup** is a toggle in Account → Settings,
under System. It registers the app with macOS's own login-items service, so
it works on every version the app supports and the entry shows up in System
Settings → General → Login Items, where you can also remove it by hand.
Turning the toggle off unregisters it again.

### How the kill switch works here

Same as on iOS: the app ships a **Kill switch** toggle in
Account → Settings → Connections, the same SDK control every URnetwork app
has. It starts off, so switching it on is a deliberate act. With it on, the
client refuses to fall back to your local route, so traffic stops rather
than leaking. What the Mac does not add is OS-level enforcement. The app
does not set `includeAllNetworks`, so if the tunnel process dies
unexpectedly, macOS restores normal networking rather than failing closed:
your apps keep working over the underlying network with your real IP,
likely without you noticing more than a blip. The menu-bar check/cross is
the at-a-glance tripwire. The app supervises the tunnel and recovers
profiles aggressively, but it does not currently ask the OS to hard-block
traffic when the tunnel is down. If you need guaranteed fail-closed
behavior, enforce it outside the Mac (a router or firewall rule that only
passes tunnel traffic), or do browser-critical work through the URnetwork
browser extension, whose kill switch is on by default and covers browser
traffic only.

### Reading the tunnel's logs

The tunnel extension logs to the unified system log: Console.app, not
files.

1. Open **Console.app** and select your Mac.
2. In the Action menu, enable **Include Info Messages** and **Include Debug
   Messages**. The useful lines are at those levels.
3. Filter by the `network.ur.extension` subsystem or search "URnetwork",
   then reproduce the connect.

### Sleep behavior

The tunnel is configured with `disconnectOnSleep` off: closing the lid does
not tear the session down, so you resume where you left off instead of
re-handshaking on every wake. A sleeping Mac moves no traffic. It is not
browsing and it is not providing; the setting only spares you the
re-handshake.

## Where next

- [Getting started on macOS](/docs/getting-started-macos) for the short
  path.
- [The iOS tour](/docs/tour-ios) for the same features in their exhaustive
  form, plus Siri shortcuts.
- The [overview](/docs/overview) for how the network works end to end, and
  the [FAQ](/docs/faq) for quick answers.
