Claude Code notifications and approvals on your phone
Claude Code has hooks: points where it runs a command of yours. That's enough to build an alert for when it asks for permission or finishes, and even to answer it from your phone. Here's how it works under the hood and how Wendo uses it.
What a Claude Code hook is
A hook is a command Claude Code runs when something happens: a session starts, you send a prompt, it needs a permission, it finishes a reply. You declare them in ~/.claude/settings.json, one event per key, each pointing at a command:
{
"hooks": {
"Stop": [
{ "hooks": [{ "type": "command", "command": "~/.wendo/wendo-hook.sh" }] }
]
}
}
Claude Code runs that command and passes a JSON document on standard input with the event's data: the event name, the working directory, the session id and, depending on the case, the tool it wants to use. The command does whatever it likes with that. For some events it can also write a response to standard output, which is how Claude Code learns the decision.
The events Wendo's hook registers
The installer adds the same script to six events:
PermissionRequest: Claude Code is about to ask for your permission.Notification: a Claude Code notice that needs attention.Stop: it has finished replying.UserPromptSubmit: you sent a prompt, so it's working.SessionStartandSessionEnd: a session begins or ends.
Each event is stored as a line in ~/.wendo/events.jsonl on the computer. The app reads that file over SSH with your key, so there's no intermediate server and no account. What you see in the Inbox comes from there.
To install it, one command:
curl -fsSL https://wendo.lirafy.dev/install.sh | sh
Before touching settings.json it saves a copy as settings.json.bak-wendo, and you can run it repeatedly without duplicating entries. Any hooks you already have are left alone. The options and the manual setup are on the alerts and approvals page; the broader walkthrough for building the whole environment is in how to use Claude Code from your phone.
How an approval works
PermissionRequest is the one event where the hook stays and waits. When Claude Code asks for permission, the script records the request as pending, and the app's Inbox shows the row with buttons to approve or deny. When you tap one, the app drops the answer in a file on the computer, the hook picks it up, and hands the decision back to Claude Code.
The wait lasts 90 seconds. If you haven't answered by then, the hook prints nothing and Claude Code shows its normal prompt in the terminal, as if Wendo weren't there. That matters: if your phone dies or you lose signal, nothing stays blocked, you just fall back to how it always worked.
If you answer in the terminal before the phone, that's recorded too, as resolved locally.
A few environment variables tune it, set in front of the hook command:
WENDO_APPROVAL_TIMEOUT: seconds to wait. The hook'stimeoutinsettings.json(120 in the installed setup) must be larger.WENDO_BLOCKING=0: only alert, without waiting for an answer.WENDO_HOST: the name the app knows the computer by, if it differs fromhostname -s.
Claude's questions (AskUserQuestion) and plan approvals (ExitPlanMode) don't block. They ask for a choice rather than a yes or no, so you answer them from the chat view.
Alerts with the app closed: ntfy
While Wendo is open, the app reads the inbox every few seconds. With the app closed, something has to push the alert to your phone, and that's ntfy: a simple push notification service you publish to with an HTTP request.
- Put
NTFY_TOPICin front of the hook command insettings.json:
NTFY_TOPIC=a-long-random-topic ~/.wendo/wendo-hook.sh
- Install the ntfy app on your phone and subscribe to that same topic.
- Enter the topic in Wendo too, under Settings › Agents › Notifications.
To generate a topic nobody will guess:
openssl rand -hex 16
The topic acts as a password. On the public ntfy server, anyone who knows a topic's name can read what's published to it and publish their own messages, so don't use something like claude-john. The alerts include the project and an excerpt of the message or command, enough to decide on, and not something you want strangers reading.
If you'd rather not depend on the public server, NTFY_URL points the hook at your own ntfy server. The default is https://ntfy.sh. Tapping an alert opens the tmux, zellij or herdr pane where the agent runs, as long as you run it inside one of them (see the tmux page).
On Android there is also a background check at least every 15 minutes. Only permission, notification and task-finished alerts go to ntfy; the hook doesn't push session start, session end, or every prompt.
Limits
- Claude Code only for now. The hook isn't registered with other agents.
- It needs
jqon the computer.curlis only needed for ntfy. - Without a multiplexer, the app doesn't know which pane Claude is in and can't take you straight to it.
- The free plan includes 5 trial approvals from the Inbox; with Pro there's no limit.
- Wendo isn't in the stores yet: it's coming soon to the App Store and Google Play.