claude-relay 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,125 +1,129 @@
1
1
  # claude-relay
2
2
 
3
- Claude Code on your phone with push notifications. One command, zero install.
3
+ <p align="center">
4
+ <img src="media/phone.gif" alt="claude-relay on phone" width="300">
5
+ </p>
4
6
 
5
- ![claude-relay demo](screenshot.gif)
7
+ <h3 align="center">Claude Code on your phone. Push notifications. Zero install.</h3>
6
8
 
7
- You start a long task in Claude Code. You step away. Claude needs permission to edit a file. It waits. You come back 30 minutes later to a stalled session.
9
+ [![npm](https://img.shields.io/npm/v/claude-relay)](https://www.npmjs.com/package/claude-relay) [![downloads](https://img.shields.io/npm/dw/claude-relay)](https://www.npmjs.com/package/claude-relay)
8
10
 
9
- **claude-relay fixes this.** Run `npx claude-relay` and your phone gets push notifications when Claude needs you. Tap to approve. Claude keeps working. You keep living.
11
+ You step away. Claude Code stops.
10
12
 
11
- ```
12
- npx claude-relay
13
- ```
13
+ > "A 10-second approval can block it for hours if you're not at your desk."
14
+ > — [#25115](https://github.com/anthropics/claude-code/issues/25115)
14
15
 
15
- No app to install. No cloud server. No account to create. Your data stays on your machine.
16
+ > "I don't need to write code on my phone. I need to approve, reject, continue, stop. That's it."
17
+ > — [#18189](https://github.com/anthropics/claude-code/issues/18189)
16
18
 
17
- ## Use Claude Code from your phone
19
+ **claude-relay fixes this.** Your phone buzzes when Claude needs you. Tap approve. Claude keeps working. You keep doing whatever you were doing.
18
20
 
19
- claude-relay runs on your machine and connects Claude Code to a web UI over WebSocket. Open the URL on your phone, add it to your home screen, and you get push notifications whenever Claude needs input.
21
+ No app. No cloud. No account. Your code never touches a third-party server.
20
22
 
21
- Sessions are real-time synced across all connected devices. Type on your PC, see it on your phone. Approve on your phone, see it on your PC. Everything is live.
23
+ Runs a Claude Code session on your machine via the [Claude Agent SDK](https://www.npmjs.com/package/@anthropic-ai/claude-agent-sdk) and streams it to your browser over WebSocket. Nothing is proxied through external servers.
22
24
 
23
- ```
24
- Your phone/tablet <--> claude-relay (your machine) <--> Claude Code
25
- browser WebSocket + HTTPS
26
- ```
25
+ ---
27
26
 
28
27
  ## Push notifications for Claude Code
29
28
 
30
- Get notified on your phone when Claude needs approval, finishes a task, or hits an error. Works even when the browser is closed. Tap the notification to jump straight in.
31
-
32
- No app required. Add to your home screen and notifications work like a native app (PWA). The built-in setup wizard walks you through it in 3 steps.
29
+ Permission request. Task done. Error. Question. Your phone buzzes. Browser can be closed.
33
30
 
34
- ## Approve Claude Code permissions remotely
31
+ Add to home screen PWA → push notifications work like a native app. Setup wizard handles everything.
35
32
 
36
- Kick off a refactoring task, go make coffee. Your phone buzzes: "Claude wants to edit `src/auth.ts`". Tap approve. Claude continues. No need to walk back to your desk.
33
+ <p align="center">
34
+ <img src="media/push-notification.jpg" alt="push notification" width="300">
35
+ </p>
37
36
 
38
- Running tests, migrations, or multi-file changes? Watch the progress from your phone or tablet without staying at your desk.
37
+ ## Use Claude Code from any device
39
38
 
40
- ## Claude Code on iPad and tablets
39
+ Open claude-relay on your phone, tablet, or any browser. Type a prompt, watch Claude work, review code all in real time. Every connected device sees the same session live.
41
40
 
42
- Full Claude Code access from any browser. No SSH terminal app, no GitHub repo required, no sandboxed VM. Your actual dev environment, your tools, your MCP servers, your CLAUDE.md, your files.
41
+ Permission prompt? Approve from whichever device is closest. The session updates everywhere instantly.
43
42
 
44
- ## Session handoff between CLI and browser
43
+ ## Quick start
45
44
 
46
- Start a session in the terminal. Pick it up on your phone. Hand it back to the terminal. Sessions survive server restarts, browser closes, and reconnects. Your conversation is never lost.
45
+ ```bash
46
+ # Run in your project directory
47
+ npx claude-relay
47
48
 
48
- ## Run Claude Code remotely with Tailscale
49
+ # Scan the QR code with your phone — opens Claude Code in your browser
49
50
 
50
- To access Claude Code from outside your local network, use [Tailscale](https://tailscale.com). Install it on your machine and your phone, sign in with the same account, and you are connected. claude-relay detects Tailscale automatically.
51
+ # Press 's' setup wizard push + remote access in 3 steps
52
+ ```
51
53
 
52
- Tailscale creates a private encrypted tunnel between your devices. No port forwarding, no cloud relay, no data leaving your control.
54
+ <p align="center">
55
+ <img src="media/start.gif" alt="npx claude-relay" width="600">
56
+ </p>
53
57
 
54
- ## Features
58
+ ## All features
55
59
 
56
- - **Push notifications** on permission requests, task completion, and errors
57
- - **Real-time sync** across all connected devices via WebSocket
58
- - **Session persistence** across server restarts and reconnects
59
- - **Mobile-first UI** with big tap targets for approve/deny
60
- - **Setup wizard** guides you through Tailscale, HTTPS, and push setup
61
- - **Multi-session** support with automatic port selection
62
- - **PIN protection** for access control
63
- - **HTTPS** via mkcert, automatic certificate generation
64
- - **Slash commands** with autocomplete
65
- - **Zero config** uses your local Claude Code installation as-is
60
+ - **Push notifications** permission requests, completions, errors, questions. Works with browser closed.
61
+ - **Real-time sync** every device sees the same session live via WebSocket. Type on desktop, see it on phone.
62
+ - **Session persistence** server restarts, browser crashes, network drops. Session survives. Conversation is never lost.
63
+ - **Session handoff** start in the terminal, pick it up on your phone, hand it back. Seamless.
64
+ - **Conversation rewind** click any previous message to roll back conversation and files together, with full diffs
65
+ - **Mobile-first UI** big approve/deny buttons, one-handed use
66
+ - **iPad and tablet support** full Claude Code from any browser. Your actual machine, your tools, your MCP servers, your files.
67
+ - **Setup wizard** Tailscale, HTTPS, push. Step by step.
68
+ - **Multi-session** multiple projects, automatic port selection
69
+ - **PIN protection** access control beyond network security
70
+ - **HTTPS** — automatic certs via mkcert
71
+ - **Slash commands** — with autocomplete
72
+ - **Zero config** — works with your existing Claude Code setup
66
73
 
67
- ## Quick start
74
+ ## Network access
68
75
 
69
- ```bash
70
- # 1. Run in your project directory
71
- npx claude-relay
76
+ On the same Wi-Fi? It just works. Open the URL shown in the terminal from any device on your network.
72
77
 
73
- # 2. Scan the QR code with your phone
74
- # or open the URL shown in the terminal
78
+ Outside your network? [Tailscale](https://tailscale.com) creates an encrypted tunnel between your devices. No port forwarding. No cloud relay. Your code never leaves your control.
75
79
 
76
- # 3. Press 's' for the setup wizard
77
- # to enable push notifications and remote access
78
- ```
80
+ Install on both devices. Same account. Done. claude-relay detects it automatically. Free for personal use.
79
81
 
80
- ## HTTPS setup for push notifications
82
+ ## HTTPS for push notifications
81
83
 
82
- Push notifications require HTTPS. claude-relay supports automatic HTTPS via [mkcert](https://github.com/FiloSottile/mkcert):
84
+ Push needs HTTPS. [mkcert](https://github.com/FiloSottile/mkcert) makes it painless:
83
85
 
84
86
  ```bash
85
87
  brew install mkcert
86
88
  mkcert -install
87
89
  ```
88
90
 
89
- Certificates are generated automatically on first run. The setup wizard checks for mkcert and guides you if it is missing.
91
+ Certificates generate automatically. Setup wizard handles the rest.
90
92
 
91
93
  ## CLI options
92
94
 
93
95
  ```bash
94
- npx claude-relay # Start with defaults
95
- npx claude-relay -p 8080 # Custom port (default: 2633)
96
- npx claude-relay --no-https # Disable HTTPS
97
- npx claude-relay --no-update # Skip auto-update check
98
- npx claude-relay --debug # Enable debug panel
96
+ npx claude-relay # defaults
97
+ npx claude-relay -p 8080 # custom port (default: 2633)
98
+ npx claude-relay --no-https # disable HTTPS
99
+ npx claude-relay --no-update # skip update check
100
+ npx claude-relay --debug # debug panel
99
101
  ```
100
102
 
101
103
  ## Requirements
102
104
 
103
105
  - [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code) installed and authenticated
104
106
  - Node.js 18+
105
- - [mkcert](https://github.com/FiloSottile/mkcert) (for HTTPS and push notifications)
106
- - [Tailscale](https://tailscale.com) (for remote access outside your network)
107
+ - [mkcert](https://github.com/FiloSottile/mkcert) for HTTPS and push
108
+ - [Tailscale](https://tailscale.com) for remote access
107
109
 
108
110
  ## Security
109
111
 
110
- **Anyone with access to the URL gets full Claude Code access to your machine**, including reading, writing, and executing files with your user permissions.
112
+ **Anyone with the URL gets full Claude Code access to your machine.** Read, write, execute your user permissions.
113
+
114
+ PIN protection is enabled during setup — every new device must enter the PIN shown in your terminal before accessing any session. This prevents casual shoulder-surfing of the QR code, but is not a substitute for network-level security.
111
115
 
112
- Use a private network. We strongly recommend [Tailscale](https://tailscale.com), WireGuard, or a VPN. PIN protection adds a layer of access control but is not a substitute for network-level security. Do not expose claude-relay to the public internet.
116
+ Private network only. [Tailscale](https://tailscale.com), WireGuard, or a VPN. Never expose to the public internet.
113
117
 
114
- **Entirely at your own risk.** The authors assume no responsibility for any damage, data loss, or security incidents.
118
+ **Entirely at your own risk.**
115
119
 
116
- ## Issues
120
+ ## Contributing
117
121
 
118
- Found a bug or have a feature request? [Open an issue](https://github.com/chadbyte/claude-relay/issues).
122
+ Bug fixes and typos PR welcome. Feature ideas — [open an issue](https://github.com/chadbyte/claude-relay/issues) first. See [CONTRIBUTING.md](CONTRIBUTING.md).
119
123
 
120
124
  ## Disclaimer
121
125
 
122
- claude-relay is an independent, unofficial project. It is not affiliated with, endorsed by, or sponsored by Anthropic. "Claude" is a trademark of Anthropic.
126
+ Independent project. Not affiliated with Anthropic. "Claude" is a trademark of Anthropic.
123
127
 
124
128
  ## License
125
129
 
package/bin/cli.js CHANGED
@@ -3,7 +3,7 @@
3
3
  const os = require("os");
4
4
  const fs = require("fs");
5
5
  const path = require("path");
6
- const { execSync } = require("child_process");
6
+ const { execSync, execFileSync } = require("child_process");
7
7
  const qrcode = require("qrcode-terminal");
8
8
  const { createServer } = require("../lib/server");
9
9
 
@@ -116,10 +116,21 @@ function startCaffeinate() {
116
116
 
117
117
  // --- Certs ---
118
118
  function ensureCerts(ip) {
119
- var certDir = path.join(cwd, ".claude-relay", "certs");
119
+ var homeDir = process.env.HOME || process.env.USERPROFILE || os.homedir();
120
+ var certDir = path.join(homeDir, ".claude-relay", "certs");
120
121
  var keyPath = path.join(certDir, "key.pem");
121
122
  var certPath = path.join(certDir, "cert.pem");
122
123
 
124
+ // Migrate from legacy per-project certs to shared home dir
125
+ var legacyDir = path.join(cwd, ".claude-relay", "certs");
126
+ var legacyKey = path.join(legacyDir, "key.pem");
127
+ var legacyCert = path.join(legacyDir, "cert.pem");
128
+ if (!fs.existsSync(keyPath) && fs.existsSync(legacyKey) && fs.existsSync(legacyCert)) {
129
+ fs.mkdirSync(certDir, { recursive: true });
130
+ fs.copyFileSync(legacyKey, keyPath);
131
+ fs.copyFileSync(legacyCert, certPath);
132
+ }
133
+
123
134
  var caRoot = null;
124
135
  try {
125
136
  caRoot = path.join(
@@ -130,7 +141,15 @@ function ensureCerts(ip) {
130
141
  } catch (e) { }
131
142
 
132
143
  if (fs.existsSync(keyPath) && fs.existsSync(certPath)) {
133
- return { key: keyPath, cert: certPath, caRoot: caRoot };
144
+ // Re-generate if current IP is not in the cert's SAN
145
+ var needRegen = false;
146
+ if (ip && ip !== "localhost") {
147
+ try {
148
+ var certText = execFileSync("openssl", ["x509", "-in", certPath, "-text", "-noout"], { encoding: "utf8" });
149
+ if (certText.indexOf(ip) === -1) needRegen = true;
150
+ } catch (e) { /* openssl not available, skip check */ }
151
+ }
152
+ if (!needRegen) return { key: keyPath, cert: certPath, caRoot: caRoot };
134
153
  }
135
154
 
136
155
  fs.mkdirSync(certDir, { recursive: true });