Skip to content

JanJetze/claude-remote

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

claude-remote

Control Claude Code from your phone.

Get push notifications when Claude needs you, then tap to open a full terminal on your phone — approve permissions, answer questions, or keep working from anywhere.

How it works

Computer:                                  Phone:
┌──────────────────┐                      ┌────────────────────┐
│ tmux session     │                      │ Browser            │
│  └── claude      │◄── PTY ──► ttyd ──WebSocket──► xterm.js  │
│                  │                      │ (full terminal)    │
└──────────────────┘                      └────────────────────┘
         │
    Claude Code hooks ──POST──► Server ──ntfy──► Phone notification
                                  │              "Claude needs you"
                                  └── serves landing page + QR code
  1. ttyd shares your tmux session as a web terminal on your phone
  2. Claude Code hooks detect when Claude needs attention
  3. Server tracks session state, sends notifications via ntfy
  4. If the terminal page is open on your phone, you get vibration + sound instead of a push notification

Prerequisites

  • macOS or Linux
  • Docker
  • tmux (brew install tmux / apt install tmux)
  • ttyd (brew install ttyd / apt install ttyd)
  • Python 3 (for hooks — stdlib only, no pip packages needed on host)
  • ntfy app on your phone (Android/iOS)

Setup

git clone https://github.com/JanJetze/claude-remote.git
cd claude-remote
./setup.sh

The setup script will:

  1. Check that tmux, ttyd, and Docker are installed
  2. Build the Docker image
  3. Generate auth tokens, TLS certificate, and VAPID keys
  4. Create config at ~/.config/claude-remote/config.json
  5. Tell you what Claude Code hooks to add (if not already configured)

Follow the printed instructions, then re-run ./setup.sh to verify and install.

Daily use

cd myproject
claude_remote

This starts the server + ntfy via Docker, opens Claude Code in a tmux session, and starts ttyd.

Connect your phone

  1. Open the landing page URL printed by claude_remote (or scan the QR code)
  2. Tap "Subscribe in ntfy app" to get push notifications
  3. Tap "Open Terminal" to access the full terminal

Workflow

  1. Start working with Claude, then walk away
  2. Phone buzzes via ntfy: "Permission: Bash — npm test"
  3. Tap the notification — terminal opens in your browser
  4. Approve the permission, type a response, or just check progress
  5. Continue from phone or go back to desk

Hooks

claude-remote uses three Claude Code hooks to detect when Claude needs your attention. The hooks are added to ~/.claude/settings.json and fire for all Claude Code sessions, but only send notifications for sessions started via claude_remote.

Which hooks and why

Hook Matcher What it catches Timing
Stop "" (all) Claude finished responding and is waiting for input: questions, choices, plan approval, task completion Immediate
PermissionRequest "" (all) Claude needs permission to run a tool (Bash, Edit, etc.) Immediate
Notification idle_prompt Claude has been idle for 60 seconds waiting for input After 60s

Why all three?

  • Stop gives you an immediate notification whenever Claude stops and waits — this is the primary hook
  • PermissionRequest provides a more specific notification with the tool name and command (e.g., "Permission: Bash — npm test")
  • Notification with idle_prompt acts as a backup reminder if you missed the initial notification

Required settings

setup.sh will print the exact JSON to add. Here's the structure:

{
  "hooks": {
    "PermissionRequest": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "python3 /path/to/claude-remote/hooks/permission.py",
            "async": true
          }
        ]
      }
    ],
    "Notification": [
      {
        "matcher": "idle_prompt",
        "hooks": [
          {
            "type": "command",
            "command": "python3 /path/to/claude-remote/hooks/notification.py",
            "async": true
          }
        ]
      }
    ],
    "Stop": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "python3 /path/to/claude-remote/hooks/stop.py",
            "async": true
          }
        ]
      }
    ]
  }
}

How hooks are scoped

The hooks live in ~/.claude/settings.json (global), so they run for every Claude Code session on your machine. However, they only send notifications for claude-remote sessions:

  • bin/claude_remote launches Claude with the CLAUDE_REMOTE=1 environment variable
  • Each hook checks for this variable and exits immediately if it's not set
  • Regular claude sessions are never affected

Configuration

Generated at ~/.config/claude-remote/config.json:

{
  "server_port": 7778,
  "ttyd_port": 7779,
  "ntfy_port": 2586,
  "auth_token": "<generated>",
  "host": "0.0.0.0",
  "tls_cert": "tls/cert.pem",
  "tls_key": "tls/key.pem",
  "vapid_public_key": "<generated>",
  "vapid_private_key": "<generated>"
}

Components

Component Description
bin/claude_remote Entry point: starts Docker services, ttyd, and Claude in tmux
src/claude_remote/ Python server: landing page, session tracking, ntfy notifications
hooks/ Claude Code hooks that notify the server (permission, stop, idle)
docker-compose.yml Runs the server + ntfy containers

Security

  • Everything runs on your local network — no external services except ntfy push delivery
  • Auth token required for all API endpoints
  • Self-signed TLS certificate generated automatically
  • For access outside your LAN, use Tailscale or similar VPN

Enable / Disable

  • Pause notifications: Toggle on the landing page — server stays running, no push alerts
  • Stop everything: docker compose down in the repo directory
  • Remove hooks: Delete hook entries from ~/.claude/settings.json
  • Uninstall: Remove ~/.local/bin/claude_remote, ~/.config/claude-remote/, and the hook entries

License

MIT

About

Control Claude Code from your phone

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors