clay-server 2.17.0-beta.2 → 2.17.0-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 +1 -1
- package/bin/cli.js +70 -27
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -168,7 +168,7 @@ Yes. Create as many as you need. A code reviewer, a writing partner, a project m
|
|
|
168
168
|
|
|
169
169
|
## HTTPS
|
|
170
170
|
|
|
171
|
-
HTTPS is enabled by default using a builtin wildcard certificate for `*.d.clay.studio`. No setup required. Your browser connects to a URL like:
|
|
171
|
+
HTTPS is enabled by default using a builtin wildcard certificate for `*.d.clay.studio`. No setup required. Available from `v2.17.0-beta.2`. Your browser connects to a URL like:
|
|
172
172
|
|
|
173
173
|
```
|
|
174
174
|
https://192-168-1-50.d.clay.studio:2633
|
package/bin/cli.js
CHANGED
|
@@ -53,6 +53,7 @@ var args = process.argv.slice(2);
|
|
|
53
53
|
var port = _isDev ? 2635 : 2633;
|
|
54
54
|
var useHttps = true;
|
|
55
55
|
var forceMkcert = false;
|
|
56
|
+
var forceBuiltin = false;
|
|
56
57
|
var skipUpdate = false;
|
|
57
58
|
var debugMode = false;
|
|
58
59
|
var autoYes = false;
|
|
@@ -84,6 +85,8 @@ for (var i = 0; i < args.length; i++) {
|
|
|
84
85
|
useHttps = false;
|
|
85
86
|
} else if (args[i] === "--local-cert") {
|
|
86
87
|
forceMkcert = true;
|
|
88
|
+
} else if (args[i] === "--builtin-cert") {
|
|
89
|
+
forceBuiltin = true;
|
|
87
90
|
} else if (args[i] === "--no-update" || args[i] === "--skip-update") {
|
|
88
91
|
skipUpdate = true;
|
|
89
92
|
} else if (args[i] === "--dev") {
|
|
@@ -128,7 +131,8 @@ for (var i = 0; i < args.length; i++) {
|
|
|
128
131
|
console.log(" -p, --port <port> Port to listen on (default: 2633)");
|
|
129
132
|
console.log(" --host <address> Address to bind to (default: 0.0.0.0)");
|
|
130
133
|
console.log(" --no-https Disable HTTPS (enabled by default)");
|
|
131
|
-
console.log(" --local-cert Use local certificate (mkcert)
|
|
134
|
+
console.log(" --local-cert Use local certificate (mkcert), suppress migration notice");
|
|
135
|
+
console.log(" --builtin-cert Use builtin certificate even if mkcert is installed");
|
|
132
136
|
console.log(" --no-update Skip auto-update check on startup");
|
|
133
137
|
console.log(" --debug Enable debug panel in the web UI");
|
|
134
138
|
console.log(" -y, --yes Skip interactive prompts (accept defaults)");
|
|
@@ -599,10 +603,11 @@ function toClayStudioUrl(ip, port, protocol) {
|
|
|
599
603
|
}
|
|
600
604
|
|
|
601
605
|
function ensureCerts(ip) {
|
|
602
|
-
//
|
|
603
|
-
if (
|
|
606
|
+
// --builtin-cert: skip mkcert entirely, go straight to builtin
|
|
607
|
+
if (forceBuiltin) {
|
|
604
608
|
var builtin = getBuiltinCert();
|
|
605
609
|
if (builtin) return builtin;
|
|
610
|
+
return null;
|
|
606
611
|
}
|
|
607
612
|
|
|
608
613
|
var homeDir = os.homedir();
|
|
@@ -619,24 +624,30 @@ function ensureCerts(ip) {
|
|
|
619
624
|
fs.copyFileSync(legacyCert, certPath);
|
|
620
625
|
}
|
|
621
626
|
|
|
627
|
+
var mkcertInstalled = hasMkcert();
|
|
628
|
+
|
|
622
629
|
var caRoot = null;
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
+
if (mkcertInstalled) {
|
|
631
|
+
try {
|
|
632
|
+
caRoot = path.join(
|
|
633
|
+
execSync("mkcert -CAROOT", { encoding: "utf8" }).trim(),
|
|
634
|
+
"rootCA.pem"
|
|
635
|
+
);
|
|
636
|
+
if (!fs.existsSync(caRoot)) caRoot = null;
|
|
637
|
+
} catch (e) {}
|
|
638
|
+
}
|
|
630
639
|
|
|
631
640
|
// Collect all IPv4 addresses (Tailscale + LAN)
|
|
632
641
|
var allIPs = getAllIPs();
|
|
633
642
|
|
|
634
643
|
if (fs.existsSync(keyPath) && fs.existsSync(certPath)) {
|
|
635
644
|
var needRegen = false;
|
|
645
|
+
var isMkcertCert = false;
|
|
636
646
|
try {
|
|
637
647
|
var certText = execFileSync("openssl", ["x509", "-in", certPath, "-text", "-noout"], { encoding: "utf8" });
|
|
638
648
|
// If cert is from an external CA (e.g. Tailscale/Let's Encrypt), never regenerate
|
|
639
649
|
if (certText.indexOf("mkcert") === -1) return { key: keyPath, cert: certPath, caRoot: caRoot };
|
|
650
|
+
isMkcertCert = true;
|
|
640
651
|
for (var i = 0; i < allIPs.length; i++) {
|
|
641
652
|
if (certText.indexOf(allIPs[i]) === -1) {
|
|
642
653
|
needRegen = true;
|
|
@@ -644,24 +655,41 @@ function ensureCerts(ip) {
|
|
|
644
655
|
}
|
|
645
656
|
}
|
|
646
657
|
} catch (e) { needRegen = true; }
|
|
647
|
-
|
|
658
|
+
// mkcert cert but mkcert uninstalled: CA is gone, cert is untrusted. Skip it.
|
|
659
|
+
if (isMkcertCert && !mkcertInstalled) needRegen = true;
|
|
660
|
+
if (!needRegen) {
|
|
661
|
+
return { key: keyPath, cert: certPath, caRoot: caRoot, mkcertDetected: mkcertInstalled && !forceMkcert };
|
|
662
|
+
}
|
|
648
663
|
}
|
|
649
664
|
|
|
650
|
-
|
|
665
|
+
// mkcert installed: generate local cert (legacy behavior)
|
|
666
|
+
if (mkcertInstalled) {
|
|
667
|
+
fs.mkdirSync(certDir, { recursive: true });
|
|
668
|
+
|
|
669
|
+
var domains = ["localhost", "127.0.0.1", "::1"];
|
|
670
|
+
for (var i = 0; i < allIPs.length; i++) {
|
|
671
|
+
if (domains.indexOf(allIPs[i]) === -1) domains.push(allIPs[i]);
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
try {
|
|
675
|
+
var mkcertArgs = ["-key-file", keyPath, "-cert-file", certPath].concat(domains);
|
|
676
|
+
execFileSync("mkcert", mkcertArgs, { stdio: "pipe" });
|
|
677
|
+
} catch (err) {
|
|
678
|
+
// mkcert generation failed, fall through to builtin
|
|
679
|
+
}
|
|
651
680
|
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
681
|
+
if (fs.existsSync(keyPath) && fs.existsSync(certPath)) {
|
|
682
|
+
return { key: keyPath, cert: certPath, caRoot: caRoot, mkcertDetected: !forceMkcert };
|
|
683
|
+
}
|
|
655
684
|
}
|
|
656
685
|
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
return null;
|
|
686
|
+
// Fallback: builtin cert (unless --local-cert forces mkcert-only)
|
|
687
|
+
if (!forceMkcert) {
|
|
688
|
+
var builtin = getBuiltinCert();
|
|
689
|
+
if (builtin) return builtin;
|
|
662
690
|
}
|
|
663
691
|
|
|
664
|
-
return
|
|
692
|
+
return null;
|
|
665
693
|
}
|
|
666
694
|
|
|
667
695
|
// --- Logo ---
|
|
@@ -1436,12 +1464,14 @@ async function forkDaemon(mode, keepAwake, extraProjects, addCwd, wantOsUsers) {
|
|
|
1436
1464
|
var ip = getLocalIP();
|
|
1437
1465
|
var hasTls = false;
|
|
1438
1466
|
var hasBuiltinCert = false;
|
|
1467
|
+
var mkcertDetected = false;
|
|
1439
1468
|
|
|
1440
1469
|
if (useHttps) {
|
|
1441
1470
|
var certPaths = ensureCerts(ip);
|
|
1442
1471
|
if (certPaths) {
|
|
1443
1472
|
hasTls = true;
|
|
1444
1473
|
if (certPaths.builtin) hasBuiltinCert = true;
|
|
1474
|
+
if (certPaths.mkcertDetected) mkcertDetected = true;
|
|
1445
1475
|
} else {
|
|
1446
1476
|
log(sym.warn + " " + a.yellow + "HTTPS unavailable" + a.reset + a.dim + " · mkcert not installed" + a.reset);
|
|
1447
1477
|
}
|
|
@@ -1516,6 +1546,7 @@ async function forkDaemon(mode, keepAwake, extraProjects, addCwd, wantOsUsers) {
|
|
|
1516
1546
|
pinHash: mode === "multi" && cliPin ? generateAuthToken(cliPin) : null,
|
|
1517
1547
|
tls: hasTls,
|
|
1518
1548
|
builtinCert: hasBuiltinCert,
|
|
1549
|
+
mkcertDetected: mkcertDetected,
|
|
1519
1550
|
debug: debugMode,
|
|
1520
1551
|
keepAwake: keepAwake,
|
|
1521
1552
|
dangerouslySkipPermissions: dangerouslySkipPermissions,
|
|
@@ -1595,7 +1626,8 @@ async function forkDaemon(mode, keepAwake, extraProjects, addCwd, wantOsUsers) {
|
|
|
1595
1626
|
: protocol + "://" + ip + ":" + config.port;
|
|
1596
1627
|
console.log(" " + sym.done + " Daemon started (PID " + config.pid + ")");
|
|
1597
1628
|
console.log(" " + sym.done + " " + url);
|
|
1598
|
-
if (config.builtinCert) console.log(" " + sym.done + " d.clay.studio
|
|
1629
|
+
if (config.builtinCert) console.log(" " + sym.done + " d.clay.studio provides HTTPS certificates only. Your traffic never leaves your network.");
|
|
1630
|
+
if (config.mkcertDetected) console.log(" " + sym.warn + " Clay now ships with a builtin HTTPS certificate. To use it, pass --builtin-cert or uninstall mkcert.");
|
|
1599
1631
|
console.log(" " + sym.done + " Headless mode — exiting CLI");
|
|
1600
1632
|
process.exit(0);
|
|
1601
1633
|
return;
|
|
@@ -1612,12 +1644,14 @@ async function devMode(mode, keepAwake, existingPinHash) {
|
|
|
1612
1644
|
var ip = getLocalIP();
|
|
1613
1645
|
var hasTls = false;
|
|
1614
1646
|
var hasBuiltinCert = false;
|
|
1647
|
+
var mkcertDetected = false;
|
|
1615
1648
|
|
|
1616
1649
|
if (useHttps) {
|
|
1617
1650
|
var certPaths = ensureCerts(ip);
|
|
1618
1651
|
if (certPaths) {
|
|
1619
1652
|
hasTls = true;
|
|
1620
1653
|
if (certPaths.builtin) hasBuiltinCert = true;
|
|
1654
|
+
if (certPaths.mkcertDetected) mkcertDetected = true;
|
|
1621
1655
|
}
|
|
1622
1656
|
}
|
|
1623
1657
|
|
|
@@ -1681,6 +1715,7 @@ async function devMode(mode, keepAwake, existingPinHash) {
|
|
|
1681
1715
|
pinHash: existingPinHash || null,
|
|
1682
1716
|
tls: hasTls,
|
|
1683
1717
|
builtinCert: hasBuiltinCert,
|
|
1718
|
+
mkcertDetected: mkcertDetected,
|
|
1684
1719
|
debug: true,
|
|
1685
1720
|
keepAwake: keepAwake || false,
|
|
1686
1721
|
dangerouslySkipPermissions: dangerouslySkipPermissions,
|
|
@@ -1830,6 +1865,7 @@ async function restartDaemonWithTLS(config, callback) {
|
|
|
1830
1865
|
return;
|
|
1831
1866
|
}
|
|
1832
1867
|
var hasBuiltinCert = !!(certPaths && certPaths.builtin);
|
|
1868
|
+
var mkcertDetected = !!(certPaths && certPaths.mkcertDetected);
|
|
1833
1869
|
|
|
1834
1870
|
// Shut down old daemon
|
|
1835
1871
|
stopDaemonWatcher();
|
|
@@ -1854,6 +1890,7 @@ async function restartDaemonWithTLS(config, callback) {
|
|
|
1854
1890
|
pinHash: config.pinHash || null,
|
|
1855
1891
|
tls: true,
|
|
1856
1892
|
builtinCert: hasBuiltinCert,
|
|
1893
|
+
mkcertDetected: mkcertDetected,
|
|
1857
1894
|
debug: config.debug || false,
|
|
1858
1895
|
keepAwake: config.keepAwake || false,
|
|
1859
1896
|
dangerouslySkipPermissions: config.dangerouslySkipPermissions || false,
|
|
@@ -1952,7 +1989,7 @@ function showMainMenu(config, ip) {
|
|
|
1952
1989
|
function afterQr() {
|
|
1953
1990
|
// Status line
|
|
1954
1991
|
log(" " + a.dim + "clay" + a.reset + " " + a.dim + "v" + currentVersion + a.reset + a.dim + " — " + url + a.reset);
|
|
1955
|
-
if (config.builtinCert) log(" " + a.dim + "d.clay.studio
|
|
1992
|
+
if (config.builtinCert) log(" " + a.dim + "d.clay.studio provides HTTPS certificates only. Your traffic never leaves your network." + a.reset);
|
|
1956
1993
|
var parts = [];
|
|
1957
1994
|
parts.push(a.bold + projs.length + a.reset + a.dim + (projs.length === 1 ? " project" : " projects"));
|
|
1958
1995
|
parts.push(a.reset + a.bold + totalSessions + a.reset + a.dim + (totalSessions === 1 ? " session" : " sessions"));
|
|
@@ -1963,6 +2000,13 @@ function showMainMenu(config, ip) {
|
|
|
1963
2000
|
log(" Press " + a.bold + "o" + a.reset + " to open in browser");
|
|
1964
2001
|
log("");
|
|
1965
2002
|
|
|
2003
|
+
if (config.mkcertDetected) {
|
|
2004
|
+
log(" " + sym.warn + " " + a.yellow + "Clay now ships with a builtin HTTPS certificate." + a.reset);
|
|
2005
|
+
log(" " + a.dim + "No more CA setup on each device." + a.reset);
|
|
2006
|
+
log(" " + a.dim + "To use it, pass --builtin-cert or uninstall mkcert." + a.reset);
|
|
2007
|
+
log("");
|
|
2008
|
+
}
|
|
2009
|
+
|
|
1966
2010
|
showMenuItems();
|
|
1967
2011
|
}
|
|
1968
2012
|
|
|
@@ -2032,9 +2076,8 @@ function showMainMenu(config, ip) {
|
|
|
2032
2076
|
}
|
|
2033
2077
|
}, {
|
|
2034
2078
|
hint: [
|
|
2035
|
-
"claude-relay has been renamed to clay-server · npx clay-server",
|
|
2036
2079
|
"Run npx clay-server in other directories to add more projects.",
|
|
2037
|
-
"★ github.com/chadbyte/
|
|
2080
|
+
"★ github.com/chadbyte/clay — Press s to star the repo",
|
|
2038
2081
|
],
|
|
2039
2082
|
keys: [
|
|
2040
2083
|
{ key: "o", onKey: function () {
|
|
@@ -2042,7 +2085,7 @@ function showMainMenu(config, ip) {
|
|
|
2042
2085
|
showMainMenu(config, ip);
|
|
2043
2086
|
}},
|
|
2044
2087
|
{ key: "s", onKey: function () {
|
|
2045
|
-
openUrl("https://github.com/chadbyte/
|
|
2088
|
+
openUrl("https://github.com/chadbyte/clay");
|
|
2046
2089
|
showMainMenu(config, ip);
|
|
2047
2090
|
}},
|
|
2048
2091
|
],
|
|
@@ -2727,7 +2770,7 @@ var currentVersion = require("../package.json").version;
|
|
|
2727
2770
|
: protocol + "://" + ip + ":" + config.port;
|
|
2728
2771
|
console.log(" " + sym.done + " Daemon already running (PID " + config.pid + ")");
|
|
2729
2772
|
console.log(" " + sym.done + " " + url);
|
|
2730
|
-
if (config.builtinCert) console.log(" " + sym.done + " d.clay.studio
|
|
2773
|
+
if (config.builtinCert) console.log(" " + sym.done + " d.clay.studio provides HTTPS certificates only. Your traffic never leaves your network.");
|
|
2731
2774
|
process.exit(0);
|
|
2732
2775
|
return;
|
|
2733
2776
|
}
|