webstudio 0.274.0 → 0.274.2

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.
@@ -16,7 +16,7 @@ import path, { join, dirname, resolve, sep, normalize as normalize$2, basename,
16
16
  import envPaths from "env-paths";
17
17
  import { z } from "zod";
18
18
  import { randomUUID } from "node:crypto";
19
- import fs, { access, constants, writeFile, mkdir, readFile, rename, rm, copyFile, readdir, cp, mkdtemp } from "node:fs/promises";
19
+ import fs, { access, constants, writeFile, readFile, mkdir, rename, rm, copyFile, readdir, cp, mkdtemp } from "node:fs/promises";
20
20
  import { text, isCancel, cancel, log, spinner, confirm, select as select$1 } from "@clack/prompts";
21
21
  import { createTRPCUntypedClient, httpBatchLink } from "@trpc/client";
22
22
  import { Upload } from "tus-js-client";
@@ -26,9 +26,9 @@ import { constants as constants$1, createWriteStream, existsSync } from "node:fs
26
26
  import { pipeline } from "node:stream/promises";
27
27
  import pLimit from "p-limit";
28
28
  import "warn-once";
29
+ import { isDeepStrictEqual, promisify } from "node:util";
29
30
  import { pathToFileURL, fileURLToPath } from "node:url";
30
31
  import merge from "deepmerge";
31
- import { promisify } from "node:util";
32
32
  import { parseFragment, defaultTreeAdapter } from "parse5";
33
33
  import { kebabCase, camelCase } from "change-case";
34
34
  import reservedIdentifiers from "reserved-identifiers";
@@ -5139,6 +5139,10 @@ const getBundleVersion = (data) => {
5139
5139
  const version2 = data.bundleVersion;
5140
5140
  return typeof version2 === "number" || typeof version2 === "string" ? version2 : void 0;
5141
5141
  };
5142
+ const getBundleVersionMismatchMessage = ({
5143
+ ignoreVersionCheckHint,
5144
+ receivedVersion
5145
+ }) => `Project bundle format is incompatible. Expected version ${bundleVersion}, received ${receivedVersion ?? "missing"}. Sync with a compatible API/CLI version and retry, or ${ignoreVersionCheckHint}.`;
5142
5146
  const publicApiOperationDocumentation = [
5143
5147
  {
5144
5148
  command: "whoami",
@@ -7513,15 +7517,15 @@ const importProjectBundleWithAssets = async (params) => {
7513
7517
  if (missingAssets.length !== assetNames.length) {
7514
7518
  throw error;
7515
7519
  }
7516
- const readAssetData2 = params.skipAssets === true ? void 0 : params.readAssetData;
7517
- if (readAssetData2 === void 0) {
7520
+ const readAssetData = params.skipAssets === true ? void 0 : params.readAssetData;
7521
+ if (readAssetData === void 0) {
7518
7522
  throw error;
7519
7523
  }
7520
7524
  (_c = params.onMissingAssets) == null ? void 0 : _c.call(params, missingAssets);
7521
7525
  await uploadAssets({
7522
7526
  ...params,
7523
7527
  assets: missingAssets,
7524
- readAssetData: readAssetData2
7528
+ readAssetData
7525
7529
  });
7526
7530
  }
7527
7531
  }
@@ -7631,7 +7635,7 @@ class HandledCliError extends Error {
7631
7635
  }
7632
7636
  const isHandledCliError = (error) => error instanceof HandledCliError;
7633
7637
  const name$N = "webstudio";
7634
- const version = "0.274.0";
7638
+ const version = "0.274.2";
7635
7639
  const description = "Webstudio CLI";
7636
7640
  const author = "Webstudio <github@webstudio.is>";
7637
7641
  const homepage = "https://webstudio.is";
@@ -7713,6 +7717,9 @@ const getLocalAssetPath = (assetName, assetsDirectory = LOCAL_ASSETS_DIR) => {
7713
7717
  }
7714
7718
  throw new Error(`Asset path escapes ${assetsDirectory}: ${assetName}`);
7715
7719
  };
7720
+ const createLocalAssetDataReader = (readFile2, assetsDirectory) => async (asset2) => await readFile2(
7721
+ getLocalAssetPath(asset2.name, assetsDirectory)
7722
+ );
7716
7723
  const downloadUrlToFile = async (url, filePath) => {
7717
7724
  const tempFilePath = `${filePath}.tmp`;
7718
7725
  if (await isFileExists(filePath)) {
@@ -7836,7 +7843,7 @@ const resolveApiConnection = async (dependencies2 = defaultApiConnectionDependen
7836
7843
  projectId: localConfig.projectId
7837
7844
  };
7838
7845
  };
7839
- const defaultDependencies$2 = {
7846
+ const defaultDependencies$3 = {
7840
7847
  createFileIfNotExists,
7841
7848
  downloadAssetFiles,
7842
7849
  isFileExists,
@@ -7857,7 +7864,7 @@ const syncOptions = (yargs) => yargs.option("buildId", {
7857
7864
  type: "string",
7858
7865
  describe: "[Experimental] Service token"
7859
7866
  });
7860
- const sync = async (options, dependencies2 = defaultDependencies$2) => {
7867
+ const sync = async (options, dependencies2 = defaultDependencies$3) => {
7861
7868
  const syncing = dependencies2.spinner();
7862
7869
  let project;
7863
7870
  syncing.start(`Synchronizing project bundle`);
@@ -7953,6 +7960,210 @@ const sync = async (options, dependencies2 = defaultDependencies$2) => {
7953
7960
  );
7954
7961
  syncing.stop("Project bundle synchronized successfully");
7955
7962
  };
7963
+ const LOCAL_AUTH_FILE = ".webstudio/auth.json";
7964
+ const createAuthConfigResources = (pages2) => {
7965
+ var _a3;
7966
+ return createWsAuthResources({
7967
+ projectContent: (_a3 = pages2.meta) == null ? void 0 : _a3.auth,
7968
+ pages: getAllPages(pages2).filter((page2) => page2.meta.auth !== void 0).map((page2) => ({
7969
+ route: getPagePath(page2.id, pages2),
7970
+ auth: page2.meta.auth
7971
+ }))
7972
+ });
7973
+ };
7974
+ const createAuthConfigContentFromBundle = (data) => createAuthConfigResources(migratePages(data.build.pages)).content;
7975
+ const assertAuthConfigMatchesBundle = ({
7976
+ authFileContent,
7977
+ data
7978
+ }) => {
7979
+ let actual;
7980
+ try {
7981
+ actual = JSON.parse(authFileContent);
7982
+ } catch {
7983
+ throw new Error(`${LOCAL_AUTH_FILE} is invalid JSON`);
7984
+ }
7985
+ const expected = JSON.parse(createAuthConfigContentFromBundle(data));
7986
+ if (isDeepStrictEqual(actual, expected) === false) {
7987
+ throw new Error(`${LOCAL_AUTH_FILE} does not match .webstudio/data.json`);
7988
+ }
7989
+ };
7990
+ const validateAuthConfigFile = async ({
7991
+ data,
7992
+ filePath
7993
+ }) => {
7994
+ const authFileContent = await readFile(filePath, "utf8").catch((error) => {
7995
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
7996
+ return;
7997
+ }
7998
+ throw error;
7999
+ });
8000
+ if (authFileContent === void 0) {
8001
+ return false;
8002
+ }
8003
+ assertAuthConfigMatchesBundle({ authFileContent, data });
8004
+ return true;
8005
+ };
8006
+ const formatZodIssues = (issues) => issues.map((issue) => {
8007
+ const path2 = issue.path.join(".");
8008
+ return path2 === "" ? issue.message : `${path2}: ${issue.message}`;
8009
+ }).join(", ");
8010
+ const isInteractiveTerminal = () => stdin.isTTY === true && stdout.isTTY === true;
8011
+ const defaultDependencies$2 = {
8012
+ importProjectBundleWithAssets,
8013
+ loadJSONFile,
8014
+ readFile,
8015
+ text,
8016
+ isInteractive: isInteractiveTerminal(),
8017
+ log,
8018
+ spinner
8019
+ };
8020
+ const missingDestinationMessage = "Please specify a destination share link with --to";
8021
+ const missingProjectBundleMessage = "Project bundle is missing. Please run webstudio sync before importing.";
8022
+ const invalidProjectBundleMessage = "Project bundle is invalid. Please run webstudio sync before importing.";
8023
+ const invalidAuthConfigMessage = "Project bundle auth config is invalid. Please run webstudio build before importing.";
8024
+ const invalidDestinationMessage = "Destination share link is invalid.";
8025
+ const importOptions = (yargs) => yargs.option("to", {
8026
+ type: "string",
8027
+ describe: "Share link with build permissions to import synced data into"
8028
+ }).option("assets-dir", {
8029
+ type: "string",
8030
+ default: LOCAL_ASSETS_DIR,
8031
+ describe: "Directory containing local asset files referenced by the bundle"
8032
+ }).option("ignore-version-check", {
8033
+ type: "boolean",
8034
+ describe: "Import data without a compatible data version; import may fail if source and target API data formats differ"
8035
+ }).option("skip-assets", {
8036
+ type: "boolean",
8037
+ describe: "Import project data without uploading or importing asset files; referenced assets may be missing in the target project"
8038
+ }).check((options) => {
8039
+ if (options.to === void 0 && isInteractiveTerminal() === false) {
8040
+ return missingDestinationMessage;
8041
+ }
8042
+ return true;
8043
+ });
8044
+ const importProject = async (options, dependencies2 = defaultDependencies$2) => {
8045
+ const importing = dependencies2.spinner();
8046
+ importing.start("Importing project bundle");
8047
+ if (options.to === void 0 && dependencies2.isInteractive === false) {
8048
+ importing.stop(missingDestinationMessage, 2);
8049
+ throw new HandledCliError();
8050
+ }
8051
+ importing.message(`Reading ${LOCAL_DATA_FILE}`);
8052
+ let data;
8053
+ try {
8054
+ data = await dependencies2.loadJSONFile(
8055
+ join(cwd(), LOCAL_DATA_FILE)
8056
+ );
8057
+ } catch {
8058
+ importing.stop(invalidProjectBundleMessage, 2);
8059
+ throw new HandledCliError();
8060
+ }
8061
+ if (data === null) {
8062
+ importing.stop(missingProjectBundleMessage, 2);
8063
+ throw new HandledCliError();
8064
+ }
8065
+ const localBundleVersion = getBundleVersion(data);
8066
+ if (localBundleVersion !== bundleVersion && options.ignoreVersionCheck !== true) {
8067
+ importing.stop(
8068
+ getBundleVersionMismatchMessage({
8069
+ ignoreVersionCheckHint: "pass --ignore-version-check if you know the source and target data formats are compatible",
8070
+ receivedVersion: localBundleVersion
8071
+ }),
8072
+ 2
8073
+ );
8074
+ throw new HandledCliError();
8075
+ }
8076
+ const parsedData = publishedProjectBundle.safeParse(data);
8077
+ if (parsedData.success === false) {
8078
+ importing.stop(
8079
+ `${invalidProjectBundleMessage} Invalid fields: ${formatZodIssues(
8080
+ parsedData.error.issues
8081
+ )}`,
8082
+ 2
8083
+ );
8084
+ throw new HandledCliError();
8085
+ }
8086
+ const importData = parsedData.data;
8087
+ importing.message(`Reading ${LOCAL_AUTH_FILE}`);
8088
+ try {
8089
+ if (await validateAuthConfigFile({
8090
+ data: importData,
8091
+ filePath: join(cwd(), LOCAL_AUTH_FILE)
8092
+ })) {
8093
+ dependencies2.log.info(`Read ${LOCAL_AUTH_FILE}`);
8094
+ }
8095
+ } catch (error) {
8096
+ importing.stop(
8097
+ error instanceof Error ? `${invalidAuthConfigMessage} ${error.message}` : invalidAuthConfigMessage,
8098
+ 2
8099
+ );
8100
+ throw new HandledCliError();
8101
+ }
8102
+ let destinationShareLink = options.to;
8103
+ if (destinationShareLink === void 0 && dependencies2.isInteractive === true) {
8104
+ importing.stop(`Read ${LOCAL_DATA_FILE}`);
8105
+ const shareLink = await dependencies2.text({
8106
+ message: "Please paste a destination share link with build permissions",
8107
+ validate: validateShareLink
8108
+ });
8109
+ if (isCancel(shareLink)) {
8110
+ cancel("Project import is cancelled");
8111
+ throw new HandledCliError();
8112
+ }
8113
+ destinationShareLink = shareLink;
8114
+ importing.start("Importing project bundle");
8115
+ }
8116
+ if (destinationShareLink === void 0) {
8117
+ importing.stop(missingDestinationMessage, 2);
8118
+ throw new HandledCliError();
8119
+ }
8120
+ let destination;
8121
+ try {
8122
+ destination = parseShareLink(destinationShareLink);
8123
+ } catch {
8124
+ importing.stop(invalidDestinationMessage, 2);
8125
+ throw new HandledCliError();
8126
+ }
8127
+ dependencies2.log.info(`Read ${LOCAL_DATA_FILE}`);
8128
+ dependencies2.log.info(`Destination project: ${destination.projectId}`);
8129
+ dependencies2.log.info(`Destination origin: ${destination.origin}`);
8130
+ const destinationRequest = {
8131
+ projectId: destination.projectId,
8132
+ authToken: destination.token,
8133
+ origin: destination.origin,
8134
+ headers: apiCompatibilityHeaders
8135
+ };
8136
+ try {
8137
+ await dependencies2.importProjectBundleWithAssets({
8138
+ ...destinationRequest,
8139
+ data: importData,
8140
+ ignoreVersionCheck: options.ignoreVersionCheck,
8141
+ ...options.skipAssets === true ? { skipAssets: true } : {
8142
+ readAssetData: createLocalAssetDataReader(
8143
+ dependencies2.readFile,
8144
+ options.assetsDir
8145
+ )
8146
+ },
8147
+ onUploadAssets: (assets) => importing.message(`Uploading ${assets.length} assets`),
8148
+ onMissingAssets: (assets) => importing.message(`Re-uploading ${assets.length} missing assets`),
8149
+ onImportAttempt: () => importing.message(
8150
+ `Waiting for API response while importing into ${destination.projectId}`
8151
+ )
8152
+ });
8153
+ } catch (error) {
8154
+ stopSpinnerWithError(
8155
+ importing,
8156
+ error,
8157
+ "Unable to import project bundle",
8158
+ "import"
8159
+ );
8160
+ throw new HandledCliError();
8161
+ }
8162
+ if (options.skipAssets === true) {
8163
+ dependencies2.log.info("Skipped asset upload and asset rows");
8164
+ }
8165
+ importing.stop("Project imported successfully");
8166
+ };
7956
8167
  const getRemixSegment = (segment) => {
7957
8168
  var _a3, _b2;
7958
8169
  if (segment === "*") {
@@ -8666,17 +8877,6 @@ const generateWebstudioComponent = ({
8666
8877
  `;
8667
8878
  return generatedComponent;
8668
8879
  };
8669
- const LOCAL_AUTH_FILE = ".webstudio/auth.json";
8670
- const createAuthConfigResources = (pages2) => {
8671
- var _a3;
8672
- return createWsAuthResources({
8673
- projectContent: (_a3 = pages2.meta) == null ? void 0 : _a3.auth,
8674
- pages: getAllPages(pages2).filter((page2) => page2.meta.auth !== void 0).map((page2) => ({
8675
- route: getPagePath(page2.id, pages2),
8676
- auth: page2.meta.auth
8677
- }))
8678
- });
8679
- };
8680
8880
  const BOOLEAN_ATTRIBUTES = /* @__PURE__ */ new Set([
8681
8881
  "async",
8682
8882
  "autofocus",
@@ -8788,13 +8988,9 @@ const htmlToJsx = (html2) => {
8788
8988
  }
8789
8989
  return result;
8790
8990
  };
8791
- const formatZodIssues = (issues) => issues.map((issue) => {
8792
- const path2 = issue.path.join(".");
8793
- return path2 === "" ? issue.message : `${path2}: ${issue.message}`;
8794
- }).join(", ");
8795
- const createRemixFramework = async () => (await import("./framework-remix-B05uGrvd.js")).createFramework();
8796
- const createReactRouterFramework = async () => (await import("./framework-react-router-CVBhO7ll.js")).createFramework();
8797
- const createVikeSsgFramework = async () => (await import("./framework-vike-ssg-BOMCgE0f.js")).createFramework();
8991
+ const createRemixFramework = async () => (await import("./framework-remix-KhlqR_BH.js")).createFramework();
8992
+ const createReactRouterFramework = async () => (await import("./framework-react-router-BtDy2QPF.js")).createFramework();
8993
+ const createVikeSsgFramework = async () => (await import("./framework-vike-ssg-De0xD5T4.js")).createFramework();
8798
8994
  const mergeJsonInto = async (sourcePath, destinationPath) => {
8799
8995
  const sourceJson = await readFile(sourcePath, "utf8");
8800
8996
  const destinationJson = await readFile(destinationPath, "utf8").catch(
@@ -10837,10 +11033,38 @@ const previewInputSchema = {
10837
11033
  }
10838
11034
  }
10839
11035
  };
11036
+ const importInputSchema = {
11037
+ ...emptyInputSchema,
11038
+ description: "Import local .webstudio/data.json into another project using a destination share link with build permissions.",
11039
+ properties: {
11040
+ to: {
11041
+ type: "string",
11042
+ description: "Destination Builder share link with build permissions."
11043
+ },
11044
+ assetsDir: {
11045
+ type: "string",
11046
+ description: "Directory containing local asset files referenced by the bundle."
11047
+ },
11048
+ ignoreVersionCheck: {
11049
+ type: "boolean",
11050
+ description: "Import even when local bundle version differs from the current CLI/API contract."
11051
+ },
11052
+ skipAssets: {
11053
+ type: "boolean",
11054
+ description: "Import project data without uploading or importing asset files."
11055
+ }
11056
+ },
11057
+ required: ["to"]
11058
+ };
10840
11059
  const mcpArgumentExamples = {
10841
11060
  "meta.guide": [{ brief: "Create a pricing page and style the hero" }],
10842
11061
  "meta.get_more_tools": [{ brief: "update-styles" }],
10843
11062
  refresh: [{ namespaces: ["pages", "instances", "styles"] }],
11063
+ import: [
11064
+ {
11065
+ to: "https://p-destination-project-id.wstd.dev/?authToken=destination-token"
11066
+ }
11067
+ ],
10844
11068
  "preview.start": [{ host: "127.0.0.1", port: 5173 }],
10845
11069
  "preview.status": [{}],
10846
11070
  "list-pages": [{ includeFolders: true }],
@@ -11113,6 +11337,25 @@ const installOcrTool = {
11113
11337
  retryOnConflict: false
11114
11338
  }
11115
11339
  };
11340
+ const importTool = {
11341
+ name: "import",
11342
+ description: "Import the local synced project bundle into a destination project. Run sync first; pass a destination share link with build permissions.",
11343
+ inputSchema: importInputSchema,
11344
+ mcpExamples: getMcpExamples("import"),
11345
+ annotations: {
11346
+ command: "import",
11347
+ operationId: "project.import",
11348
+ method: "session",
11349
+ permit: "build",
11350
+ inputFields: ["to", "assetsDir", "ignoreVersionCheck", "skipAssets"],
11351
+ localCapable: false,
11352
+ serverOnly: true,
11353
+ readNamespaces: [],
11354
+ writeNamespaces: [],
11355
+ invalidatesNamespaces: [],
11356
+ retryOnConflict: false
11357
+ }
11358
+ };
11116
11359
  const previewTools = [
11117
11360
  {
11118
11361
  name: "preview.start",
@@ -11179,6 +11422,7 @@ const listProjectSessionMcpTools = (operations, options = {}) => [
11179
11422
  ...tool,
11180
11423
  mcpExamples: getMcpExamples(tool.name)
11181
11424
  })),
11425
+ ...options.includeImport ? [importTool] : [],
11182
11426
  ...options.includeScreenshot ? [screenshotTool] : [],
11183
11427
  ...options.includeScreenshotDiff ? [screenshotDiffTool] : [],
11184
11428
  ...options.includeInstallOcr ? [installOcrTool] : [],
@@ -11220,6 +11464,11 @@ const capabilityAreas = [
11220
11464
  "inspect"
11221
11465
  ]
11222
11466
  },
11467
+ {
11468
+ area: "project-lifecycle",
11469
+ goal: "Refresh local project state and move synced project bundles between projects.",
11470
+ tools: ["refresh", "reset-session", "import"]
11471
+ },
11223
11472
  {
11224
11473
  area: "pages",
11225
11474
  goal: "Create, inspect, update, duplicate, delete, and organize pages and folders.",
@@ -11656,10 +11905,26 @@ const getPreviewInput = (input2) => {
11656
11905
  port
11657
11906
  };
11658
11907
  };
11908
+ const getImportInput = (input2) => {
11909
+ if (isRecord(input2) === false) {
11910
+ throw new Error("import input must be an object.");
11911
+ }
11912
+ if (typeof input2.to !== "string" || input2.to.length === 0) {
11913
+ throw new Error("import requires destination share link in to.");
11914
+ }
11915
+ const assetsDir = typeof input2.assetsDir === "string" && input2.assetsDir.length > 0 ? input2.assetsDir : void 0;
11916
+ return {
11917
+ to: input2.to,
11918
+ assetsDir,
11919
+ ignoreVersionCheck: input2.ignoreVersionCheck === true,
11920
+ skipAssets: input2.skipAssets === true
11921
+ };
11922
+ };
11659
11923
  const createProjectSessionMcpCore = ({
11660
11924
  operations,
11661
11925
  createProjectSession: createProjectSession2,
11662
11926
  executeOperation,
11927
+ importProject: importProject2,
11663
11928
  captureScreenshot: captureScreenshot2,
11664
11929
  diffScreenshots,
11665
11930
  installOcr,
@@ -11672,6 +11937,7 @@ const createProjectSessionMcpCore = ({
11672
11937
  operations.map((operation) => operation.command)
11673
11938
  );
11674
11939
  const listTools = () => listProjectSessionMcpTools(operations, {
11940
+ includeImport: importProject2 !== void 0,
11675
11941
  includeScreenshot: captureScreenshot2 !== void 0,
11676
11942
  includeScreenshotDiff: diffScreenshots !== void 0,
11677
11943
  includeInstallOcr: installOcr !== void 0,
@@ -11752,6 +12018,9 @@ const createProjectSessionMcpCore = ({
11752
12018
  const session2 = getSession();
11753
12019
  return toCallResult(await session2.reset());
11754
12020
  }
12021
+ if (name2 === "import" && importProject2 !== void 0) {
12022
+ return toMetaResult(await importProject2(getImportInput(input2)));
12023
+ }
11755
12024
  if (name2 === "screenshot" && captureScreenshot2 !== void 0) {
11756
12025
  return toMetaResult(await captureScreenshot2(getScreenshotInput(input2)));
11757
12026
  }
@@ -11810,6 +12079,7 @@ const createProjectSessionMcpServer = async ({
11810
12079
  operations,
11811
12080
  createProjectSession: createProjectSession2,
11812
12081
  executeOperation,
12082
+ importProject: importProject2,
11813
12083
  captureScreenshot: captureScreenshot2,
11814
12084
  diffScreenshots,
11815
12085
  installOcr,
@@ -11822,6 +12092,7 @@ const createProjectSessionMcpServer = async ({
11822
12092
  operations,
11823
12093
  createProjectSession: createProjectSession2,
11824
12094
  executeOperation,
12095
+ importProject: importProject2,
11825
12096
  captureScreenshot: captureScreenshot2,
11826
12097
  diffScreenshots,
11827
12098
  installOcr,
@@ -11903,7 +12174,7 @@ const createMcpStdioTransport = async ({
11903
12174
  return new StdioServerTransport(stdin2, stdout2);
11904
12175
  };
11905
12176
  const cliDocs = {
11906
- "api-use-cases": '# CLI API Use Cases\n\n## Link/configure one project\n\nCommands:\n\n- webstudio init --link <api-share-link> --json\n\nNotes:\n\n- Writes local project id and global origin/token config.\n\n## Identify current token\n\nCommands:\n\n- MCP tool: whoami {}\n\n## Check token permissions\n\nCommands:\n\n- webstudio permissions --json\n\n## Inspect project/build/version\n\nCommands:\n\n- MCP tool: inspect {}\n- MCP tool: snapshot {"include":["pages","instances","styles"]}\n\n## Discover CLI/API capabilities\n\nCommands:\n\n- webstudio schema api --json\n- webstudio man api --json\n- webstudio man llm --json\n- webstudio man mcp --json\n- MCP tool: meta.index {}\n- MCP tool: meta.guide {"brief":"Create a pricing page"}\n- MCP tool: meta.get_more_tools {"brief":"update-styles"}\n\nNotes:\n\n- Use `tools/list` for machine-readable MCP tool schemas.\n- Use `resources/list` and `resources/read` for longer MCP resources such as `webstudio://project/tools` and `webstudio://project/guide`.\n\n## Inspect and refresh MCP session cache\n\nCommands:\n\n- MCP tool: status {}\n- MCP tool: refresh {"namespaces":["pages","instances","styles"]}\n- MCP tool: reset-session {}\n\nNotes:\n\n- Use status before a task to understand the cached ProjectSession state.\n- Use refresh when project data may have changed outside the current MCP session.\n- Use reset-session when local cached state is corrupt or incompatible.\n\n## Visually verify rendered work with AI vision\n\nCommands:\n\n- MCP tool: preview.start {"host":"127.0.0.1","port":5173}\n- MCP tool: preview.status {}\n- MCP tool: screenshot {"path":"/","output":"current.png","viewport":{"width":1440,"height":900},"waitUntil":"load","waitForTimeout":250}\n- MCP tool: screenshot.diff {"baselinePath":"before.png","currentPath":"current.png","outputDir":".webstudio/screenshots"}\n- MCP tool: vision.install-ocr {"confirm":true}\n\nNotes:\n\n- Use this after page/content/style mutations and after generated project files are current so a vision-capable AI can see what was actually built.\n- Use waitForSelector when the rendered app has a reliable ready marker, waitUntil:"networkidle" for network-heavy pages, and waitForTimeout only for final visual settling.\n- For a fresh checkout, copied fixture, or newly generated app, run npm install or pnpm install in the generated project before preview.start or webstudio preview.\n- If preview fails with a missing generated-app command/package such as react-router or vite, install the generated app dependencies and retry.\n- When a baseline exists, use screenshot.diff to get changed regions, OCR textAnalysis, and diff artifact paths before deciding whether the result matches.\n- If screenshot.diff reports OCR unavailable and the user agrees to install it, call vision.install-ocr {"confirm":true}; otherwise continue with pixel diff and visual inspection.\n- Compare the PNG, OCR text evidence, and diff artifacts against the user\'s intent for layout, typography, colors, spacing, imagery, and responsive framing; then iterate with focused mutations.\n- Root CLI equivalent: webstudio preview --template ssg, then webstudio screenshot <url> --output current.png.\n\n## List pages\n\nCommands:\n\n- MCP tool: list-pages {"includeFolders":true}\n\n## Read page by id\n\nCommands:\n\n- MCP tool: get-page {"pageId":"<pageId>"}\n\n## Read page by path\n\nCommands:\n\n- MCP tool: get-page-by-path {"path":"/pricing"}\n\n## Create page\n\nCommands:\n\n- MCP tool: create-page {"name":"Pricing","path":"/pricing"}\n\n## Update page settings/metadata\n\nCommands:\n\n- MCP tool: update-page {"pageId":"<pageId>","title":"Pricing","description":"Plans","status":"200"}\n- MCP tool: update-page {"pageId":"<pageId>","auth":{"login":"<login>","password":"<password>"}}\n\n## Read project settings\n\nCommands:\n\n- MCP tool: get-project-settings {}\n\n## Update project settings\n\nCommands:\n\n- MCP tool: update-project-settings {"settings":"project-settings.json contents"}\n\n## List redirects\n\nCommands:\n\n- MCP tool: list-redirects {}\n\n## Create redirect\n\nCommands:\n\n- MCP tool: create-redirect {"oldPath":"/old","newPath":"/new","status":301}\n\n## Update redirect\n\nCommands:\n\n- MCP tool: update-redirect {"oldPath":"/old","newPath":"/newer","status":302}\n- MCP tool: update-redirect {"oldPath":"/old","status":null}\n\n## Delete redirect\n\nCommands:\n\n- MCP tool: delete-redirect {"oldPath":"/old"}\n\n## List breakpoints\n\nCommands:\n\n- MCP tool: list-breakpoints {}\n\n## Create breakpoint\n\nCommands:\n\n- MCP tool: create-breakpoint {"breakpointId":"tablet","label":"Tablet","maxWidth":991}\n\n## Update breakpoint\n\nCommands:\n\n- MCP tool: update-breakpoint {"breakpointId":"tablet","label":"Tablet","maxWidth":1023}\n- MCP tool: update-breakpoint {"breakpointId":"tablet","condition":null,"minWidth":768}\n- MCP tool: update-breakpoint {"breakpointId":"tablet","minWidth":null,"maxWidth":null,"condition":"(hover: hover)"}\n\n## Delete breakpoint\n\nCommands:\n\n- MCP tool: delete-breakpoint {"breakpointId":"tablet","confirm":true}\n\n## Duplicate page\n\nCommands:\n\n- MCP tool: duplicate-page {"pageId":"<pageId>","name":"Pricing Copy","path":"/pricing-copy"}\n\n## List page templates\n\nCommands:\n\n- MCP tool: list-page-templates {}\n\n## Create page from template\n\nCommands:\n\n- MCP tool: create-page-from-template {"templateId":"<templateId>","name":"Landing","path":"/landing"}\n\n## Delete page\n\nCommands:\n\n- MCP tool: delete-page {"pageId":"<pageId>"}\n\n## List folders\n\nCommands:\n\n- MCP tool: list-folders {"includePages":true}\n\n## Create folder\n\nCommands:\n\n- MCP tool: create-folder {"name":"Blog","slug":"blog"}\n\n## Update folder\n\nCommands:\n\n- MCP tool: update-folder {"folderId":"<folderId>","name":"Blog","slug":"blog"}\n\n## Delete folder\n\nCommands:\n\n- MCP tool: delete-folder {"folderId":"<folderId>"}\n\n## List element instances\n\nCommands:\n\n- MCP tool: list-instances {"pagePath":"/","maxDepth":3}\n\n## Inspect one element instance\n\nCommands:\n\n- MCP tool: inspect-instance {"instanceId":"<instanceId>","include":["props","styles","children"]}\n\n## Append/prepend/replace child elements\n\nCommands:\n\n- MCP tool: append-instance {"parentInstanceId":"<instanceId>","children":"children.json contents"}\n\n## Move elements\n\nCommands:\n\n- MCP tool: move-instance {"moves":"moves.json contents"}\n\n## Clone element subtree\n\nCommands:\n\n- MCP tool: clone-instance {"sourceInstanceId":"<instanceId>","parentInstanceId":"<targetParentId>"}\n\n## Delete element subtree\n\nCommands:\n\n- MCP tool: delete-instance {"instanceId":"<instanceId>"}\n\n## List text/expression children\n\nCommands:\n\n- MCP tool: list-texts {"pagePath":"/"}\n\n## Update text child\n\nCommands:\n\n- MCP tool: update-text {"instanceId":"<instanceId>","childIndex":0,"text":"Launch faster"}\n\n## Update props\n\nCommands:\n\n- MCP tool: update-props {"updates":"props.json contents"}\n\n## Delete props\n\nCommands:\n\n- MCP tool: delete-props {"deletions":"props.json contents"}\n\n## Bind props to expressions/resources/actions\n\nCommands:\n\n- MCP tool: bind-props {"bindings":"bindings.json contents"}\n\n## Read styles\n\nCommands:\n\n- MCP tool: get-styles {"instanceId":"<instanceId>","includeTokens":true}\n\n## Update local styles\n\nCommands:\n\n- MCP tool: update-styles {"updates":"styles.json contents"}\n\n## Delete local styles\n\nCommands:\n\n- MCP tool: delete-styles {"deletions":"styles.json contents"}\n\n## Replace matching style values\n\nCommands:\n\n- MCP tool: replace-styles {"replacements":"replace.json contents"}\n\n## List design tokens\n\nCommands:\n\n- MCP tool: list-design-tokens {"withUsage":true}\n\n## Create design tokens\n\nCommands:\n\n- MCP tool: create-design-token {"tokens":"tokens.json contents"}\n\n## Update design token styles\n\nCommands:\n\n- MCP tool: update-design-token-styles {"styleSourceId":"<tokenId>","updates":"styles.json contents"}\n\n## Delete design token styles\n\nCommands:\n\n- MCP tool: delete-design-token-styles {"styleSourceId":"<tokenId>","deletions":"styles.json contents"}\n\n## Attach design token to instances\n\nCommands:\n\n- MCP tool: attach-design-token {"styleSourceId":"<tokenId>","instanceIds":"instances.json contents"}\n\n## Detach design token from instances\n\nCommands:\n\n- MCP tool: detach-design-token {"styleSourceId":"<tokenId>","instanceIds":"instances.json contents"}\n\n## Extract design token from local styles\n\nCommands:\n\n- MCP tool: extract-design-token {"token":"token.json contents"}\n\n## List CSS variables\n\nCommands:\n\n- MCP tool: list-css-variables {"withUsage":true}\n\n## Define CSS variables\n\nCommands:\n\n- MCP tool: define-css-variable {"variables":"vars.json contents"}\n\n## Delete CSS variables\n\nCommands:\n\n- MCP tool: delete-css-variable {"names":"names.json contents","confirm":true}\n\n## Rewrite CSS variable references\n\nCommands:\n\n- MCP tool: rewrite-css-variable-refs {"variables":"variables.json contents"}\n\n## List data variables\n\nCommands:\n\n- MCP tool: list-variables {}\n\n## Create data variable\n\nCommands:\n\n- MCP tool: create-variable {"scopeInstanceId":"<instanceId>","name":"title","value":{"type":"string","value":"Hello"}}\n\n## Update data variable\n\nCommands:\n\n- MCP tool: update-variable {"variableId":"<variableId>","value":{"type":"json","value":{"count":1}}}\n\n## Delete data variable\n\nCommands:\n\n- MCP tool: delete-variable {"variableId":"<variableId>"}\n\n## List resources\n\nCommands:\n\n- MCP tool: list-resources {}\n\n## Create resource\n\nCommands:\n\n- MCP tool: create-resource {"name":"Posts","method":"get","url":"https://api.example.com/posts"}\n\n## Update resource\n\nCommands:\n\n- MCP tool: update-resource {"resourceId":"<resourceId>","url":"https://api.example.com/posts"}\n\n## Delete resource\n\nCommands:\n\n- MCP tool: delete-resource {"resourceId":"<resourceId>"}\n\n## List assets\n\nCommands:\n\n- MCP tool: list-assets {"withUsage":true}\n\n## Upload one asset\n\nCommands:\n\n- MCP tool: upload-asset {"asset":"asset.json contents","assetsDir":".webstudio/assets"}\n\n## Upload asset batch\n\nCommands:\n\n- MCP tool: upload-assets {"assets":"assets.json contents","assetsDir":".webstudio/assets"}\n\n## Find asset usage\n\nCommands:\n\n- MCP tool: find-asset-usage {"assetId":"<assetId>"}\n\n## Replace asset references\n\nCommands:\n\n- MCP tool: replace-asset {"fromAssetId":"<oldAssetId>","toAssetId":"<newAssetId>","confirm":true}\n\n## Delete assets\n\nCommands:\n\n- MCP tool: delete-asset {"assetId":"<assetId>","confirm":true}\n\n## Publish project\n\nCommands:\n\n- webstudio publish deploy --target production --json\n\n## List publishes\n\nCommands:\n\n- webstudio publish list --json\n\n## Check publish job\n\nCommands:\n\n- webstudio publish status --job <buildId> --json\n\n## Unpublish\n\nCommands:\n\n- webstudio publish unpublish --target production --confirm --json\n\n## List domains\n\nCommands:\n\n- webstudio domains list --json\n\n## Create domain\n\nCommands:\n\n- webstudio domains create --domain example.com --json\n\n## Update domain\n\nCommands:\n\n- webstudio domains update --domain-id <domainId> --domain www.example.com --json\n\n## Delete domain\n\nCommands:\n\n- webstudio domains delete --domain-id <domainId> --confirm --json\n\n## Verify domain\n\nCommands:\n\n- webstudio domains verify --domain-id <domainId> --json\n\n## Make arbitrary store-level changes\n\nCommands:\n\n- MCP tool: inspect {}\n- MCP tool: snapshot {"include":["<namespace>"]}\n- MCP tool: apply-patch {"baseVersion":"<version>","transactions":"patch.json contents"}\n\nNotes:\n\n- Use only when no semantic command exists.\n\n## Manage marketplace metadata\n\nCommands:\n\n- MCP tool: snapshot {"include":["marketplaceProduct"]}\n- MCP tool: apply-patch {"baseVersion":"<version>","transactions":"patch.json contents"}\n\nPatch namespaces:\n\n- marketplaceProduct\n\n## Search and inspect safely\n\nCommands:\n\n- MCP tool: list-instances {"pagePath":"/","maxDepth":5}\n- MCP tool: inspect-instance {"instanceId":"<instanceId>","include":["props","styles","children"]}\n- MCP tool: list-texts {"pagePath":"/"}\n- MCP tool: list-assets {"withUsage":true}\n- MCP tool: find-asset-usage {"assetId":"<assetId>"}\n- MCP tool: snapshot {"include":["pages","instances","props","resources","assets"]}\n\nNotes:\n\n- Use this for finding elements by label, type, href/resource patterns, HTML snippets, missing accessibility metadata, or asset usage.\n\n## Refactor targeted content\n\nCommands:\n\n- MCP tool: list-instances {"pagePath":"/"}\n- MCP tool: list-texts {"pagePath":"/"}\n- MCP tool: update-text {"instanceId":"<instanceId>","childIndex":0,"text":"Launch faster"}\n- MCP tool: update-props {"updates":"props.json contents"}\n- MCP tool: update-page {"pageId":"<pageId>","title":"Pricing","description":"Plans"}\n- MCP tool: update-resource {"resourceId":"<resourceId>","url":"https://api.example.com/posts"}\n- MCP tool: replace-asset {"fromAssetId":"<oldAssetId>","toAssetId":"<newAssetId>","confirm":true}\n- MCP tool: replace-styles {"replacements":"replace.json contents"}\n- MCP tool: rewrite-css-variable-refs {"variables":"variables.json contents"}\n\nNotes:\n\n- Use focused reads first, then mutate only matching instances, props, metadata, resource URLs, assets, or style references.\n\n## Optimize existing project\n\nCommands:\n\n- MCP tool: list-pages {"includeFolders":true}\n- MCP tool: update-page {"pageId":"<pageId>","title":"Pricing","description":"Plans"}\n- MCP tool: update-props {"updates":"props.json contents"}\n- MCP tool: list-breakpoints {}\n- MCP tool: update-breakpoint {"breakpointId":"tablet","maxWidth":1023}\n- MCP tool: get-styles {"instanceId":"<instanceId>","includeTokens":true}\n- MCP tool: update-styles {"updates":"styles.json contents"}\n- MCP tool: attach-design-token {"styleSourceId":"<tokenId>","instanceIds":"instances.json contents"}\n- MCP tool: update-project-settings {"settings":"project-settings.json contents"}\n\nNotes:\n\n- Use this for SEO metadata, accessibility labels, responsive behavior, token consistency, and project settings.\n\n## Connect external data\n\nCommands:\n\n- MCP tool: create-variable {"scopeInstanceId":"<instanceId>","name":"title","value":{"type":"string","value":"Hello"}}\n- MCP tool: create-resource {"name":"Posts","method":"get","url":"https://api.example.com/posts"}\n- MCP tool: update-resource {"resourceId":"<resourceId>","url":"https://api.example.com/posts"}\n- MCP tool: bind-props {"bindings":"bindings.json contents"}\n- MCP tool: append-instance {"parentInstanceId":"<instanceId>","children":"children.json contents"}\n\nNotes:\n\n- Use this for CMS sections, blog listings, Ghost/headless CMS pages, n8n-style integrations, and API URLs built from variables.\n\n## Support dynamic runtime behavior\n\nCommands:\n\n- MCP tool: append-instance {"parentInstanceId":"<instanceId>","children":"children.json contents"}\n- MCP tool: update-props {"updates":"props.json contents"}\n- MCP tool: bind-props {"bindings":"bindings.json contents"}\n- MCP tool: create-resource {"name":"Seats","method":"get","url":"https://api.example.com/seats"}\n- MCP tool: snapshot {"include":["instances","props","resources"]}\n- MCP tool: apply-patch {"baseVersion":"<version>","transactions":"patch.json contents"}\n\nNotes:\n\n- Use existing scripts/resources for behavior, then move presentational structure into editable Webstudio instances where possible.\n- There is no dedicated semantic command yet for converting script-generated UI into editable Webstudio structure.\n\n## Build authenticated pages\n\nCommands:\n\n- MCP tool: create-page {"name":"Account","path":"/account"}\n- MCP tool: update-page {"pageId":"<pageId>","auth":{"login":"<login>","password":"<password>"}}\n- MCP tool: create-resource {"name":"Session","method":"get","url":"https://api.example.com/session"}\n- MCP tool: create-variable {"scopeInstanceId":"<instanceId>","name":"user","value":{"type":"json","value":{}}}\n- MCP tool: update-props {"updates":"props.json contents"}\n- MCP tool: bind-props {"bindings":"bindings.json contents"}\n\nNotes:\n\n- Basic auth is semantic today. Provider-specific Supabase/Firebase setup still requires manual resources, props, embeds, or patches.\n\n## Generate from design input\n\nCommands:\n\n- MCP tool: create-page {"name":"Landing","path":"/landing"}\n- MCP tool: create-design-token {"tokens":"tokens.json contents"}\n- MCP tool: define-css-variable {"variables":"vars.json contents"}\n- MCP tool: append-instance {"parentInstanceId":"<instanceId>","children":"children.json contents"}\n- MCP tool: update-styles {"updates":"styles.json contents"}\n- MCP tool: preview.start {"host":"127.0.0.1","port":5173}\n- MCP tool: screenshot {"path":"/","output":"current.png","viewport":{"width":1440,"height":900},"waitUntil":"load","waitForTimeout":250}\n\nNotes:\n\n- Use this after external design interpretation. There is no dedicated import command for Figma, screenshots, Inception output, or design.md yet.\n\n## Cross-project maintenance\n\nCommands:\n\n- webstudio init --link <api-share-link> --json\n- webstudio permissions --json\n- webstudio mcp\n\nNotes:\n\n- Public API and CLI intentionally operate on one configured project at a time. Use an external script to loop over projects.\n\n# Known CLI Gaps\n\n## General project search and audit\n\nMissing:\nNo single semantic command searches across instance labels, props, hrefs, resource URLs, HTML embeds, asset references, and missing accessibility metadata.\n\nCurrent fallback:\nUse focused MCP reads such as list-instances, list-texts, list-assets, find-asset-usage, and snapshot.\n\nSuggested commands:\n\n- search-project\n- audit-accessibility\n- find-prop-usage\n\n## Save and manage page templates\n\nMissing:\nCLI can list page templates and create pages from existing templates, but cannot save a page as a template or update/delete templates semantically.\n\nCurrent fallback:\nUse MCP snapshot and apply-patch only when the template data model is understood.\n\nSuggested commands:\n\n- create-page-template\n- update-page-template\n- delete-page-template\n\n## Semantic marketplace metadata\n\nMissing:\nMarketplace metadata is only available through MCP snapshot/apply-patch, not dedicated semantic commands.\n\nCurrent fallback:\nUse MCP snapshot --include marketplaceProduct and apply-patch.\n\nSuggested commands:\n\n- get-marketplace\n- update-marketplace\n\n## Provider-specific authenticated pages\n\nMissing:\nCLI supports page basic auth and generic resources/props/embeds, but not guided Supabase/Firebase auth setup.\n\nCurrent fallback:\nCreate the page, resources, variables, props, and embeds manually with existing MCP semantic tools.\n\nSuggested commands:\n\n- setup-auth-page\n\n## Dynamic script/runtime integration helpers\n\nMissing:\nCLI can manipulate props/resources/embeds, but has no semantic workflow for converting script-generated UI into editable Webstudio structures.\n\nCurrent fallback:\nUse MCP append-instance, props, resources, and raw patch where necessary.\n\nSuggested commands:\n\n- integrate-runtime-ui\n\n## Generate from design input\n\nMissing:\nNo command imports Figma, screenshots, Inception output, or design.md and turns it into pages/tokens/layout.\n\nCurrent fallback:\nUse external generation, then apply semantic CLI commands or apply-patch.\n\nSuggested commands:\n\n- generate-from-design\n\n## Built-in cross-project maintenance\n\nMissing:\nPublic API and CLI intentionally operate on one configured project at a time; there is no built-in multi-project discovery or loop runner.\n\nCurrent fallback:\nRun the CLI from an external script that reconfigures one project/session at a time.\n\nSuggested commands:\n\n- none\n',
12177
+ "api-use-cases": '# CLI API Use Cases\n\n## Link/configure one project\n\nCommands:\n\n- webstudio init --link <api-share-link> --json\n\nNotes:\n\n- Writes local project id and global origin/token config.\n\n## Import synced project bundle into another project\n\nCommands:\n\n- webstudio sync\n- webstudio import --to <destination-share-link>\n- MCP tool: import {"to":"<destination-share-link>"}\n\nNotes:\n\n- Imports local `.webstudio/data.json` into the destination project.\n- Destination share link must allow build/import access.\n- Use `--skip-assets` only when asset rows and files should not be imported.\n\n## Identify current token\n\nCommands:\n\n- MCP tool: whoami {}\n\n## Check token permissions\n\nCommands:\n\n- webstudio permissions --json\n\n## Inspect project/build/version\n\nCommands:\n\n- MCP tool: inspect {}\n- MCP tool: snapshot {"include":["pages","instances","styles"]}\n\n## Discover CLI/API capabilities\n\nCommands:\n\n- webstudio schema api --json\n- webstudio man api --json\n- webstudio man llm --json\n- webstudio man mcp --json\n- MCP tool: meta.index {}\n- MCP tool: meta.guide {"brief":"Create a pricing page"}\n- MCP tool: meta.get_more_tools {"brief":"update-styles"}\n\nNotes:\n\n- Use `tools/list` for machine-readable MCP tool schemas.\n- Use `resources/list` and `resources/read` for longer MCP resources such as `webstudio://project/tools` and `webstudio://project/guide`.\n\n## Inspect and refresh MCP session cache\n\nCommands:\n\n- MCP tool: status {}\n- MCP tool: refresh {"namespaces":["pages","instances","styles"]}\n- MCP tool: reset-session {}\n\nNotes:\n\n- Use status before a task to understand the cached ProjectSession state.\n- Use refresh when project data may have changed outside the current MCP session.\n- Use reset-session when local cached state is corrupt or incompatible.\n\n## Visually verify rendered work with AI vision\n\nCommands:\n\n- MCP tool: preview.start {"host":"127.0.0.1","port":5173}\n- MCP tool: preview.status {}\n- MCP tool: screenshot {"path":"/","output":"current.png","viewport":{"width":1440,"height":900},"waitUntil":"load","waitForTimeout":250}\n- MCP tool: screenshot.diff {"baselinePath":"before.png","currentPath":"current.png","outputDir":".webstudio/screenshots"}\n- MCP tool: vision.install-ocr {"confirm":true}\n\nNotes:\n\n- Use this after page/content/style mutations and after generated project files are current so a vision-capable AI can see what was actually built.\n- Use waitForSelector when the rendered app has a reliable ready marker, waitUntil:"networkidle" for network-heavy pages, and waitForTimeout only for final visual settling.\n- For a fresh checkout, copied fixture, or newly generated app, run npm install or pnpm install in the generated project before preview.start or webstudio preview.\n- If preview fails with a missing generated-app command/package such as react-router or vite, install the generated app dependencies and retry.\n- When a baseline exists, use screenshot.diff to get changed regions, OCR textAnalysis, and diff artifact paths before deciding whether the result matches.\n- If screenshot.diff reports OCR unavailable and the user agrees to install it, call vision.install-ocr {"confirm":true}; otherwise continue with pixel diff and visual inspection.\n- Compare the PNG, OCR text evidence, and diff artifacts against the user\'s intent for layout, typography, colors, spacing, imagery, and responsive framing; then iterate with focused mutations.\n- Root CLI equivalent: webstudio preview --template ssg, then webstudio screenshot <url> --output current.png.\n\n## List pages\n\nCommands:\n\n- MCP tool: list-pages {"includeFolders":true}\n\n## Read page by id\n\nCommands:\n\n- MCP tool: get-page {"pageId":"<pageId>"}\n\n## Read page by path\n\nCommands:\n\n- MCP tool: get-page-by-path {"path":"/pricing"}\n\n## Create page\n\nCommands:\n\n- MCP tool: create-page {"name":"Pricing","path":"/pricing"}\n\n## Update page settings/metadata\n\nCommands:\n\n- MCP tool: update-page {"pageId":"<pageId>","title":"Pricing","description":"Plans","status":"200"}\n- MCP tool: update-page {"pageId":"<pageId>","auth":{"login":"<login>","password":"<password>"}}\n\n## Read project settings\n\nCommands:\n\n- MCP tool: get-project-settings {}\n\n## Update project settings\n\nCommands:\n\n- MCP tool: update-project-settings {"settings":"project-settings.json contents"}\n\n## List redirects\n\nCommands:\n\n- MCP tool: list-redirects {}\n\n## Create redirect\n\nCommands:\n\n- MCP tool: create-redirect {"oldPath":"/old","newPath":"/new","status":301}\n\n## Update redirect\n\nCommands:\n\n- MCP tool: update-redirect {"oldPath":"/old","newPath":"/newer","status":302}\n- MCP tool: update-redirect {"oldPath":"/old","status":null}\n\n## Delete redirect\n\nCommands:\n\n- MCP tool: delete-redirect {"oldPath":"/old"}\n\n## List breakpoints\n\nCommands:\n\n- MCP tool: list-breakpoints {}\n\n## Create breakpoint\n\nCommands:\n\n- MCP tool: create-breakpoint {"breakpointId":"tablet","label":"Tablet","maxWidth":991}\n\n## Update breakpoint\n\nCommands:\n\n- MCP tool: update-breakpoint {"breakpointId":"tablet","label":"Tablet","maxWidth":1023}\n- MCP tool: update-breakpoint {"breakpointId":"tablet","condition":null,"minWidth":768}\n- MCP tool: update-breakpoint {"breakpointId":"tablet","minWidth":null,"maxWidth":null,"condition":"(hover: hover)"}\n\n## Delete breakpoint\n\nCommands:\n\n- MCP tool: delete-breakpoint {"breakpointId":"tablet","confirm":true}\n\n## Duplicate page\n\nCommands:\n\n- MCP tool: duplicate-page {"pageId":"<pageId>","name":"Pricing Copy","path":"/pricing-copy"}\n\n## List page templates\n\nCommands:\n\n- MCP tool: list-page-templates {}\n\n## Create page from template\n\nCommands:\n\n- MCP tool: create-page-from-template {"templateId":"<templateId>","name":"Landing","path":"/landing"}\n\n## Delete page\n\nCommands:\n\n- MCP tool: delete-page {"pageId":"<pageId>"}\n\n## List folders\n\nCommands:\n\n- MCP tool: list-folders {"includePages":true}\n\n## Create folder\n\nCommands:\n\n- MCP tool: create-folder {"name":"Blog","slug":"blog"}\n\n## Update folder\n\nCommands:\n\n- MCP tool: update-folder {"folderId":"<folderId>","name":"Blog","slug":"blog"}\n\n## Delete folder\n\nCommands:\n\n- MCP tool: delete-folder {"folderId":"<folderId>"}\n\n## List element instances\n\nCommands:\n\n- MCP tool: list-instances {"pagePath":"/","maxDepth":3}\n\n## Inspect one element instance\n\nCommands:\n\n- MCP tool: inspect-instance {"instanceId":"<instanceId>","include":["props","styles","children"]}\n\n## Append/prepend/replace child elements\n\nCommands:\n\n- MCP tool: append-instance {"parentInstanceId":"<instanceId>","children":"children.json contents"}\n\n## Move elements\n\nCommands:\n\n- MCP tool: move-instance {"moves":"moves.json contents"}\n\n## Clone element subtree\n\nCommands:\n\n- MCP tool: clone-instance {"sourceInstanceId":"<instanceId>","parentInstanceId":"<targetParentId>"}\n\n## Delete element subtree\n\nCommands:\n\n- MCP tool: delete-instance {"instanceId":"<instanceId>"}\n\n## List text/expression children\n\nCommands:\n\n- MCP tool: list-texts {"pagePath":"/"}\n\n## Update text child\n\nCommands:\n\n- MCP tool: update-text {"instanceId":"<instanceId>","childIndex":0,"text":"Launch faster"}\n\n## Update props\n\nCommands:\n\n- MCP tool: update-props {"updates":"props.json contents"}\n\n## Delete props\n\nCommands:\n\n- MCP tool: delete-props {"deletions":"props.json contents"}\n\n## Bind props to expressions/resources/actions\n\nCommands:\n\n- MCP tool: bind-props {"bindings":"bindings.json contents"}\n\n## Read styles\n\nCommands:\n\n- MCP tool: get-styles {"instanceId":"<instanceId>","includeTokens":true}\n\n## Update local styles\n\nCommands:\n\n- MCP tool: update-styles {"updates":"styles.json contents"}\n\n## Delete local styles\n\nCommands:\n\n- MCP tool: delete-styles {"deletions":"styles.json contents"}\n\n## Replace matching style values\n\nCommands:\n\n- MCP tool: replace-styles {"replacements":"replace.json contents"}\n\n## List design tokens\n\nCommands:\n\n- MCP tool: list-design-tokens {"withUsage":true}\n\n## Create design tokens\n\nCommands:\n\n- MCP tool: create-design-token {"tokens":"tokens.json contents"}\n\n## Update design token styles\n\nCommands:\n\n- MCP tool: update-design-token-styles {"styleSourceId":"<tokenId>","updates":"styles.json contents"}\n\n## Delete design token styles\n\nCommands:\n\n- MCP tool: delete-design-token-styles {"styleSourceId":"<tokenId>","deletions":"styles.json contents"}\n\n## Attach design token to instances\n\nCommands:\n\n- MCP tool: attach-design-token {"styleSourceId":"<tokenId>","instanceIds":"instances.json contents"}\n\n## Detach design token from instances\n\nCommands:\n\n- MCP tool: detach-design-token {"styleSourceId":"<tokenId>","instanceIds":"instances.json contents"}\n\n## Extract design token from local styles\n\nCommands:\n\n- MCP tool: extract-design-token {"token":"token.json contents"}\n\n## List CSS variables\n\nCommands:\n\n- MCP tool: list-css-variables {"withUsage":true}\n\n## Define CSS variables\n\nCommands:\n\n- MCP tool: define-css-variable {"variables":"vars.json contents"}\n\n## Delete CSS variables\n\nCommands:\n\n- MCP tool: delete-css-variable {"names":"names.json contents","confirm":true}\n\n## Rewrite CSS variable references\n\nCommands:\n\n- MCP tool: rewrite-css-variable-refs {"variables":"variables.json contents"}\n\n## List data variables\n\nCommands:\n\n- MCP tool: list-variables {}\n\n## Create data variable\n\nCommands:\n\n- MCP tool: create-variable {"scopeInstanceId":"<instanceId>","name":"title","value":{"type":"string","value":"Hello"}}\n\n## Update data variable\n\nCommands:\n\n- MCP tool: update-variable {"variableId":"<variableId>","value":{"type":"json","value":{"count":1}}}\n\n## Delete data variable\n\nCommands:\n\n- MCP tool: delete-variable {"variableId":"<variableId>"}\n\n## List resources\n\nCommands:\n\n- MCP tool: list-resources {}\n\n## Create resource\n\nCommands:\n\n- MCP tool: create-resource {"name":"Posts","method":"get","url":"https://api.example.com/posts"}\n\n## Update resource\n\nCommands:\n\n- MCP tool: update-resource {"resourceId":"<resourceId>","url":"https://api.example.com/posts"}\n\n## Delete resource\n\nCommands:\n\n- MCP tool: delete-resource {"resourceId":"<resourceId>"}\n\n## List assets\n\nCommands:\n\n- MCP tool: list-assets {"withUsage":true}\n\n## Upload one asset\n\nCommands:\n\n- MCP tool: upload-asset {"asset":"asset.json contents","assetsDir":".webstudio/assets"}\n\n## Upload asset batch\n\nCommands:\n\n- MCP tool: upload-assets {"assets":"assets.json contents","assetsDir":".webstudio/assets"}\n\n## Find asset usage\n\nCommands:\n\n- MCP tool: find-asset-usage {"assetId":"<assetId>"}\n\n## Replace asset references\n\nCommands:\n\n- MCP tool: replace-asset {"fromAssetId":"<oldAssetId>","toAssetId":"<newAssetId>","confirm":true}\n\n## Delete assets\n\nCommands:\n\n- MCP tool: delete-asset {"assetId":"<assetId>","confirm":true}\n\n## Publish project\n\nCommands:\n\n- webstudio publish deploy --target production --json\n\n## List publishes\n\nCommands:\n\n- webstudio publish list --json\n\n## Check publish job\n\nCommands:\n\n- webstudio publish status --job <buildId> --json\n\n## Unpublish\n\nCommands:\n\n- webstudio publish unpublish --target production --confirm --json\n\n## List domains\n\nCommands:\n\n- webstudio domains list --json\n\n## Create domain\n\nCommands:\n\n- webstudio domains create --domain example.com --json\n\n## Update domain\n\nCommands:\n\n- webstudio domains update --domain-id <domainId> --domain www.example.com --json\n\n## Delete domain\n\nCommands:\n\n- webstudio domains delete --domain-id <domainId> --confirm --json\n\n## Verify domain\n\nCommands:\n\n- webstudio domains verify --domain-id <domainId> --json\n\n## Make arbitrary store-level changes\n\nCommands:\n\n- MCP tool: inspect {}\n- MCP tool: snapshot {"include":["<namespace>"]}\n- MCP tool: apply-patch {"baseVersion":"<version>","transactions":"patch.json contents"}\n\nNotes:\n\n- Use only when no semantic command exists.\n\n## Manage marketplace metadata\n\nCommands:\n\n- MCP tool: snapshot {"include":["marketplaceProduct"]}\n- MCP tool: apply-patch {"baseVersion":"<version>","transactions":"patch.json contents"}\n\nPatch namespaces:\n\n- marketplaceProduct\n\n## Search and inspect safely\n\nCommands:\n\n- MCP tool: list-instances {"pagePath":"/","maxDepth":5}\n- MCP tool: inspect-instance {"instanceId":"<instanceId>","include":["props","styles","children"]}\n- MCP tool: list-texts {"pagePath":"/"}\n- MCP tool: list-assets {"withUsage":true}\n- MCP tool: find-asset-usage {"assetId":"<assetId>"}\n- MCP tool: snapshot {"include":["pages","instances","props","resources","assets"]}\n\nNotes:\n\n- Use this for finding elements by label, type, href/resource patterns, HTML snippets, missing accessibility metadata, or asset usage.\n\n## Refactor targeted content\n\nCommands:\n\n- MCP tool: list-instances {"pagePath":"/"}\n- MCP tool: list-texts {"pagePath":"/"}\n- MCP tool: update-text {"instanceId":"<instanceId>","childIndex":0,"text":"Launch faster"}\n- MCP tool: update-props {"updates":"props.json contents"}\n- MCP tool: update-page {"pageId":"<pageId>","title":"Pricing","description":"Plans"}\n- MCP tool: update-resource {"resourceId":"<resourceId>","url":"https://api.example.com/posts"}\n- MCP tool: replace-asset {"fromAssetId":"<oldAssetId>","toAssetId":"<newAssetId>","confirm":true}\n- MCP tool: replace-styles {"replacements":"replace.json contents"}\n- MCP tool: rewrite-css-variable-refs {"variables":"variables.json contents"}\n\nNotes:\n\n- Use focused reads first, then mutate only matching instances, props, metadata, resource URLs, assets, or style references.\n\n## Optimize existing project\n\nCommands:\n\n- MCP tool: list-pages {"includeFolders":true}\n- MCP tool: update-page {"pageId":"<pageId>","title":"Pricing","description":"Plans"}\n- MCP tool: update-props {"updates":"props.json contents"}\n- MCP tool: list-breakpoints {}\n- MCP tool: update-breakpoint {"breakpointId":"tablet","maxWidth":1023}\n- MCP tool: get-styles {"instanceId":"<instanceId>","includeTokens":true}\n- MCP tool: update-styles {"updates":"styles.json contents"}\n- MCP tool: attach-design-token {"styleSourceId":"<tokenId>","instanceIds":"instances.json contents"}\n- MCP tool: update-project-settings {"settings":"project-settings.json contents"}\n\nNotes:\n\n- Use this for SEO metadata, accessibility labels, responsive behavior, token consistency, and project settings.\n\n## Connect external data\n\nCommands:\n\n- MCP tool: create-variable {"scopeInstanceId":"<instanceId>","name":"title","value":{"type":"string","value":"Hello"}}\n- MCP tool: create-resource {"name":"Posts","method":"get","url":"https://api.example.com/posts"}\n- MCP tool: update-resource {"resourceId":"<resourceId>","url":"https://api.example.com/posts"}\n- MCP tool: bind-props {"bindings":"bindings.json contents"}\n- MCP tool: append-instance {"parentInstanceId":"<instanceId>","children":"children.json contents"}\n\nNotes:\n\n- Use this for CMS sections, blog listings, Ghost/headless CMS pages, n8n-style integrations, and API URLs built from variables.\n\n## Support dynamic runtime behavior\n\nCommands:\n\n- MCP tool: append-instance {"parentInstanceId":"<instanceId>","children":"children.json contents"}\n- MCP tool: update-props {"updates":"props.json contents"}\n- MCP tool: bind-props {"bindings":"bindings.json contents"}\n- MCP tool: create-resource {"name":"Seats","method":"get","url":"https://api.example.com/seats"}\n- MCP tool: snapshot {"include":["instances","props","resources"]}\n- MCP tool: apply-patch {"baseVersion":"<version>","transactions":"patch.json contents"}\n\nNotes:\n\n- Use existing scripts/resources for behavior, then move presentational structure into editable Webstudio instances where possible.\n- There is no dedicated semantic command yet for converting script-generated UI into editable Webstudio structure.\n\n## Build authenticated pages\n\nCommands:\n\n- MCP tool: create-page {"name":"Account","path":"/account"}\n- MCP tool: update-page {"pageId":"<pageId>","auth":{"login":"<login>","password":"<password>"}}\n- MCP tool: create-resource {"name":"Session","method":"get","url":"https://api.example.com/session"}\n- MCP tool: create-variable {"scopeInstanceId":"<instanceId>","name":"user","value":{"type":"json","value":{}}}\n- MCP tool: update-props {"updates":"props.json contents"}\n- MCP tool: bind-props {"bindings":"bindings.json contents"}\n\nNotes:\n\n- Basic auth is semantic today. Provider-specific Supabase/Firebase setup still requires manual resources, props, embeds, or patches.\n\n## Generate from design input\n\nCommands:\n\n- MCP tool: create-page {"name":"Landing","path":"/landing"}\n- MCP tool: create-design-token {"tokens":"tokens.json contents"}\n- MCP tool: define-css-variable {"variables":"vars.json contents"}\n- MCP tool: append-instance {"parentInstanceId":"<instanceId>","children":"children.json contents"}\n- MCP tool: update-styles {"updates":"styles.json contents"}\n- MCP tool: preview.start {"host":"127.0.0.1","port":5173}\n- MCP tool: screenshot {"path":"/","output":"current.png","viewport":{"width":1440,"height":900},"waitUntil":"load","waitForTimeout":250}\n\nNotes:\n\n- Use this after external design interpretation. There is no dedicated import command for Figma, screenshots, Inception output, or design.md yet.\n\n## Cross-project maintenance\n\nCommands:\n\n- webstudio init --link <api-share-link> --json\n- webstudio permissions --json\n- webstudio mcp\n\nNotes:\n\n- Public API and CLI intentionally operate on one configured project at a time. Use an external script to loop over projects.\n\n# Known CLI Gaps\n\n## General project search and audit\n\nMissing:\nNo single semantic command searches across instance labels, props, hrefs, resource URLs, HTML embeds, asset references, and missing accessibility metadata.\n\nCurrent fallback:\nUse focused MCP reads such as list-instances, list-texts, list-assets, find-asset-usage, and snapshot.\n\nSuggested commands:\n\n- search-project\n- audit-accessibility\n- find-prop-usage\n\n## Save and manage page templates\n\nMissing:\nCLI can list page templates and create pages from existing templates, but cannot save a page as a template or update/delete templates semantically.\n\nCurrent fallback:\nUse MCP snapshot and apply-patch only when the template data model is understood.\n\nSuggested commands:\n\n- create-page-template\n- update-page-template\n- delete-page-template\n\n## Semantic marketplace metadata\n\nMissing:\nMarketplace metadata is only available through MCP snapshot/apply-patch, not dedicated semantic commands.\n\nCurrent fallback:\nUse MCP snapshot --include marketplaceProduct and apply-patch.\n\nSuggested commands:\n\n- get-marketplace\n- update-marketplace\n\n## Provider-specific authenticated pages\n\nMissing:\nCLI supports page basic auth and generic resources/props/embeds, but not guided Supabase/Firebase auth setup.\n\nCurrent fallback:\nCreate the page, resources, variables, props, and embeds manually with existing MCP semantic tools.\n\nSuggested commands:\n\n- setup-auth-page\n\n## Dynamic script/runtime integration helpers\n\nMissing:\nCLI can manipulate props/resources/embeds, but has no semantic workflow for converting script-generated UI into editable Webstudio structures.\n\nCurrent fallback:\nUse MCP append-instance, props, resources, and raw patch where necessary.\n\nSuggested commands:\n\n- integrate-runtime-ui\n\n## Generate from design input\n\nMissing:\nNo command imports Figma, screenshots, Inception output, or design.md and turns it into pages/tokens/layout.\n\nCurrent fallback:\nUse external generation, then apply semantic CLI commands or apply-patch.\n\nSuggested commands:\n\n- generate-from-design\n\n## Built-in cross-project maintenance\n\nMissing:\nPublic API and CLI intentionally operate on one configured project at a time; there is no built-in multi-project discovery or loop runner.\n\nCurrent fallback:\nRun the CLI from an external script that reconfigures one project/session at a time.\n\nSuggested commands:\n\n- none\n',
11907
12178
  "manual-api": '# Webstudio API CLI Manual\n\nThe API commands operate on the single project configured by:\n\n- .webstudio/config.json: projectId\n- global Webstudio config: origin and token\n\nRules:\n\n- Always pass --json.\n- Never pass a project id. Commands use configured project only.\n- Read ids before writing. Do not invent ids for existing records.\n- stdout is one JSON object. stderr is diagnostics.\n- Prefer MCP semantic tools for detailed project edits. Use MCP apply-patch only when no semantic tool exists.\n\n## Start\n\n{{start}}\n\n## Read First\n\n{{readFirst}}\n\n## Project Session Cache\n\n- CLI commands use one local ProjectSession snapshot for the configured project.\n- Local-capable reads use cached namespaces when compatible and fetch only missing or stale namespaces.\n- Local-capable mutations build patches from the local snapshot, then commit with the cached build version.\n- Successful mutation commits update the local snapshot only after the remote commit succeeds.\n- Server-only commands run remotely and invalidate/refetch namespaces declared by the operation catalog.\n- Use --refresh on local-capable commands to refresh required namespaces before running.\n- Successful JSON responses include meta.session with operationId, buildId, version, source, committed, compatibility, namespace freshness, and diagnostics.\n\n## CLI Capability Inventory\n\n### Top-Level Commands\n\n{{topLevelCapabilityIndex}}\n\n### High-Level API Commands By Area\n\n{{apiCapabilityIndex}}\n\n### MCP-Only Operations\n\nThese are intentionally exposed through `webstudio mcp`, not as top-level shell commands:\n\n{{mcpOnlyCommandIndex}}\n\n## Task Recipes\n\n{{taskRecipeIndex}}\n\n## Use Case Index\n\n{{useCaseIndex}}\n\n## Known CLI Gaps\n\n{{knownCliGapIndex}}\n\n## Input File Shapes\n\n{{inputFileShapeIndex}}\n\n## Raw Patch Fallback\n\napply-patch accepts either BuildPatchTransaction[] or { "transactions": BuildPatchTransaction[] }.\n\nEach transaction has:\n\n{\n"id": "unique-client-transaction-id",\n"payload": [\n{\n"namespace": "pages",\n"patches": [\n{ "op": "replace", "path": ["meta", "siteName"], "value": "New Site" }\n]\n}\n]\n}\n\nPatch paths are JSON-patch-like paths into Builder store data. Map-like namespaces use ids as the first path item.\n\nSupported namespaces:\n\n- pages: site metadata, redirects, page records, folders, compiler settings\n- instances: element instances and children, including text/expression children\n- props: element props, bindings, page references, resource bindings\n- styles: CSS declarations keyed by style declaration key\n- styleSources: local style sources and reusable design tokens\n- styleSourceSelections: instance-to-style-source connections\n- dataSources: data variables, parameters, and resource data sources\n- resources: data resource definitions\n- assets: project asset records handled by the existing asset patch path\n- breakpoints: responsive breakpoints\n- marketplaceProduct: marketplace metadata\n\nCommit raw patch:\n\nMCP tool: apply-patch\n\n## Raw Patch Examples\n\nRename the site:\n\n[\n{\n"id": "tx-site-name",\n"payload": [\n{\n"namespace": "pages",\n"patches": [\n{ "op": "add", "path": ["meta", "siteName"], "value": "Acme Studio" }\n]\n}\n]\n}\n]\n\nUpdate page title metadata:\n\n[\n{\n"id": "tx-page-title",\n"payload": [\n{\n"namespace": "pages",\n"patches": [\n{ "op": "replace", "path": ["pages", "page-id", "meta", "title"], "value": "Pricing" }\n]\n}\n]\n}\n]\n\nUpdate a text child on an element:\n\n[\n{\n"id": "tx-text",\n"payload": [\n{\n"namespace": "instances",\n"patches": [\n{ "op": "replace", "path": ["instance-id", "children", 0, "value"], "value": "Launch faster" }\n]\n}\n]\n}\n]\n\nCreate a data variable:\n\n[\n{\n"id": "tx-variable",\n"payload": [\n{\n"namespace": "dataSources",\n"patches": [\n{\n"op": "add",\n"path": ["variable-id"],\n"value": {\n"type": "variable",\n"id": "variable-id",\n"scopeInstanceId": "instance-id",\n"name": "headline",\n"value": { "type": "string", "value": "Launch faster" }\n}\n}\n]\n}\n]\n}\n]\n\nCreate a design token:\n\n[\n{\n"id": "tx-token",\n"payload": [\n{\n"namespace": "styleSources",\n"patches": [\n{ "op": "add", "path": ["token-id"], "value": { "type": "token", "id": "token-id", "name": "Brand Primary" } }\n]\n},\n{\n"namespace": "styles",\n"patches": [\n{\n"op": "add",\n"path": ["token-id:base:color:"],\n"value": {\n"styleSourceId": "token-id",\n"breakpointId": "base",\n"property": "color",\n"value": { "type": "keyword", "value": "red" }\n}\n}\n]\n}\n]\n}\n]\n\n## Safety Rules\n\n- For MCP apply-patch, read the latest version with MCP snapshot before writing.\n- Reuse ids from MCP snapshot output when updating existing records.\n- Generate new unique ids when adding records.\n- If apply-patch reports a version conflict, read the latest build and regenerate the patch.\n- Prefer semantic MCP read tools for discovery, then use MCP snapshot for exact patch paths.\n\n## Command Index\n\n{{commandIndex}}\n',
11908
12179
  "manual-llm": "# Webstudio CLI Manual for LLMs\n\nUse this order. Stop only when a command returns ok:false.\n\n## Always\n\n1. webstudio permissions --json\n2. webstudio mcp\n3. Read MCP resource webstudio://project/tools.\n4. Pick focused MCP read tool.\n5. Pick semantic MCP write tool.\n\n## Pick Read Command\n\n{{readFirst}}\n\n## Pick Write Command\n\n{{taskRecipeIndex}}\n\n## Raw Patch Only If Needed\n\n1. Use MCP tool: snapshot.\n2. Write BuildPatchTransaction[].\n3. Use MCP tool: apply-patch.\n\n## MCP Argument Examples\n\nMCP tools receive JSON argument objects, not CLI flags. Use these shapes:\n\n{{mcpArgumentExampleIndex}}\n\n## Rules\n\n- Never guess ids for existing records. Read them first.\n- Never use project ids from user input. Commands use the configured project.\n- Use --refresh before a local-capable command when cached data may be stale.\n- On VERSION_CONFLICT, read MCP snapshot again, regenerate the patch, then retry.\n- Treat stdout JSON as the API contract and stderr as diagnostics.\n- Confirm destructive commands with --confirm only when user requested deletion/unpublish/replacement.\n- Use webstudio schema api --json for machine-readable command metadata.\n\n## Known Gaps\n\n{{knownCliGapIndex}}\n",
11909
12180
  "manual-mcp": "# Webstudio MCP Manual\n\n`webstudio mcp` starts a stdio MCP server for the configured project.\n\n## Startup\n\n1. Configure a project with `webstudio init --link <api-share-link> --json`.\n2. Check capabilities with `webstudio permissions --json`.\n3. Start the server with `webstudio mcp`.\n\nWhile the server is running, stdout is reserved for MCP JSON-RPC messages. Do not print human text from the server process.\n\n## Discovery\n\nUse MCP itself after startup:\n\n- `tools/list`: machine-readable available tools\n- `resources/list`: available longer JSON resources\n- `meta.index`: concise capability catalog\n- `meta.guide`: workflow for a user goal\n- `meta.get_more_tools`: detailed params, examples, namespaces, and local/server behavior\n\nUseful resources:\n\n- `webstudio://project/status`: current ProjectSession status\n- `webstudio://project/tools`: operation catalog\n- `webstudio://project/guide`: concise discovery guide\n\n## Core Rules\n\n- Operate on the configured project only.\n- Read ids before writing.\n- Prefer semantic tools over `apply-patch`.\n- Use `status` and `refresh` when cached namespaces may be stale.\n- A mutation is durable only when `meta.session.committed` is true.\n- For visual/design work, verify the rendered result with vision before finishing.\n\n## Vision Verification Loop\n\nVision-capable AI can use MCP to see what it is building:\n\n{{mcpVisionVerificationLoopMarkdown}}\n\nGenerated app setup:\n\n{{mcpGeneratedAppDependencyNotes}}\n\n## MCP Argument Examples\n\nMCP tools receive JSON argument objects:\n\n{{mcpArgumentExampleIndex}}\n\n## Screenshot Verification\n\n{{screenshotVerificationSummary}}\n",
@@ -32370,9 +32641,6 @@ const readJsonArray = async (dependencies2, path2, name2) => {
32370
32641
  };
32371
32642
  const readInputObject = async (dependencies2, options) => await readOptionalJsonObject(dependencies2, options.input);
32372
32643
  const readInputArray = async (dependencies2, options) => await readJsonArray(dependencies2, options.input, "--input");
32373
- const readAssetData = (dependencies2, assetsDirectory) => async (asset2) => await dependencies2.readFile(
32374
- getLocalAssetPath(asset2.name, assetsDirectory)
32375
- );
32376
32644
  const parseVariableValue = (type2, value2) => {
32377
32645
  const valueType = requireOption(type2, "--value-type");
32378
32646
  const rawValue = requireStringOption(value2, "--value");
@@ -33379,7 +33647,10 @@ const apiCommandHandlers = {
33379
33647
  "upload-asset": async (options, connection, dependencies2) => {
33380
33648
  const input2 = {
33381
33649
  asset: await readInputObject(dependencies2, options),
33382
- readAssetData: readAssetData(dependencies2, options.assetsDir)
33650
+ readAssetData: createLocalAssetDataReader(
33651
+ dependencies2.readFile,
33652
+ options.assetsDir
33653
+ )
33383
33654
  };
33384
33655
  return runProjectSessionCommand(
33385
33656
  "upload-asset",
@@ -33391,7 +33662,10 @@ const apiCommandHandlers = {
33391
33662
  "upload-assets": async (options, connection, dependencies2) => {
33392
33663
  const input2 = {
33393
33664
  assets: await readInputArray(dependencies2, options),
33394
- readAssetData: readAssetData(dependencies2, options.assetsDir)
33665
+ readAssetData: createLocalAssetDataReader(
33666
+ dependencies2.readFile,
33667
+ options.assetsDir
33668
+ )
33395
33669
  };
33396
33670
  return runProjectSessionCommand(
33397
33671
  "upload-assets",
@@ -33522,6 +33796,11 @@ const topLevelCliCommandMetadata = [
33522
33796
  description: "Download the configured project bundle and asset files into .webstudio",
33523
33797
  examples: ["webstudio sync"]
33524
33798
  },
33799
+ {
33800
+ command: "import",
33801
+ description: "Import the synced .webstudio/data.json project bundle into a destination project",
33802
+ examples: ["webstudio import --to <destination-share-link>"]
33803
+ },
33525
33804
  {
33526
33805
  command: "build",
33527
33806
  description: "Build the synced project with the selected template",
@@ -39114,6 +39393,16 @@ const mcp = async () => {
39114
39393
  ...connection,
39115
39394
  headers: apiCompatibilityHeaders
39116
39395
  };
39396
+ let importErrorMessage = "Project import failed.";
39397
+ const silentImportIndicator = {
39398
+ start: () => void 0,
39399
+ message: () => void 0,
39400
+ stop: (message) => {
39401
+ if (message !== void 0) {
39402
+ importErrorMessage = message;
39403
+ }
39404
+ }
39405
+ };
39117
39406
  const session = createCliProjectSession({ connection: apiConnection });
39118
39407
  const preview2 = createPreviewController({ host: "127.0.0.1", port: 5173 });
39119
39408
  await connectProjectSessionMcpServer({
@@ -39126,6 +39415,36 @@ const mcp = async () => {
39126
39415
  createProjectSession: () => session,
39127
39416
  dryRun
39128
39417
  }),
39418
+ async importProject(input2) {
39419
+ importErrorMessage = "Project import failed.";
39420
+ try {
39421
+ await importProject(
39422
+ {
39423
+ to: input2.to,
39424
+ assetsDir: input2.assetsDir,
39425
+ ignoreVersionCheck: input2.ignoreVersionCheck,
39426
+ skipAssets: input2.skipAssets
39427
+ },
39428
+ {
39429
+ importProjectBundleWithAssets,
39430
+ loadJSONFile,
39431
+ readFile,
39432
+ text: async () => {
39433
+ throw new Error("MCP import requires to.");
39434
+ },
39435
+ isInteractive: false,
39436
+ log: { info: () => void 0 },
39437
+ spinner: () => silentImportIndicator
39438
+ }
39439
+ );
39440
+ } catch (error) {
39441
+ if (isHandledCliError(error)) {
39442
+ throw new Error(importErrorMessage);
39443
+ }
39444
+ throw error;
39445
+ }
39446
+ return { imported: true };
39447
+ },
39129
39448
  async startPreview(input2) {
39130
39449
  return preview2.startAndWait(input2);
39131
39450
  },
@@ -39676,6 +39995,12 @@ const registerCommands = (cmd) => {
39676
39995
  );
39677
39996
  cmd.command(["link"], "Link the project with the cloud", linkOptions, link);
39678
39997
  cmd.command(["sync"], "Sync your project", syncOptions, sync);
39998
+ cmd.command(
39999
+ ["import"],
40000
+ "Import the synced project bundle into another project",
40001
+ importOptions,
40002
+ importProject
40003
+ );
39679
40004
  cmd.command(
39680
40005
  ["preview"],
39681
40006
  "Run the generated project dev server for visual verification",
package/lib/cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import "node:process";
2
2
  import "yargs/helpers";
3
- import { ay, ax } from "./cli-DfnIxogH.js";
3
+ import { ay, ax } from "./cli-B3sZoyrv.js";
4
4
  import "yargs";
5
5
  export {
6
6
  ay as main,
@@ -1,7 +1,7 @@
1
1
  import { join } from "node:path";
2
2
  import { readFile, rm } from "node:fs/promises";
3
- import { b as baseComponentMetas, r as radixComponentMetas, a as animationComponentMetas } from "./metas-rxEC7Qu1.js";
4
- import { g as generateRemixRoute } from "./cli-DfnIxogH.js";
3
+ import { b as baseComponentMetas, r as radixComponentMetas, a as animationComponentMetas } from "./metas-pq7CBZny.js";
4
+ import { g as generateRemixRoute } from "./cli-B3sZoyrv.js";
5
5
  const createFramework = async () => {
6
6
  const routeTemplatesDir = join("app", "route-templates");
7
7
  const htmlTemplate = await readFile(
@@ -1,7 +1,7 @@
1
1
  import { join } from "node:path";
2
2
  import { readFile, rm } from "node:fs/promises";
3
- import { b as baseComponentMetas, r as radixComponentMetas, a as animationComponentMetas } from "./metas-rxEC7Qu1.js";
4
- import { g as generateRemixRoute } from "./cli-DfnIxogH.js";
3
+ import { b as baseComponentMetas, r as radixComponentMetas, a as animationComponentMetas } from "./metas-pq7CBZny.js";
4
+ import { g as generateRemixRoute } from "./cli-B3sZoyrv.js";
5
5
  const createFramework = async () => {
6
6
  const routeTemplatesDir = join("app", "route-templates");
7
7
  const htmlTemplate = await readFile(
@@ -1,7 +1,7 @@
1
1
  import { join } from "node:path";
2
2
  import { readFile, rm } from "node:fs/promises";
3
- import { b as baseComponentMetas, r as radixComponentMetas, a as animationComponentMetas } from "./metas-rxEC7Qu1.js";
4
- import { i as isPathnamePattern } from "./cli-DfnIxogH.js";
3
+ import { b as baseComponentMetas, r as radixComponentMetas, a as animationComponentMetas } from "./metas-pq7CBZny.js";
4
+ import { i as isPathnamePattern } from "./cli-B3sZoyrv.js";
5
5
  const generateVikeRoute = (pagePath) => {
6
6
  if (pagePath === "/") {
7
7
  return "index";
@@ -1,4 +1,4 @@
1
- import { S as SlotComponentIcon, d as descendantComponent, E as EmbedIcon, M as MarkdownEmbedIcon, b as body, s as section, n as nav, m as main, h as header, f as footer, a as figure, c as aside, e as article, j as address, k as div, T as TextIcon, l as h6, o as h5, p as h4, q as h3, r as h2, t as h1, u as p, v as a, w as span, P as PaintBrushIcon, x as b, y as i, z as sup, A as sub, B as button, C as input, D as form, W as WebhookFormIcon, F as img, G as ul, H as ol, I as li, J as hr, K as code, L as BracesIcon, N as label, O as textarea, Q as radio, R as RadioCheckedIcon, U as checkbox, V as CheckboxCheckedIcon, X as VimeoIcon, Y as YoutubeIcon, Z as ButtonElementIcon, _ as BoxIcon, $ as XmlIcon, a0 as CalendarIcon, a1 as time, a2 as select, a3 as HeaderIcon, a4 as ResourceIcon, a5 as WindowInfoIcon, a6 as WindowTitleIcon, a7 as VideoIcon, a8 as AnimationGroupIcon, a9 as TextAnimationIcon, aa as StaggerAnimationIcon, ab as PlayIcon, ac as CollapsibleIcon, ad as TriggerIcon, ae as ContentIcon, af as DialogIcon, ag as OverlayIcon, ah as HeadingIcon, ai as PopoverIcon, aj as TooltipIcon, ak as TabsIcon, al as LabelIcon, am as AccordionIcon, an as ItemIcon, ao as NavigationMenuIcon, ap as ListIcon, aq as ListItemIcon, ar as ViewportIcon, as as SelectIcon, at as FormTextFieldIcon, au as CheckMarkIcon, av as SwitchIcon, aw as RadioGroupIcon } from "./cli-DfnIxogH.js";
1
+ import { S as SlotComponentIcon, d as descendantComponent, E as EmbedIcon, M as MarkdownEmbedIcon, b as body, s as section, n as nav, m as main, h as header, f as footer, a as figure, c as aside, e as article, j as address, k as div, T as TextIcon, l as h6, o as h5, p as h4, q as h3, r as h2, t as h1, u as p, v as a, w as span, P as PaintBrushIcon, x as b, y as i, z as sup, A as sub, B as button, C as input, D as form, W as WebhookFormIcon, F as img, G as ul, H as ol, I as li, J as hr, K as code, L as BracesIcon, N as label, O as textarea, Q as radio, R as RadioCheckedIcon, U as checkbox, V as CheckboxCheckedIcon, X as VimeoIcon, Y as YoutubeIcon, Z as ButtonElementIcon, _ as BoxIcon, $ as XmlIcon, a0 as CalendarIcon, a1 as time, a2 as select, a3 as HeaderIcon, a4 as ResourceIcon, a5 as WindowInfoIcon, a6 as WindowTitleIcon, a7 as VideoIcon, a8 as AnimationGroupIcon, a9 as TextAnimationIcon, aa as StaggerAnimationIcon, ab as PlayIcon, ac as CollapsibleIcon, ad as TriggerIcon, ae as ContentIcon, af as DialogIcon, ag as OverlayIcon, ah as HeadingIcon, ai as PopoverIcon, aj as TooltipIcon, ak as TabsIcon, al as LabelIcon, am as AccordionIcon, an as ItemIcon, ao as NavigationMenuIcon, ap as ListIcon, aq as ListItemIcon, ar as ViewportIcon, as as SelectIcon, at as FormTextFieldIcon, au as CheckMarkIcon, av as SwitchIcon, aw as RadioGroupIcon } from "./cli-B3sZoyrv.js";
2
2
  const meta$N = {
3
3
  category: "general",
4
4
  description: "Slot is a container for content that you want to reference across the project. Changes made to a Slot's children will be reflected in all other instances of that Slot.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webstudio",
3
- "version": "0.274.0",
3
+ "version": "0.274.2",
4
4
  "description": "Webstudio CLI",
5
5
  "author": "Webstudio <github@webstudio.is>",
6
6
  "homepage": "https://webstudio.is",
@@ -47,10 +47,10 @@
47
47
  "warn-once": "^0.1.1",
48
48
  "yargs": "^17.7.2",
49
49
  "zod": "^3.24.2",
50
- "@webstudio-is/http-client": "0.274.0",
51
- "@webstudio-is/project-migrations": "0.274.0",
50
+ "@webstudio-is/http-client": "0.274.2",
52
51
  "@webstudio-is/project-build": "0.0.0",
53
- "@webstudio-is/protocol": "0.274.0"
52
+ "@webstudio-is/project-migrations": "0.274.2",
53
+ "@webstudio-is/protocol": "0.274.2"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@cloudflare/vite-plugin": "^1.1.0",
@@ -80,17 +80,17 @@
80
80
  "vite": "^6.3.4",
81
81
  "vitest": "^3.1.2",
82
82
  "wrangler": "^3.63.2",
83
- "@webstudio-is/css-engine": "0.274.0",
84
- "@webstudio-is/image": "0.274.0",
85
- "@webstudio-is/react-sdk": "0.274.0",
86
- "@webstudio-is/sdk": "0.274.0",
87
- "@webstudio-is/sdk-components-animation": "0.274.0",
88
- "@webstudio-is/sdk-components-react": "0.274.0",
89
- "@webstudio-is/sdk-components-react-remix": "0.274.0",
90
- "@webstudio-is/sdk-components-react-router": "0.274.0",
91
- "@webstudio-is/sdk-components-react-radix": "0.274.0",
83
+ "@webstudio-is/css-engine": "0.274.2",
84
+ "@webstudio-is/react-sdk": "0.274.2",
85
+ "@webstudio-is/image": "0.274.2",
86
+ "@webstudio-is/sdk": "0.274.2",
87
+ "@webstudio-is/sdk-components-animation": "0.274.2",
88
+ "@webstudio-is/sdk-components-react": "0.274.2",
89
+ "@webstudio-is/sdk-components-react-remix": "0.274.2",
90
+ "@webstudio-is/sdk-components-react-radix": "0.274.2",
91
+ "@webstudio-is/sdk-components-react-router": "0.274.2",
92
92
  "@webstudio-is/tsconfig": "1.0.7",
93
- "@webstudio-is/wsauth": "0.274.0"
93
+ "@webstudio-is/wsauth": "0.274.2"
94
94
  },
95
95
  "scripts": {
96
96
  "typecheck": "tsgo --noEmit",
@@ -12,7 +12,7 @@
12
12
  "build-cf-types": "wrangler types"
13
13
  },
14
14
  "dependencies": {
15
- "@webstudio-is/wsauth": "0.274.0",
15
+ "@webstudio-is/wsauth": "0.274.2",
16
16
  "@remix-run/cloudflare": "2.16.5",
17
17
  "@remix-run/cloudflare-pages": "2.16.5"
18
18
  },
@@ -11,14 +11,14 @@
11
11
  "@remix-run/node": "2.16.5",
12
12
  "@remix-run/react": "2.16.5",
13
13
  "@remix-run/server-runtime": "2.16.5",
14
- "@webstudio-is/image": "0.274.0",
15
- "@webstudio-is/react-sdk": "0.274.0",
16
- "@webstudio-is/sdk": "0.274.0",
17
- "@webstudio-is/sdk-components-react": "0.274.0",
18
- "@webstudio-is/sdk-components-animation": "0.274.0",
19
- "@webstudio-is/sdk-components-react-radix": "0.274.0",
20
- "@webstudio-is/sdk-components-react-remix": "0.274.0",
21
- "@webstudio-is/wsauth": "0.274.0",
14
+ "@webstudio-is/image": "0.274.2",
15
+ "@webstudio-is/react-sdk": "0.274.2",
16
+ "@webstudio-is/sdk": "0.274.2",
17
+ "@webstudio-is/sdk-components-react": "0.274.2",
18
+ "@webstudio-is/sdk-components-animation": "0.274.2",
19
+ "@webstudio-is/sdk-components-react-radix": "0.274.2",
20
+ "@webstudio-is/sdk-components-react-remix": "0.274.2",
21
+ "@webstudio-is/wsauth": "0.274.2",
22
22
  "isbot": "^5.1.25",
23
23
  "react": "18.3.0-canary-14898b6a9-20240318",
24
24
  "react-dom": "18.3.0-canary-14898b6a9-20240318"
@@ -10,14 +10,14 @@
10
10
  "dependencies": {
11
11
  "@react-router/dev": "^7.5.3",
12
12
  "@react-router/fs-routes": "^7.5.3",
13
- "@webstudio-is/image": "0.274.0",
14
- "@webstudio-is/react-sdk": "0.274.0",
15
- "@webstudio-is/sdk": "0.274.0",
16
- "@webstudio-is/sdk-components-animation": "0.274.0",
17
- "@webstudio-is/sdk-components-react-radix": "0.274.0",
18
- "@webstudio-is/sdk-components-react-router": "0.274.0",
19
- "@webstudio-is/sdk-components-react": "0.274.0",
20
- "@webstudio-is/wsauth": "0.274.0",
13
+ "@webstudio-is/image": "0.274.2",
14
+ "@webstudio-is/react-sdk": "0.274.2",
15
+ "@webstudio-is/sdk": "0.274.2",
16
+ "@webstudio-is/sdk-components-animation": "0.274.2",
17
+ "@webstudio-is/sdk-components-react-radix": "0.274.2",
18
+ "@webstudio-is/sdk-components-react-router": "0.274.2",
19
+ "@webstudio-is/sdk-components-react": "0.274.2",
20
+ "@webstudio-is/wsauth": "0.274.2",
21
21
  "isbot": "^5.1.25",
22
22
  "react": "18.3.0-canary-14898b6a9-20240318",
23
23
  "react-dom": "18.3.0-canary-14898b6a9-20240318",
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "dependencies": {
9
9
  "@cloudflare/vite-plugin": "^1.1.0",
10
- "@webstudio-is/wsauth": "0.274.0",
10
+ "@webstudio-is/wsauth": "0.274.2",
11
11
  "wrangler": "^4.14.1"
12
12
  }
13
13
  }
@@ -8,12 +8,12 @@
8
8
  "typecheck": "tsgo --noEmit"
9
9
  },
10
10
  "dependencies": {
11
- "@webstudio-is/image": "0.274.0",
12
- "@webstudio-is/react-sdk": "0.274.0",
13
- "@webstudio-is/sdk": "0.274.0",
14
- "@webstudio-is/sdk-components-react": "0.274.0",
15
- "@webstudio-is/sdk-components-animation": "0.274.0",
16
- "@webstudio-is/sdk-components-react-radix": "0.274.0",
11
+ "@webstudio-is/image": "0.274.2",
12
+ "@webstudio-is/react-sdk": "0.274.2",
13
+ "@webstudio-is/sdk": "0.274.2",
14
+ "@webstudio-is/sdk-components-react": "0.274.2",
15
+ "@webstudio-is/sdk-components-animation": "0.274.2",
16
+ "@webstudio-is/sdk-components-react-radix": "0.274.2",
17
17
  "react": "18.3.0-canary-14898b6a9-20240318",
18
18
  "react-dom": "18.3.0-canary-14898b6a9-20240318",
19
19
  "vike": "^0.4.229"