>_watch-control
Remote AI Approval — Codex & Claude Code
watch-control app icon

>_ watch-control

Approve Codex and Claude Code commands from your Apple Watch — no need to stay at your laptop.

Your AI agent runs on a remote Linux server inside tmux. When it needs permission, the request streams to the native watchOS app over Tailscale — one tap to approve. Works with both Codex and Claude Code, with Pushover as an optional fallback.

terminal
$ git clone https://github.com/CryptoPilot16/watch-control.git
$ cd watch-control/bridge && node server.js
✓ Bridge listening on :7860
✓ Pairing code: 482917
 enter code in Apple Watch app to pair

# How It Works

Three steps from agent prompt to approval on your wrist

1

Your AI agent runs on your server

Start Codex or Claude Code inside a tmux session on your remote Linux server. It keeps running even when you close your laptop or disconnect from SSH. You can watch multiple panes — one per agent — simultaneously.

2

Approval requests reach the bridge

For Codex, a watcher script polls tmux output and POSTs detected prompts to a Node.js bridge server. For Claude Code, native hooks fire on PermissionRequest and post directly. Either way, the bridge receives the request and waits for your decision.

3

You tap approve on your Apple Watch

A native watchOS app connects to the bridge over Tailscale and shows the prompt on your wrist. One tap to approve or deny — the bridge returns the decision and your agent continues. Pushover notifications work as an optional fallback.

~ Why It Matters

Stop babysitting your terminal. Approve from anywhere.

Making coffee

Step away from your desk without pausing your agent. Approve commands from your wrist while your hands are busy.

🤝

In a meeting

Your agent keeps working in the background. A quick glance at your watch, a tap, and the build continues — no one notices.

🚶

On the go

Leave the house entirely. Your server runs the agent, your watch handles approvals. Code gets written while you walk the dog.

🌙

Overnight builds

Kick off a long task before bed. When your agent needs approval at 2 AM, your watch buzzes gently — tap and go back to sleep.

& Technology Overview

A small stack — bridge, hooks, Tailscale, and a watchOS app

Codex or Claude Code in tmux

Either agent runs inside a persistent tmux session on your Linux server so it survives SSH disconnects. Watch multiple panes at once.

codex_watch.sh

Polls tmux output for Codex approval prompts. Auto-detects which agent is asking and POSTs the request to the bridge server, then injects the keystroke once the watch responds.

Claude Code hooks

Native PermissionRequest hooks fire instantly when Claude needs approval. No polling required — Claude pauses, posts to the bridge, and waits for your decision.

bridge/server.js

Lightweight Node.js bridge — handles SSE streaming to the watch, 6-digit pairing, session tokens, and blocks Claude/Codex until you decide.

Tailscale

Private tailnet connecting your VPS to your Apple Watch. The bridge is reachable only on your tailnet — no public ports, no port forwarding.

Apple Watch app

A native watchOS app pairs with the bridge over Tailscale. Shows incoming approval requests on your wrist with one-tap Approve / Deny.

Pushover (optional)

Optional fallback for delivering push notifications to your iPhone and Apple Watch if you prefer not to install the native app.

$ Quick Start

Bridge server, watcher, and watch pairing

Before you start

Linux serverwith tmux, Python 3, and Node.js 18+ installed
Tailscaleinstalled and authenticated on your server and watch/iPhone
Apple Watch appnative watchOS app sideloaded (Apple Developer account)
Pushover (optional)fallback notifications if you skip the native app
01

Clone the repo

git clone https://github.com/CryptoPilot16/watch-control.git
cd watch-control
02

Configure environment

cp .env.example .env

# Edit .env and set:
APPROVE_SECRET=your-secret-here
BRIDGE_URL=http://<your-tailscale-ip>:7860

# Optional fallback:
PUSHOVER_APP_TOKEN=your-pushover-token
PUSHOVER_USER_KEY=your-pushover-key
03

Start the bridge server

cd bridge
node server.js

# Prints a 6-digit pairing code at startup —
# enter this in the Apple Watch app to pair.
04

