@layoutdesign/context 0.6.0 → 0.11.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.
Files changed (77) hide show
  1. package/README.md +71 -0
  2. package/dist/bin/cli.js +13 -5
  3. package/dist/bin/cli.js.map +1 -1
  4. package/dist/src/cli/fetch-kit.d.ts +16 -0
  5. package/dist/src/cli/fetch-kit.d.ts.map +1 -0
  6. package/dist/src/cli/fetch-kit.js +52 -0
  7. package/dist/src/cli/fetch-kit.js.map +1 -0
  8. package/dist/src/cli/import-zip.d.ts +13 -0
  9. package/dist/src/cli/import-zip.d.ts.map +1 -1
  10. package/dist/src/cli/import-zip.js +75 -56
  11. package/dist/src/cli/import-zip.js.map +1 -1
  12. package/dist/src/cli/install.d.ts +2 -1
  13. package/dist/src/cli/install.d.ts.map +1 -1
  14. package/dist/src/cli/install.js +46 -1
  15. package/dist/src/cli/install.js.map +1 -1
  16. package/dist/src/cli/live-notify.d.ts +2 -0
  17. package/dist/src/cli/live-notify.d.ts.map +1 -0
  18. package/dist/src/cli/live-notify.js +29 -0
  19. package/dist/src/cli/live-notify.js.map +1 -0
  20. package/dist/src/cli/use.d.ts.map +1 -1
  21. package/dist/src/cli/use.js +37 -18
  22. package/dist/src/cli/use.js.map +1 -1
  23. package/dist/src/install/live.d.ts +5 -0
  24. package/dist/src/install/live.d.ts.map +1 -0
  25. package/dist/src/install/live.js +285 -0
  26. package/dist/src/install/live.js.map +1 -0
  27. package/dist/src/kit/registry.d.ts.map +1 -1
  28. package/dist/src/kit/registry.js +4 -2
  29. package/dist/src/kit/registry.js.map +1 -1
  30. package/dist/src/mcp/live-lock-store.d.ts +40 -0
  31. package/dist/src/mcp/live-lock-store.d.ts.map +1 -0
  32. package/dist/src/mcp/live-lock-store.js +134 -0
  33. package/dist/src/mcp/live-lock-store.js.map +1 -0
  34. package/dist/src/mcp/server.d.ts.map +1 -1
  35. package/dist/src/mcp/server.js +11 -0
  36. package/dist/src/mcp/server.js.map +1 -1
  37. package/dist/src/mcp/tools/_live-socket.d.ts +23 -0
  38. package/dist/src/mcp/tools/_live-socket.d.ts.map +1 -0
  39. package/dist/src/mcp/tools/_live-socket.js +135 -0
  40. package/dist/src/mcp/tools/_live-socket.js.map +1 -0
  41. package/dist/src/mcp/tools/check-setup.d.ts +14 -1
  42. package/dist/src/mcp/tools/check-setup.d.ts.map +1 -1
  43. package/dist/src/mcp/tools/check-setup.js +75 -1
  44. package/dist/src/mcp/tools/check-setup.js.map +1 -1
  45. package/dist/src/mcp/tools/get-recent-visual-edits.d.ts +40 -0
  46. package/dist/src/mcp/tools/get-recent-visual-edits.d.ts.map +1 -0
  47. package/dist/src/mcp/tools/get-recent-visual-edits.js +106 -0
  48. package/dist/src/mcp/tools/get-recent-visual-edits.js.map +1 -0
  49. package/dist/src/mcp/tools/get-selected-element.d.ts +10 -0
  50. package/dist/src/mcp/tools/get-selected-element.d.ts.map +1 -0
  51. package/dist/src/mcp/tools/get-selected-element.js +46 -0
  52. package/dist/src/mcp/tools/get-selected-element.js.map +1 -0
  53. package/dist/src/mcp/tools/lock-file.d.ts +28 -0
  54. package/dist/src/mcp/tools/lock-file.d.ts.map +1 -0
  55. package/dist/src/mcp/tools/lock-file.js +42 -0
  56. package/dist/src/mcp/tools/lock-file.js.map +1 -0
  57. package/dist/src/mcp/tools/unlock-file.d.ts +23 -0
  58. package/dist/src/mcp/tools/unlock-file.d.ts.map +1 -0
  59. package/dist/src/mcp/tools/unlock-file.js +23 -0
  60. package/dist/src/mcp/tools/unlock-file.js.map +1 -0
  61. package/dist/src/plugins/next/babel-loader.d.ts +8 -0
  62. package/dist/src/plugins/next/babel-loader.d.ts.map +1 -0
  63. package/dist/src/plugins/next/babel-loader.js +26 -0
  64. package/dist/src/plugins/next/babel-loader.js.map +1 -0
  65. package/dist/src/plugins/next/index.d.ts +23 -0
  66. package/dist/src/plugins/next/index.d.ts.map +1 -0
  67. package/dist/src/plugins/next/index.js +58 -0
  68. package/dist/src/plugins/next/index.js.map +1 -0
  69. package/dist/src/plugins/transform.d.ts +19 -0
  70. package/dist/src/plugins/transform.d.ts.map +1 -0
  71. package/dist/src/plugins/transform.js +177 -0
  72. package/dist/src/plugins/transform.js.map +1 -0
  73. package/dist/src/plugins/vite/index.d.ts +24 -0
  74. package/dist/src/plugins/vite/index.d.ts.map +1 -0
  75. package/dist/src/plugins/vite/index.js +56 -0
  76. package/dist/src/plugins/vite/index.js.map +1 -0
  77. package/package.json +31 -9
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live-notify.js","sourceRoot":"","sources":["../../../src/cli/live-notify.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE7D,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAAa;IACnD,IAAI,IAAI,GAA8C,IAAI,CAAC;IAC3D,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAC1C,IAAI,CAAC,IAAI;YAAE,OAAO,CAAC,kCAAkC;QACrD,MAAM,IAAI,CAAC,IAAI,CAAC;YACd,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE;SACvD,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,oEAAoE;QACpE,+DAA+D;IACjE,CAAC;YAAS,CAAC;QACT,IAAI,EAAE,KAAK,EAAE,CAAC;IAChB,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"use.d.ts","sourceRoot":"","sources":["../../../src/cli/use.ts"],"names":[],"mappings":"AAOA,wBAAsB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA2E/D"}
1
+ {"version":3,"file":"use.d.ts","sourceRoot":"","sources":["../../../src/cli/use.ts"],"names":[],"mappings":"AAQA,wBAAsB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA8C/D"}
@@ -3,35 +3,53 @@ import path from "node:path";
3
3
  import chalk from "chalk";
