How it works.
Two verbs.
ask waits for the person's answer. notify tells them something and never waits. Few verbs on purpose: the fewer an agent chooses between, the better it calls them.
authz ask waits for the answer.authz notify tells and moves on.The exit status is the decision
- 0
- allowed or answered
- 77
- denied
- 75
- nobody answered in time, or withdrawn
- 79
- “no, do this instead”, with the reply
- 65 · 64
- an invalid request · a wrong call
A command Authz ran exits with its own status. The decisions use codes a program rarely returns, so a command never reads as a decision.
A notice that runs
Once (“CI failed”), or --begin, --update and --end on one --id, updating in place on every Mac and the iPhone. It may carry links, never answers.
One document.
Every request is one JSON document, written the same way by agents and programs: what to read, what the person can say, and what their yes lets happen. JSON, not HTML, so text quoted from a page or a file can never become structure on the person's card. Chosen by measurement: 588 agent runs, 14 tasks, three models.
- Content
- A paragraph in Markdown, or a link. Never an answer.
- Fields
- text, password, email, url, number, date, checkbox, textarea, select. HTML's attributes, so every model already knows them.
- Pages
- A form over several pages, shown in order.
- Secrets
- A 1Password item the request uses. Its value never reaches the caller: it fills the command's environment, never its command line.
- Payloads
- What the yes lets happen: a command Authz runs, a patch it applies, a step the caller executes, or a payment.
{tag}is filled from the form, so the person sees what will run while they type.
Where it asks.
A request presents where the person last touched input, and the phone rings only when it must.
- Nobody at a computer
- the iPhone rings at once
- At a Mac
- that Mac asks; the iPhone holds it quietly
- Not visibly there
- the iPhone rings after 2.5 s
- There, not answering
- the iPhone rings after 45 s
- The Mac's card
- takes the keyboard only after 0.8 s without a keystroke, so typing never answers it
- The iPhone
- a card in the app, a notification with Allow and Deny, one Live Activity per Mac
- Voice and a nod
- questions that need only intent; never a command, a grant or a secret
What a yes is bound to.
An approval means something only if what runs is, byte for byte, what was shown, and the record of it can be checked afterwards.
A finger, not a click
A yes that matters needs Touch ID or Face ID. It carries a signature by a Secure Enclave key whose use needs the finger or the face, so the app cannot claim a presence the hardware did not see.
Bound to the bytes
A command is pinned whole: its arguments, where it runs, the file that runs and every file its arguments name, by SHA-256. Authz runs it itself, checked again just before; any change refuses. A payment binds its amount and who is paid. This binds the yes, not the agent: what an agent runs without asking was never approved.
Secrets stay in a helper
1Password values and wallet keys live in a process of their own. It checks the answer itself and releases a value, or one signature, only for what was approved. A key never leaves it.
A receipt for every yes
The request's digest, who answered on which device and how, then what ran and how it ended. The asker checks the receipt's signatures before it acts.
The answer, as the asker reads it on stdout
Payments.
Over x402 a resource answers HTTP 402 with its price. Authz asks “Pay 0.005 USDC”, one Touch ID releases the wallet's signature for exactly that transfer, and the resource is fetched.
authz ask --pay https://authz.space/toll/data --wallet <ref>What is not done.
Authz runs on one person's Macs and iPhone.
- Release
- undecided
- Download, sign-up, pricing
- none
- Security review
- first read 2026-10-17 · open findings before any release (warning)
- Payments
- Base Sepolia, test money only