Start the watcher (for Codex)

bash ./restart.sh

# Or start manually:
# Terminal 1: python3 approve_webhook.py
# Terminal 2: bash ./codex_watch.sh
05

Wire up Claude Code hooks

# Add to ~/.claude/settings.json so Claude Code
# posts directly to the bridge on PermissionRequest.
# See the README for the exact JSON snippet.

Environment Variables

APPROVE_SECRETShared secret for webhook auth
BRIDGE_URLBridge server address (tailnet)
PUSHOVER_APP_TOKENOptional — fallback notifications
PUSHOVER_USER_KEYOptional — fallback notifications
TMUX_SESSIONTarget pane (default: codex:0.0)
COOLDOWN_SECONDSMin time between notifications (30)

Watch Setup

Pair your Apple Watch with the bridge — one code, one tap

01

Sideload the native watchOS app

# clone and open in Xcode on a Mac
git clone https://github.com/CryptoPilot16/claude-watch
open claude-watch/ios/ClaudeWatch/ClaudeWatch.xcodeproj

Build and install the watch-control app via Xcode (requires an Apple Developer account, $99/yr). The app is open source and pairs with your bridge server over Tailscale.

02

Connect over Tailscale

# on your server, get the tailnet IP
tailscale ip -4

Install Tailscale on the iPhone paired with your Apple Watch and authenticate to the same tailnet as your server. The watch app reaches the bridge through your private network.

03

Pair with the bridge

  1. 1.Start the bridge — node bridge/server.js — and copy the 6-digit pairing code from the logs
  2. 2.Open the watch-control app on your Apple Watch
  3. 3.Enter your server's Tailscale IP (e.g. 100.x.x.x)
  4. 4.Type the 6-digit code — the bridge issues a session token and you're paired
04

Approve from your wrist

When Codex or Claude Code needs permission, the request streams to the watch over SSE. Tap Approve or Deny. The bridge returns the decision and your agent resumes.

No Apple Developer account?

You can use Pushover as a fallback — set PUSHOVER_APP_TOKEN and PUSHOVER_USER_KEY in your .env and the watcher will send notifications to your phone instead. An iOS Shortcut wired to the legacy /approve webhook lets you tap-to-approve from your watch without the native app.

# Architecture

The approval flow from your AI agent to your wrist — step by step

1Agent needs approval
2Hook or watcher posts to bridge
3SSE pushes to watch
4You tap Approve
5Bridge returns decision
6Agent continues
⌨️

Codex / Claude Code (tmux)

Persistent execution environment — keeps running when SSH disconnects

👁️

codex_watch.sh

Polls tmux output for Codex approval prompts and POSTs to the bridge

🪝

Claude Code hooks

Native PermissionRequest hooks POST directly to the bridge — instant, no polling

🌉

bridge/server.js

Node.js bridge — SSE streaming, pairing codes, blocks until watch responds

🔒

Tailscale

Private tailnet connecting your VPS to your Apple Watch — no public ports

Apple Watch app

Native watchOS app — pairs with the bridge, shows prompts, one-tap approve/deny

Security Model

  • Bridge reachable only over your Tailscale tailnet
  • 6-digit pairing code required to register a watch
  • Session token Bearer auth for all subsequent requests
  • Rate-limited pairing endpoint blocks brute force

Bridge Endpoints

/pairPair the watch with a 6-digit code, returns session token
/eventsSSE stream — watch listens here for approval requests
/hooks/permissionClaude Code PermissionRequest hook
/hooks/codexCodex approval — codex_watch.sh posts here

@ Infrastructure

What runs where

Landing Page

Static Next.js site, self-hosted and served by Caddy.

cryptopilot.dev/watchcontrol

Bridge Server

Node.js server runs on your Linux box. SSE streams approval requests to the watch and blocks the agent until you respond.

Reachable only via your Tailscale tailnet

Apple Watch App

Native watchOS app sideloaded via Xcode. Pairs with the bridge using a 6-digit code and a session token.

No App Store, no public exposure