Claude Code pauses for permission before running commands. Nod sends that prompt to your watch. Tap once to approve. Type a 2-digit code from your terminal for destructive commands — no accidental rm -rf.
You're working in claude. It wants to run a command that needs your sign-off — a Bash, Write, Edit, or anything else Claude classifies as needing review.
Nod's PreToolUse hook sees the request, classifies it, and pushes a notification with the tool name plus a one-line summary. Safe tools (Read, Grep) skip this entirely — the hook returns allow in ~75µs with zero network.
Approve or deny. For destructive commands (rm -rf, git push -f, DROP TABLE…) you type a 2-digit code from your terminal on the watch. Claude resumes within seconds of the tap.
For anything that could ruin your day — rm -rf, git push -f, DROP TABLE, terraform destroy, kubectl delete — the notification turns red with a clear warning. Same single tap to approve, but you see exactly what you're about to do.
Plus a hard-deny list: rm -rf /, DROP DATABASE production, mkfs — refused regardless of taps. Some disasters shouldn't be one click away.
Read, Grep, Glob, WebSearch) get an instant allow with zero network. ~75µs measured per call.claude in three terminals across three repos. Each notification carries the repo name and session ID. Taps route back to the right session.rm -rf, git push -f, DROP TABLE, kubectl delete, terraform destroy, npm publish, AWS S3 deletes… full list.rm -rf /, DROP DATABASE production, mkfs, fdisk. Refused regardless of approval.
┌──────────────┐ stdin / stdout ┌─────────────────┐
│ Claude Code │ ◄─────────────────► │ claude-watch │ PreToolUse hook
│ │ │ hook (Go) │ ~75 µs allow on safe tools
└──────────────┘ └────────┬────────┘
│ HTTPS long-poll
▼
┌─────────────────┐
│ nod-gateway │ Go + Chi on Fly.io
│ Fly.io │ Stateful approval queue
└────────┬────────┘ Sign APNs JWT → push
│
│ APNs
▼
┌─────────────────┐
│ iOS + watchOS │ SwiftUI notification actions
│ (Nod app) │ Secure Enclave signed verdicts
└─────────────────┘
~10 MB Go binary on the Mac. 9 MB distroless Docker image on the gateway. Native SwiftUI on the watch. No Electron, no JavaScript runtime, no surprise dependencies.
$ brew install speculative-dynamics/nod/nod $ nod pair <code> # from the iOS app
That's it. Your wrist will buzz on the next risky tool call from claude.
$ git clone git@github.com:Speculative-Dynamics/nod.git $ cd nod $ (cd daemon && go build -o bin/claude-watch-hook ./hook \ && go build -o bin/nod ./nod) $ ./scripts/install.sh # For local testing without the iOS app: $ (cd gateway && go run . -dev-register) & $ nod dev-pair http://localhost:8080
Uninstall: nod unpair && brew uninstall nod — the settings.json hook entry stays harmless after.