Security model
Remote control reaches a machine that holds your source, your credentials, and shells that can run anything. The design below is the record of what that costs and what is done about it — stated plainly, including the parts that are still deliberate limitations.
The invariants
Your account is the trust model
A device pairs because it holds a session on the same Marginal Utility account the Mac is signed into, and every authorized request re-checks that it still does. Signing the Mac out revokes every paired device on the next request.
There is no armed setting that skips this: an option to turn the trust model off would be an option to have no trust model.
Nothing listens
The Mac opens no port and serves no certificate. It dials out and holds a connection to the relay, which lets remote control work without exposing anything on your network — and why Off is the setting that genuinely matters, since dialing out is what carries your credential off the Mac.
Remote control runs only in the native app
There is no browser client. A web page fetches its code on every visit, so the code that seals your traffic would only be as trustworthy as the latest deploy and every network in between, and a browser keeps its keys where extensions and injected scripts can reach them.
The Saggar phone app is signed code you installed. The relay refuses any device request a web page makes, and the Mac revokes grants that browsers held.
Local website tunnels stay local and origin-bound
The iOS browser uses an unguessable loopback URL on the phone; it does not publish the Mac's development server. The Mac:
- accepts only localhost origins at approve and private-network origins only at drive, never link-local;
- pins each tunnel to the exact scheme, host, and port the user opened;
- strips credentials and hop-by-hop headers;
- bounds request and response bodies;
- closes the tunnel and its WebSockets when the view or app closes.
Each WebSocket is tied to its parent tunnel; receiving requires approve, while sending requires drive. Page and socket bytes remain inside the same end-to-end encrypted envelopes as other remote requests.
Account isolation is the topology, not a check
The relay routes every caller to an object named for their account, so two accounts are two objects with no path between them. There is no name a device could ask for that reaches someone else's Mac.
The Mac's own account check still runs on every request; that is defense in depth, not a duplicate.
Two credentials, separate jobs
| Credential | Authenticates the device to |
|---|---|
| Your account session | The relay |
| Its Saggar grant | The Mac |
Ordinary requests leave the account token at the relay. During pairing, the same account proof is sealed to the Mac so it can independently enforce the account match without the relay being able to inspect or replace that proof.
The code alone is not sufficient
Two things gate a pairing, in order. The account check runs first, so a device on someone else's account is refused before anyone is asked about it; then a human at that Mac confirms the device. Neither is optional. The ceremony.
Capabilities are clamped server-side
What a client asks for is not what it gets — the Mac clamps every grant to its own ceiling, at the moment it authorizes the pairing.
Data is minimized by tier
A view-tier device receives no transcript tails and no filesystem paths. Redaction happens on the Mac, before the bytes leave it.
No bearer token in a URL
A live stream cannot set a header, so it carries two single-use, short-lived
tickets instead — one for the Mac, one for the relay. Nothing sensitive lands
in history, proxy logs, or Referer headers.
Grants live in the Keychain
The Mac stores pairing grants in the login Keychain, not a JSON file beside your code. Revocation is immediate on the next request, and it takes a device's push subscription with it.
Push content is sealed to the phone
Each app installation registers a P-256 public key with its grant. The visible push names only the kind of alert, such as a session needing you; its actionable target travels as an encrypted payload that the push service cannot open.
A lock-screen reply is sealed again to the Mac before the account relay accepts it. The relay can hold that opaque request for two minutes across a Mac disconnect and deduplicates its random opaque reply identifier, but cannot read the grant or typed text.
Rate limits and an audit log
Per-peer limits blunt grinding, and the Settings pane shows you the log of what was asked and what was answered — denials included. This is remote code execution by design; an action with no record of which device asked for it would be the bug.
What this does not claim
The relay cannot read or forge terminal traffic
The phone app and your Mac derive an end-to-end AES-GCM key from their P-256 keys. Commands authenticate their route and a one-time nonce, and responses bind themselves to that request and carry their own status inside the seal.
Each device pins the Mac's public key the first time it sees it; a pairing link carries the key from the Mac's own screen, and a key the account list advertises later never replaces the pin. The Mac in turn binds every grant to the device key that sealed its pairing request. A Mac that changes its key has to be forgotten and paired again.
The relay can still interrupt availability and learns routing and timing metadata, including which Macs are online.
Deliberate limits
- There is no offline path. A relay outage means no remote control at all, even from the next room.
- An external security review is still the recommended next step, and it now belongs at the relay: what changed with it is the reachability, not the authorization model.
- A drive-tier grant can type anything into a shell on your Mac. That is the point of the tier, and the reason it is separated from approve. Computer-wide folder browsing and search therefore require drive; approve remains confined to saved project roots.
- Saggar is unsandboxed by design; it drives your real shells in your real directories.
Cloud AI features
Two optional features send terminal content off the Mac. Both require a signed-in Marginal Utility account, and a fresh install sends nothing.
| Feature | Sends | When |
|---|---|---|
| Session summaries | The last 80 KB of the chosen transcript. | When you ask for a summary. Nothing is sent until you ask. |
| Smart session naming | The first 12 KB of a verbose or vague agent prompt, to get a short name. | Automatically once enabled. It is off by default. |
Before upload, Saggar redacts recognizable credentials on the Mac: vendor API
keys, JSON web tokens, private-key blocks, authorization headers, URL
passwords, and password=-style assignments. That is best effort; it does not
catch every secret. Turn the features off for sessions that handle sensitive
material.
Content travels to Marginal Utility's account service, which forwards it to a model provider through OpenRouter and returns the result. The account service records usage and a hash of the content, not the content itself. Retention beyond that hop is governed by the model provider's terms.
Reporting a security issue
Email contact@mcclowes.com with what you found and the smallest way to reproduce it, and give it a chance to be fixed before writing it up anywhere public. Don't include credentials or private terminal output in the report.