4
4
  import { getBundledKitPath, listBundledKits } from "../kit/loader.js";
5
5
  import { findKitInRegistry, getRegistry } from "../kit/registry.js";
6
+ import { fetchKitFromGallery } from "./fetch-kit.js";
6
7
  import { LAYOUT_DIR } from "../kit/types.js";
7
8
  export async function useCommand(kitName) {
8
9
  const targetDir = path.join(process.cwd(), LAYOUT_DIR);
9
- // Check bundled kits first
10
+ // 1. Bundled kits ship with the package — copy directly.
10
11
  const bundledPath = getBundledKitPath(kitName);
11
12
  if (bundledPath) {
12
13
  fs.cpSync(bundledPath, targetDir, { recursive: true });
13
- console.log(chalk.green("✓"), `Installed the ${chalk.bold(kitName)} kit into .layout/`);
14
- console.log();
15
- console.log(`Run ${chalk.cyan("layout-context serve")} to start the MCP server.`);
14
+ printInstalled(kitName);
16
15
  return;
17
16
  }
18
- // Check registry
17
+ // 2. Premium kits in the static registry require purchase.
19
18
  const registryEntry = findKitInRegistry(kitName);
20
- if (registryEntry) {
21
- if (registryEntry.tier === "pro") {
22
- console.log(chalk.yellow("Pro kit:"), `${chalk.bold(registryEntry.displayName)} is a premium kit (${chalk.yellow(registryEntry.price ?? "paid")}).`);
23
- console.log();
24
- console.log(` Purchase at ${chalk.cyan("https://layout.design/kits/" + kitName)}`);
25
- console.log(` Then import with: ${chalk.cyan(`layout-context import <path-to-zip>`)}`);
26
- return;
27
- }
28
- // Free registry kit not bundled — packaging issue
29
- console.log(chalk.red("Error:"), `Kit "${kitName}" is listed as free but not bundled. This may be a packaging issue.`);
19
+ if (registryEntry?.tier === "pro") {
20
+ console.log(chalk.yellow("Pro kit:"), `${chalk.bold(registryEntry.displayName)} is a premium kit (${chalk.yellow(registryEntry.price ?? "paid")}).`);
21
+ console.log();
22
+ console.log(` Purchase at ${chalk.cyan("https://layout.design/kits/" + kitName)}`);
23
+ console.log(` Then import with: ${chalk.cyan(`layout-context import <path-to-zip>`)}`);
24
+ return;
25
+ }
26
+ // 3. Anything else — try the public gallery at layout.design.
27
+ console.log(chalk.dim(`Fetching ${chalk.bold(kitName)} from the gallery…`));
28
+ const result = await fetchKitFromGallery(kitName);
29
+ if (result.status === "installed") {
30
+ printInstalled(kitName, result.imported);
31
+ return;
32
+ }
33
+ if (result.status === "error") {
34
+ console.log(chalk.red("Error:"), result.message);
30
35
  return;
31
36
  }
32
- // Not found
33
- console.log(chalk.red("Error:"), `Kit "${kitName}" not found.`);
37
+ // not-found — show what is available
38
+ console.log(chalk.red("Error:"), `Kit "${kitName}" not found in the gallery.`);
39
+ console.log();
40
+ printAvailableKits();
41
+ }
42
+ function printInstalled(kitName, imported) {
43
+ console.log(chalk.green("✓"), `Installed the ${chalk.bold(kitName)} kit into .layout/`);
44
+ if (imported && imported.length > 0) {
45
+ for (const file of imported) {
46
+ console.log(` ${chalk.dim("•")} ${file}`);
47
+ }
48
+ }
34
49
  console.log();
50
+ console.log(`Run ${chalk.cyan("layout-context install")} to connect the MCP server.`);
51
+ }
52
+ function printAvailableKits() {
35
53
  const bundled = listBundledKits();
36
54
  const registry = getRegistry();
37
55
  if (bundled.length > 0) {
@@ -49,6 +67,7 @@ export async function useCommand(kitName) {
49
67
  }
50
68
  console.log();
51
69
  }
52
- console.log(`Run ${chalk.cyan("layout-context list")} for full details.`);
70
+ console.log(`Browse all community kits at ${chalk.cyan("https://layout.design/gallery")}.`);
71
+ console.log(`Run ${chalk.cyan("layout-context list")} for bundled and premium kits.`);
53
72
  }
54
73
  //# sourceMappingURL=use.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use.js","sourceRoot":"","sources":["../../../src/cli/use.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"use.js","sourceRoot":"","sources":["../../../src/cli/use.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export type Framework = "vite" | "next" | "unknown";
2
+ /** Read package.json deps to decide which build plugin applies. */
3
+ export declare function detectFramework(projectRoot: string): Framework;
4
+ export declare function installLive(projectRoot: string): Promise<void>;
5
+ //# sourceMappingURL=live.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../../src/install/live.ts"],"names":[],"mappings":"AAuBA,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AA2CpD,mEAAmE;AACnE,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAe9D;AA2QD,wBAAsB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBpE"}
@@ -0,0 +1,285 @@
1
+ /**
2
+ * `npx @layoutdesign/context install --live`
3
+ *
4
+ * Wires a project up for layout Live:
5
+ * 1. Detect framework (vite | next) from package.json
6
+ * 2. Add the matching build plugin to vite.config / next.config (recast —
7
+ * formatting + comments preserved; original backed up first)
8
+ * 3. Create .layout/live/ with config.json + a local .gitignore
9
+ * 4. Append the layout-live managed block to CLAUDE.md
10
+ *
11
+ * Every step is idempotent: re-running --live when everything is already set
12
+ * up makes no changes and reports "already configured".
13
+ */
14
+ import fs from "node:fs";
15
+ import path from "node:path";
16
+ import { createRequire } from "node:module";
17
+ import chalk from "chalk";
18
+ const require = createRequire(import.meta.url);
19
+ // recast + its TS/JSX parser are CJS — load via createRequire under ESM.
20
+ const recast = require("recast");
21
+ const babelTsParser = require("recast/parsers/babel-ts");
22
+ const VITE_IMPORT = `import layout from "@layoutdesign/context/vite-plugin";`;
23
+ const NEXT_IMPORT = `import withLayout from "@layoutdesign/context/next-plugin";`;
24
+ const CLAUDE_BEGIN = "<!-- BEGIN layout-live (managed) -->";
25
+ const CLAUDE_END = "<!-- END layout-live (managed) -->";
26
+ const CLAUDE_BLOCK = `${CLAUDE_BEGIN}
27
+ ## Recent visual edits (layout Live)
28
+
29
+ The user has layout Live installed (desktop app). They may make visual edits — colour, spacing, typography tweaks — directly in their running app. These edits land in source files instantly.
30
+
31
+ When relevant, use these MCP tools:
32
+ - \`get-recent-visual-edits\` — recent class/token changes
33
+ - \`get-selected-element\` — element currently selected in Live (use when the user says "this" or "that one")
34
+ - \`lock-file\` / \`unlock-file\` — coordinate file access before editing
35
+
36
+ If you are about to edit a file the user is also editing visually:
37
+ 1. Call \`lock-file\` with the file path and a short TTL (default 60s).
38
+ 2. If the lock is held by Live, wait briefly and retry, or surface to the user.
39
+ 3. Make your edit, then call \`unlock-file\`.
40
+
41
+ The user holds priority on visual edits. Don't undo visual tweaks unless they explicitly ask.
42
+ ${CLAUDE_END}`;
43
+ const LIVE_CONFIG = {
44
+ $schema: "https://layout.design/schema/live-config/v1.json",
45
+ version: 1,
46
+ snapToScale: true,
47
+ complianceScoring: {
48
+ enabled: true,
49
+ debounceMs: 2000,
50
+ minEditsBetweenChecks: 5,
51
+ },
52
+ exclude: [],
53
+ };
54
+ const LIVE_GITIGNORE = "recent-edits.*\nlocks.json\nconflicts.json\n";
55
+ /** Read package.json deps to decide which build plugin applies. */
56
+ export function detectFramework(projectRoot) {
57
+ const pkgPath = path.join(projectRoot, "package.json");
58
+ if (!fs.existsSync(pkgPath))
59
+ return "unknown";
60
+ try {
61
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
62
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
63
+ if (deps["next"])
64
+ return "next";
65
+ if (deps["vite"])
66
+ return "vite";
67
+ }
68
+ catch {
69
+ /* fall through */
70
+ }
71
+ return "unknown";
72
+ }
73
+ function findConfig(projectRoot, base) {
74
+ for (const ext of ["ts", "mts", "js", "mjs"]) {
75
+ const p = path.join(projectRoot, `${base}.config.${ext}`);
76
+ if (fs.existsSync(p))
77
+ return p;
78
+ }
79
+ return null;
80
+ }
81
+ function backup(configPath) {
82
+ const backupPath = `${configPath}.layout-backup`;
83
+ if (!fs.existsSync(backupPath)) {
84
+ fs.copyFileSync(configPath, backupPath);
85
+ }
86
+ }
87
+ function parse(src) {
88
+ return recast.parse(src, { parser: babelTsParser });
89
+ }
90
+ /** Insert an import line at the top if its specifier isn't already present. */
91
+ function ensureImport(src, importLine, specifier) {
92
+ if (src.includes(specifier))
93
+ return src;
94
+ return `${importLine}\n${src}`;
95
+ }
96
+ /**
97
+ * Add `layout()` as the first entry of the Vite `plugins` array. Returns the
98
+ * new source, or null if the config shape is too unusual to edit safely.
99
+ */
100
+ function patchViteConfig(src) {
101
+ if (src.includes("@layoutdesign/context/vite-plugin"))
102
+ return src; // idempotent
103
+ let ast;
104
+ try {
105
+ ast = parse(src);
106
+ }
107
+ catch {
108
+ return null;
109
+ }
110
+ let patched = false;
111
+ // babel-ts produces ObjectProperty nodes (not ESTree Property).
112
+ recast.types.visit(ast, {
113
+ visitObjectProperty(p) {
114
+ const key = p.node.key;
115
+ const keyName = key?.name ?? key?.value;
116
+ if (keyName === "plugins" && p.node.value?.type === "ArrayExpression") {
117
+ const callExpr = recast.types.builders.callExpression(recast.types.builders.identifier("layout"), []);
118
+ p.node.value.elements.unshift(callExpr);
119
+ patched = true;
120
+ return false;
121
+ }
122
+ this.traverse(p);
123
+ },
124
+ });
125
+ if (!patched)
126
+ return null;
127
+ const printed = recast.print(ast).code;
128
+ return ensureImport(printed, VITE_IMPORT, "@layoutdesign/context/vite-plugin");
129
+ }
130
+ /**
131
+ * Wrap the default export with `withLayout(...)`. Handles
132
+ * `export default <expr>` (incl. an identifier referencing the config object).
133
+ */
134
+ function patchNextConfig(src) {
135
+ if (src.includes("@layoutdesign/context/next-plugin"))
136
+ return src; // idempotent
137
+ let ast;
138
+ try {
139
+ ast = parse(src);
140
+ }
141
+ catch {
142
+ return null;
143
+ }
144
+ const b = recast.types.builders;
145
+ let patched = false;
146
+ recast.types.visit(ast, {
147
+ visitExportDefaultDeclaration(p) {
148
+ const decl = p.node.declaration;
149
+ if (decl) {
150
+ p.node.declaration = b.callExpression(b.identifier("withLayout"), [
151
+ decl,
152
+ ]);
153
+ patched = true;
154
+ }
155
+ return false;
156
+ },
157
+ visitAssignmentExpression(p) {
158
+ // CommonJS: module.exports = <expr>
159
+ const left = p.node.left;
160
+ if (left?.type === "MemberExpression" &&
161
+ left.object?.name === "module" &&
162
+ left.property?.name === "exports") {
163
+ p.node.right = b.callExpression(b.identifier("withLayout"), [
164
+ p.node.right,
165
+ ]);
166
+ patched = true;
167
+ return false;
168
+ }
169
+ this.traverse(p);
170
+ },
171
+ });
172
+ if (!patched)
173
+ return null;
174
+ const printed = recast.print(ast).code;
175
+ const importLine = src.includes("module.exports")
176
+ ? `const withLayout = require("@layoutdesign/context/next-plugin").default;`
177
+ : NEXT_IMPORT;
178
+ return ensureImport(printed, importLine, "@layoutdesign/context/next-plugin");
179
+ }
180
+ function installPlugin(projectRoot, framework) {
181
+ const base = framework === "next" ? "next" : "vite";
182
+ const configPath = findConfig(projectRoot, base);
183
+ if (!configPath) {
184
+ console.log(chalk.yellow(" ⚠"), `No ${base}.config.* found. Add the plugin manually:`);
185
+ console.log(chalk.dim(framework === "next"
186
+ ? ` ${NEXT_IMPORT}\n export default withLayout({ /* ...config */ });`
187
+ : ` ${VITE_IMPORT}\n plugins: [layout(), react()]`));
188
+ return { changed: false };
189
+ }
190
+ const original = fs.readFileSync(configPath, "utf8");
191
+ const patched = framework === "next"
192
+ ? patchNextConfig(original)
193
+ : patchViteConfig(original);
194
+ if (patched === null) {
195
+ console.log(chalk.yellow(" ⚠"), `${path.basename(configPath)} has an unusual shape — not modified. Add manually:`);
196
+ console.log(chalk.dim(framework === "next"
197
+ ? ` Wrap your config export with withLayout() from @layoutdesign/context/next-plugin`
198
+ : ` Add layout() (before react()) to plugins, import from @layoutdesign/context/vite-plugin`));
199
+ return { changed: false };
200
+ }
201
+ if (patched === original) {
202
+ console.log(chalk.dim(" ↳"), `${path.basename(configPath)}: plugin already configured`);
203
+ return { changed: false };
204
+ }
205
+ backup(configPath);
206
+ fs.writeFileSync(configPath, patched);
207
+ console.log(chalk.green(" ✓"), `${path.basename(configPath)}: added layout build plugin ${chalk.dim("(backup: " + path.basename(configPath) + ".layout-backup)")}`);
208
+ return { changed: true };
209
+ }
210
+ function ensureLayoutLiveDir(projectRoot) {
211
+ const liveDir = path.join(projectRoot, ".layout", "live");
212
+ let changed = false;
213
+ fs.mkdirSync(liveDir, { recursive: true });
214
+ const configFile = path.join(liveDir, "config.json");
215
+ if (!fs.existsSync(configFile)) {
216
+ fs.writeFileSync(configFile, JSON.stringify(LIVE_CONFIG, null, 2) + "\n");
217
+ changed = true;
218
+ }
219
+ const gitignoreFile = path.join(liveDir, ".gitignore");
220
+ if (!fs.existsSync(gitignoreFile)) {
221
+ fs.writeFileSync(gitignoreFile, LIVE_GITIGNORE);
222
+ changed = true;
223
+ }
224
+ console.log(changed ? chalk.green(" ✓") : chalk.dim(" ↳"), changed
225
+ ? ".layout/live/ created (config.json + .gitignore)"
226
+ : ".layout/live/ already present");
227
+ return { changed };
228
+ }
229
+ /**
230
+ * Apply the delimited managed block to one agent file, idempotently.
231
+ * `createIfMissing` distinguishes CLAUDE.md (always created) from
232
+ * AGENTS.md / .cursorrules (only augmented if the project already has them).
233
+ */
234
+ function applyManagedBlock(file, label, createIfMissing) {
235
+ const exists = fs.existsSync(file);
236
+ if (!exists && !createIfMissing)
237
+ return { changed: false };
238
+ const existing = exists ? fs.readFileSync(file, "utf8") : "";
239
+ if (existing.includes(CLAUDE_BEGIN)) {
240
+ const before = existing.slice(0, existing.indexOf(CLAUDE_BEGIN));
241
+ const afterIdx = existing.indexOf(CLAUDE_END);
242
+ const after = afterIdx === -1 ? "" : existing.slice(afterIdx + CLAUDE_END.length);
243
+ const next = `${before}${CLAUDE_BLOCK}${after}`;
244
+ if (next === existing) {
245
+ console.log(chalk.dim(" ↳"), `${label}: managed block already current`);
246
+ return { changed: false };
247
+ }
248
+ fs.writeFileSync(file, next);
249
+ console.log(chalk.green(" ✓"), `${label}: refreshed layout-live block`);
250
+ return { changed: true };
251
+ }
252
+ const sep = existing.length === 0 ? "" : existing.endsWith("\n") ? "\n" : "\n\n";
253
+ fs.writeFileSync(file, `${existing}${sep}${CLAUDE_BLOCK}\n`);
254
+ console.log(chalk.green(" ✓"), existing.length === 0
255
+ ? `${label}: created with layout-live block`
256
+ : `${label}: appended layout-live block`);
257
+ return { changed: true };
258
+ }
259
+ function appendClaudeMdSection(projectRoot) {
260
+ // CLAUDE.md is created if absent; AGENTS.md / .cursorrules are only
261
+ // augmented when the project already exports them.
262
+ const claude = applyManagedBlock(path.join(projectRoot, "CLAUDE.md"), "CLAUDE.md", true);
263
+ const agents = applyManagedBlock(path.join(projectRoot, "AGENTS.md"), "AGENTS.md", false);
264
+ const cursor = applyManagedBlock(path.join(projectRoot, ".cursorrules"), ".cursorrules", false);
265
+ return {
266
+ changed: claude.changed || agents.changed || cursor.changed,
267
+ };
268
+ }
269
+ export async function installLive(projectRoot) {
270
+ console.log();
271
+ console.log(chalk.bold(" layout Live"));
272
+ const framework = detectFramework(projectRoot);
273
+ if (framework === "unknown") {
274
+ console.log(chalk.yellow(" ⚠"), "Could not detect Vite or Next.js in package.json — skipping plugin step.");
275
+ }
276
+ else {
277
+ console.log(chalk.dim(` ↳ Framework detected: ${framework}`));
278
+ installPlugin(projectRoot, framework);
279
+ }
280
+ ensureLayoutLiveDir(projectRoot);
281
+ appendClaudeMdSection(projectRoot);
282
+ console.log();
283
+ console.log(chalk.dim(" layout Live tools are exposed by the MCP server automatically."));
284
+ }
285
+ //# sourceMappingURL=live.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live.js","sourceRoot":"","sources":["../../../src/install/live.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/kit/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAuFhD,wBAAgB,WAAW,IAAI,aAAa,EAAE,CAE7C;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAEzE"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/kit/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAyFhD,wBAAgB,WAAW,IAAI,aAAa,EAAE,CAE7C;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAEzE"}
@@ -1,6 +1,8 @@
1
1
  /**
2
- * Local registry of available kits.
3
- * In Phase 2, this will fetch from layout.design/api/kits.
2
+ * Static registry of bundled free kits and premium (purchasable) kits.
3
+ * Community kits published to the gallery are NOT listed here — `use <slug>`
4
+ * and `install <slug>` fetch those on demand from
5
+ * layout.design/api/public/kits/<slug>/download (see fetch-kit.ts).
4
6
  */
5
7
  const REGISTRY = [
6
8
  {
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/kit/registry.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,QAAQ,GAAoB;IAChC;QACE,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,QAAQ;QACrB,WAAW,EAAE,0CAA0C;QACvD,IAAI,EAAE,MAAM;QACZ,SAAS,EAAE,kCAAkC;KAC9C;IACD;QACE,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,QAAQ;QACrB,WAAW,EAAE,iCAAiC;QAC9C,IAAI,EAAE,MAAM;QACZ,SAAS,EAAE,0BAA0B;KACtC;IACD;QACE,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,QAAQ;QACrB,WAAW,EAAE,sCAAsC;QACnD,IAAI,EAAE,MAAM;QACZ,SAAS,EAAE,mCAAmC;KAC/C;IACD,yBAAyB;IACzB;QACE,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,eAAe;QAC5B,WAAW,EAAE,2DAA2D;QACxE,IAAI,EAAE,KAAK;QACX,KAAK,EAAE,KAAK;QACZ,SAAS,EAAE,kCAAkC;KAC9C;IACD;QACE,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,gBAAgB;QAC7B,WAAW,EAAE,4DAA4D;QACzE,IAAI,EAAE,KAAK;QACX,KAAK,EAAE,KAAK;QACZ,SAAS,EAAE,yBAAyB;KACrC;IACD;QACE,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,eAAe;QAC5B,WAAW,EAAE,2DAA2D;QACxE,IAAI,EAAE,KAAK;QACX,KAAK,EAAE,KAAK;QACZ,SAAS,EAAE,0BAA0B;KACtC;IACD;QACE,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,eAAe;QAC5B,WAAW,EAAE,2DAA2D;QACxE,IAAI,EAAE,KAAK;QACX,KAAK,EAAE,KAAK;QACZ,SAAS,EAAE,8BAA8B;KAC1C;IACD;QACE,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,eAAe;QAC5B,WAAW,EAAE,2DAA2D;QACxE,IAAI,EAAE,KAAK;QACX,KAAK,EAAE,KAAK;QACZ,SAAS,EAAE,mCAAmC;KAC/C;IACD;QACE,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,eAAe;QAC5B,WAAW,EAAE,2DAA2D;QACxE,IAAI,EAAE,KAAK;QACX,KAAK,EAAE,KAAK;QACZ,SAAS,EAAE,4BAA4B;KACxC;IACD;QACE,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,gBAAgB;QAC7B,WAAW,EAAE,4DAA4D;QACzE,IAAI,EAAE,KAAK;QACX,KAAK,EAAE,KAAK;QACZ,SAAS,EAAE,kCAAkC;KAC9C;CACF,CAAC;AAEF,MAAM,UAAU,WAAW;IACzB,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AACvD,CAAC"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/kit/registry.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,QAAQ,GAAoB;IAChC;QACE,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,QAAQ;QACrB,WAAW,EAAE,0CAA0C;QACvD,IAAI,EAAE,MAAM;QACZ,SAAS,EAAE,kCAAkC;KAC9C;IACD;QACE,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,QAAQ;QACrB,WAAW,EAAE,iCAAiC;QAC9C,IAAI,EAAE,MAAM;QACZ,SAAS,EAAE,0BAA0B;KACtC;IACD;QACE,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,QAAQ;QACrB,WAAW,EAAE,sCAAsC;QACnD,IAAI,EAAE,MAAM;QACZ,SAAS,EAAE,mCAAmC;KAC/C;IACD,yBAAyB;IACzB;QACE,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,eAAe;QAC5B,WAAW,EAAE,2DAA2D;QACxE,IAAI,EAAE,KAAK;QACX,KAAK,EAAE,KAAK;QACZ,SAAS,EAAE,kCAAkC;KAC9C;IACD;QACE,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,gBAAgB;QAC7B,WAAW,EAAE,4DAA4D;QACzE,IAAI,EAAE,KAAK;QACX,KAAK,EAAE,KAAK;QACZ,SAAS,EAAE,yBAAyB;KACrC;IACD;QACE,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,eAAe;QAC5B,WAAW,EAAE,2DAA2D;QACxE,IAAI,EAAE,KAAK;QACX,KAAK,EAAE,KAAK;QACZ,SAAS,EAAE,0BAA0B;KACtC;IACD;QACE,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,eAAe;QAC5B,WAAW,EAAE,2DAA2D;QACxE,IAAI,EAAE,KAAK;QACX,KAAK,EAAE,KAAK;QACZ,SAAS,EAAE,8BAA8B;KAC1C;IACD;QACE,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,eAAe;QAC5B,WAAW,EAAE,2DAA2D;QACxE,IAAI,EAAE,KAAK;QACX,KAAK,EAAE,KAAK;QACZ,SAAS,EAAE,mCAAmC;KAC/C;IACD;QACE,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,eAAe;QAC5B,WAAW,EAAE,2DAA2D;QACxE,IAAI,EAAE,KAAK;QACX,KAAK,EAAE,KAAK;QACZ,SAAS,EAAE,4BAA4B;KACxC;IACD;QACE,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,gBAAgB;QAC7B,WAAW,EAAE,4DAA4D;QACzE,IAAI,EAAE,KAAK;QACX,KAAK,EAAE,KAAK;QACZ,SAAS,EAAE,kCAAkC;KAC9C;CACF,CAAC;AAEF,MAAM,UAAU,WAAW;IACzB,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AACvD,CAAC"}
@@ -0,0 +1,40 @@
1
+ export type LockHolder = "live" | "claude" | string;
2
+ export interface LockEntry {
3
+ holder: LockHolder;
4
+ lock_id: string;
5
+ acquired_at: string;
6
+ expires_at: string;
7
+ reason?: string;
8
+ }
9
+ export type LocksFile = Record<string, LockEntry>;
10
+ export type AcquireResult = {
11
+ acquired: true;
12
+ lock_id: string;
13
+ expires_at: string;
14
+ } | {
15
+ acquired: false;
16
+ current_holder: LockHolder;
17
+ expires_at: string;
18
+ };
19
+ /**
20
+ * Acquire (or take over an expired) write lock for `relPath`.
21
+ *
22
+ * Returns `{ acquired: false, current_holder, expires_at }` when a live,
23
+ * unexpired lock is already held by someone else.
24
+ */
25
+ export declare function acquireLock(projectRoot: string, opts: {
26
+ path: string;
27
+ ttlSeconds: number;
28
+ reason?: string;
29
+ holder?: LockHolder;
30
+ }): Promise<AcquireResult>;
31
+ /**
32
+ * Release a lock by its `lock_id`. Only the matching entry is removed, so a
33
+ * stale `lock_id` from a since-taken-over lock cannot evict the new holder.
34
+ */
35
+ export declare function releaseLock(projectRoot: string, lockId: string): Promise<{
36
+ released: boolean;
37
+ }>;
38
+ /** Read the current locks map (best-effort; empty if file absent/corrupt). */
39
+ export declare function readLocks(projectRoot: string): Promise<LocksFile>;
40
+ //# sourceMappingURL=live-lock-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live-lock-store.d.ts","sourceRoot":"","sources":["../../../src/mcp/live-lock-store.ts"],"names":[],"mappings":"AAmBA,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEpD,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAElD,MAAM,MAAM,aAAa,GACrB;IAAE,QAAQ,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,QAAQ,EAAE,KAAK,CAAC;IAAC,cAAc,EAAE,UAAU,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AA+DxE;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE;IACJ,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB,GACA,OAAO,CAAC,aAAa,CAAC,CAwCxB;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC,CAYhC;AAED,8EAA8E;AAC9E,wBAAsB,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAGvE"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * File-based write-lock coordination between Claude Code (via the MCP tools)
3
+ * and the layout Live desktop app.
4
+ *
5
+ * Locks live in `.layout/live/locks.json` at the project root (gitignored by
6
+ * default). Both Live and these MCP handlers mutate that file, so every
7
+ * read-modify-write is wrapped in a `proper-lockfile` advisory lock for
8
+ * atomicity. Stale locks (past `expires_at`) are taken over automatically with
9
+ * a warning logged to stderr.
10
+ *
11
+ * The file-based design means Claude's `lock-file` MCP call does not have to
12
+ * wait on IPC to a desktop app — it works even when Live's socket is slow or
13
+ * Live isn't running at all.
14
+ */
15
+ import { promises as fs } from "node:fs";
16
+ import path from "node:path";
17
+ import crypto from "node:crypto";
18
+ import lockfile from "proper-lockfile";
19
+ const LIVE_DIR = path.join(".layout", "live");
20
+ const LOCKS_FILE = "locks.json";
21
+ function locksPath(projectRoot) {
22
+ return path.join(projectRoot, LIVE_DIR, LOCKS_FILE);
23
+ }
24
+ async function ensureLocksFile(projectRoot) {
25
+ const file = locksPath(projectRoot);
26
+ await fs.mkdir(path.dirname(file), { recursive: true });
27
+ try {
28
+ await fs.access(file);
29
+ }
30
+ catch {
31
+ await fs.writeFile(file, "{}\n", "utf8");
32
+ }
33
+ return file;
34
+ }
35
+ async function readLocksFile(file) {
36
+ try {
37
+ const raw = await fs.readFile(file, "utf8");
38
+ const parsed = JSON.parse(raw || "{}");
39
+ return parsed && typeof parsed === "object" ? parsed : {};
40
+ }
41
+ catch {
42
+ return {};
43
+ }
44
+ }
45
+ async function writeLocksFile(file, locks) {
46
+ await fs.writeFile(file, JSON.stringify(locks, null, 2) + "\n", "utf8");
47
+ }
48
+ /**
49
+ * Run `fn` against the locks file while holding an exclusive advisory lock on
50
+ * it, so concurrent Live + MCP writers never interleave a read-modify-write.
51
+ */
52
+ async function withLocksFile(projectRoot, fn) {
53
+ const file = await ensureLocksFile(projectRoot);
54
+ const release = await lockfile.lock(file, {
55
+ retries: { retries: 10, factor: 1.5, minTimeout: 20, maxTimeout: 200 },
56
+ stale: 10_000,
57
+ realpath: false,
58
+ });
59
+ try {
60
+ const current = await readLocksFile(file);
61
+ const { result, locks } = await fn(current);
62
+ await writeLocksFile(file, locks);
63
+ return result;
64
+ }
65
+ finally {
66
+ await release();
67
+ }
68
+ }
69
+ function isExpired(entry, now) {
70
+ const expiry = Date.parse(entry.expires_at);
71
+ return Number.isNaN(expiry) || expiry <= now;
72
+ }
73
+ /**
74
+ * Acquire (or take over an expired) write lock for `relPath`.
75
+ *
76
+ * Returns `{ acquired: false, current_holder, expires_at }` when a live,
77
+ * unexpired lock is already held by someone else.
78
+ */
79
+ export async function acquireLock(projectRoot, opts) {
80
+ const holder = opts.holder ?? "claude";
81
+ return withLocksFile(projectRoot, (locks) => {
82
+ const now = Date.now();
83
+ const existing = locks[opts.path];
84
+ if (existing && !isExpired(existing, now)) {
85
+ return {
86
+ result: {
87
+ acquired: false,
88
+ current_holder: existing.holder,
89
+ expires_at: existing.expires_at,
90
+ },
91
+ locks,
92
+ };
93
+ }
94
+ if (existing && isExpired(existing, now)) {
95
+ console.warn(`[layout-context] Taking over stale lock on "${opts.path}" ` +
96
+ `(was held by "${existing.holder}", expired ${existing.expires_at})`);
97
+ }
98
+ const lockId = crypto.randomUUID();
99
+ const acquiredAt = new Date(now).toISOString();
100
+ const expiresAt = new Date(now + opts.ttlSeconds * 1000).toISOString();
101
+ const entry = {
102
+ holder,
103
+ lock_id: lockId,
104
+ acquired_at: acquiredAt,
105
+ expires_at: expiresAt,
106
+ ...(opts.reason ? { reason: opts.reason } : {}),
107
+ };
108
+ return {
109
+ result: { acquired: true, lock_id: lockId, expires_at: expiresAt },
110
+ locks: { ...locks, [opts.path]: entry },
111
+ };
112
+ });
113
+ }
114
+ /**
115
+ * Release a lock by its `lock_id`. Only the matching entry is removed, so a
116
+ * stale `lock_id` from a since-taken-over lock cannot evict the new holder.
117
+ */
118
+ export async function releaseLock(projectRoot, lockId) {
119
+ return withLocksFile(projectRoot, (locks) => {
120
+ const entry = Object.entries(locks).find(([, v]) => v.lock_id === lockId);
121
+ if (!entry) {
122
+ return { result: { released: false }, locks };
123
+ }
124
+ const next = { ...locks };
125
+ delete next[entry[0]];
126
+ return { result: { released: true }, locks: next };
127
+ });
128
+ }
129
+ /** Read the current locks map (best-effort; empty if file absent/corrupt). */
130
+ export async function readLocks(projectRoot) {
131
+ const file = locksPath(projectRoot);
132
+ return readLocksFile(file);
133
+ }
134
+ //# sourceMappingURL=live-lock-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live-lock-store.js","sourceRoot":"","sources":["../../../src/mcp/live-lock-store.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/mcp/server.ts"],"names":[],"mappings":"AA+BA;;;GAGG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAoMjD"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/mcp/server.ts"],"names":[],"mappings":"AAoCA;;;GAGG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAkOjD"}