Claude Code pauses for permission before running commands. Nod sends that prompt to your watch. Tap once to approve. Destructive commands arrive in red so you can't miss them — 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.Nod lives on your wrist. When Claude Code wants to run something, Nod taps you. You tap back. If the command could hurt, Nod gets a little worried and the whole notification turns red. That's the whole app. No settings, no onboarding flow, no dashboard.
┌──────────────┐ 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.