@cryptiklemur/lattice 1.36.4 → 1.37.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/CLAUDE.md CHANGED
@@ -44,9 +44,28 @@ DO NOT EVER LEAVE PRE-EXISTING ERRORS. FIX THEM.
44
44
  - ANTHROPIC_API_KEY is optional — server uses the token from `claude setup-token` if not set.
45
45
  - Server binds to 0.0.0.0:7654 (WSL2 compatible).
46
46
  - Client dev server runs on :5173 but production serves from server via client/dist/.
47
+ - `LATTICE_HOME` — override data directory (default: `~/.lattice`).
48
+ - `LATTICE_PORT` — override server port (default: 7654). Also: `--port=N`.
47
49
 
48
50
  ## Testing
49
51
  - Playwright tests live in `tests/` at the project root.
50
52
  - Tests require the server running on localhost:7654.
51
53
  - Screenshots on failure go to `test-results/`.
52
54
  - Use Playwright MCP for visual verification. Save screenshots to `.playwright-mcp/`.
55
+
56
+ ### Testing Mesh/Node Functionality
57
+ Run a second Lattice instance with a separate data directory and port:
58
+ ```bash
59
+ LATTICE_HOME=/tmp/lattice-test-node LATTICE_PORT=7655 bun server/src/index.ts daemon
60
+ ```
61
+ Then pair the two instances via the UI or WebSocket:
62
+ ```bash
63
+ # Generate invite on :7654, then pair from :7655:
64
+ bun -e "
65
+ var ws = new WebSocket('ws://localhost:7655/ws');
66
+ ws.onopen = function() { ws.send(JSON.stringify({ type: 'mesh:pair', code: 'LTCE-XXXX-...' })); };
67
+ ws.onmessage = function(e) { console.log(JSON.parse(e.data).type); };
68
+ "
69
+ ```
70
+ The test instance serves from `client/dist/` (run `bun run build` first for UI access on :7655).
71
+ Clean up: `rm -rf /tmp/lattice-test-node`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cryptiklemur/lattice",
3
- "version": "1.36.4",
3
+ "version": "1.37.0",
4
4
  "description": "Multi-machine agentic dashboard for Claude Code. Monitor sessions, manage MCP servers and skills, orchestrate across mesh-networked nodes.",
5
5
  "license": "MIT",
6
6
  "author": "Aaron Scherer <me@aaronscherer.me>",
@@ -4,7 +4,7 @@ import { join } from "node:path";
4
4
  import { DEFAULT_PORT, LATTICE_HOME_DIR } from "@lattice/shared";
5
5
  import type { LatticeConfig } from "@lattice/shared";
6
6
 
7
- var home = join(homedir(), LATTICE_HOME_DIR);
7
+ var home = process.env.LATTICE_HOME || join(homedir(), LATTICE_HOME_DIR);
8
8
  var cachedConfig: LatticeConfig | null = null;
9
9
 
10
10
  export function getLatticeHome(): string {
@@ -1,4 +1,4 @@
1
- import { chmodSync, renameSync, writeFileSync, accessSync, constants as fsConstants } from "node:fs";
1
+ import { chmodSync, writeFileSync, accessSync, copyFileSync, unlinkSync, constants as fsConstants } from "node:fs";
2
2
  import { tmpdir } from "node:os";
3
3
  import { join } from "node:path";
4
4
  import { execSync } from "node:child_process";
@@ -60,13 +60,16 @@ async function downloadBinaryUpdate(): Promise<{ success: boolean; message: stri
60
60
 
61
61
  if (needsSudo) {
62
62
  try {
63
- execSync("sudo mv " + JSON.stringify(tmpPath) + " " + JSON.stringify(execPath), { stdio: "pipe", timeout: 10000 });
63
+ execSync("sudo cp " + JSON.stringify(tmpPath) + " " + JSON.stringify(execPath), { stdio: "pipe", timeout: 10000 });
64
64
  execSync("sudo chmod +x " + JSON.stringify(execPath), { stdio: "pipe", timeout: 5000 });
65
+ unlinkSync(tmpPath);
65
66
  } catch {
66
- return { success: false, message: "Update downloaded but needs sudo to install. Run: sudo mv " + tmpPath + " " + execPath };
67
+ return { success: false, message: "Update downloaded but needs sudo to install. Run: sudo cp " + tmpPath + " " + execPath };
67
68
  }
68
69
  } else {
69
- renameSync(tmpPath, execPath);
70
+ copyFileSync(tmpPath, execPath);
71
+ chmodSync(execPath, 0o755);
72
+ unlinkSync(tmpPath);
70
73
  }
71
74
 
72
75
  return { success: true, message: "Updated successfully. Restart the server to apply." };
@@ -7,7 +7,7 @@ import { IS_COMPILED } from "./runtime";
7
7
 
8
8
  var args = process.argv.slice(2);
9
9
  var command = "start";
10
- var portOverride: number | null = null;
10
+ var portOverride: number | null = process.env.LATTICE_PORT ? parseInt(process.env.LATTICE_PORT, 10) : null;
11
11
 
12
12
  for (var i = 0; i < args.length; i++) {
13
13
  if (args[i] === "--port" && i + 1 < args.length) {
@@ -259,10 +259,13 @@ async function runUpdate(): Promise<void> {
259
259
  if (needsSudo) {
260
260
  console.log("[lattice] Needs elevated permissions to replace binary...");
261
261
  var { execSync } = await import("node:child_process");
262
- execSync("sudo mv " + JSON.stringify(tmpPath) + " " + JSON.stringify(process.execPath), { stdio: "inherit" });
262
+ execSync("sudo cp " + JSON.stringify(tmpPath) + " " + JSON.stringify(process.execPath), { stdio: "inherit" });
263
263
  execSync("sudo chmod +x " + JSON.stringify(process.execPath), { stdio: "inherit" });
264
264
  } else {
265
- renameSync(tmpPath, process.execPath);
265
+ var { copyFileSync: cpSync, unlinkSync: rmSync } = await import("node:fs");
266
+ cpSync(tmpPath, process.execPath);
267
+ chmodSync(process.execPath, 0o755);
268
+ rmSync(tmpPath);
266
269
  }
267
270
  code = 0;
268
271
  } catch (err) {