clay-server 2.9.3-beta.2 → 2.9.3-beta.4
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 +152 -162
- package/bin/cli.js +5 -1
- package/lib/project.js +1 -0
- package/lib/public/app.js +4 -4
- package/lib/sdk-bridge.js +24 -3
- package/lib/server.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,226 +4,226 @@
|
|
|
4
4
|
<img src="media/phone.gif" alt="Clay on phone" width="300">
|
|
5
5
|
</p>
|
|
6
6
|
|
|
7
|
-
<h3 align="center">
|
|
7
|
+
<h3 align="center">A multi-user web UI for Claude Code, built on the Agent SDK.</h3>
|
|
8
8
|
|
|
9
|
-
[](https://www.npmjs.com/package/clay-server) [](https://www.npmjs.com/package/clay-server) [](https://github.com/chadbyte/clay) [](https://github.com/chadbyte/clay/blob/main/LICENSE)
|
|
10
10
|
|
|
11
|
-
Claude Code.
|
|
12
|
-
Same session. Same files. Same machine.
|
|
13
|
-
Your files stay on your computer. Nothing leaves for the cloud.
|
|
11
|
+
Clay extends Claude Code from a single-user CLI into a multi-user, multi-session web platform. It runs locally as a daemon, serves a browser UI over WebSocket, and lets non-technical teammates use Claude Code without touching the terminal.
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
Start in the terminal, continue on your phone, switch back anytime.
|
|
13
|
+
No relay server in the cloud. Your machine is the server. Zero install — one command:
|
|
17
14
|
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
```bash
|
|
16
|
+
npx clay-server
|
|
17
|
+
# Scan the QR code to connect from any device
|
|
18
|
+
```
|
|
20
19
|
|
|
21
|
-
|
|
22
|
-
It is not a thin wrapper that intercepts input/output. It drives Claude Code via the Claude Agent SDK and relays the stream from your local machine to your browser.
|
|
20
|
+
---
|
|
23
21
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
## Getting Started
|
|
23
|
+
|
|
24
|
+
**Requirements:** Node.js 20+, Claude Code CLI (authenticated).
|
|
27
25
|
|
|
28
26
|
```bash
|
|
29
|
-
|
|
30
|
-
npx claude-relay
|
|
31
|
-
# First run: Set Port/PIN -> Scan QR -> Connect
|
|
27
|
+
npx clay-server
|
|
32
28
|
```
|
|
33
29
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
## Never Miss an Approval
|
|
30
|
+
On first run, it walks you through port and PIN setup.
|
|
31
|
+
Scan the QR code to connect from your phone instantly.
|
|
37
32
|
|
|
38
|
-
|
|
39
|
-
One tap, and Claude Code gets back to work.
|
|
33
|
+
For remote access, use a VPN like Tailscale.
|
|
40
34
|
|
|
41
35
|
<p align="center">
|
|
42
|
-
<img src="media/
|
|
36
|
+
<img src="media/start.gif" alt="Clay starting from CLI" width="600">
|
|
43
37
|
</p>
|
|
44
38
|
|
|
45
|
-
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Multi-session, multi-project
|
|
46
42
|
|
|
47
|
-
|
|
43
|
+
Add a project in the browser and an agent attaches to it.
|
|
44
|
+
Run backend, frontend, and docs simultaneously. Switch between them in the sidebar.
|
|
45
|
+
|
|
46
|
+
The server runs as a background daemon. Sessions persist even after you close the terminal.
|
|
47
|
+
|
|
48
|
+
Mermaid diagrams render as diagrams. Tables render as tables.
|
|
49
|
+
Code blocks highlight 180+ languages.
|
|
50
|
+
Browse project files in the file browser — changes reflect live while the agent works.
|
|
48
51
|
|
|
49
52
|
<p align="center">
|
|
50
53
|
<img src="media/split.gif" alt="split-screen workflow" width="700">
|
|
51
54
|
</p>
|
|
52
55
|
|
|
53
|
-
|
|
54
|
-
Watch the results update live while Claude Code fixes your source files.
|
|
55
|
-
|
|
56
|
-
Mermaid diagrams render as diagrams, and tables appear as actual tables.
|
|
57
|
-
You can explore files in the sidebar and use the built-in terminal to run shell commands.
|
|
56
|
+
---
|
|
58
57
|
|
|
59
|
-
##
|
|
58
|
+
## Multi-user
|
|
60
59
|
|
|
61
|
-
|
|
62
|
-
Manage all your active sessions from a single dashboard.
|
|
60
|
+
Invite teammates and give them access to a project. They talk to Claude Code directly in the browser — no terminal, no setup on their end.
|
|
63
61
|
|
|
64
|
-
|
|
65
|
-
cd ~/projects/backend && npx claude-relay # Register project
|
|
66
|
-
cd ~/projects/frontend && npx claude-relay # Adds to the same server
|
|
67
|
-
```
|
|
62
|
+
Add a CLAUDE.md and the AI operates within those rules: explains technical terms in plain language, escalates risky operations to seniors, summarizes changes in simple words.
|
|
68
63
|
|
|
69
|
-
|
|
64
|
+
If someone gets stuck, join their session to unblock them in real time. Permissions can be separated per project and per session. Real-time presence shows who's where.
|
|
70
65
|
|
|
71
66
|
---
|
|
72
67
|
|
|
73
|
-
##
|
|
68
|
+
## Mobile & notifications
|
|
74
69
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
70
|
+
Phone, tablet, couch. All you need is a browser.
|
|
71
|
+
Pick up a terminal session in the browser. Continue a browser session from another device.
|
|
72
|
+
One QR code to connect. Install as a PWA for a native-like experience.
|
|
73
|
+
|
|
74
|
+
When Claude asks for approval, your phone buzzes. You also get notified on completion or error. No need to keep the browser open.
|
|
78
75
|
|
|
79
76
|
<p align="center">
|
|
80
|
-
<img src="media/
|
|
77
|
+
<img src="media/push-notification.jpg" alt="push notification" width="300">
|
|
81
78
|
</p>
|
|
82
79
|
|
|
83
|
-
|
|
84
|
-
Scan the QR code with your phone to connect instantly, or open the URL displayed in your terminal.
|
|
80
|
+
---
|
|
85
81
|
|
|
86
|
-
##
|
|
82
|
+
## Automation
|
|
83
|
+
|
|
84
|
+
The scheduler kicks off agents at set times.
|
|
85
|
+
Have it check open issues and submit PRs every morning at 8 AM.
|
|
86
|
+
Or compile world news and email you a digest every day.
|
|
87
|
+
|
|
88
|
+
Take it further with Ralph Loop — autonomous iteration built into Clay. Define a task (`PROMPT.md`) and success criteria (`JUDGE.md`), then start the loop. The agent works, commits, and a judge evaluates the git diff as PASS or FAIL. On FAIL, a fresh session starts over. Each iteration has **no memory of previous conversations** — only the code carries over. Based on [Geoffrey Huntley's Ralph Wiggum technique](https://ghuntley.com/loop/).
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Security & Privacy
|
|
93
|
+
|
|
94
|
+
Clay turns your machine into the relay server. There is no intermediary server on the internet. No third-party service sits between your browser and your code.
|
|
95
|
+
|
|
96
|
+
The best relay server to trust is the one that doesn't exist. Clay has none. Your data flows directly from your machine to the Anthropic API — exactly as it does when you use the CLI. No one intercepts, collects, or reroutes it. Clay adds a browser layer on top, not a middleman.
|
|
97
|
+
|
|
98
|
+
PIN authentication, per-project/session permissions, and HTTPS are supported by default. For local network use, this is sufficient. For remote access, we recommend a VPN like Tailscale.
|
|
99
|
+
|
|
100
|
+
---
|
|
87
101
|
|
|
88
|
-
|
|
89
|
-
* **Multi Project Daemon** - Manage all projects via a single port. Add and remove projects from the browser.
|
|
90
|
-
* **Usage and Model Switching** - View token usage, rate limit bars, and switch models from the browser.
|
|
91
|
-
* **Session Search** - Full-text search across all session messages with hit timeline.
|
|
92
|
-
* **Auto Session Logs (JSONL)** - Conversations and execution history are always saved locally. No data loss on crashes or restarts. Location: `./.claude-relay/sessions/`
|
|
93
|
-
* **File Browser and Terminal** - Inspect files, execute commands, and manage multiple terminal tabs from the browser.
|
|
102
|
+
## Why Clay?
|
|
94
103
|
|
|
95
|
-
|
|
104
|
+
*As of March 2026.*
|
|
96
105
|
|
|
97
|
-
|
|
98
|
-
|
|
106
|
+
| | CLI + Remote Control | tmux | Desktop | Cowork | **Clay** |
|
|
107
|
+
|---|---|---|---|---|---|
|
|
108
|
+
| Multi-user | ❌ | ✅ | ❌ | ❌ | ✅ |
|
|
109
|
+
| Mobile / PWA | ✅ | ➖ | ➖ | ➖ | ✅ |
|
|
110
|
+
| Push notifications | 🟠 | ❌ | 🟠 | ❌ | ✅ |
|
|
111
|
+
| GUI | 🟠 | ❌ | ✅ | ✅ | ✅ |
|
|
112
|
+
| Scheduler (cron) | 🟠 | ❌ | ✅ | ✅ | ✅ |
|
|
113
|
+
| Scheduler survives logout | ❌ | ➖ | 🟠 | 🟠 | ✅ |
|
|
114
|
+
| Join teammate's session | ❌ | 🟠 | ❌ | ❌ | ✅ |
|
|
99
115
|
|
|
100
|
-
|
|
116
|
+
✅ Supported · 🟠 Partial / limited · ❌ Not supported · ➖ N/A
|
|
101
117
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Key Features
|
|
121
|
+
|
|
122
|
+
* **Multi-user** - Accounts, invitations, per-project/session permissions, real-time presence.
|
|
123
|
+
* **Multi-agent** - Parallel agents per project, sidebar switching.
|
|
124
|
+
* **Push notifications** - Approval, completion, error. Native-like PWA experience.
|
|
125
|
+
* **Scheduler** - Cron-based automatic agent execution.
|
|
126
|
+
* **Ralph Loop** - Autonomous coding loop with PROMPT.md + JUDGE.md. Iterates until the judge says PASS.
|
|
127
|
+
* **File browser** - File exploration, syntax highlighting, live reload.
|
|
128
|
+
* **Built-in terminal** - Multi-tab terminal, mobile keyboard support.
|
|
129
|
+
* **Session search** - Full-text search across all conversation history.
|
|
130
|
+
* **Session persistence** - Survives crashes, restarts, and network drops.
|
|
131
|
+
|
|
132
|
+
---
|
|
105
133
|
|
|
106
|
-
|
|
134
|
+
## FAQ
|
|
107
135
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
* **Session Persistence** - Sessions survive server restarts, browser crashes, and network drops.
|
|
111
|
-
* **Session Handoff** - Start in the terminal, continue on your phone, pass back to desktop. Browse and resume CLI sessions directly from the web UI.
|
|
112
|
-
* **Session Search** - Full-text search across all session content with highlighted results and a rewind-style hit timeline.
|
|
113
|
-
* **Rewind (Native Claude Code)** - Accessible directly from the browser UI.
|
|
114
|
-
* **Draft Persistence** - Unsent messages are saved per session and restored when you switch back.
|
|
136
|
+
**"Is this just a terminal wrapper?"**
|
|
137
|
+
No. Clay runs on the Claude Agent SDK. It doesn't wrap terminal output. It communicates directly with the agent through the SDK.
|
|
115
138
|
|
|
116
|
-
**
|
|
139
|
+
**"Is it free? Open source?"**
|
|
140
|
+
Free. MIT-licensed open source. All code is public.
|
|
117
141
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
* **File Browser** - Sidebar navigation with file previews, markdown rendering, and live-reload on external changes.
|
|
121
|
-
* **Built in Terminal** - Multi-tab terminal sessions with rename, reorder, and a mobile special-key toolbar.
|
|
122
|
-
* **Slash Commands** - Execute standard Claude Code commands from the browser, with autocomplete.
|
|
123
|
-
* **Usage Panel** - View token counts and rate limit progress bars via `/usage` command or header button.
|
|
124
|
-
* **Model Switching** - Change the active model directly from the browser header.
|
|
125
|
-
* **Plan Approval** - Review and approve Claude implementation plans from the browser UI.
|
|
142
|
+
**"Do I need to install anything?"**
|
|
143
|
+
No. `npx clay-server` runs it directly. No global install, no build step, no Docker. Node.js and Claude Code are the only prerequisites.
|
|
126
144
|
|
|
127
|
-
**
|
|
145
|
+
**"Does my code leave my machine?"**
|
|
146
|
+
The Clay server runs locally. Files stay local. Only Claude API calls go out, which is the same as using the CLI.
|
|
128
147
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
* **QR Code** - Scan to connect instantly.
|
|
132
|
-
* **Image Paste and Camera** - Paste images from clipboard or attach photos directly from your camera.
|
|
133
|
-
* **Send While Processing** - Queue messages without waiting for the current response to finish.
|
|
134
|
-
* **Sticky Todo Overlay** - TodoWrite tasks float as a progress bar while you scroll through the conversation.
|
|
135
|
-
* **Scroll Position Hold** - Reading earlier messages will not get interrupted by new content arriving.
|
|
136
|
-
* **RTL Text Support** - Automatic bidirectional text rendering for Arabic, Hebrew, and other RTL languages.
|
|
148
|
+
**"Is it secure?"**
|
|
149
|
+
PIN authentication, per-project/session permissions, and HTTPS are supported by default. See [Security & Privacy](#security--privacy) for details.
|
|
137
150
|
|
|
138
|
-
**
|
|
151
|
+
**"What OS does it run on?"**
|
|
152
|
+
Windows, Linux, and macOS are all supported.
|
|
139
153
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
* **PIN Protection** - Restrict access with a 6 digit PIN.
|
|
143
|
-
* **HTTPS** - Automatic certificate generation via mkcert.
|
|
144
|
-
* **Zero Config** - Inherits your existing Claude Code configuration.
|
|
154
|
+
**"Can I continue a CLI session?"**
|
|
155
|
+
Yes. Pick up a CLI session in the browser, or continue a browser session in the CLI.
|
|
145
156
|
|
|
146
|
-
|
|
157
|
+
**"Does my existing CLAUDE.md work?"**
|
|
158
|
+
Yes. If your project has a CLAUDE.md, it works in Clay as-is.
|
|
147
159
|
|
|
148
|
-
|
|
160
|
+
**"Can I use it as an app?"**
|
|
161
|
+
PWA is supported. On mobile, tap the download icon in the top-left corner to open the PWA install guide. Once installed, it provides a native-like experience.
|
|
149
162
|
|
|
150
|
-
|
|
163
|
+
**"Can I use the terminal on mobile?"**
|
|
164
|
+
Yes. Clay provides a built-in terminal with mobile keyboard support.
|
|
151
165
|
|
|
152
|
-
|
|
166
|
+
**"Does each teammate need their own API key?"**
|
|
167
|
+
No. Teammates share the Claude Code session logged in on the server. If needed, you can configure per-project environment variables to use different API keys.
|
|
153
168
|
|
|
154
|
-
|
|
169
|
+
**"Does it work with MCP servers?"**
|
|
170
|
+
Yes. MCP configurations from the CLI carry over as-is.
|
|
155
171
|
|
|
156
|
-
|
|
157
|
-
|
|
172
|
+
**"How do I update?"**
|
|
173
|
+
Auto-update is supported. When a new version is available, apply it with one click.
|
|
158
174
|
|
|
159
|
-
|
|
175
|
+
**"Can I use other AI models besides Claude?"**
|
|
176
|
+
Currently Clay is Claude Code only. Other model support is on the roadmap.
|
|
160
177
|
|
|
161
|
-
|
|
162
|
-
|
|
178
|
+
**"Can I run it in Docker?"**
|
|
179
|
+
There's no official Docker image yet, but it can run in a container with a Node.js environment.
|
|
163
180
|
|
|
164
|
-
|
|
181
|
+
---
|
|
165
182
|
|
|
166
183
|
## HTTPS for Push
|
|
167
184
|
|
|
168
|
-
|
|
185
|
+
Everything works out of the box. Only push notifications require HTTPS.
|
|
169
186
|
|
|
170
|
-
Set it up once
|
|
187
|
+
Set it up once with [mkcert](https://github.com/FiloSottile/mkcert):
|
|
171
188
|
|
|
172
189
|
```bash
|
|
173
190
|
brew install mkcert
|
|
174
191
|
mkcert -install
|
|
175
192
|
```
|
|
176
193
|
|
|
177
|
-
Certificates are generated
|
|
194
|
+
Certificates are auto-generated. The setup wizard handles the rest.
|
|
195
|
+
|
|
196
|
+
If push registration fails: check that your browser trusts the HTTPS certificate and that your phone can reach the server address.
|
|
178
197
|
|
|
179
|
-
|
|
198
|
+
---
|
|
180
199
|
|
|
181
200
|
## CLI Options
|
|
182
201
|
|
|
183
202
|
```bash
|
|
184
|
-
npx
|
|
185
|
-
npx
|
|
186
|
-
npx
|
|
187
|
-
npx
|
|
188
|
-
# Non-interactive
|
|
189
|
-
npx
|
|
190
|
-
npx
|
|
191
|
-
npx
|
|
192
|
-
npx
|
|
193
|
-
npx
|
|
194
|
-
npx
|
|
195
|
-
npx
|
|
196
|
-
npx
|
|
197
|
-
npx
|
|
198
|
-
# Bypass all permission prompts (PIN
|
|
199
|
-
npx
|
|
203
|
+
npx clay-server # Default (port 2633)
|
|
204
|
+
npx clay-server -p 8080 # Specify port
|
|
205
|
+
npx clay-server --yes # Skip interactive prompts (use defaults)
|
|
206
|
+
npx clay-server -y --pin 123456
|
|
207
|
+
# Non-interactive + PIN (for scripts/CI)
|
|
208
|
+
npx clay-server --no-https # Disable HTTPS
|
|
209
|
+
npx clay-server --no-update # Skip update check
|
|
210
|
+
npx clay-server --debug # Enable debug panel
|
|
211
|
+
npx clay-server --add . # Add current directory to running daemon
|
|
212
|
+
npx clay-server --add /path # Add project by path
|
|
213
|
+
npx clay-server --remove . # Remove project
|
|
214
|
+
npx clay-server --list # List registered projects
|
|
215
|
+
npx clay-server --shutdown # Stop running daemon
|
|
216
|
+
npx clay-server --dangerously-skip-permissions
|
|
217
|
+
# Bypass all permission prompts (requires PIN at setup)
|
|
218
|
+
npx clay-server --dev # Dev mode (foreground, auto-restart on lib/ changes, port 2635)
|
|
200
219
|
```
|
|
201
220
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
* [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code) installed and authenticated
|
|
205
|
-
* Node.js 18+
|
|
206
|
-
* [mkcert](https://github.com/FiloSottile/mkcert) - For push notifications (optional)
|
|
207
|
-
* [Tailscale](https://tailscale.com) - For remote access (optional)
|
|
208
|
-
|
|
209
|
-
## Why claude-relay?
|
|
210
|
-
|
|
211
|
-
**Why not just use tmux + Termius?**
|
|
212
|
-
You can monitor the terminal remotely, but there are no push notifications and no way to approve permission requests without switching back to the terminal. On a phone, navigating a raw terminal session is clunky. You end up checking manually instead of getting notified, and the experience never feels native.
|
|
213
|
-
|
|
214
|
-
**Why not just add hooks to send notifications?**
|
|
215
|
-
Hooks with ntfy or Pushover can get you push notifications, but you still need shell scripts, config files, and third-party accounts just to get alerts. And once you get the notification, there is no UI to approve or reject from. You are back to opening a terminal. claude-relay gives you notifications, a one-tap approval UI, and a full web interface with a single command.
|
|
216
|
-
|
|
217
|
-
**Why not use Claude Code Desktop?**
|
|
218
|
-
The desktop app works great on your computer, but there is no mobile version. To access sessions from your phone, you need remote sessions on Anthropic's cloud, which requires pushing your code to GitHub first. claude-relay runs entirely on your machine and lets you connect from any device on your network.
|
|
219
|
-
|
|
220
|
-
**Why not use Happy Coder?**
|
|
221
|
-
Happy Coder requires installing a native app and routes through its own relay server with end-to-end encryption. claude-relay *is* the relay server, running on your machine. Open a URL and you are in. No app install, no signup, nothing leaves your network.
|
|
221
|
+
---
|
|
222
222
|
|
|
223
223
|
## Architecture
|
|
224
224
|
|
|
225
|
-
|
|
226
|
-
It
|
|
225
|
+
Clay is not a wrapper that intercepts stdio.
|
|
226
|
+
It's a local relay server that drives Claude Code execution through the [Claude Agent SDK](https://www.npmjs.com/package/@anthropic-ai/claude-agent-sdk) and streams it to the browser over WebSocket.
|
|
227
227
|
|
|
228
228
|
```mermaid
|
|
229
229
|
graph LR
|
|
@@ -244,39 +244,29 @@ graph LR
|
|
|
244
244
|
Push -->|Notification| Browser
|
|
245
245
|
```
|
|
246
246
|
|
|
247
|
-
For
|
|
248
|
-
|
|
249
|
-
## Star History
|
|
250
|
-
|
|
251
|
-
<a href="https://star-history.com/#chadbyte/claude-relay&Date">
|
|
252
|
-
<picture>
|
|
253
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=chadbyte/claude-relay&type=Date&theme=dark" />
|
|
254
|
-
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=chadbyte/claude-relay&type=Date" />
|
|
255
|
-
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=chadbyte/claude-relay&type=Date" width="600" />
|
|
256
|
-
</picture>
|
|
257
|
-
</a>
|
|
247
|
+
For detailed sequence diagrams, daemon architecture, and design decisions, see [docs/architecture.md](docs/architecture.md).
|
|
258
248
|
|
|
259
249
|
---
|
|
260
250
|
|
|
261
251
|
## Contributors
|
|
262
252
|
|
|
263
|
-
<a href="https://github.com/chadbyte/
|
|
264
|
-
<img src="https://contrib.rocks/image?repo=chadbyte/
|
|
253
|
+
<a href="https://github.com/chadbyte/clay/graphs/contributors">
|
|
254
|
+
<img src="https://contrib.rocks/image?repo=chadbyte/clay" />
|
|
265
255
|
</a>
|
|
266
256
|
|
|
267
257
|
## Contributing
|
|
268
258
|
|
|
269
|
-
Bug fixes and
|
|
270
|
-
[https://github.com/chadbyte/
|
|
259
|
+
Bug fixes and typo corrections are welcome. For feature suggestions, please open an issue first:
|
|
260
|
+
[https://github.com/chadbyte/clay/issues](https://github.com/chadbyte/clay/issues)
|
|
271
261
|
|
|
272
|
-
If you
|
|
273
|
-
[https://github.com/chadbyte/
|
|
262
|
+
If you're using Clay, let us know how in Discussions:
|
|
263
|
+
[https://github.com/chadbyte/clay/discussions](https://github.com/chadbyte/clay/discussions)
|
|
274
264
|
|
|
275
265
|
## Disclaimer
|
|
276
266
|
|
|
277
267
|
This is an independent project and is not affiliated with Anthropic. Claude is a trademark of Anthropic.
|
|
278
268
|
|
|
279
|
-
Clay is provided "as is" without warranty of any kind. Users are responsible for
|
|
269
|
+
Clay is provided "as is" without warranty of any kind. Users are responsible for complying with the terms of service of underlying AI providers (e.g., Anthropic, OpenAI) and all applicable terms of any third-party services. Features such as multi-user mode are experimental and may involve sharing access to API-based services. Before enabling such features, review your provider's usage policies regarding account sharing, acceptable use, and any applicable rate limits or restrictions. The authors assume no liability for misuse or violations arising from the use of this software.
|
|
280
270
|
|
|
281
271
|
## License
|
|
282
272
|
|
package/bin/cli.js
CHANGED
|
@@ -23,7 +23,11 @@ var net = require("net");
|
|
|
23
23
|
|
|
24
24
|
// Detect dev mode — dev and prod use separate daemon files so they can run simultaneously
|
|
25
25
|
var _isDev = (process.argv[1] && path.basename(process.argv[1]) === "clay-dev") || process.argv.includes("--dev");
|
|
26
|
-
if (_isDev)
|
|
26
|
+
if (_isDev) {
|
|
27
|
+
process.env.CLAY_DEV = "1";
|
|
28
|
+
// Preserve console output in dev mode so logs remain readable
|
|
29
|
+
console.clear = function() {};
|
|
30
|
+
}
|
|
27
31
|
|
|
28
32
|
var { loadConfig, saveConfig, configPath, socketPath, logPath, ensureConfigDir, isDaemonAlive, isDaemonAliveAsync, generateSlug, clearStaleConfig, loadClayrc, saveClayrc, readCrashInfo } = require("../lib/config");
|
|
29
33
|
var { sendIPCCommand } = require("../lib/ipc");
|
package/lib/project.js
CHANGED
|
@@ -3047,6 +3047,7 @@ function createProjectContext(opts) {
|
|
|
3047
3047
|
stopAllDirWatches();
|
|
3048
3048
|
// Abort all active sessions
|
|
3049
3049
|
sm.sessions.forEach(function (session) {
|
|
3050
|
+
session.destroying = true;
|
|
3050
3051
|
if (session.abortController) {
|
|
3051
3052
|
try { session.abortController.abort(); } catch (e) {}
|
|
3052
3053
|
}
|
package/lib/public/app.js
CHANGED
|
@@ -2557,6 +2557,10 @@ import { initAdmin, checkAdminAccess } from './modules/admin.js';
|
|
|
2557
2557
|
break;
|
|
2558
2558
|
|
|
2559
2559
|
case "info":
|
|
2560
|
+
if (msg.text && !msg.project && !msg.cwd) {
|
|
2561
|
+
addSystemMessage(msg.text, false);
|
|
2562
|
+
break;
|
|
2563
|
+
}
|
|
2560
2564
|
projectName = msg.project || msg.cwd;
|
|
2561
2565
|
if (msg.slug) currentSlug = msg.slug;
|
|
2562
2566
|
try { localStorage.setItem("clay-project-name-" + (currentSlug || "default"), projectName); } catch (e) {}
|
|
@@ -2994,10 +2998,6 @@ import { initAdmin, checkAdminAccess } from './modules/admin.js';
|
|
|
2994
2998
|
addSystemMessage(msg.text, false);
|
|
2995
2999
|
break;
|
|
2996
3000
|
|
|
2997
|
-
case "info":
|
|
2998
|
-
addSystemMessage(msg.text, false);
|
|
2999
|
-
break;
|
|
3000
|
-
|
|
3001
3001
|
case "error":
|
|
3002
3002
|
setActivity(null);
|
|
3003
3003
|
addSystemMessage(msg.text, true);
|
package/lib/sdk-bridge.js
CHANGED
|
@@ -626,13 +626,27 @@ function createSDKBridge(opts) {
|
|
|
626
626
|
for await (var msg of session.queryInstance) {
|
|
627
627
|
processSDKMessage(session, msg);
|
|
628
628
|
}
|
|
629
|
+
// Stream ended normally after a task stop — no "result" message was sent,
|
|
630
|
+
// so the session is still marked as processing. Send interrupted feedback.
|
|
631
|
+
if (session.isProcessing && session.taskStopRequested) {
|
|
632
|
+
session.isProcessing = false;
|
|
633
|
+
onProcessingChanged();
|
|
634
|
+
sendAndRecord(session, { type: "info", text: "Interrupted \u00b7 What should Claude do instead?" });
|
|
635
|
+
sendAndRecord(session, { type: "done", code: 0 });
|
|
636
|
+
sm.broadcastSessionList();
|
|
637
|
+
}
|
|
629
638
|
} catch (err) {
|
|
630
639
|
if (session.isProcessing) {
|
|
631
640
|
session.isProcessing = false;
|
|
632
641
|
onProcessingChanged();
|
|
633
|
-
if (err.name === "AbortError" || (session.abortController && session.abortController.signal.aborted)) {
|
|
634
|
-
|
|
635
|
-
|
|
642
|
+
if (err.name === "AbortError" || (session.abortController && session.abortController.signal.aborted) || session.taskStopRequested) {
|
|
643
|
+
if (!session.destroying) {
|
|
644
|
+
sendAndRecord(session, { type: "info", text: "Interrupted \u00b7 What should Claude do instead?" });
|
|
645
|
+
sendAndRecord(session, { type: "done", code: 0 });
|
|
646
|
+
}
|
|
647
|
+
} else if (session.destroying) {
|
|
648
|
+
// Suppress error messages during shutdown
|
|
649
|
+
console.log("[sdk-bridge] Suppressing stream error during shutdown for session " + session.localId);
|
|
636
650
|
} else {
|
|
637
651
|
var errDetail = err.message || String(err);
|
|
638
652
|
if (err.stderr) errDetail += "\nstderr: " + err.stderr;
|
|
@@ -681,6 +695,7 @@ function createSDKBridge(opts) {
|
|
|
681
695
|
session.queryInstance = null;
|
|
682
696
|
session.messageQueue = null;
|
|
683
697
|
session.abortController = null;
|
|
698
|
+
session.taskStopRequested = false;
|
|
684
699
|
session.pendingPermissions = {};
|
|
685
700
|
session.pendingAskUser = {};
|
|
686
701
|
}
|
|
@@ -1007,11 +1022,17 @@ function createSDKBridge(opts) {
|
|
|
1007
1022
|
async function stopTask(taskId) {
|
|
1008
1023
|
var session = sm.getActiveSession();
|
|
1009
1024
|
if (!session || !session.queryInstance) return;
|
|
1025
|
+
session.taskStopRequested = true;
|
|
1010
1026
|
try {
|
|
1011
1027
|
await session.queryInstance.stopTask(taskId);
|
|
1012
1028
|
} catch (e) {
|
|
1013
1029
|
console.error("[sdk-bridge] stopTask error:", e.message);
|
|
1014
1030
|
}
|
|
1031
|
+
// SDK stopTask doesn't reliably stop the sub-agent, so abort the entire
|
|
1032
|
+
// session as a fallback to ensure the process actually stops.
|
|
1033
|
+
if (session.abortController) {
|
|
1034
|
+
session.abortController.abort();
|
|
1035
|
+
}
|
|
1015
1036
|
}
|
|
1016
1037
|
|
|
1017
1038
|
return {
|
package/lib/server.js
CHANGED
|
@@ -390,7 +390,7 @@ function createServer(opts) {
|
|
|
390
390
|
var securityHeaders = {
|
|
391
391
|
"X-Content-Type-Options": "nosniff",
|
|
392
392
|
"X-Frame-Options": "DENY",
|
|
393
|
-
"Content-Security-Policy": "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://esm.sh; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://cdn.jsdelivr.net; img-src
|
|
393
|
+
"Content-Security-Policy": "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://esm.sh; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://cdn.jsdelivr.net; img-src * data: blob:; connect-src 'self' ws: wss: https://cdn.jsdelivr.net https://esm.sh https://api.dicebear.com https://api.open-meteo.com; font-src 'self' data: https://fonts.gstatic.com https://cdn.jsdelivr.net;",
|
|
394
394
|
};
|
|
395
395
|
if (tlsOptions) {
|
|
396
396
|
securityHeaders["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains";
|