@lifeaitools/clauth 1.30.6 → 1.30.7

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.
@@ -32,6 +32,16 @@ function writeCache(primary, secondary) {
32
32
  }
33
33
 
34
34
  function getMachineId() {
35
+ // Containers do not have a durable /etc/machine-id. Coolify supplies this
36
+ // value as a private runtime secret so a redeploy remains the same enrolled
37
+ // clauth machine. Accept the lowercase-dash form used by Coolify too.
38
+ const containerMachineId = process.env.CLAUTH_MACHINE_ID || process.env["clauth-machine-id"];
39
+ if (containerMachineId) {
40
+ const value = containerMachineId.trim();
41
+ if (!value) throw new Error("CLAUTH_MACHINE_ID must not be empty");
42
+ return { primary: value, secondary: value, platform: os.platform() };
43
+ }
44
+
35
45
  // Fast path: use cached IDs if available (avoids WMI/PowerShell on every restart)
36
46
  const cached = readCache();
37
47
  if (cached) return { ...cached, platform: os.platform() };
package/cli/index.js CHANGED
@@ -13,11 +13,53 @@ import { writeCredentialWithRecovery } from "./recovery.js";
13
13
  import os from "os";
14
14
  import fs from "fs";
15
15
  import path from "path";
16
- import { writeEnrollmentScript } from "./enrollment-script.js";
17
16
 
18
17
  const config = new Conf(getConfOptions());
19
18
  const VERSION = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version;
20
19
 
20
+ function shellSingleQuote(value) {
21
+ return `'${String(value ?? "").replace(/'/g, "''")}'`;
22
+ }
23
+
24
+ function enrollmentScriptName(label) {
25
+ const slug = String(label || "new-computer")
26
+ .toLowerCase()
27
+ .replace(/[^a-z0-9]+/g, "-")
28
+ .replace(/^-+|-+$/g, "")
29
+ .slice(0, 40) || "new-computer";
30
+ return `clauth-enroll-${slug}.ps1`;
31
+ }
32
+
33
+ function writeEnrollmentScript({ supabaseUrl, anonKey, enrollmentCode, label }) {
34
+ const appDir = process.platform === "win32"
35
+ ? path.join(process.env.APPDATA || path.join(os.homedir(), "AppData", "Roaming"), "clauth")
36
+ : path.join(os.homedir(), ".config", "clauth");
37
+ fs.mkdirSync(appDir, { recursive: true });
38
+ const scriptPath = path.join(appDir, enrollmentScriptName(label));
39
+ const script = [
40
+ "$ErrorActionPreference = 'Stop'",
41
+ "$label = $env:COMPUTERNAME",
42
+ "if (-not $label) { $label = [System.Net.Dns]::GetHostName() }",
43
+ "Write-Host 'Installing clauth...'",
44
+ "npm install -g @lifeaitools/clauth@latest",
45
+ "Write-Host 'Enrolling this computer with clauth...'",
46
+ [
47
+ "clauth setup",
48
+ `--supabase-url ${shellSingleQuote(supabaseUrl)}`,
49
+ `--anon-key ${shellSingleQuote(anonKey)}`,
50
+ `--enrollment-code ${shellSingleQuote(enrollmentCode)}`,
51
+ "--label \"$label\"",
52
+ ].join(" "),
53
+ "Write-Host 'Installing clauth startup service...'",
54
+ "clauth serve install",
55
+ "Write-Host 'clauth enrollment complete.'",
56
+ "$self = $PSCommandPath",
57
+ "Start-Process powershell.exe -WindowStyle Hidden -ArgumentList @('-NoProfile','-Command',\"Start-Sleep -Seconds 2; Remove-Item -LiteralPath '$self' -Force -ErrorAction SilentlyContinue\")",
58
+ ].join("\r\n");
59
+ fs.writeFileSync(scriptPath, `${script}\r\n`, "utf8");
60
+ return scriptPath;
61
+ }
62
+
21
63
  // ============================================================
22
64
  // Password prompt helper
23
65
  // ============================================================
@@ -119,7 +161,7 @@ async function searchServices(auth, query, opts = {}) {
119
161
  .map(([field]) => field);
120
162
 
121
163
  let addressHints = [];
122
- if (opts.addresses === true && ADDRESS_KEY_TYPES.has(String(s.key_type || "").toLowerCase()) && s.vault_key) {
164
+ if (opts.addresses !== false && ADDRESS_KEY_TYPES.has(String(s.key_type || "").toLowerCase()) && s.vault_key) {
123
165
  const secret = await api.retrieve(auth.password, auth.machineHash, auth.token, auth.timestamp, s.name);
124
166
  if (!secret.error) {
125
167
  addressHints = collectAddressHints(secret.value, s.key_type);
@@ -349,7 +391,6 @@ program
349
391
  .option("--label <label>", "Suggested label for the new computer")
350
392
  .option("--ttl-minutes <minutes>", "Enrollment lifetime, 5 to 1440 minutes", "60")
351
393
  .option("--install-id <id>", "Override install id; default is current machine's install id")
352
- .option("--target <target>", "Enrollment target: windows or linux", "windows")
353
394
  .option("-p, --pw <password>", "Password (or will prompt)")
354
395
  .action(async (opts) => {
355
396
  console.log(chalk.cyan("\nšŸ” clauth enroll\n"));
@@ -373,7 +414,6 @@ program
373
414
  anonKey,
374
415
  enrollmentCode: result.enrollment_code,
375
416
  label: opts.label,
376
- target: opts.target,
377
417
  });
378
418
  spinner.succeed(chalk.green(`Enrollment created for install_id=${result.install_id}`));
379
419
  console.log("");
@@ -635,15 +675,15 @@ program
635
675
 
636
676
  program
637
677
  .command("search <query>")
638
- .description("Search services by name, label, project, description, or type")
678
+ .description("Search services by name, label, project, description, type, or redacted address hints")
639
679
  .option("-p, --pw <password>")
640
680
  .option("--project <name>", "Filter by project scope")
641
- .option("--addresses", "Also search redacted address hints from address-bearing secrets (may retrieve multiple secrets)")
681
+ .option("--no-addresses", "Skip address-bearing secret metadata scans")
642
682
  .action(async (query, opts) => {
643
683
  const auth = await getAuth(opts.pw);
644
684
  const spinner = ora("Searching services...").start();
645
685
  try {
646
- const rows = await searchServices(auth, query, { project: opts.project, addresses: opts.addresses === true });
686
+ const rows = await searchServices(auth, query, { project: opts.project, addresses: opts.addresses });
647
687
  spinner.stop();
648
688
  console.log(chalk.cyan(`\n Search results for "${query}":\n`));
649
689
  if (!rows.length) {
@@ -746,13 +786,9 @@ program
746
786
  .addHelpText("after", `
747
787
  Examples:
748
788
  clauth scrub Scrub the most recent (active) transcript
749
- clauth scrub <file> Scrub a specific file
750
- clauth scrub all Scrub every transcript + tool-result sidecar (.jsonl + .txt)
789
+ clauth scrub <file> Scrub a specific .jsonl file
790
+ clauth scrub all Scrub every transcript in ~/.claude/projects/
751
791
  clauth scrub all --force Rescrub all files (ignore markers)
752
- clauth scrub session Scrub ONLY the ending session (transcript + sidecars); reads SessionEnd hook JSON on stdin
753
-
754
- Redacts: built-in token patterns, your ~/.clauth/scrub-patterns.json,
755
- and this machine's live vault values (best-effort via the daemon).
756
792
  `)
757
793
  .action(async (target, opts) => {
758
794
  await runScrub(target, opts);
@@ -1000,16 +1036,14 @@ program.addHelpText("beforeAll", chalk.cyan(`
1000
1036
  // ──────────────────────────────────────────────
1001
1037
  program
1002
1038
  .command("serve [action]")
1003
- .description("Manage localhost HTTP vault daemon (start|stop|restart|ping|install|uninstall)")
1039
+ .description("Manage localhost HTTP vault daemon and supervisor (start|stop|restart|ping|supervisor|install|uninstall)")
1004
1040
  .option("--port <n>", "Port (default: 52437)")
1005
1041
  .option("-p, --pw <password>", "clauth password (optional — omit to start locked, unlock in browser)")
1006
1042
  .option("--services <list>", "Comma-separated service whitelist (default: all)")
1007
1043
  .option("--tunnel <hostname>", "Fixed tunnel hostname (e.g. clauth.prtrust.fund) — uses named Cloudflare Tunnel instead of random URL")
1008
1044
  .option("--staged", "Start on staging port (52438) for blue-green verification before make-live")
1009
1045
  .option("--isolated", "Run on a non-live port without touching live PID files, browser, or boot-key credentials")
1010
- .option("--from-boot-key", "Internal: password came from boot.key auto-unlock (degrade gracefully on verify failure)")
1011
- .option("--pw-env", "Internal: read the daemon password from CLAUTH_BOOT_PASSWORD")
1012
- .option("--pw-stdin", "Internal: read the installer password from standard input")
1046
+ .option("--from-boot-key", "Internal: password came from boot.key auto-unlock (degrade gracefully on verify failure)")
1013
1047
  .option("--action <action>", "Internal: action override for daemon child")
1014
1048
  .addHelpText("after", `
1015
1049
  Actions:
@@ -1018,8 +1052,9 @@ Actions:
1018
1052
  restart Stop + start
1019
1053
  ping Check if the daemon is running
1020
1054
  foreground Run in foreground (Ctrl+C to stop) — default if no action given
1021
- mcp Run as MCP stdio server for Claude Code (JSON-RPC over stdin/stdout)
1022
- install Store password securely + register auto-start service (cross-platform)
1055
+ mcp Run as MCP stdio server for Claude Code (JSON-RPC over stdin/stdout)
1056
+ supervisor Run localhost-only supervisor control plane on port 52439
1057
+ install Store password securely + register auto-start service (cross-platform)
1023
1058
  Windows: DPAPI + HKCU\\Run | macOS: Keychain + LaunchAgent | Linux: libsecret/openssl + systemd
1024
1059
  uninstall Remove auto-start service + delete stored password
1025
1060
  upgrade Blue-green upgrade: start new version on staging port, verify, then make live
@@ -1035,9 +1070,10 @@ Examples:
1035
1070
  clauth serve ping Check status
1036
1071
  clauth serve restart Restart (stays locked until browser unlock)
1037
1072
  clauth serve start --services github,vercel
1038
- clauth serve mcp Start MCP server for Claude Code
1039
- clauth serve mcp -p mypass Start MCP server pre-unlocked
1040
- clauth serve foreground --port 53137 --isolated
1073
+ clauth serve mcp Start MCP server for Claude Code
1074
+ clauth serve mcp -p mypass Start MCP server pre-unlocked
1075
+ clauth serve supervisor Start supervisor API on http://127.0.0.1:52439
1076
+ clauth serve foreground --port 53137 --isolated
1041
1077
  Start isolated passwordless server for route tests
1042
1078
  clauth serve install Set up auto-start on login (DPAPI/Keychain/libsecret)
1043
1079
  clauth serve install --tunnel host Auto-start with Cloudflare Tunnel