clay-server 3.6.0-beta.1 → 3.6.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 +54 -196
- package/bin/cli.js +7 -42
- package/lib/builtin-mates.js +1 -1
- package/lib/cli-wordmark.js +32 -0
- package/lib/pages.js +47 -35
- package/lib/public/app.js +2 -10
- package/lib/public/apple-touch-icon.png +0 -0
- package/lib/public/clay-studio-favicon-32.png +0 -0
- package/lib/public/clay-studio-symbol.png +0 -0
- package/lib/public/clay-studio-wordmark.svg +20 -0
- package/lib/public/css/base.css +143 -61
- package/lib/public/css/filebrowser.css +54 -8
- package/lib/public/css/icon-strip.css +33 -19
- package/lib/public/css/input.css +15 -5
- package/lib/public/css/messages.css +17 -14
- package/lib/public/css/mobile-nav.css +5 -5
- package/lib/public/css/overlays.css +58 -6
- package/lib/public/css/pane.css +0 -1
- package/lib/public/css/session-actions.css +9 -3
- package/lib/public/css/sidebar.css +104 -161
- package/lib/public/css/title-bar.css +51 -18
- package/lib/public/css/user-settings.css +114 -8
- package/lib/public/icon-192.png +0 -0
- package/lib/public/icon-512.png +0 -0
- package/lib/public/index.html +32 -76
- package/lib/public/manifest.json +1 -6
- package/lib/public/modules/app-connection.js +0 -3
- package/lib/public/modules/app-favicon.js +22 -29
- package/lib/public/modules/app-messages.js +1 -2
- package/lib/public/modules/app-notifications.js +3 -3
- package/lib/public/modules/command-palette.js +1 -1
- package/lib/public/modules/server-settings.js +0 -77
- package/lib/public/modules/sidebar-projects.js +1 -1
- package/lib/public/modules/sidebar-sessions.js +18 -5
- package/lib/public/modules/sidebar.js +2 -2
- package/lib/public/modules/theme.js +88 -249
- package/lib/public/modules/user-settings.js +2 -3
- package/lib/public/style.css +10 -10
- package/lib/public/sw.js +4 -2
- package/lib/themes/clay-dark.json +11 -0
- package/lib/themes/clay-light.json +11 -0
- package/package.json +1 -1
- package/lib/public/apple-touch-icon-dark.png +0 -0
- package/lib/public/clay-logo.png +0 -0
- package/lib/public/favicon-banded-32.png +0 -0
- package/lib/public/favicon-banded.png +0 -0
- package/lib/public/favicon-dark.svg +0 -1
- package/lib/public/favicon.svg +0 -1
- package/lib/public/icon-192-dark.png +0 -0
- package/lib/public/icon-512-dark.png +0 -0
- package/lib/public/icon-banded-76.png +0 -0
- package/lib/public/icon-banded-96.png +0 -0
- package/lib/public/icon-mono.svg +0 -1
- package/lib/public/modules/ascii-logo.js +0 -442
- package/lib/public/wordmark-banded-20.png +0 -0
- package/lib/public/wordmark-banded-32.png +0 -0
- package/lib/public/wordmark-banded-64.png +0 -0
- package/lib/public/wordmark-banded-80.png +0 -0
package/README.md
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="
|
|
2
|
+
<img src="lib/public/icon-192.png" width="120" alt="Clay Studio symbol" /><br>
|
|
3
|
+
<img src="lib/public/clay-studio-wordmark.svg" width="280" alt="Clay Studio" />
|
|
3
4
|
</p>
|
|
4
5
|
|
|
5
|
-
<h2 align="center">
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
</
|
|
6
|
+
<h2 align="center">Where minds work together.</h2>
|
|
7
|
+
|
|
8
|
+
<p align="center">
|
|
9
|
+
A self-hosted workspace where people and coding agents work together<br>
|
|
10
|
+
across projects, sessions, and providers.
|
|
11
|
+
</p>
|
|
11
12
|
|
|
12
13
|
<p align="center">
|
|
13
14
|
<a href="https://www.npmjs.com/package/clay-server"><img src="https://img.shields.io/npm/v/clay-server" alt="npm version" /></a>
|
|
@@ -16,235 +17,92 @@ Self-hosted, one toggle between vendors.
|
|
|
16
17
|
<a href="https://github.com/chadbyte/clay/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT" /></a>
|
|
17
18
|
</p>
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
Clay Studio turns local coding agents into a shared, persistent team. Run different agents from one browser workspace, join a teammate's live session, keep project knowledge between conversations, and automate work without handing your workspace to another cloud.
|
|
20
21
|
|
|
21
|
-
|
|
22
|
+
## Quick start
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
**Requirements:** Node.js 20+ and at least one supported coding-agent CLI installed and authenticated.
|
|
24
25
|
|
|
25
26
|
```bash
|
|
26
27
|
npx clay-server
|
|
27
|
-
#
|
|
28
|
+
# Open the URL or scan the QR code from another device
|
|
28
29
|
```
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
- **A browser-based workspace for Claude Code and Codex.** Open it on any device, alone or with your whole team.
|
|
33
|
-
- **A place where your team collaborates across projects.** Engineers, PMs, designers, and domain experts share one workspace, hop between projects, drop into each other's sessions.
|
|
34
|
-
- **Your virtual team.** Mates with names, memory, and roles — architect, reviewer, designer, whoever you need. They learn your codebase, push back on bad ideas, and don't reset between sessions.
|
|
35
|
-
- **A multi-project dashboard.** Every repo on your machine in one sidebar. Run agents across several in parallel; permission requests and completions surface as notifications.
|
|
36
|
-
- **A self-hosted dev server.** Runs on your machine in plain JSONL and Markdown. No proprietary database, no cloud relay, no lock-in. Walk away whenever — your data walks with you.
|
|
37
|
-
- **A work-automation system.** Ralph Loop iterates a feature overnight; cron schedules agents while you're away. Wake up to results, or a clean failure trace.
|
|
38
|
-
|
|
39
|
-
## What it does
|
|
40
|
-
|
|
41
|
-
### Run Claude Code and Codex in one workspace
|
|
42
|
-
|
|
43
|
-
Open a session, pick a vendor. Switch sessions, pick the other. Clay's adapter layer (YOKE) speaks the Claude Agent SDK and the Codex app-server protocol natively. Cross-vendor instruction loading: Codex reads AGENTS.md, Claude reads CLAUDE.md, Clay merges the rest into the system prompt automatically.
|
|
44
|
-
|
|
45
|
-
<p align="center">
|
|
46
|
-
<img src="media/split.gif" alt="Toggle between Claude Code and Codex in one click" width="700">
|
|
47
|
-
</p>
|
|
48
|
-
|
|
49
|
-
### Every project on one dashboard
|
|
50
|
-
|
|
51
|
-
All your projects live in the sidebar. Jump between them in one click, see live status across each, run agents in several at once. No more `cd ~/work/foo && tmux attach && ...`. One Clay daemon hosts every repo on your machine and gives you a single pane of glass over all of them.
|
|
52
|
-
|
|
53
|
-
### Mates: AI teammates with persistent memory
|
|
54
|
-
|
|
55
|
-
Mates are AI personas with their own CLAUDE.md, knowledge files, and memory that compounds across sessions. They learn your stack, your conventions, your decision history. @mention them mid-session, DM them directly, or drop them into a debate. **They don't flatter you. They push back.**
|
|
31
|
+
Clay Studio runs on your machine and serves the workspace to your browser. For access outside your local network, use a private network such as Tailscale.
|
|
56
32
|
|
|
57
|
-
|
|
58
|
-
<img src="media/mates.gif" alt="An AI teammate (Mate) pushing back on a bad design pitch in Clay" width="640">
|
|
59
|
-
</p>
|
|
60
|
-
|
|
61
|
-
### Debate: structured multi-Mate decisions
|
|
62
|
-
|
|
63
|
-
Stuck on REST vs GraphQL? Monorepo or split? Surface the question to a debate. Pick panelists, set the format, let your Mates argue both sides with moderated turns. You walk away with a recorded decision, not a vibe check.
|
|
64
|
-
|
|
65
|
-
### Parallel worktrees
|
|
66
|
-
|
|
67
|
-
Detect existing git worktrees, spin up new ones from the sidebar, and run agents in each one independently. No more "wait, I have uncommitted changes." Each worktree is an isolated session with its own history.
|
|
68
|
-
|
|
69
|
-
### Ralph Loop: autonomous coding while you sleep
|
|
33
|
+
## Why Clay Studio
|
|
70
34
|
|
|
71
|
-
|
|
35
|
+
### Work together
|
|
72
36
|
|
|
73
|
-
|
|
37
|
+
Projects, sessions, people, and agents share one workspace. Teammates can see live activity, enter the same session, hand off work, and respond to permission requests without gathering around one terminal.
|
|
74
38
|
|
|
75
|
-
|
|
39
|
+
### Keep the context
|
|
76
40
|
|
|
77
|
-
|
|
41
|
+
Sessions do not have to be disposable chats. Mates retain their roles and knowledge, project instructions carry across supported runtimes, and decisions remain available when the next task begins.
|
|
78
42
|
|
|
79
|
-
###
|
|
43
|
+
### Stay in control
|
|
80
44
|
|
|
81
|
-
|
|
45
|
+
The daemon runs on infrastructure you control. Sessions and knowledge live on disk in portable JSONL and Markdown rather than a proprietary database. Change coding agents without migrating the workspace around them.
|
|
82
46
|
|
|
83
|
-
|
|
47
|
+
## Supported coding agents
|
|
84
48
|
|
|
85
|
-
|
|
49
|
+
Clay Studio currently includes integrations for:
|
|
86
50
|
|
|
87
|
-
|
|
51
|
+
**Claude Code · Codex · Grok Build · Kimi Code · GitHub Copilot CLI · Qwen Code · Junie CLI · Antigravity CLI · OpenCode · Kiro CLI**
|
|
88
52
|
|
|
89
|
-
|
|
53
|
+
Clay detects locally installed runtimes and exposes the ones available on your machine. Each runtime keeps its own authentication and may expose different models, modes, and capabilities.
|
|
90
54
|
|
|
91
|
-
|
|
55
|
+
## Core capabilities
|
|
92
56
|
|
|
93
|
-
|
|
57
|
+
- **Shared projects and live sessions.** Organize several repositories in one sidebar, run sessions in parallel, and collaborate with presence, cursors, mentions, and handoffs.
|
|
58
|
+
- **Persistent Mates.** Create AI collaborators with their own identity, instructions, knowledge, memory, direct messages, and roles in structured debates.
|
|
59
|
+
- **Cross-provider continuity.** YOKE gives supported coding agents a common session interface and carries project instruction files across vendor boundaries.
|
|
60
|
+
- **Parallel and background work.** Use git worktrees, paired sessions, spawned workers, scheduled tasks, and Ralph Loops without losing visibility into what is running.
|
|
61
|
+
- **A workspace on every device.** Use the desktop browser or install the PWA on mobile. Receive push notifications for approvals, failures, and completed work.
|
|
62
|
+
- **Tools where the work happens.** Browse and edit files, inspect diffs and history, open terminals, install skills, connect MCP servers, and manage project knowledge from the same workspace.
|
|
94
63
|
|
|
95
|
-
##
|
|
64
|
+
## Your machine is the server
|
|
96
65
|
|
|
97
|
-
|
|
66
|
+
The normal request path is:
|
|
98
67
|
|
|
99
|
-
```
|
|
100
|
-
|
|
68
|
+
```text
|
|
69
|
+
Browser → Clay Studio daemon → selected coding-agent runtime → model provider
|
|
101
70
|
```
|
|
102
71
|
|
|
103
|
-
|
|
72
|
+
Clay Studio does not relay project traffic through a Clay-hosted cloud. Your code leaves the machine only when the selected runtime sends it to its model provider, just as it would when you use that CLI directly.
|
|
104
73
|
|
|
105
|
-
|
|
74
|
+
The `d.clay.studio` hostname used for local HTTPS is a DNS-only service: no application data passes through it. See [clay-dns](clay-dns/) for the implementation and threat model.
|
|
106
75
|
|
|
107
|
-
|
|
108
|
-
<img src="media/start.gif" alt="Starting Clay daemon from the CLI with npx clay-server" width="600">
|
|
109
|
-
</p>
|
|
110
|
-
|
|
111
|
-
## CLI Options
|
|
76
|
+
## Common CLI commands
|
|
112
77
|
|
|
113
78
|
```bash
|
|
114
|
-
npx clay-server #
|
|
115
|
-
npx clay-server -p 8080 #
|
|
116
|
-
npx clay-server --
|
|
117
|
-
npx clay-server -y --pin 123456
|
|
118
|
-
# Non-interactive + PIN (for scripts/CI)
|
|
119
|
-
npx clay-server --add . # Add current directory to running daemon
|
|
120
|
-
npx clay-server --remove . # Remove project
|
|
79
|
+
npx clay-server # Start on the default port (2633)
|
|
80
|
+
npx clay-server -p 8080 # Use a different port
|
|
81
|
+
npx clay-server --add . # Add the current directory
|
|
121
82
|
npx clay-server --list # List registered projects
|
|
122
|
-
npx clay-server --shutdown # Stop
|
|
123
|
-
npx clay-server --dangerously-skip-permissions
|
|
124
|
-
# Bypass all permission prompts (requires PIN at setup)
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
Run `npx clay-server --help` for all options.
|
|
128
|
-
|
|
129
|
-
## FAQ
|
|
130
|
-
|
|
131
|
-
**"Is this a Claude Code wrapper?"**
|
|
132
|
-
No. Clay drives Claude Code through the [Claude Agent SDK](https://www.npmjs.com/package/@anthropic-ai/claude-agent-sdk) and Codex through the Codex app-server protocol. Both are first-class. Clay adds multi-session orchestration, persistent Mates, structured debates, scheduled agents, multi-user collaboration, built-in MCP servers, and a full browser UI on top.
|
|
133
|
-
|
|
134
|
-
**"Can I run Claude Code and Codex in the same workspace?"**
|
|
135
|
-
Yes. Pick a vendor when you open a session. Switch per session. Same projects, same Mates, same memory.
|
|
136
|
-
|
|
137
|
-
**"How are Mates different from Claude Code's sub-agents?"**
|
|
138
|
-
Sub-agents are ephemeral specialists spawned inside a single Claude Code session — a role and a system prompt for one task, then forgotten when the task ends. Mates are persistent teammates with their own knowledge files and memory that survive every session. A sub-agent forgets you the moment it returns; a Mate remembers your codebase, your decisions, and your conventions across months of work. @mention a Mate mid-session, DM it between sessions, or drop several into a debate.
|
|
139
|
-
|
|
140
|
-
**"Does my code leave my machine?"**
|
|
141
|
-
Only as model API calls (the same as using the CLI directly). Sessions, Mates, knowledge, and settings all stay on disk.
|
|
142
|
-
|
|
143
|
-
**"Does my existing CLAUDE.md / AGENTS.md / .cursorrules work?"**
|
|
144
|
-
Yes. Clay loads native instruction files for each vendor and merges the rest into the system prompt automatically.
|
|
145
|
-
|
|
146
|
-
**"Can I continue a CLI session in the browser?"**
|
|
147
|
-
Yes. CLI sessions show up in the sidebar. Browser sessions can be picked up in the CLI.
|
|
148
|
-
|
|
149
|
-
**"Does each teammate need their own API key?"**
|
|
150
|
-
No. Share one org-wide key, or let each user bring their own. On Linux with OS-level isolation, each member can also use their own Claude Code or Codex login.
|
|
151
|
-
|
|
152
|
-
**"What does OS-level isolation actually do?"**
|
|
153
|
-
On Linux, opt in and Clay provisions each user as a real Linux account. File ACLs are enforced via `setfacl`, agent processes spawn under the user's UID/GID, and the kernel handles the rest. One teammate can't read another's project files, even by accident. The guarantee comes from the OS, not from a promise in our code.
|
|
154
|
-
|
|
155
|
-
**"Does it work with MCP servers?"**
|
|
156
|
-
Yes. User-configured MCPs from `~/.clay/mcp.json` plus built-in browser, email, ask-user, and debate servers. All work in both Claude and Codex sessions.
|
|
157
|
-
|
|
158
|
-
**"Can I use it on my phone?"**
|
|
159
|
-
Yes. Install as a PWA on iOS or Android. Push notifications for approvals, errors, and task completion.
|
|
160
|
-
|
|
161
|
-
**"What is d.clay.studio in my browser URL?"**
|
|
162
|
-
A DNS-only service that resolves to your local IP for HTTPS certificate validation. No data passes through it. All traffic stays between your browser and your machine. See [clay-dns](clay-dns/) for details.
|
|
163
|
-
|
|
164
|
-
## Our Philosophy
|
|
165
|
-
|
|
166
|
-
One idea: **user experience sovereignty**.
|
|
167
|
-
|
|
168
|
-
Not a grand statement. A simple wish: not to have your thinking, your work, and your data locked in the moment a vendor changes a price or rewrites a ToS.
|
|
169
|
-
|
|
170
|
-
That shows up in the technical choices we made:
|
|
171
|
-
|
|
172
|
-
- **Your machine is the server.** Browser → your daemon → model API. That's the full chain. No vendor cloud, no relay server, no middle tier syncing your sessions through someone else's infrastructure.
|
|
173
|
-
- **One toggle between vendors.** The adapter layer (YOKE) speaks the Claude Agent SDK and the Codex app-server protocol natively. Switching is a setting, not a migration.
|
|
174
|
-
- **Plain text on disk.** Sessions, Mates, knowledge, and settings live as JSONL and Markdown. No proprietary database. You can `cat`, `grep`, version, and back up everything yourself.
|
|
175
|
-
- **Standard formats only.** CLAUDE.md, AGENTS.md, `.cursorrules`, MCP, Unix cron. If you walk away from Clay, your data walks with you in formats every other tool already understands.
|
|
176
|
-
|
|
177
|
-
That's the principle. The rest of the README is what it makes possible.
|
|
178
|
-
|
|
179
|
-
## Architecture
|
|
180
|
-
|
|
181
|
-
Clay is a self-hosted daemon. It drives Claude Code (via the [Claude Agent SDK](https://www.npmjs.com/package/@anthropic-ai/claude-agent-sdk)) and Codex (via the `codex app-server` JSON-RPC protocol) through a vendor-agnostic adapter layer (**YOKE**), and serves a multi-user web workspace over HTTP/WS. Sessions, Mates, and knowledge live as plain JSONL/Markdown on disk.
|
|
182
|
-
|
|
183
|
-
```mermaid
|
|
184
|
-
graph LR
|
|
185
|
-
subgraph Clients
|
|
186
|
-
B1["Browser<br/>User A"]
|
|
187
|
-
B2["Browser<br/>User B"]
|
|
188
|
-
Phone["Phone PWA<br/>+ Push"]
|
|
189
|
-
end
|
|
190
|
-
|
|
191
|
-
subgraph Daemon["Clay Daemon (your machine)"]
|
|
192
|
-
Auth["Auth + RBAC"]
|
|
193
|
-
Server["HTTP / WS Server"]
|
|
194
|
-
Project["Project Context"]
|
|
195
|
-
YOKE["YOKE Adapter Layer"]
|
|
196
|
-
MCP["Built-in MCP servers<br/>ask-user / browser /<br/>debate / email"]
|
|
197
|
-
Push["Push (VAPID)"]
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
subgraph Vendors["Agent runtimes"]
|
|
201
|
-
Claude["Claude Agent SDK"]
|
|
202
|
-
Codex["codex app-server<br/>(JSON-RPC stdio)"]
|
|
203
|
-
end
|
|
204
|
-
|
|
205
|
-
B1 <-->|WS| Server
|
|
206
|
-
B2 <-->|WS| Server
|
|
207
|
-
Phone <-->|WS + push| Server
|
|
208
|
-
Server --> Auth
|
|
209
|
-
Server --> Project
|
|
210
|
-
Project --> YOKE
|
|
211
|
-
Project --> MCP
|
|
212
|
-
Project --> Push
|
|
213
|
-
YOKE --> Claude
|
|
214
|
-
YOKE --> Codex
|
|
215
|
-
Push -.-> Phone
|
|
83
|
+
npx clay-server --shutdown # Stop the daemon
|
|
216
84
|
```
|
|
217
85
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
## Community Projects
|
|
221
|
-
|
|
222
|
-
Projects built by the community on top of Clay.
|
|
223
|
-
|
|
224
|
-
| Project | Description |
|
|
225
|
-
|---------|-------------|
|
|
226
|
-
| [clay-streamdeck-plugin](https://github.com/egns-ai/clay-streamdeck-plugin) | Stream Deck plugin that turns physical buttons into a live dashboard for managing Clay sessions, worktrees, and permission requests. |
|
|
227
|
-
|
|
228
|
-
Building something with Clay? Share it in [Discussions](https://github.com/chadbyte/clay/discussions).
|
|
86
|
+
Run `npx clay-server --help` for the complete command reference.
|
|
229
87
|
|
|
230
|
-
##
|
|
88
|
+
## Documentation
|
|
231
89
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
90
|
+
- [Documentation index](docs/README.md)
|
|
91
|
+
- [Architecture](docs/guides/architecture.md)
|
|
92
|
+
- [MCP integration](docs/guides/MCP-IMPLEMENTATION.md)
|
|
93
|
+
- [Contributing](CONTRIBUTING.md)
|
|
94
|
+
- [Changelog](CHANGELOG.md)
|
|
235
95
|
|
|
236
|
-
##
|
|
96
|
+
## Community
|
|
237
97
|
|
|
238
|
-
|
|
239
|
-
[https://github.com/chadbyte/clay/issues](https://github.com/chadbyte/clay/issues)
|
|
98
|
+
The community-built [Clay Stream Deck plugin](https://github.com/egns-ai/clay-streamdeck-plugin) turns physical buttons into a live dashboard for sessions, worktrees, and permission requests.
|
|
240
99
|
|
|
241
|
-
|
|
242
|
-
[https://github.com/chadbyte/clay/discussions](https://github.com/chadbyte/clay/discussions)
|
|
100
|
+
Building something with Clay Studio? Share it in [GitHub Discussions](https://github.com/chadbyte/clay/discussions).
|
|
243
101
|
|
|
244
102
|
## Disclaimer
|
|
245
103
|
|
|
246
|
-
|
|
104
|
+
Clay Studio is not affiliated with the providers of the coding agents it supports. Product names and trademarks belong to their respective owners. The software is provided "as is," and users are responsible for complying with the terms of their selected providers.
|
|
247
105
|
|
|
248
106
|
## License
|
|
249
107
|
|
|
250
|
-
MIT
|
|
108
|
+
[MIT](LICENSE)
|
package/bin/cli.js
CHANGED
|
@@ -38,6 +38,7 @@ var { sendIPCCommand } = require("../lib/ipc");
|
|
|
38
38
|
var { generateAuthToken } = require("../lib/server");
|
|
39
39
|
var { enableMultiUser, disableMultiUser, hasAdmin, isMultiUser, getSetupCode } = require("../lib/users");
|
|
40
40
|
var clayStudioCert = require("../lib/clay-studio-cert");
|
|
41
|
+
var cliWordmark = require("../lib/cli-wordmark");
|
|
41
42
|
|
|
42
43
|
function openUrl(url) {
|
|
43
44
|
try {
|
|
@@ -303,11 +304,11 @@ var a = {
|
|
|
303
304
|
|
|
304
305
|
function gradient(text) {
|
|
305
306
|
if (isBasicTerm) {
|
|
306
|
-
return a.
|
|
307
|
+
return a.clay + text + a.reset;
|
|
307
308
|
}
|
|
308
|
-
//
|
|
309
|
-
var r0 =
|
|
310
|
-
var r1 =
|
|
309
|
+
// Clay Indigo (#5857FC) → Clay Green (#07E5A3)
|
|
310
|
+
var r0 = 88, g0 = 87, b0 = 252;
|
|
311
|
+
var r1 = 7, g1 = 229, b1 = 163;
|
|
311
312
|
var out = "";
|
|
312
313
|
var len = text.length;
|
|
313
314
|
for (var i = 0; i < len; i++) {
|
|
@@ -693,46 +694,10 @@ function ensureCerts(ip) {
|
|
|
693
694
|
|
|
694
695
|
// --- Logo ---
|
|
695
696
|
function printLogo() {
|
|
696
|
-
var
|
|
697
|
-
var lines = [
|
|
698
|
-
"________/\\\\\\\\\\\\\\\\\\__/\\\\\\_________________/\\\\\\\\\\\\\\\\\\_____/\\\\\\________/\\\\\\",
|
|
699
|
-
" _____/\\\\\\////////__\\/\\\\\\_______________/\\\\\\\\\\\\\\\\\\\\\\\\\\__\\///\\\\\\____/\\\\\\/_",
|
|
700
|
-
" ___/\\\\\\/___________\\/\\\\\\______________/\\\\\\/////////\\\\\\___\\///\\\\\\/\\\\\\/___",
|
|
701
|
-
" __/\\\\\\_____________\\/\\\\\\_____________\\/\\\\\\_______\\/\\\\\\_____\\///\\\\\\/_____",
|
|
702
|
-
" _\\/\\\\\\_____________\\/\\\\\\_____________\\/\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\_______\\/\\\\\\______",
|
|
703
|
-
" _\\//\\\\\\____________\\/\\\\\\_____________\\/\\\\\\/////////\\\\\\_______\\/\\\\\\______",
|
|
704
|
-
" __\\///\\\\\\__________\\/\\\\\\_____________\\/\\\\\\_______\\/\\\\\\_______\\/\\\\\\______",
|
|
705
|
-
" ____\\////\\\\\\\\\\\\\\\\\\_\\/\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\_\\/\\\\\\_______\\/\\\\\\_______\\/\\\\\\______",
|
|
706
|
-
" _______\\/////////__\\///////////////__\\///________\\///________\\///_______",
|
|
707
|
-
];
|
|
697
|
+
var lines = cliWordmark.getWordmarkLines(process.stdout.columns);
|
|
708
698
|
console.log("");
|
|
709
|
-
if (isBasicTerm) {
|
|
710
|
-
for (var i = 0; i < lines.length; i++) {
|
|
711
|
-
console.log(a.green + lines[i] + r);
|
|
712
|
-
}
|
|
713
|
-
return;
|
|
714
|
-
}
|
|
715
|
-
// Tri-accent vertical gradient: Green (#09E5A3) → Indigo (#5857FC) → Terracotta (#FE7150)
|
|
716
|
-
var stops = [
|
|
717
|
-
[9, 229, 163],
|
|
718
|
-
[88, 87, 252],
|
|
719
|
-
[254, 113, 80],
|
|
720
|
-
];
|
|
721
699
|
for (var i = 0; i < lines.length; i++) {
|
|
722
|
-
|
|
723
|
-
var cr, cg, cb;
|
|
724
|
-
if (t <= 0.5) {
|
|
725
|
-
var s = t * 2;
|
|
726
|
-
cr = Math.round(stops[0][0] + (stops[1][0] - stops[0][0]) * s);
|
|
727
|
-
cg = Math.round(stops[0][1] + (stops[1][1] - stops[0][1]) * s);
|
|
728
|
-
cb = Math.round(stops[0][2] + (stops[1][2] - stops[0][2]) * s);
|
|
729
|
-
} else {
|
|
730
|
-
var s = (t - 0.5) * 2;
|
|
731
|
-
cr = Math.round(stops[1][0] + (stops[2][0] - stops[1][0]) * s);
|
|
732
|
-
cg = Math.round(stops[1][1] + (stops[2][1] - stops[1][1]) * s);
|
|
733
|
-
cb = Math.round(stops[1][2] + (stops[2][2] - stops[1][2]) * s);
|
|
734
|
-
}
|
|
735
|
-
console.log("\x1b[38;2;" + cr + ";" + cg + ";" + cb + "m" + lines[i] + r);
|
|
700
|
+
console.log(lines[i]);
|
|
736
701
|
}
|
|
737
702
|
}
|
|
738
703
|
|
package/lib/builtin-mates.js
CHANGED
|
@@ -20,7 +20,7 @@ var BUILTIN_MATES = [
|
|
|
20
20
|
bio: "Your workspace memory. Searches every session, project, and decision you've made and answers from the receipts. The chat surface for the home screen.",
|
|
21
21
|
avatarColor: "#7c3aed",
|
|
22
22
|
avatarStyle: "bottts",
|
|
23
|
-
avatarCustom: "/
|
|
23
|
+
avatarCustom: "/clay-studio-symbol.png", // Clay is the app — use the app symbol
|
|
24
24
|
avatarLocked: true,
|
|
25
25
|
primary: true, // code-managed, auto-updated on startup
|
|
26
26
|
globalSearch: true, // searches all mates' sessions and projects
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Terminal-safe Clay Studio wordmarks. The wide form uses a Roman serif
|
|
2
|
+
// construction; the compact form preserves the mixed-case silhouette.
|
|
3
|
+
|
|
4
|
+
var WIDE_WORDMARK = [
|
|
5
|
+
" ,, ,, ,,",
|
|
6
|
+
" .g8\"\"\"bgd `7MM .M\"\"\"bgd mm `7MM db",
|
|
7
|
+
".dP' `M MM ,MI \"Y MM MM",
|
|
8
|
+
"dM' ` MM ,6\"Yb.`7M' `MF' `MMb. mmMMmm `7MM `7MM ,M\"\"bMM `7MM ,pW\"Wq.",
|
|
9
|
+
"MM MM 8) MM VA ,V `YMMNq. MM MM MM ,AP MM MM 6W' `Wb",
|
|
10
|
+
"MM. MM ,pm9MM VA ,V . `MM MM MM MM 8MI MM MM 8M M8",
|
|
11
|
+
"`Mb. ,' MM 8M MM VVV Mb dM MM MM MM `Mb MM MM YA. ,A9",
|
|
12
|
+
" `\"bmmmd' .JMML.`Moo9^Yo. ,V P\"Ybmmd\" `Mbmo `Mbod\"YML.`Wbmd\"MML..JMML.`Ybmd9'",
|
|
13
|
+
" ,V",
|
|
14
|
+
" OOb\"",
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
var COMPACT_WORDMARK = [
|
|
18
|
+
",---.| ,---.| |o",
|
|
19
|
+
"| | ,---., . `---.|--- . .,---|.,---.",
|
|
20
|
+
"| | ,---|| | || | || ||| |",
|
|
21
|
+
"`---'`---'`---^`---| `---'`---'`---'`---'``---'",
|
|
22
|
+
" `---'",
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
function getWordmarkLines(columns) {
|
|
26
|
+
var width = Number(columns) || 80;
|
|
27
|
+
if (width >= 92) return WIDE_WORDMARK.slice();
|
|
28
|
+
if (width >= 50) return COMPACT_WORDMARK.slice();
|
|
29
|
+
return ["Clay Studio"];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
module.exports = { getWordmarkLines: getWordmarkLines };
|
package/lib/pages.js
CHANGED
|
@@ -3,9 +3,9 @@ function pinPageHtml() {
|
|
|
3
3
|
'<meta charset="UTF-8">' +
|
|
4
4
|
'<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">' +
|
|
5
5
|
'<meta name="mobile-web-app-capable" content="yes">' +
|
|
6
|
-
'<link rel="icon" type="image/png" href="/favicon-
|
|
6
|
+
'<link rel="icon" type="image/png" sizes="32x32" href="/clay-studio-favicon-32.png">' +
|
|
7
7
|
'<link rel="apple-touch-icon" href="/apple-touch-icon.png">' +
|
|
8
|
-
'<title>Clay</title>' +
|
|
8
|
+
'<title>Clay Studio</title>' +
|
|
9
9
|
'<style>' + authPageStyles + '</style></head><body><div class="c">' +
|
|
10
10
|
'<h1 id="greeting"></h1>' +
|
|
11
11
|
'<div class="sub">Enter your PIN to continue</div>' +
|
|
@@ -44,9 +44,10 @@ function setupPageHtml(httpsUrl, httpUrl, hasCert, lanMode) {
|
|
|
44
44
|
<meta charset="UTF-8">
|
|
45
45
|
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
|
|
46
46
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
47
|
+
<link rel="icon" type="image/png" sizes="32x32" href="/clay-studio-favicon-32.png">
|
|
47
48
|
<link rel="manifest" href="/manifest.json">
|
|
48
49
|
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
|
|
49
|
-
<title>Setup - Clay</title>
|
|
50
|
+
<title>Setup - Clay Studio</title>
|
|
50
51
|
<style>
|
|
51
52
|
:root{--s-bg:#282a36;--s-text:#f8f8f2;--s-accent:#ffb86c;--s-muted:#6272a4;--s-border:#44475a;--s-dimmer:#6272a4;--s-success:#50fa7b;--s-accent-15:rgba(255,184,108,0.15);--s-success-10:rgba(80,250,123,0.1);--s-success-15:rgba(80,250,123,0.15);--s-accent-06:rgba(255,184,108,0.06);--s-muted-06:rgba(98,114,164,0.06);--s-muted-15:rgba(98,114,164,0.15)}
|
|
52
53
|
@media(prefers-color-scheme:light){:root{--s-bg:#FAFAFA;--s-text:#5C6166;--s-accent:#FA8D3E;--s-muted:#A0A6AC;--s-border:#D2D4D8;--s-dimmer:#8A9199;--s-success:#6CBF49;--s-accent-15:rgba(250,141,62,0.15);--s-success-10:rgba(108,191,73,0.1);--s-success-15:rgba(108,191,73,0.15);--s-accent-06:rgba(250,141,62,0.06);--s-muted-06:rgba(160,166,172,0.06);--s-muted-15:rgba(160,166,172,0.15)}}
|
|
@@ -662,9 +663,10 @@ function escapeHtml(s) {
|
|
|
662
663
|
return String(s).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
663
664
|
}
|
|
664
665
|
|
|
665
|
-
// --- Build auth page CSS variables from
|
|
666
|
+
// --- Build auth page CSS variables from the Clay Studio theme pair ---
|
|
666
667
|
var path = require("path");
|
|
667
|
-
var _authTheme = require(path.join(__dirname, "themes", "
|
|
668
|
+
var _authTheme = require(path.join(__dirname, "themes", "clay-light.json"));
|
|
669
|
+
var _authDarkTheme = require(path.join(__dirname, "themes", "clay-dark.json"));
|
|
668
670
|
|
|
669
671
|
function _hexToRgb(hex) {
|
|
670
672
|
hex = hex.replace("#", "");
|
|
@@ -689,35 +691,39 @@ function _mixColors(hex1, hex2, weight) {
|
|
|
689
691
|
return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
|
|
690
692
|
}
|
|
691
693
|
|
|
692
|
-
var _t = {};
|
|
693
694
|
var _keys = ["base00","base01","base02","base03","base04","base05","base06","base07",
|
|
694
695
|
"base08","base09","base0A","base0B","base0C","base0D","base0E","base0F"];
|
|
695
|
-
for (var _ki = 0; _ki < _keys.length; _ki++) {
|
|
696
|
-
_t[_keys[_ki]] = "#" + _authTheme[_keys[_ki]];
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
var _authVarsObj = {
|
|
700
|
-
"--bg": _t.base00,
|
|
701
|
-
"--bg-alt": _t.base01,
|
|
702
|
-
"--text": _t.base06,
|
|
703
|
-
"--text-muted": _t.base04,
|
|
704
|
-
"--text-dimmer": _t.base03,
|
|
705
|
-
"--accent": _t.base09,
|
|
706
|
-
"--accent-15": _hexToRgba(_t.base09, 0.15),
|
|
707
|
-
"--accent-20": _hexToRgba(_t.base09, 0.20),
|
|
708
|
-
"--border": _t.base02,
|
|
709
|
-
"--input-bg": _mixColors(_t.base01, _t.base02, 0.5),
|
|
710
|
-
"--error": _t.base08,
|
|
711
|
-
};
|
|
712
696
|
|
|
713
|
-
|
|
714
|
-
var
|
|
715
|
-
for (var
|
|
716
|
-
|
|
697
|
+
function _buildAuthVarDeclarations(theme) {
|
|
698
|
+
var t = {};
|
|
699
|
+
for (var ki = 0; ki < _keys.length; ki++) {
|
|
700
|
+
t[_keys[ki]] = "#" + theme[_keys[ki]];
|
|
701
|
+
}
|
|
702
|
+
var vars = {
|
|
703
|
+
"--bg": t.base00,
|
|
704
|
+
"--bg-alt": t.base01,
|
|
705
|
+
"--text": t.base06,
|
|
706
|
+
"--text-muted": t.base04,
|
|
707
|
+
"--text-dimmer": t.base03,
|
|
708
|
+
"--accent": t.base09,
|
|
709
|
+
"--accent-15": _hexToRgba(t.base09, 0.15),
|
|
710
|
+
"--accent-20": _hexToRgba(t.base09, 0.20),
|
|
711
|
+
"--border": t.base02,
|
|
712
|
+
"--input-bg": _mixColors(t.base01, t.base02, 0.5),
|
|
713
|
+
"--error": t.base08,
|
|
714
|
+
};
|
|
715
|
+
var declarations = "";
|
|
716
|
+
var names = Object.keys(vars);
|
|
717
|
+
for (var vi = 0; vi < names.length; vi++) {
|
|
718
|
+
declarations += names[vi] + ":" + vars[names[vi]] + ";";
|
|
719
|
+
}
|
|
720
|
+
return declarations;
|
|
717
721
|
}
|
|
718
|
-
_authVarsStr += "}";
|
|
719
722
|
|
|
720
|
-
|
|
723
|
+
var _authVarsStr = ":root{" + _buildAuthVarDeclarations(_authTheme) + "}" +
|
|
724
|
+
"@media(prefers-color-scheme:dark){:root{" + _buildAuthVarDeclarations(_authDarkTheme) + "}}";
|
|
725
|
+
|
|
726
|
+
// --- Shared CSS for auth pages ---
|
|
721
727
|
var authPageStyles =
|
|
722
728
|
_authVarsStr +
|
|
723
729
|
// Reset & layout
|
|
@@ -806,7 +812,8 @@ function adminSetupPageHtml() {
|
|
|
806
812
|
return '<!DOCTYPE html><html lang="en"><head>' +
|
|
807
813
|
'<meta charset="UTF-8">' +
|
|
808
814
|
'<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">' +
|
|
809
|
-
'<
|
|
815
|
+
'<link rel="icon" type="image/png" sizes="32x32" href="/clay-studio-favicon-32.png">' +
|
|
816
|
+
'<title>Admin Setup - Clay Studio</title>' +
|
|
810
817
|
'<style>' + authPageStyles + '</style></head><body><div class="c">' +
|
|
811
818
|
'<div class="steps-bar"><span class="steps-dot current" id="dot0"></span><span class="steps-dot" id="dot1"></span><span class="steps-dot" id="dot2"></span><span class="steps-dot" id="dot3"></span></div>' +
|
|
812
819
|
|
|
@@ -901,7 +908,8 @@ function multiUserLoginPageHtml() {
|
|
|
901
908
|
return '<!DOCTYPE html><html lang="en"><head>' +
|
|
902
909
|
'<meta charset="UTF-8">' +
|
|
903
910
|
'<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">' +
|
|
904
|
-
'<
|
|
911
|
+
'<link rel="icon" type="image/png" sizes="32x32" href="/clay-studio-favicon-32.png">' +
|
|
912
|
+
'<title>Login - Clay Studio</title>' +
|
|
905
913
|
'<style>' + authPageStyles + '</style></head><body><div class="c">' +
|
|
906
914
|
'<div class="steps-bar"><span class="steps-dot current" id="dot0"></span><span class="steps-dot" id="dot1"></span></div>' +
|
|
907
915
|
|
|
@@ -986,7 +994,8 @@ function invitePageHtml(inviteCode) {
|
|
|
986
994
|
return '<!DOCTYPE html><html lang="en"><head>' +
|
|
987
995
|
'<meta charset="UTF-8">' +
|
|
988
996
|
'<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">' +
|
|
989
|
-
'<
|
|
997
|
+
'<link rel="icon" type="image/png" sizes="32x32" href="/clay-studio-favicon-32.png">' +
|
|
998
|
+
'<title>Join - Clay Studio</title>' +
|
|
990
999
|
'<style>' + authPageStyles + '</style></head><body><div class="c">' +
|
|
991
1000
|
'<div class="steps-bar"><span class="steps-dot current" id="dot0"></span><span class="steps-dot" id="dot1"></span><span class="steps-dot" id="dot2"></span></div>' +
|
|
992
1001
|
|
|
@@ -1067,7 +1076,8 @@ function smtpLoginPageHtml() {
|
|
|
1067
1076
|
return '<!DOCTYPE html><html lang="en"><head>' +
|
|
1068
1077
|
'<meta charset="UTF-8">' +
|
|
1069
1078
|
'<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">' +
|
|
1070
|
-
'<
|
|
1079
|
+
'<link rel="icon" type="image/png" sizes="32x32" href="/clay-studio-favicon-32.png">' +
|
|
1080
|
+
'<title>Login - Clay Studio</title>' +
|
|
1071
1081
|
'<style>' + authPageStyles +
|
|
1072
1082
|
'.otp-input{width:100%;font-size:24px;letter-spacing:8px;text-align:center;padding:12px;' +
|
|
1073
1083
|
'background:var(--field-bg);border:1px solid var(--field-border);border-radius:8px;color:var(--fg);' +
|
|
@@ -1223,7 +1233,8 @@ function smtpInvitePageHtml(inviteCode) {
|
|
|
1223
1233
|
return '<!DOCTYPE html><html lang="en"><head>' +
|
|
1224
1234
|
'<meta charset="UTF-8">' +
|
|
1225
1235
|
'<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">' +
|
|
1226
|
-
'<
|
|
1236
|
+
'<link rel="icon" type="image/png" sizes="32x32" href="/clay-studio-favicon-32.png">' +
|
|
1237
|
+
'<title>Join - Clay Studio</title>' +
|
|
1227
1238
|
'<style>' + authPageStyles + '</style></head><body><div class="c">' +
|
|
1228
1239
|
'<div class="steps-bar"><span class="steps-dot current" id="dot0"></span><span class="steps-dot" id="dot1"></span><span class="steps-dot" id="dot2"></span></div>' +
|
|
1229
1240
|
|
|
@@ -1311,7 +1322,8 @@ function noProjectsPageHtml() {
|
|
|
1311
1322
|
return '<!DOCTYPE html><html lang="en"><head>' +
|
|
1312
1323
|
'<meta charset="UTF-8">' +
|
|
1313
1324
|
'<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">' +
|
|
1314
|
-
'<
|
|
1325
|
+
'<link rel="icon" type="image/png" sizes="32x32" href="/clay-studio-favicon-32.png">' +
|
|
1326
|
+
'<title>Clay Studio</title>' +
|
|
1315
1327
|
'<style>' + authPageStyles + '</style></head><body><div class="c">' +
|
|
1316
1328
|
'<h1>Hang tight!</h1>' +
|
|
1317
1329
|
'<div class="sub">No projects have been assigned to your account yet.</div>' +
|