@bezel-labs/bezel-kit 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -8
- package/dist/agent-skill.cjs +5 -5
- package/dist/agent-skill.cjs.map +1 -1
- package/dist/agent-skill.js +1 -1
- package/dist/{chunk-DXZXDPQ6.js → chunk-N57FDE2K.js} +118 -1
- package/dist/chunk-N57FDE2K.js.map +1 -0
- package/dist/chunk-NCIAL4MY.js +17 -0
- package/dist/chunk-NCIAL4MY.js.map +1 -0
- package/dist/chunk-U3AGS46P.js +444 -0
- package/dist/chunk-U3AGS46P.js.map +1 -0
- package/dist/cli.cjs +430 -67
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +84 -5
- package/dist/cli.js.map +1 -1
- package/dist/{index-Bme8IB4Z.d.cts → index-CA8VoEc5.d.cts} +79 -1
- package/dist/{index-BF0AyEbO.d.ts → index-HiFqW1Ju.d.ts} +79 -1
- package/dist/index.cjs +135 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +26 -4
- package/dist/node.cjs +383 -42
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.cts +53 -9
- package/dist/node.d.ts +53 -9
- package/dist/node.js +36 -6
- package/package.json +2 -1
- package/dist/chunk-ACUFL3QJ.js +0 -238
- package/dist/chunk-ACUFL3QJ.js.map +0 -1
- package/dist/chunk-DXZXDPQ6.js.map +0 -1
- package/dist/chunk-WQRF54FG.js +0 -17
- package/dist/chunk-WQRF54FG.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
changedPaths,
|
|
4
|
+
diffTokens,
|
|
3
5
|
generateVariablesCss,
|
|
4
6
|
initConfig,
|
|
5
7
|
mergeManagedBlock,
|
|
6
|
-
readPackageScripts
|
|
7
|
-
|
|
8
|
+
readPackageScripts,
|
|
9
|
+
syncFromStaging
|
|
10
|
+
} from "./chunk-U3AGS46P.js";
|
|
8
11
|
import {
|
|
9
12
|
DEFAULT_CONFIG_FILE,
|
|
10
|
-
DEFAULT_VARIABLES_OUTPUT
|
|
11
|
-
|
|
13
|
+
DEFAULT_VARIABLES_OUTPUT,
|
|
14
|
+
LOCKFILE_NAME,
|
|
15
|
+
SYNC_STAGING_PATH
|
|
16
|
+
} from "./chunk-N57FDE2K.js";
|
|
12
17
|
import {
|
|
13
18
|
AGENT_SKILL
|
|
14
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-NCIAL4MY.js";
|
|
15
20
|
|
|
16
21
|
// src/cli.ts
|
|
17
22
|
import { existsSync } from "fs";
|
|
@@ -319,8 +324,15 @@ Usage:
|
|
|
319
324
|
Teach claude-code, codex, cursor, or all about Bezel
|
|
320
325
|
bezel init [options] Create a bezel.json for this project
|
|
321
326
|
bezel build [options] Generate the outputs (default command)
|
|
327
|
+
bezel diff [--json] Local edits not in Bezel yet (vs ${LOCKFILE_NAME});
|
|
328
|
+
--json prints them as JSON Patch operations for a push
|
|
329
|
+
bezel sync [--discard-local-edits]
|
|
330
|
+
Apply the tokens the Bezel MCP returned (${SYNC_STAGING_PATH}):
|
|
331
|
+
writes ${LOCKFILE_NAME} and design-tokens.json, then builds.
|
|
332
|
+
Run after every sync and every push.
|
|
322
333
|
|
|
323
334
|
Reads design-tokens.json from the project root (the working directory).
|
|
335
|
+
Commit design-tokens.json and ${LOCKFILE_NAME} together; never edit the lockfile by hand.
|
|
324
336
|
|
|
325
337
|
install-mcp options:
|
|
326
338
|
--skills Also run install-skills for the same client (skips the question)
|
|
@@ -391,6 +403,8 @@ var OPTIONS = {
|
|
|
391
403
|
"no-contexts": { type: "boolean" },
|
|
392
404
|
"no-fonts": { type: "boolean" },
|
|
393
405
|
force: { type: "boolean", short: "f" },
|
|
406
|
+
json: { type: "boolean" },
|
|
407
|
+
"discard-local-edits": { type: "boolean" },
|
|
394
408
|
help: { type: "boolean", short: "h" }
|
|
395
409
|
};
|
|
396
410
|
var TOKENS_FILE_HINT = "Add design-tokens.json to the project root \u2014 ask your AI agent for it via the\n Bezel MCP, or download it from your project.";
|
|
@@ -423,6 +437,10 @@ async function runInit(values) {
|
|
|
423
437
|
}
|
|
424
438
|
if (result.config.version !== result.previousVersion) {
|
|
425
439
|
process.stderr.write(`bezel: set version to ${result.config.version} in ${configName}
|
|
440
|
+
`);
|
|
441
|
+
}
|
|
442
|
+
if (result.removedLockfile) {
|
|
443
|
+
process.stderr.write(`bezel: removed ${LOCKFILE_NAME} (it belonged to the previous project)
|
|
426
444
|
`);
|
|
427
445
|
}
|
|
428
446
|
if (!result.hasTokensFile) {
|
|
@@ -487,6 +505,59 @@ async function runBuild(values) {
|
|
|
487
505
|
`);
|
|
488
506
|
}
|
|
489
507
|
}
|
|
508
|
+
var EXIT_UNPUSHED_EDITS = 2;
|
|
509
|
+
async function runDiff(values) {
|
|
510
|
+
const result = await diffTokens({ cwd: process.cwd() });
|
|
511
|
+
const json = values.json;
|
|
512
|
+
if (result.ok === false) {
|
|
513
|
+
if (json) process.stdout.write(`${JSON.stringify(result, null, 2)}
|
|
514
|
+
`);
|
|
515
|
+
process.stderr.write(`bezel: ${result.message}
|
|
516
|
+
`);
|
|
517
|
+
process.exitCode = 1;
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
if (json) {
|
|
521
|
+
const { projectId, version, baseRevision, operations } = result;
|
|
522
|
+
process.stdout.write(`${JSON.stringify({ ok: true, projectId, version, baseRevision, operations })}
|
|
523
|
+
`);
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
526
|
+
const edits = result.operations.filter((operation) => operation.op !== "test");
|
|
527
|
+
if (edits.length === 0) {
|
|
528
|
+
process.stdout.write(`In sync with Bezel revision ${result.baseRevision} (${result.version}). No local edits.
|
|
529
|
+
`);
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
const paths = changedPaths(result.operations);
|
|
533
|
+
process.stdout.write(
|
|
534
|
+
`${edits.length} local ${edits.length === 1 ? "edit" : "edits"} not in Bezel yet (based on revision ${result.baseRevision}):
|
|
535
|
+
`
|
|
536
|
+
);
|
|
537
|
+
for (const path of paths.slice(0, 50)) process.stdout.write(` ${path}
|
|
538
|
+
`);
|
|
539
|
+
if (paths.length > 50) process.stdout.write(` ...and ${paths.length - 50} more
|
|
540
|
+
`);
|
|
541
|
+
process.stdout.write('Push them with the Bezel MCP ("push my token changes to Bezel").\n');
|
|
542
|
+
}
|
|
543
|
+
async function runSync(values) {
|
|
544
|
+
const result = await syncFromStaging({ cwd: process.cwd(), discardLocalEdits: values["discard-local-edits"] });
|
|
545
|
+
if (result.ok === false) {
|
|
546
|
+
process.stderr.write(`bezel: ${result.message}
|
|
547
|
+
`);
|
|
548
|
+
process.exitCode = result.reason === "unpushed-edits" || result.reason === "unknown-local-edits" ? EXIT_UNPUSHED_EDITS : 1;
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
process.stderr.write(
|
|
552
|
+
`bezel: synced revision ${result.revision} (${result.version}) of project ${result.projectId} into ${LOCKFILE_NAME}${result.tokensChanged ? " and design-tokens.json" : "; design-tokens.json already matched"}
|
|
553
|
+
`
|
|
554
|
+
);
|
|
555
|
+
if (result.discardedEdits > 0) {
|
|
556
|
+
process.stderr.write(`bezel: discarded ${result.discardedEdits} local ${result.discardedEdits === 1 ? "edit" : "edits"}
|
|
557
|
+
`);
|
|
558
|
+
}
|
|
559
|
+
await runBuild(values);
|
|
560
|
+
}
|
|
490
561
|
async function main(argv) {
|
|
491
562
|
const { values, positionals } = parseArgs({
|
|
492
563
|
args: argv,
|
|
@@ -510,6 +581,14 @@ async function main(argv) {
|
|
|
510
581
|
await runInit(values);
|
|
511
582
|
return;
|
|
512
583
|
}
|
|
584
|
+
if (command === "diff") {
|
|
585
|
+
await runDiff(values);
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
if (command === "sync") {
|
|
589
|
+
await runSync(values);
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
513
592
|
if (command !== "build") {
|
|
514
593
|
process.stderr.write(`bezel: unknown command "${command}".
|
|
515
594
|
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/install-mcp.ts","../src/install-skills.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { existsSync } from \"node:fs\"\nimport { readFile } from \"node:fs/promises\"\nimport { pathToFileURL } from \"node:url\"\nimport { parseArgs } from \"node:util\"\nimport { relative, resolve } from \"node:path\"\nimport { generateVariablesCss } from \"./node\"\nimport { installMcp } from \"./install-mcp\"\nimport { installSkillsCommand, skillDirectories } from \"./install-skills\"\nimport { initConfig, readPackageScripts } from \"./init\"\nimport type { BezelOptions } from \"./config\"\nimport { DEFAULT_CONFIG_FILE, DEFAULT_VARIABLES_OUTPUT } from \"./defaults\"\n\nconst USAGE = `bezel — convert a W3C Design Tokens (DTCG) file into a scoped variables.css\n\nUsage:\n bezel install-mcp [--client <name>] [--skills]\n Connect claude-code, codex, cursor, vscode, or other\n bezel install-skills [--client <name>] [--no-agents-md]\n Teach claude-code, codex, cursor, or all about Bezel\n bezel init [options] Create a bezel.json for this project\n bezel build [options] Generate the outputs (default command)\n\nReads design-tokens.json from the project root (the working directory).\n\ninstall-mcp options:\n --skills Also run install-skills for the same client (skips the question)\n\ninstall-skills options:\n --client <name> claude-code | codex | cursor | all (asked when omitted)\n --no-agents-md Only write the skill folder; leave AGENTS.md alone\n\ninit options:\n --dir <path> Directory for all outputs\n (default: src/bezel, or bezel with no src/)\n --variables-output <path> Override just the CSS path\n --contexts-output <path> Override just the contexts module path\n --fonts-output <path> Override just the fonts module path\n --no-contexts Skip the generated CONTEXTS module\n --no-fonts Skip the generated FONTS module\n --color <format> Color output: oklch | hex (default: oklch)\n --unit <mode> Dimension unit: preserve | rem (default: preserve)\n --include-all Also emit variables for tokens without an exportName\n (kebab-cased full path, e.g. --base-color-primary-500)\n --project <uuid> Link this repo to a Bezel project (writes projectId)\n --tokens-version <v> Tokens version the Bezel MCP fetches: latest | semver (default: latest)\n -f, --force Overwrite an existing bezel.json\n\nbuild options:\n -c, --config <path> Config file (.json or .js exporting BezelOptions)\n --variables-output <path> Output CSS file (default: ${DEFAULT_VARIABLES_OUTPUT})\n --contexts-output <path> Also write a generated TS module exporting CONTEXTS\n --fonts-output <path> Also write a generated TS module exporting FONTS\n --color <format> Color output: oklch | hex (default: oklch)\n --unit <mode> Dimension unit: preserve | rem (default: preserve)\n --include-all Also emit variables for tokens without an exportName\n (kebab-cased full path, e.g. --base-color-primary-500)\n --stdout Print CSS to stdout instead of writing the file\n --no-gitignore Don't create/update .gitignore for generated files\n\n -h, --help Show this help\n\nA ${DEFAULT_CONFIG_FILE} file in the working directory is loaded automatically when -c is omitted.\nThe contexts/fonts modules are TypeScript, so init only scaffolds them for a\nTypeScript project unless you pass the paths explicitly.\n--project and --tokens-version update only their own key in an existing bezel.json; no --force needed.\n`\n\n/** Load options from a `.json` or `.js`/`.mjs` config file. */\nasync function loadConfig(path: string): Promise<BezelOptions> {\n const abs = resolve(process.cwd(), path)\n if (/\\.json$/.test(abs)) {\n return JSON.parse(await readFile(abs, \"utf8\")) as BezelOptions\n }\n const mod = (await import(pathToFileURL(abs).href)) as {\n default?: BezelOptions\n } & BezelOptions\n return (mod.default ?? mod) as BezelOptions\n}\n\ntype Values = ReturnType<typeof parseArgs<{ options: typeof OPTIONS }>>[\"values\"]\n\nconst OPTIONS = {\n client: { type: \"string\" },\n config: { type: \"string\", short: \"c\" },\n dir: { type: \"string\" },\n \"variables-output\": { type: \"string\" },\n \"contexts-output\": { type: \"string\" },\n \"fonts-output\": { type: \"string\" },\n color: { type: \"string\" },\n unit: { type: \"string\" },\n \"include-all\": { type: \"boolean\" },\n project: { type: \"string\" },\n \"tokens-version\": { type: \"string\" },\n stdout: { type: \"boolean\" },\n \"no-gitignore\": { type: \"boolean\" },\n \"no-agents-md\": { type: \"boolean\" },\n skills: { type: \"boolean\" },\n \"no-contexts\": { type: \"boolean\" },\n \"no-fonts\": { type: \"boolean\" },\n force: { type: \"boolean\", short: \"f\" },\n help: { type: \"boolean\", short: \"h\" },\n} as const\n\nconst TOKENS_FILE_HINT =\n \"Add design-tokens.json to the project root — ask your AI agent for it via the\\n Bezel MCP, or download it from your project.\"\n\n/** `bezel init` — scaffold a bezel.json, then print what to do next. */\nasync function runInit(values: Values): Promise<void> {\n const cwd = process.cwd()\n const result = await initConfig({\n cwd,\n outputDir: values.dir,\n variablesOutput: values[\"variables-output\"],\n contextsOutput: values[\"contexts-output\"],\n fontsOutput: values[\"fonts-output\"],\n contexts: values[\"no-contexts\"] ? false : undefined,\n fonts: values[\"no-fonts\"] ? false : undefined,\n colorFormat: values.color as BezelOptions[\"colorFormat\"],\n dimensionUnit: values.unit as BezelOptions[\"dimensionUnit\"],\n includeAll: values[\"include-all\"],\n force: values.force,\n projectId: values.project,\n version: values[\"tokens-version\"],\n })\n\n const configName = relative(cwd, result.configPath) || DEFAULT_CONFIG_FILE\n\n if (result.updated) {\n if (values.project) {\n const changed = result.previousProjectId && result.previousProjectId !== values.project\n process.stderr.write(\n changed\n ? `bezel: updated projectId in ${configName} (was ${result.previousProjectId})\\n`\n : `bezel: set projectId in ${configName}\\n`,\n )\n }\n if (result.config.version !== result.previousVersion) {\n process.stderr.write(`bezel: set version to ${result.config.version} in ${configName}\\n`)\n }\n if (!result.hasTokensFile) {\n process.stderr.write(`\\n${TOKENS_FILE_HINT}\\n`)\n }\n return\n }\n\n if (!result.written) {\n process.stderr.write(\n `bezel: ${configName} already exists — leaving it alone. Re-run with --force to overwrite, or pass --project <uuid> / --tokens-version <v> to just update the project link.\\n`,\n )\n process.exitCode = 1\n return\n }\n\n const outputs = [\n result.config.variablesOutput,\n result.config.contextsOutput,\n result.config.fontsOutput,\n ].filter((p): p is string => p !== undefined)\n\n process.stderr.write(`bezel: wrote ${configName}\\n`)\n for (const output of outputs) {\n process.stderr.write(`bezel: ${output}\\n`)\n }\n\n const scripts = await readPackageScripts(cwd)\n const steps: string[] = []\n\n if (!result.hasTokensFile) {\n steps.push(TOKENS_FILE_HINT)\n }\n if (!scripts[\"tokens\"]) {\n steps.push('Add \"tokens\": \"bezel build\" to your package.json scripts.')\n }\n if (!skillDirectories(\"all\").some((dir) => existsSync(resolve(cwd, dir, \"bezel\")))) {\n steps.push(\"Teach your AI coding agent about Bezel: npx bezel install-skills\")\n }\n steps.push(`Run the build, then import ${result.config.variablesOutput} in your entry file.`)\n\n process.stderr.write(\"\\nNext:\\n\")\n steps.forEach((step, i) => process.stderr.write(` ${i + 1}. ${step}\\n`))\n}\n\n/** `bezel build` — generate the outputs. */\nasync function runBuild(values: Values): Promise<void> {\n const configPath =\n values.config ??\n (existsSync(resolve(process.cwd(), DEFAULT_CONFIG_FILE)) ? DEFAULT_CONFIG_FILE : undefined)\n const fileConfig = configPath ? await loadConfig(configPath) : {}\n\n const options: BezelOptions = { ...fileConfig }\n if (values[\"variables-output\"]) options.variablesOutput = values[\"variables-output\"]\n if (values[\"contexts-output\"]) options.contextsOutput = values[\"contexts-output\"]\n if (values[\"fonts-output\"]) options.fontsOutput = values[\"fonts-output\"]\n if (values.color) options.colorFormat = values.color as BezelOptions[\"colorFormat\"]\n if (values.unit) options.dimensionUnit = values.unit as BezelOptions[\"dimensionUnit\"]\n if (values[\"include-all\"]) options.includeAll = true\n if (values.stdout) options.write = false\n if (values[\"no-gitignore\"]) options.gitignore = false\n\n const css = await generateVariablesCss(options)\n\n if (values.stdout) {\n process.stdout.write(css)\n } else {\n process.stderr.write(`bezel: wrote ${options.variablesOutput ?? DEFAULT_VARIABLES_OUTPUT}\\n`)\n }\n}\n\nasync function main(argv: string[]): Promise<void> {\n const { values, positionals } = parseArgs({\n args: argv,\n allowPositionals: true,\n options: OPTIONS,\n })\n\n if (values.help || positionals[0] === \"help\") {\n process.stdout.write(USAGE)\n return\n }\n\n const command = positionals[0] ?? \"build\"\n\n if (command === \"install-mcp\") {\n await installMcp(values.client, { skills: values.skills })\n return\n }\n\n if (command === \"install-skills\") {\n await installSkillsCommand(values.client, { agentsMd: !values[\"no-agents-md\"] })\n return\n }\n\n if (command === \"init\") {\n await runInit(values)\n return\n }\n\n if (command !== \"build\") {\n process.stderr.write(`bezel: unknown command \"${command}\".\\n\\n${USAGE}`)\n process.exitCode = 1\n return\n }\n\n await runBuild(values)\n}\n\nmain(process.argv.slice(2)).catch((err: unknown) => {\n process.stderr.write(`${err instanceof Error ? err.message : String(err)}\\n`)\n process.exitCode = 1\n})\n","import { spawnSync } from \"node:child_process\"\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\"\nimport { dirname, resolve } from \"node:path\"\nimport { installSkills, reportInstallSkills, skillClientForMcpClient } from \"./install-skills\"\n\nexport const MCP_URL = \"https://mcp.bezel.new/mcp\"\nexport const CLIENTS = [\"claude-code\", \"codex\", \"cursor\", \"vscode\", \"other\"] as const\nexport type McpClient = (typeof CLIENTS)[number]\n\nexport function clientCommand(client: McpClient): { command: string; args: string[] } | undefined {\n if (client === \"claude-code\") {\n return {\n command: \"claude\",\n args: [\"mcp\", \"add\", \"--transport\", \"http\", \"--scope\", \"project\", \"bezel\", MCP_URL],\n }\n }\n if (client === \"codex\") {\n return { command: \"codex\", args: [\"mcp\", \"add\", \"bezel\", \"--url\", MCP_URL] }\n }\n return undefined\n}\n\nfunction object(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n\nexport function codexAlreadyConfigured(raw: string): boolean {\n const servers: unknown = JSON.parse(raw)\n if (\n !Array.isArray(servers) ||\n !servers.every((server) => object(server) && typeof server[\"name\"] === \"string\")\n ) {\n throw new Error(\"Could not inspect Codex MCP configuration; no changes made.\")\n }\n const existing = servers.find((server) => server[\"name\"] === \"bezel\")\n if (!existing) return false\n if (\n !object(existing[\"transport\"]) ||\n existing[\"transport\"][\"url\"] !== MCP_URL ||\n existing[\"enabled\"] === false\n ) {\n throw new Error(\n \"An existing or disabled Bezel entry needs attention in Codex; no changes made.\",\n )\n }\n return true\n}\n\n/** Preserve unrelated settings; reject conflicting or malformed configuration. */\nexport function mergeMcpConfig(raw: string, client: \"cursor\" | \"vscode\"): string {\n const config: unknown = JSON.parse(raw)\n if (!object(config)) throw new Error(\"MCP config must be a JSON object; no changes made.\")\n const key = client === \"cursor\" ? \"mcpServers\" : \"servers\"\n const servers = config[key] ?? {}\n if (!object(servers)) throw new Error(`${key} must be a JSON object; no changes made.`)\n const entry = client === \"cursor\" ? { url: MCP_URL } : { type: \"http\", url: MCP_URL }\n if (servers[\"bezel\"] !== undefined) {\n const existing = servers[\"bezel\"]\n if (\n !object(existing) ||\n existing[\"url\"] !== MCP_URL ||\n (existing[\"type\"] !== undefined && existing[\"type\"] !== \"http\") ||\n existing[\"command\"] !== undefined\n ) {\n throw new Error(\"A different bezel server is already configured; no changes made.\")\n }\n return raw\n }\n return `${JSON.stringify({ ...config, [key]: { ...servers, bezel: entry } }, null, 2)}\\n`\n}\n\nexport interface InstallMcpOptions {\n /**\n * Also install the Bezel agent skill for the same client. `true` installs without\n * asking, `false` skips, and `undefined` asks when stdin is a TTY.\n */\n skills?: boolean\n}\n\nexport async function installMcp(\n clientName?: string,\n options: InstallMcpOptions = {},\n): Promise<void> {\n let choice = clientName\n if (!choice) {\n if (!process.stdin.isTTY) {\n throw new Error(`Choose a client with --client ${CLIENTS.join(\"|\")}.`)\n }\n const { default: select } = await import(\"@inquirer/select\")\n try {\n choice = await select<McpClient>({\n message: \"Connect Bezel to your coding tool:\",\n choices: [\n { name: \"Claude Code (this project)\", value: \"claude-code\" },\n { name: \"Codex (your user configuration)\", value: \"codex\" },\n { name: \"Cursor (this project)\", value: \"cursor\" },\n { name: \"VS Code (this project)\", value: \"vscode\" },\n { name: \"Other / hosted tool\", value: \"other\" },\n ],\n })\n } catch (error) {\n if (error instanceof Error && error.name === \"ExitPromptError\") {\n console.log(\"Setup cancelled.\")\n return\n }\n throw error\n }\n }\n if (!CLIENTS.includes(choice as McpClient))\n throw new Error(`Unknown client: ${choice}. Choose ${CLIENTS.join(\", \")}.`)\n const client = choice as McpClient\n const invocation = clientCommand(client)\n if (invocation) {\n console.log(\n client === \"codex\"\n ? \"Adding Bezel to Codex user configuration.\"\n : \"Adding Bezel to this project's Claude Code configuration.\",\n )\n let alreadyConfigured = false\n if (client === \"codex\") {\n const current = spawnSync(\"codex\", [\"mcp\", \"list\", \"--json\"], {\n encoding: \"utf8\",\n shell: false,\n })\n if (current.error || current.status !== 0)\n throw new Error(\n \"Could not inspect Codex MCP configuration. Ensure the Codex CLI is installed; no changes made.\",\n )\n alreadyConfigured = codexAlreadyConfigured(current.stdout)\n }\n const result = alreadyConfigured\n ? { status: 0, error: undefined }\n : spawnSync(invocation.command, invocation.args, {\n stdio: \"inherit\",\n shell: false,\n })\n if (result.error || result.status !== 0) {\n throw new Error(\n `Could not configure ${client}. Ensure its CLI is installed and review any existing bezel entry. No existing server was removed. Manual setup: https://docs.bezel.new/docs/mcp-server/setup`,\n )\n }\n } else if (client === \"cursor\" || client === \"vscode\") {\n const path = resolve(client === \"cursor\" ? \".cursor/mcp.json\" : \".vscode/mcp.json\")\n let raw = \"{}\"\n let exists = false\n try {\n raw = await readFile(path, \"utf8\")\n exists = true\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error\n }\n // JSONC is deliberately not rewritten: preserve comments by requesting manual setup.\n let merged: string\n try {\n merged = mergeMcpConfig(raw, client)\n } catch (error) {\n throw new Error(\n `${path}: ${error instanceof Error ? error.message : String(error)} For JSON with comments, add Bezel manually: https://docs.bezel.new/docs/mcp-server/setup`,\n )\n }\n if (merged !== raw) {\n await mkdir(dirname(path), { recursive: true })\n if (exists) await writeFile(`${path}.bezel-backup`, raw, { flag: \"wx\", mode: 0o600 })\n await writeFile(path, merged, { flag: exists ? \"w\" : \"wx\" })\n }\n console.log(`Bezel configured in ${path}`)\n } else {\n console.log(\n `In your tool's MCP/connector settings, add Bezel with URL ${MCP_URL}, Streamable HTTP transport, and OAuth authentication.\\nClient instructions: https://docs.bezel.new/docs/mcp-server/setup`,\n )\n }\n console.log(\n client === \"codex\"\n ? \"Next: run `codex mcp login bezel` and complete browser sign-in.\"\n : client === \"claude-code\"\n ? \"Next: open Claude Code, run /mcp, select bezel, and sign in.\"\n : \"Next: open or reload your coding tool and sign in to Bezel when prompted.\",\n )\n console.log(\n '\\nThen open your current project in the assistant and ask:\\n\"Set up Bezel in this project.\"',\n )\n\n if (await wantsSkills(options.skills)) {\n console.log(\"\")\n reportInstallSkills(await installSkills({ client: skillClientForMcpClient(client) }))\n }\n}\n\nasync function wantsSkills(flag: boolean | undefined): Promise<boolean> {\n if (flag !== undefined) return flag\n if (!process.stdin.isTTY) return false\n const { default: select } = await import(\"@inquirer/select\")\n try {\n return await select<boolean>({\n message: \"Also install the Bezel agent skill into this repo (SKILL.md + AGENTS.md rules)?\",\n choices: [\n { name: \"Yes (recommended)\", value: true },\n { name: \"Not now (run `bezel install-skills` later)\", value: false },\n ],\n })\n } catch (error) {\n if (error instanceof Error && error.name === \"ExitPromptError\") return false\n throw error\n }\n}\n","/**\n * bezel — `install-skills`: write the Bezel agent skill into a repository.\n *\n * Coding agents (Claude Code, Codex, Cursor) load a `SKILL.md` whose description\n * matches the task at hand, and read `AGENTS.md` on every session. This installs\n * both: the skill folder under `.claude/skills/bezel/` and/or `.agents/skills/bezel/`,\n * and a marked block in `AGENTS.md` with the short rules. Files are only rewritten\n * when their content differs, existing files are backed up once before the first\n * overwrite, and nothing is ever deleted.\n */\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\"\nimport { dirname, join, relative, resolve } from \"node:path\"\nimport { AGENT_SKILL } from \"./agent-skill\"\nimport { mergeManagedBlock } from \"./managed-block\"\n\nexport const SKILL_CLIENTS = [\"claude-code\", \"codex\", \"cursor\", \"all\"] as const\nexport type SkillClient = (typeof SKILL_CLIENTS)[number]\n\n/** Opening marker for the Bezel-managed block in `AGENTS.md`. */\nexport const AGENTS_MD_START = \"<!-- bezel:start (generated by bezel install-skills — do not edit) -->\"\n/** Closing marker for the Bezel-managed block in `AGENTS.md`. */\nexport const AGENTS_MD_END = \"<!-- bezel:end -->\"\n\nconst CLAUDE_SKILLS_DIR = \".claude/skills\"\nconst AGENTS_SKILLS_DIR = \".agents/skills\"\n\nexport interface InstallSkillsOptions {\n /** Repository root the files are written under. Default: `process.cwd()`. */\n cwd?: string\n /** Which agent's skill folder(s) to write. */\n client: SkillClient\n /** Also maintain the managed block in `AGENTS.md`. Default: `true`. */\n agentsMd?: boolean\n}\n\nexport interface InstallSkillsResult {\n /** Files created or updated, relative to `cwd`. */\n written: string[]\n /** Files that already had the right content, relative to `cwd`. */\n unchanged: string[]\n /** Files backed up to `<path>.bezel-backup` before being overwritten, relative to `cwd`. */\n backedUp: string[]\n /** Follow-up notes for the user (for example a `CLAUDE.md` that does not include `AGENTS.md`). */\n hints: string[]\n}\n\n/** Skill folders a client reads, relative to the repo root. */\nexport function skillDirectories(client: SkillClient): string[] {\n if (client === \"claude-code\") return [CLAUDE_SKILLS_DIR]\n if (client === \"codex\" || client === \"cursor\") return [AGENTS_SKILLS_DIR]\n return [CLAUDE_SKILLS_DIR, AGENTS_SKILLS_DIR]\n}\n\n/** Merge the Bezel block into existing `AGENTS.md` contents. */\nexport function mergeAgentsMd(existing: string): string {\n return mergeManagedBlock(existing, AGENT_SKILL.agentsMdBlock.split(\"\\n\"), {\n start: AGENTS_MD_START,\n end: AGENTS_MD_END,\n })\n}\n\nasync function readIfExists(path: string): Promise<string | undefined> {\n try {\n return await readFile(path, \"utf8\")\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined\n throw error\n }\n}\n\n/**\n * Write `content` to `path` only when it differs from what is there. An existing file\n * is copied to `<path>.bezel-backup` the first time it is overwritten (the backup is\n * never replaced, so the user's original survives repeated runs).\n */\nasync function writeManaged(\n cwd: string,\n path: string,\n content: string,\n result: InstallSkillsResult,\n): Promise<void> {\n const rel = relative(cwd, path)\n const existing = await readIfExists(path)\n if (existing === content) {\n result.unchanged.push(rel)\n return\n }\n await mkdir(dirname(path), { recursive: true })\n if (existing !== undefined) {\n try {\n await writeFile(`${path}.bezel-backup`, existing, { flag: \"wx\", mode: 0o600 })\n result.backedUp.push(rel)\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error\n }\n }\n await writeFile(path, content, \"utf8\")\n result.written.push(rel)\n}\n\n/** Install the Bezel skill (and the `AGENTS.md` block) into a repository. */\nexport async function installSkills(options: InstallSkillsOptions): Promise<InstallSkillsResult> {\n const cwd = resolve(options.cwd ?? process.cwd())\n const result: InstallSkillsResult = { written: [], unchanged: [], backedUp: [], hints: [] }\n\n for (const dir of skillDirectories(options.client)) {\n for (const [file, content] of Object.entries(AGENT_SKILL.files)) {\n await writeManaged(cwd, join(cwd, dir, AGENT_SKILL.name, file), content, result)\n }\n }\n\n if (options.agentsMd ?? true) {\n const agentsPath = join(cwd, \"AGENTS.md\")\n const existing = (await readIfExists(agentsPath)) ?? \"\"\n const merged = mergeAgentsMd(existing)\n if (merged === existing) {\n result.unchanged.push(\"AGENTS.md\")\n } else {\n await writeFile(agentsPath, merged, \"utf8\")\n result.written.push(\"AGENTS.md\")\n }\n\n const claudeMd = await readIfExists(join(cwd, \"CLAUDE.md\"))\n if (claudeMd !== undefined && !claudeMd.includes(\"@AGENTS.md\")) {\n result.hints.push(\n \"CLAUDE.md exists and does not include AGENTS.md. Add a line containing `@AGENTS.md` to CLAUDE.md so Claude Code loads the Bezel rules.\",\n )\n }\n }\n\n return result\n}\n\n/** Map an `install-mcp` client to the skill folders it reads. */\nexport function skillClientForMcpClient(client: string): SkillClient {\n if (client === \"claude-code\" || client === \"codex\" || client === \"cursor\") return client\n return \"all\"\n}\n\n/**\n * The `bezel install-skills` command: pick a client (flag or interactive menu),\n * install, and report what changed.\n */\nexport async function installSkillsCommand(\n clientName: string | undefined,\n options: { agentsMd?: boolean; cwd?: string } = {},\n): Promise<void> {\n let choice = clientName\n if (!choice) {\n if (!process.stdin.isTTY) {\n throw new Error(`Choose a client with --client ${SKILL_CLIENTS.join(\"|\")}.`)\n }\n const { default: select } = await import(\"@inquirer/select\")\n try {\n choice = await select<SkillClient>({\n message: \"Install the Bezel skill for:\",\n choices: [\n { name: \"Claude Code (.claude/skills)\", value: \"claude-code\" },\n { name: \"Codex (.agents/skills)\", value: \"codex\" },\n { name: \"Cursor (.agents/skills)\", value: \"cursor\" },\n { name: \"All of the above\", value: \"all\" },\n ],\n })\n } catch (error) {\n if (error instanceof Error && error.name === \"ExitPromptError\") {\n console.log(\"Setup cancelled.\")\n return\n }\n throw error\n }\n }\n if (!SKILL_CLIENTS.includes(choice as SkillClient))\n throw new Error(`Unknown client: ${choice}. Choose ${SKILL_CLIENTS.join(\", \")}.`)\n\n const result = await installSkills({\n cwd: options.cwd,\n client: choice as SkillClient,\n agentsMd: options.agentsMd,\n })\n reportInstallSkills(result)\n}\n\n/** Print an {@link InstallSkillsResult} the way the CLI does. */\nexport function reportInstallSkills(result: InstallSkillsResult): void {\n for (const file of result.written) console.log(`Bezel skill: wrote ${file}`)\n for (const file of result.backedUp) console.log(`Bezel skill: backed up ${file}.bezel-backup`)\n if (result.written.length === 0) console.log(\"Bezel skill: already up to date.\")\n for (const hint of result.hints) console.log(`Note: ${hint}`)\n console.log(\n \"Next: open this repo in your assistant. The Bezel skill loads automatically when a task touches design tokens.\",\n )\n}\n"],"mappings":"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","names":["readFile","relative","resolve","mkdir","readFile","writeFile","dirname","resolve","resolve","readFile","mkdir","dirname","writeFile","resolve","readFile","relative"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/install-mcp.ts","../src/install-skills.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { existsSync } from \"node:fs\"\nimport { readFile } from \"node:fs/promises\"\nimport { pathToFileURL } from \"node:url\"\nimport { parseArgs } from \"node:util\"\nimport { relative, resolve } from \"node:path\"\nimport { generateVariablesCss } from \"./node\"\nimport { installMcp } from \"./install-mcp\"\nimport { installSkillsCommand, skillDirectories } from \"./install-skills\"\nimport { initConfig, readPackageScripts } from \"./init\"\nimport { changedPaths, diffTokens, syncFromStaging } from \"./tokens-sync\"\nimport { LOCKFILE_NAME, SYNC_STAGING_PATH } from \"./lockfile\"\nimport type { BezelOptions } from \"./config\"\nimport { DEFAULT_CONFIG_FILE, DEFAULT_VARIABLES_OUTPUT } from \"./defaults\"\n\nconst USAGE = `bezel — convert a W3C Design Tokens (DTCG) file into a scoped variables.css\n\nUsage:\n bezel install-mcp [--client <name>] [--skills]\n Connect claude-code, codex, cursor, vscode, or other\n bezel install-skills [--client <name>] [--no-agents-md]\n Teach claude-code, codex, cursor, or all about Bezel\n bezel init [options] Create a bezel.json for this project\n bezel build [options] Generate the outputs (default command)\n bezel diff [--json] Local edits not in Bezel yet (vs ${LOCKFILE_NAME});\n --json prints them as JSON Patch operations for a push\n bezel sync [--discard-local-edits]\n Apply the tokens the Bezel MCP returned (${SYNC_STAGING_PATH}):\n writes ${LOCKFILE_NAME} and design-tokens.json, then builds.\n Run after every sync and every push.\n\nReads design-tokens.json from the project root (the working directory).\nCommit design-tokens.json and ${LOCKFILE_NAME} together; never edit the lockfile by hand.\n\ninstall-mcp options:\n --skills Also run install-skills for the same client (skips the question)\n\ninstall-skills options:\n --client <name> claude-code | codex | cursor | all (asked when omitted)\n --no-agents-md Only write the skill folder; leave AGENTS.md alone\n\ninit options:\n --dir <path> Directory for all outputs\n (default: src/bezel, or bezel with no src/)\n --variables-output <path> Override just the CSS path\n --contexts-output <path> Override just the contexts module path\n --fonts-output <path> Override just the fonts module path\n --no-contexts Skip the generated CONTEXTS module\n --no-fonts Skip the generated FONTS module\n --color <format> Color output: oklch | hex (default: oklch)\n --unit <mode> Dimension unit: preserve | rem (default: preserve)\n --include-all Also emit variables for tokens without an exportName\n (kebab-cased full path, e.g. --base-color-primary-500)\n --project <uuid> Link this repo to a Bezel project (writes projectId)\n --tokens-version <v> Tokens version the Bezel MCP fetches: latest | semver (default: latest)\n -f, --force Overwrite an existing bezel.json\n\nbuild options:\n -c, --config <path> Config file (.json or .js exporting BezelOptions)\n --variables-output <path> Output CSS file (default: ${DEFAULT_VARIABLES_OUTPUT})\n --contexts-output <path> Also write a generated TS module exporting CONTEXTS\n --fonts-output <path> Also write a generated TS module exporting FONTS\n --color <format> Color output: oklch | hex (default: oklch)\n --unit <mode> Dimension unit: preserve | rem (default: preserve)\n --include-all Also emit variables for tokens without an exportName\n (kebab-cased full path, e.g. --base-color-primary-500)\n --stdout Print CSS to stdout instead of writing the file\n --no-gitignore Don't create/update .gitignore for generated files\n\n -h, --help Show this help\n\nA ${DEFAULT_CONFIG_FILE} file in the working directory is loaded automatically when -c is omitted.\nThe contexts/fonts modules are TypeScript, so init only scaffolds them for a\nTypeScript project unless you pass the paths explicitly.\n--project and --tokens-version update only their own key in an existing bezel.json; no --force needed.\n`\n\n/** Load options from a `.json` or `.js`/`.mjs` config file. */\nasync function loadConfig(path: string): Promise<BezelOptions> {\n const abs = resolve(process.cwd(), path)\n if (/\\.json$/.test(abs)) {\n return JSON.parse(await readFile(abs, \"utf8\")) as BezelOptions\n }\n const mod = (await import(pathToFileURL(abs).href)) as {\n default?: BezelOptions\n } & BezelOptions\n return (mod.default ?? mod) as BezelOptions\n}\n\ntype Values = ReturnType<typeof parseArgs<{ options: typeof OPTIONS }>>[\"values\"]\n\nconst OPTIONS = {\n client: { type: \"string\" },\n config: { type: \"string\", short: \"c\" },\n dir: { type: \"string\" },\n \"variables-output\": { type: \"string\" },\n \"contexts-output\": { type: \"string\" },\n \"fonts-output\": { type: \"string\" },\n color: { type: \"string\" },\n unit: { type: \"string\" },\n \"include-all\": { type: \"boolean\" },\n project: { type: \"string\" },\n \"tokens-version\": { type: \"string\" },\n stdout: { type: \"boolean\" },\n \"no-gitignore\": { type: \"boolean\" },\n \"no-agents-md\": { type: \"boolean\" },\n skills: { type: \"boolean\" },\n \"no-contexts\": { type: \"boolean\" },\n \"no-fonts\": { type: \"boolean\" },\n force: { type: \"boolean\", short: \"f\" },\n json: { type: \"boolean\" },\n \"discard-local-edits\": { type: \"boolean\" },\n help: { type: \"boolean\", short: \"h\" },\n} as const\n\nconst TOKENS_FILE_HINT =\n \"Add design-tokens.json to the project root — ask your AI agent for it via the\\n Bezel MCP, or download it from your project.\"\n\n/** `bezel init` — scaffold a bezel.json, then print what to do next. */\nasync function runInit(values: Values): Promise<void> {\n const cwd = process.cwd()\n const result = await initConfig({\n cwd,\n outputDir: values.dir,\n variablesOutput: values[\"variables-output\"],\n contextsOutput: values[\"contexts-output\"],\n fontsOutput: values[\"fonts-output\"],\n contexts: values[\"no-contexts\"] ? false : undefined,\n fonts: values[\"no-fonts\"] ? false : undefined,\n colorFormat: values.color as BezelOptions[\"colorFormat\"],\n dimensionUnit: values.unit as BezelOptions[\"dimensionUnit\"],\n includeAll: values[\"include-all\"],\n force: values.force,\n projectId: values.project,\n version: values[\"tokens-version\"],\n })\n\n const configName = relative(cwd, result.configPath) || DEFAULT_CONFIG_FILE\n\n if (result.updated) {\n if (values.project) {\n const changed = result.previousProjectId && result.previousProjectId !== values.project\n process.stderr.write(\n changed\n ? `bezel: updated projectId in ${configName} (was ${result.previousProjectId})\\n`\n : `bezel: set projectId in ${configName}\\n`,\n )\n }\n if (result.config.version !== result.previousVersion) {\n process.stderr.write(`bezel: set version to ${result.config.version} in ${configName}\\n`)\n }\n if (result.removedLockfile) {\n process.stderr.write(`bezel: removed ${LOCKFILE_NAME} (it belonged to the previous project)\\n`)\n }\n if (!result.hasTokensFile) {\n process.stderr.write(`\\n${TOKENS_FILE_HINT}\\n`)\n }\n return\n }\n\n if (!result.written) {\n process.stderr.write(\n `bezel: ${configName} already exists — leaving it alone. Re-run with --force to overwrite, or pass --project <uuid> / --tokens-version <v> to just update the project link.\\n`,\n )\n process.exitCode = 1\n return\n }\n\n const outputs = [\n result.config.variablesOutput,\n result.config.contextsOutput,\n result.config.fontsOutput,\n ].filter((p): p is string => p !== undefined)\n\n process.stderr.write(`bezel: wrote ${configName}\\n`)\n for (const output of outputs) {\n process.stderr.write(`bezel: ${output}\\n`)\n }\n\n const scripts = await readPackageScripts(cwd)\n const steps: string[] = []\n\n if (!result.hasTokensFile) {\n steps.push(TOKENS_FILE_HINT)\n }\n if (!scripts[\"tokens\"]) {\n steps.push('Add \"tokens\": \"bezel build\" to your package.json scripts.')\n }\n if (!skillDirectories(\"all\").some((dir) => existsSync(resolve(cwd, dir, \"bezel\")))) {\n steps.push(\"Teach your AI coding agent about Bezel: npx bezel install-skills\")\n }\n steps.push(`Run the build, then import ${result.config.variablesOutput} in your entry file.`)\n\n process.stderr.write(\"\\nNext:\\n\")\n steps.forEach((step, i) => process.stderr.write(` ${i + 1}. ${step}\\n`))\n}\n\n/** `bezel build` — generate the outputs. */\nasync function runBuild(values: Values): Promise<void> {\n const configPath =\n values.config ??\n (existsSync(resolve(process.cwd(), DEFAULT_CONFIG_FILE)) ? DEFAULT_CONFIG_FILE : undefined)\n const fileConfig = configPath ? await loadConfig(configPath) : {}\n\n const options: BezelOptions = { ...fileConfig }\n if (values[\"variables-output\"]) options.variablesOutput = values[\"variables-output\"]\n if (values[\"contexts-output\"]) options.contextsOutput = values[\"contexts-output\"]\n if (values[\"fonts-output\"]) options.fontsOutput = values[\"fonts-output\"]\n if (values.color) options.colorFormat = values.color as BezelOptions[\"colorFormat\"]\n if (values.unit) options.dimensionUnit = values.unit as BezelOptions[\"dimensionUnit\"]\n if (values[\"include-all\"]) options.includeAll = true\n if (values.stdout) options.write = false\n if (values[\"no-gitignore\"]) options.gitignore = false\n\n const css = await generateVariablesCss(options)\n\n if (values.stdout) {\n process.stdout.write(css)\n } else {\n process.stderr.write(`bezel: wrote ${options.variablesOutput ?? DEFAULT_VARIABLES_OUTPUT}\\n`)\n }\n}\n\n/** Exit code for a sync refused because it would drop local edits (distinct from errors). */\nconst EXIT_UNPUSHED_EDITS = 2\n\n/** `bezel diff` — local edits relative to the lockfile. */\nasync function runDiff(values: Values): Promise<void> {\n const result = await diffTokens({ cwd: process.cwd() })\n const json = values.json\n\n if (result.ok === false) {\n if (json) process.stdout.write(`${JSON.stringify(result, null, 2)}\\n`)\n process.stderr.write(`bezel: ${result.message}\\n`)\n process.exitCode = 1\n return\n }\n\n if (json) {\n const { projectId, version, baseRevision, operations } = result\n process.stdout.write(`${JSON.stringify({ ok: true, projectId, version, baseRevision, operations })}\\n`)\n return\n }\n\n const edits = result.operations.filter((operation) => operation.op !== \"test\")\n if (edits.length === 0) {\n process.stdout.write(`In sync with Bezel revision ${result.baseRevision} (${result.version}). No local edits.\\n`)\n return\n }\n const paths = changedPaths(result.operations)\n process.stdout.write(\n `${edits.length} local ${edits.length === 1 ? \"edit\" : \"edits\"} not in Bezel yet (based on revision ${result.baseRevision}):\\n`,\n )\n for (const path of paths.slice(0, 50)) process.stdout.write(` ${path}\\n`)\n if (paths.length > 50) process.stdout.write(` ...and ${paths.length - 50} more\\n`)\n process.stdout.write('Push them with the Bezel MCP (\"push my token changes to Bezel\").\\n')\n}\n\n/** `bezel sync` — apply the staged lockfile, then build. */\nasync function runSync(values: Values): Promise<void> {\n const result = await syncFromStaging({ cwd: process.cwd(), discardLocalEdits: values[\"discard-local-edits\"] })\n if (result.ok === false) {\n process.stderr.write(`bezel: ${result.message}\\n`)\n process.exitCode =\n result.reason === \"unpushed-edits\" || result.reason === \"unknown-local-edits\" ? EXIT_UNPUSHED_EDITS : 1\n return\n }\n process.stderr.write(\n `bezel: synced revision ${result.revision} (${result.version}) of project ${result.projectId} into ${LOCKFILE_NAME}${result.tokensChanged ? \" and design-tokens.json\" : \"; design-tokens.json already matched\"}\\n`,\n )\n if (result.discardedEdits > 0) {\n process.stderr.write(`bezel: discarded ${result.discardedEdits} local ${result.discardedEdits === 1 ? \"edit\" : \"edits\"}\\n`)\n }\n await runBuild(values)\n}\n\nasync function main(argv: string[]): Promise<void> {\n const { values, positionals } = parseArgs({\n args: argv,\n allowPositionals: true,\n options: OPTIONS,\n })\n\n if (values.help || positionals[0] === \"help\") {\n process.stdout.write(USAGE)\n return\n }\n\n const command = positionals[0] ?? \"build\"\n\n if (command === \"install-mcp\") {\n await installMcp(values.client, { skills: values.skills })\n return\n }\n\n if (command === \"install-skills\") {\n await installSkillsCommand(values.client, { agentsMd: !values[\"no-agents-md\"] })\n return\n }\n\n if (command === \"init\") {\n await runInit(values)\n return\n }\n\n if (command === \"diff\") {\n await runDiff(values)\n return\n }\n\n if (command === \"sync\") {\n await runSync(values)\n return\n }\n\n\n if (command !== \"build\") {\n process.stderr.write(`bezel: unknown command \"${command}\".\\n\\n${USAGE}`)\n process.exitCode = 1\n return\n }\n\n await runBuild(values)\n}\n\nmain(process.argv.slice(2)).catch((err: unknown) => {\n process.stderr.write(`${err instanceof Error ? err.message : String(err)}\\n`)\n process.exitCode = 1\n})\n","import { spawnSync } from \"node:child_process\"\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\"\nimport { dirname, resolve } from \"node:path\"\nimport { installSkills, reportInstallSkills, skillClientForMcpClient } from \"./install-skills\"\n\nexport const MCP_URL = \"https://mcp.bezel.new/mcp\"\nexport const CLIENTS = [\"claude-code\", \"codex\", \"cursor\", \"vscode\", \"other\"] as const\nexport type McpClient = (typeof CLIENTS)[number]\n\nexport function clientCommand(client: McpClient): { command: string; args: string[] } | undefined {\n if (client === \"claude-code\") {\n return {\n command: \"claude\",\n args: [\"mcp\", \"add\", \"--transport\", \"http\", \"--scope\", \"project\", \"bezel\", MCP_URL],\n }\n }\n if (client === \"codex\") {\n return { command: \"codex\", args: [\"mcp\", \"add\", \"bezel\", \"--url\", MCP_URL] }\n }\n return undefined\n}\n\nfunction object(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n\nexport function codexAlreadyConfigured(raw: string): boolean {\n const servers: unknown = JSON.parse(raw)\n if (\n !Array.isArray(servers) ||\n !servers.every((server) => object(server) && typeof server[\"name\"] === \"string\")\n ) {\n throw new Error(\"Could not inspect Codex MCP configuration; no changes made.\")\n }\n const existing = servers.find((server) => server[\"name\"] === \"bezel\")\n if (!existing) return false\n if (\n !object(existing[\"transport\"]) ||\n existing[\"transport\"][\"url\"] !== MCP_URL ||\n existing[\"enabled\"] === false\n ) {\n throw new Error(\n \"An existing or disabled Bezel entry needs attention in Codex; no changes made.\",\n )\n }\n return true\n}\n\n/** Preserve unrelated settings; reject conflicting or malformed configuration. */\nexport function mergeMcpConfig(raw: string, client: \"cursor\" | \"vscode\"): string {\n const config: unknown = JSON.parse(raw)\n if (!object(config)) throw new Error(\"MCP config must be a JSON object; no changes made.\")\n const key = client === \"cursor\" ? \"mcpServers\" : \"servers\"\n const servers = config[key] ?? {}\n if (!object(servers)) throw new Error(`${key} must be a JSON object; no changes made.`)\n const entry = client === \"cursor\" ? { url: MCP_URL } : { type: \"http\", url: MCP_URL }\n if (servers[\"bezel\"] !== undefined) {\n const existing = servers[\"bezel\"]\n if (\n !object(existing) ||\n existing[\"url\"] !== MCP_URL ||\n (existing[\"type\"] !== undefined && existing[\"type\"] !== \"http\") ||\n existing[\"command\"] !== undefined\n ) {\n throw new Error(\"A different bezel server is already configured; no changes made.\")\n }\n return raw\n }\n return `${JSON.stringify({ ...config, [key]: { ...servers, bezel: entry } }, null, 2)}\\n`\n}\n\nexport interface InstallMcpOptions {\n /**\n * Also install the Bezel agent skill for the same client. `true` installs without\n * asking, `false` skips, and `undefined` asks when stdin is a TTY.\n */\n skills?: boolean\n}\n\nexport async function installMcp(\n clientName?: string,\n options: InstallMcpOptions = {},\n): Promise<void> {\n let choice = clientName\n if (!choice) {\n if (!process.stdin.isTTY) {\n throw new Error(`Choose a client with --client ${CLIENTS.join(\"|\")}.`)\n }\n const { default: select } = await import(\"@inquirer/select\")\n try {\n choice = await select<McpClient>({\n message: \"Connect Bezel to your coding tool:\",\n choices: [\n { name: \"Claude Code (this project)\", value: \"claude-code\" },\n { name: \"Codex (your user configuration)\", value: \"codex\" },\n { name: \"Cursor (this project)\", value: \"cursor\" },\n { name: \"VS Code (this project)\", value: \"vscode\" },\n { name: \"Other / hosted tool\", value: \"other\" },\n ],\n })\n } catch (error) {\n if (error instanceof Error && error.name === \"ExitPromptError\") {\n console.log(\"Setup cancelled.\")\n return\n }\n throw error\n }\n }\n if (!CLIENTS.includes(choice as McpClient))\n throw new Error(`Unknown client: ${choice}. Choose ${CLIENTS.join(\", \")}.`)\n const client = choice as McpClient\n const invocation = clientCommand(client)\n if (invocation) {\n console.log(\n client === \"codex\"\n ? \"Adding Bezel to Codex user configuration.\"\n : \"Adding Bezel to this project's Claude Code configuration.\",\n )\n let alreadyConfigured = false\n if (client === \"codex\") {\n const current = spawnSync(\"codex\", [\"mcp\", \"list\", \"--json\"], {\n encoding: \"utf8\",\n shell: false,\n })\n if (current.error || current.status !== 0)\n throw new Error(\n \"Could not inspect Codex MCP configuration. Ensure the Codex CLI is installed; no changes made.\",\n )\n alreadyConfigured = codexAlreadyConfigured(current.stdout)\n }\n const result = alreadyConfigured\n ? { status: 0, error: undefined }\n : spawnSync(invocation.command, invocation.args, {\n stdio: \"inherit\",\n shell: false,\n })\n if (result.error || result.status !== 0) {\n throw new Error(\n `Could not configure ${client}. Ensure its CLI is installed and review any existing bezel entry. No existing server was removed. Manual setup: https://docs.bezel.new/docs/mcp-server/setup`,\n )\n }\n } else if (client === \"cursor\" || client === \"vscode\") {\n const path = resolve(client === \"cursor\" ? \".cursor/mcp.json\" : \".vscode/mcp.json\")\n let raw = \"{}\"\n let exists = false\n try {\n raw = await readFile(path, \"utf8\")\n exists = true\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error\n }\n // JSONC is deliberately not rewritten: preserve comments by requesting manual setup.\n let merged: string\n try {\n merged = mergeMcpConfig(raw, client)\n } catch (error) {\n throw new Error(\n `${path}: ${error instanceof Error ? error.message : String(error)} For JSON with comments, add Bezel manually: https://docs.bezel.new/docs/mcp-server/setup`,\n )\n }\n if (merged !== raw) {\n await mkdir(dirname(path), { recursive: true })\n if (exists) await writeFile(`${path}.bezel-backup`, raw, { flag: \"wx\", mode: 0o600 })\n await writeFile(path, merged, { flag: exists ? \"w\" : \"wx\" })\n }\n console.log(`Bezel configured in ${path}`)\n } else {\n console.log(\n `In your tool's MCP/connector settings, add Bezel with URL ${MCP_URL}, Streamable HTTP transport, and OAuth authentication.\\nClient instructions: https://docs.bezel.new/docs/mcp-server/setup`,\n )\n }\n console.log(\n client === \"codex\"\n ? \"Next: run `codex mcp login bezel` and complete browser sign-in.\"\n : client === \"claude-code\"\n ? \"Next: open Claude Code, run /mcp, select bezel, and sign in.\"\n : \"Next: open or reload your coding tool and sign in to Bezel when prompted.\",\n )\n console.log(\n '\\nThen open your current project in the assistant and ask:\\n\"Set up Bezel in this project.\"',\n )\n\n if (await wantsSkills(options.skills)) {\n console.log(\"\")\n reportInstallSkills(await installSkills({ client: skillClientForMcpClient(client) }))\n }\n}\n\nasync function wantsSkills(flag: boolean | undefined): Promise<boolean> {\n if (flag !== undefined) return flag\n if (!process.stdin.isTTY) return false\n const { default: select } = await import(\"@inquirer/select\")\n try {\n return await select<boolean>({\n message: \"Also install the Bezel agent skill into this repo (SKILL.md + AGENTS.md rules)?\",\n choices: [\n { name: \"Yes (recommended)\", value: true },\n { name: \"Not now (run `bezel install-skills` later)\", value: false },\n ],\n })\n } catch (error) {\n if (error instanceof Error && error.name === \"ExitPromptError\") return false\n throw error\n }\n}\n","/**\n * bezel — `install-skills`: write the Bezel agent skill into a repository.\n *\n * Coding agents (Claude Code, Codex, Cursor) load a `SKILL.md` whose description\n * matches the task at hand, and read `AGENTS.md` on every session. This installs\n * both: the skill folder under `.claude/skills/bezel/` and/or `.agents/skills/bezel/`,\n * and a marked block in `AGENTS.md` with the short rules. Files are only rewritten\n * when their content differs, existing files are backed up once before the first\n * overwrite, and nothing is ever deleted.\n */\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\"\nimport { dirname, join, relative, resolve } from \"node:path\"\nimport { AGENT_SKILL } from \"./agent-skill\"\nimport { mergeManagedBlock } from \"./managed-block\"\n\nexport const SKILL_CLIENTS = [\"claude-code\", \"codex\", \"cursor\", \"all\"] as const\nexport type SkillClient = (typeof SKILL_CLIENTS)[number]\n\n/** Opening marker for the Bezel-managed block in `AGENTS.md`. */\nexport const AGENTS_MD_START = \"<!-- bezel:start (generated by bezel install-skills — do not edit) -->\"\n/** Closing marker for the Bezel-managed block in `AGENTS.md`. */\nexport const AGENTS_MD_END = \"<!-- bezel:end -->\"\n\nconst CLAUDE_SKILLS_DIR = \".claude/skills\"\nconst AGENTS_SKILLS_DIR = \".agents/skills\"\n\nexport interface InstallSkillsOptions {\n /** Repository root the files are written under. Default: `process.cwd()`. */\n cwd?: string\n /** Which agent's skill folder(s) to write. */\n client: SkillClient\n /** Also maintain the managed block in `AGENTS.md`. Default: `true`. */\n agentsMd?: boolean\n}\n\nexport interface InstallSkillsResult {\n /** Files created or updated, relative to `cwd`. */\n written: string[]\n /** Files that already had the right content, relative to `cwd`. */\n unchanged: string[]\n /** Files backed up to `<path>.bezel-backup` before being overwritten, relative to `cwd`. */\n backedUp: string[]\n /** Follow-up notes for the user (for example a `CLAUDE.md` that does not include `AGENTS.md`). */\n hints: string[]\n}\n\n/** Skill folders a client reads, relative to the repo root. */\nexport function skillDirectories(client: SkillClient): string[] {\n if (client === \"claude-code\") return [CLAUDE_SKILLS_DIR]\n if (client === \"codex\" || client === \"cursor\") return [AGENTS_SKILLS_DIR]\n return [CLAUDE_SKILLS_DIR, AGENTS_SKILLS_DIR]\n}\n\n/** Merge the Bezel block into existing `AGENTS.md` contents. */\nexport function mergeAgentsMd(existing: string): string {\n return mergeManagedBlock(existing, AGENT_SKILL.agentsMdBlock.split(\"\\n\"), {\n start: AGENTS_MD_START,\n end: AGENTS_MD_END,\n })\n}\n\nasync function readIfExists(path: string): Promise<string | undefined> {\n try {\n return await readFile(path, \"utf8\")\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined\n throw error\n }\n}\n\n/**\n * Write `content` to `path` only when it differs from what is there. An existing file\n * is copied to `<path>.bezel-backup` the first time it is overwritten (the backup is\n * never replaced, so the user's original survives repeated runs).\n */\nasync function writeManaged(\n cwd: string,\n path: string,\n content: string,\n result: InstallSkillsResult,\n): Promise<void> {\n const rel = relative(cwd, path)\n const existing = await readIfExists(path)\n if (existing === content) {\n result.unchanged.push(rel)\n return\n }\n await mkdir(dirname(path), { recursive: true })\n if (existing !== undefined) {\n try {\n await writeFile(`${path}.bezel-backup`, existing, { flag: \"wx\", mode: 0o600 })\n result.backedUp.push(rel)\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error\n }\n }\n await writeFile(path, content, \"utf8\")\n result.written.push(rel)\n}\n\n/** Install the Bezel skill (and the `AGENTS.md` block) into a repository. */\nexport async function installSkills(options: InstallSkillsOptions): Promise<InstallSkillsResult> {\n const cwd = resolve(options.cwd ?? process.cwd())\n const result: InstallSkillsResult = { written: [], unchanged: [], backedUp: [], hints: [] }\n\n for (const dir of skillDirectories(options.client)) {\n for (const [file, content] of Object.entries(AGENT_SKILL.files)) {\n await writeManaged(cwd, join(cwd, dir, AGENT_SKILL.name, file), content, result)\n }\n }\n\n if (options.agentsMd ?? true) {\n const agentsPath = join(cwd, \"AGENTS.md\")\n const existing = (await readIfExists(agentsPath)) ?? \"\"\n const merged = mergeAgentsMd(existing)\n if (merged === existing) {\n result.unchanged.push(\"AGENTS.md\")\n } else {\n await writeFile(agentsPath, merged, \"utf8\")\n result.written.push(\"AGENTS.md\")\n }\n\n const claudeMd = await readIfExists(join(cwd, \"CLAUDE.md\"))\n if (claudeMd !== undefined && !claudeMd.includes(\"@AGENTS.md\")) {\n result.hints.push(\n \"CLAUDE.md exists and does not include AGENTS.md. Add a line containing `@AGENTS.md` to CLAUDE.md so Claude Code loads the Bezel rules.\",\n )\n }\n }\n\n return result\n}\n\n/** Map an `install-mcp` client to the skill folders it reads. */\nexport function skillClientForMcpClient(client: string): SkillClient {\n if (client === \"claude-code\" || client === \"codex\" || client === \"cursor\") return client\n return \"all\"\n}\n\n/**\n * The `bezel install-skills` command: pick a client (flag or interactive menu),\n * install, and report what changed.\n */\nexport async function installSkillsCommand(\n clientName: string | undefined,\n options: { agentsMd?: boolean; cwd?: string } = {},\n): Promise<void> {\n let choice = clientName\n if (!choice) {\n if (!process.stdin.isTTY) {\n throw new Error(`Choose a client with --client ${SKILL_CLIENTS.join(\"|\")}.`)\n }\n const { default: select } = await import(\"@inquirer/select\")\n try {\n choice = await select<SkillClient>({\n message: \"Install the Bezel skill for:\",\n choices: [\n { name: \"Claude Code (.claude/skills)\", value: \"claude-code\" },\n { name: \"Codex (.agents/skills)\", value: \"codex\" },\n { name: \"Cursor (.agents/skills)\", value: \"cursor\" },\n { name: \"All of the above\", value: \"all\" },\n ],\n })\n } catch (error) {\n if (error instanceof Error && error.name === \"ExitPromptError\") {\n console.log(\"Setup cancelled.\")\n return\n }\n throw error\n }\n }\n if (!SKILL_CLIENTS.includes(choice as SkillClient))\n throw new Error(`Unknown client: ${choice}. Choose ${SKILL_CLIENTS.join(\", \")}.`)\n\n const result = await installSkills({\n cwd: options.cwd,\n client: choice as SkillClient,\n agentsMd: options.agentsMd,\n })\n reportInstallSkills(result)\n}\n\n/** Print an {@link InstallSkillsResult} the way the CLI does. */\nexport function reportInstallSkills(result: InstallSkillsResult): void {\n for (const file of result.written) console.log(`Bezel skill: wrote ${file}`)\n for (const file of result.backedUp) console.log(`Bezel skill: backed up ${file}.bezel-backup`)\n if (result.written.length === 0) console.log(\"Bezel skill: already up to date.\")\n for (const hint of result.hints) console.log(`Note: ${hint}`)\n console.log(\n \"Next: open this repo in your assistant. The Bezel skill loads automatically when a task touches design tokens.\",\n )\n}\n"],"mappings":"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","names":["readFile","relative","resolve","mkdir","readFile","writeFile","dirname","resolve","resolve","readFile","mkdir","dirname","writeFile","resolve","readFile","relative"]}
|
|
@@ -140,6 +140,84 @@ declare function getFonts(tokens: DtcgNode): FontDef[];
|
|
|
140
140
|
/** Render the generated `fonts.ts` module emitted alongside `variables.css`. */
|
|
141
141
|
declare function formatFontsModule(fonts: FontDef[]): string;
|
|
142
142
|
|
|
143
|
+
/**
|
|
144
|
+
* `design-tokens-lock.json`: what this repo last resolved from Bezel.
|
|
145
|
+
*
|
|
146
|
+
* Like `package-lock.json` next to `package.json`: `bezel.json` says which project and
|
|
147
|
+
* version to track, the lockfile records the exact tokens and project revision the repo
|
|
148
|
+
* last synced or pushed. Pushes diff `design-tokens.json` against the lockfile's tokens,
|
|
149
|
+
* so only the edits travel. Committed to git, written only by Bezel Kit and the Bezel MCP.
|
|
150
|
+
*
|
|
151
|
+
* Pure: no `node:*`, so the Bezel MCP builds the same lockfile the CLI reads.
|
|
152
|
+
*/
|
|
153
|
+
declare const LOCKFILE_NAME = "design-tokens-lock.json";
|
|
154
|
+
declare const LOCKFILE_VERSION = 1;
|
|
155
|
+
/** Where an agent writes the lockfile text the Bezel MCP returns, for `bezel sync` to apply. */
|
|
156
|
+
declare const SYNC_STAGING_PATH = ".bezel/sync.json";
|
|
157
|
+
interface TokensLockfile {
|
|
158
|
+
lockfileVersion: typeof LOCKFILE_VERSION;
|
|
159
|
+
/** The Bezel project the tokens came from */
|
|
160
|
+
projectId: string;
|
|
161
|
+
/** "latest" (working tokens) or the published semver that was synced */
|
|
162
|
+
version: string;
|
|
163
|
+
/** The project revision the tokens belong to */
|
|
164
|
+
revision: number;
|
|
165
|
+
/** The tokens exactly as Bezel holds them at `revision` */
|
|
166
|
+
tokens: Record<string, unknown>;
|
|
167
|
+
}
|
|
168
|
+
declare function buildLockfile(input: {
|
|
169
|
+
projectId: string;
|
|
170
|
+
version: string;
|
|
171
|
+
revision: number;
|
|
172
|
+
tokens: Record<string, unknown>;
|
|
173
|
+
}): TokensLockfile;
|
|
174
|
+
/** The lockfile's on-disk text: 2-space JSON with a trailing newline. */
|
|
175
|
+
declare function serializeLockfile(lockfile: TokensLockfile): string;
|
|
176
|
+
/** The `design-tokens.json` text Bezel Kit writes: 2-space JSON with a trailing newline. */
|
|
177
|
+
declare function serializeTokensFile(tokens: Record<string, unknown>): string;
|
|
178
|
+
type LockfileProblem = "invalid-json" | "invalid-shape";
|
|
179
|
+
type ParseLockfileResult = {
|
|
180
|
+
ok: true;
|
|
181
|
+
lockfile: TokensLockfile;
|
|
182
|
+
} | {
|
|
183
|
+
ok: false;
|
|
184
|
+
reason: LockfileProblem;
|
|
185
|
+
message: string;
|
|
186
|
+
};
|
|
187
|
+
/** Parses lockfile text and checks its shape. */
|
|
188
|
+
declare function parseLockfile(text: string, name?: string): ParseLockfileResult;
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Whether RFC 6902 operations are already reflected in a document, without applying them.
|
|
192
|
+
*
|
|
193
|
+
* Two places need this. `bezel sync` uses it to tell local edits Bezel already has (a push
|
|
194
|
+
* that landed) from edits that would be lost. The Bezel MCP uses it to recognize a push
|
|
195
|
+
* that was already saved, so a repeat is "no changes" instead of a false conflict. Pure:
|
|
196
|
+
* no dependencies, safe in any runtime.
|
|
197
|
+
*/
|
|
198
|
+
/** One RFC 6902 operation, as produced by `fast-json-patch`'s `compare`. */
|
|
199
|
+
interface JsonPatchOperation {
|
|
200
|
+
op: "add" | "remove" | "replace" | "move" | "copy" | "test";
|
|
201
|
+
path: string;
|
|
202
|
+
value?: unknown;
|
|
203
|
+
from?: string;
|
|
204
|
+
}
|
|
205
|
+
/** Anything shaped like an operation, so `fast-json-patch`'s wider `Operation` type fits too. */
|
|
206
|
+
interface PatchOperationLike {
|
|
207
|
+
op: string;
|
|
208
|
+
path: string;
|
|
209
|
+
value?: unknown;
|
|
210
|
+
from?: string;
|
|
211
|
+
}
|
|
212
|
+
/** Structural equality for JSON values; object key order does not matter. */
|
|
213
|
+
declare function jsonEqual(a: unknown, b: unknown): boolean;
|
|
214
|
+
/** True when the document already holds the result of this one operation. `test` is always true. */
|
|
215
|
+
declare function isOperationApplied(document: unknown, operation: PatchOperationLike): boolean;
|
|
216
|
+
/** The operations (ignoring `test` guards) the document does not reflect yet. */
|
|
217
|
+
declare function unappliedOperations<T extends PatchOperationLike>(document: unknown, operations: readonly T[]): T[];
|
|
218
|
+
/** True when every non-`test` operation is already reflected in the document. */
|
|
219
|
+
declare function isPatchApplied(document: unknown, operations: readonly PatchOperationLike[]): boolean;
|
|
220
|
+
|
|
143
221
|
/**
|
|
144
222
|
* Convert a DTCG token object into a scoped `variables.css` string.
|
|
145
223
|
*
|
|
@@ -155,4 +233,4 @@ declare function formatFontsModule(fonts: FontDef[]): string;
|
|
|
155
233
|
*/
|
|
156
234
|
declare function tokensToCss(tokens: DtcgNode, options?: CssOptions): string;
|
|
157
235
|
|
|
158
|
-
export { type CssOptions as C, DEFAULT_CONFIG_FILE as D, FALLBACK_OUTPUT_DIR as F, type ResolvedCssOptions as R, type TokenValue as T, type ColorValue as a, DEFAULT_CONTEXTS as b, DEFAULT_CONTEXT_NAME as c, DEFAULT_NAME_EXTENSION as d, DEFAULT_OUTPUT_DIR as e, type DimensionValue as f, type DtcgNode as g, type FlatToken as h, type FontDef as i,
|
|
236
|
+
export { tokensToCss as A, unappliedOperations as B, type CssOptions as C, DEFAULT_CONFIG_FILE as D, FALLBACK_OUTPUT_DIR as F, type JsonPatchOperation as J, LOCKFILE_NAME as L, type ParseLockfileResult as P, type ResolvedCssOptions as R, SYNC_STAGING_PATH as S, type TokenValue as T, type ColorValue as a, DEFAULT_CONTEXTS as b, DEFAULT_CONTEXT_NAME as c, DEFAULT_NAME_EXTENSION as d, DEFAULT_OUTPUT_DIR as e, type DimensionValue as f, type DtcgNode as g, type FlatToken as h, type FontDef as i, LOCKFILE_VERSION as j, type LockfileProblem as k, type PatchOperationLike as l, type TokensLockfile as m, buildLockfile as n, emitCss as o, formatContextsModule as p, formatFontsModule as q, getContexts as r, getFonts as s, isOperationApplied as t, isPatchApplied as u, jsonEqual as v, parseLockfile as w, resolveCssOptions as x, serializeLockfile as y, serializeTokensFile as z };
|
|
@@ -140,6 +140,84 @@ declare function getFonts(tokens: DtcgNode): FontDef[];
|
|
|
140
140
|
/** Render the generated `fonts.ts` module emitted alongside `variables.css`. */
|
|
141
141
|
declare function formatFontsModule(fonts: FontDef[]): string;
|
|
142
142
|
|
|
143
|
+
/**
|
|
144
|
+
* `design-tokens-lock.json`: what this repo last resolved from Bezel.
|
|
145
|
+
*
|
|
146
|
+
* Like `package-lock.json` next to `package.json`: `bezel.json` says which project and
|
|
147
|
+
* version to track, the lockfile records the exact tokens and project revision the repo
|
|
148
|
+
* last synced or pushed. Pushes diff `design-tokens.json` against the lockfile's tokens,
|
|
149
|
+
* so only the edits travel. Committed to git, written only by Bezel Kit and the Bezel MCP.
|
|
150
|
+
*
|
|
151
|
+
* Pure: no `node:*`, so the Bezel MCP builds the same lockfile the CLI reads.
|
|
152
|
+
*/
|
|
153
|
+
declare const LOCKFILE_NAME = "design-tokens-lock.json";
|
|
154
|
+
declare const LOCKFILE_VERSION = 1;
|
|
155
|
+
/** Where an agent writes the lockfile text the Bezel MCP returns, for `bezel sync` to apply. */
|
|
156
|
+
declare const SYNC_STAGING_PATH = ".bezel/sync.json";
|
|
157
|
+
interface TokensLockfile {
|
|
158
|
+
lockfileVersion: typeof LOCKFILE_VERSION;
|
|
159
|
+
/** The Bezel project the tokens came from */
|
|
160
|
+
projectId: string;
|
|
161
|
+
/** "latest" (working tokens) or the published semver that was synced */
|
|
162
|
+
version: string;
|
|
163
|
+
/** The project revision the tokens belong to */
|
|
164
|
+
revision: number;
|
|
165
|
+
/** The tokens exactly as Bezel holds them at `revision` */
|
|
166
|
+
tokens: Record<string, unknown>;
|
|
167
|
+
}
|
|
168
|
+
declare function buildLockfile(input: {
|
|
169
|
+
projectId: string;
|
|
170
|
+
version: string;
|
|
171
|
+
revision: number;
|
|
172
|
+
tokens: Record<string, unknown>;
|
|
173
|
+
}): TokensLockfile;
|
|
174
|
+
/** The lockfile's on-disk text: 2-space JSON with a trailing newline. */
|
|
175
|
+
declare function serializeLockfile(lockfile: TokensLockfile): string;
|
|
176
|
+
/** The `design-tokens.json` text Bezel Kit writes: 2-space JSON with a trailing newline. */
|
|
177
|
+
declare function serializeTokensFile(tokens: Record<string, unknown>): string;
|
|
178
|
+
type LockfileProblem = "invalid-json" | "invalid-shape";
|
|
179
|
+
type ParseLockfileResult = {
|
|
180
|
+
ok: true;
|
|
181
|
+
lockfile: TokensLockfile;
|
|
182
|
+
} | {
|
|
183
|
+
ok: false;
|
|
184
|
+
reason: LockfileProblem;
|
|
185
|
+
message: string;
|
|
186
|
+
};
|
|
187
|
+
/** Parses lockfile text and checks its shape. */
|
|
188
|
+
declare function parseLockfile(text: string, name?: string): ParseLockfileResult;
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Whether RFC 6902 operations are already reflected in a document, without applying them.
|
|
192
|
+
*
|
|
193
|
+
* Two places need this. `bezel sync` uses it to tell local edits Bezel already has (a push
|
|
194
|
+
* that landed) from edits that would be lost. The Bezel MCP uses it to recognize a push
|
|
195
|
+
* that was already saved, so a repeat is "no changes" instead of a false conflict. Pure:
|
|
196
|
+
* no dependencies, safe in any runtime.
|
|
197
|
+
*/
|
|
198
|
+
/** One RFC 6902 operation, as produced by `fast-json-patch`'s `compare`. */
|
|
199
|
+
interface JsonPatchOperation {
|
|
200
|
+
op: "add" | "remove" | "replace" | "move" | "copy" | "test";
|
|
201
|
+
path: string;
|
|
202
|
+
value?: unknown;
|
|
203
|
+
from?: string;
|
|
204
|
+
}
|
|
205
|
+
/** Anything shaped like an operation, so `fast-json-patch`'s wider `Operation` type fits too. */
|
|
206
|
+
interface PatchOperationLike {
|
|
207
|
+
op: string;
|
|
208
|
+
path: string;
|
|
209
|
+
value?: unknown;
|
|
210
|
+
from?: string;
|
|
211
|
+
}
|
|
212
|
+
/** Structural equality for JSON values; object key order does not matter. */
|
|
213
|
+
declare function jsonEqual(a: unknown, b: unknown): boolean;
|
|
214
|
+
/** True when the document already holds the result of this one operation. `test` is always true. */
|
|
215
|
+
declare function isOperationApplied(document: unknown, operation: PatchOperationLike): boolean;
|
|
216
|
+
/** The operations (ignoring `test` guards) the document does not reflect yet. */
|
|
217
|
+
declare function unappliedOperations<T extends PatchOperationLike>(document: unknown, operations: readonly T[]): T[];
|
|
218
|
+
/** True when every non-`test` operation is already reflected in the document. */
|
|
219
|
+
declare function isPatchApplied(document: unknown, operations: readonly PatchOperationLike[]): boolean;
|
|
220
|
+
|
|
143
221
|
/**
|
|
144
222
|
* Convert a DTCG token object into a scoped `variables.css` string.
|
|
145
223
|
*
|
|
@@ -155,4 +233,4 @@ declare function formatFontsModule(fonts: FontDef[]): string;
|
|
|
155
233
|
*/
|
|
156
234
|
declare function tokensToCss(tokens: DtcgNode, options?: CssOptions): string;
|
|
157
235
|
|
|
158
|
-
export { type CssOptions as C, DEFAULT_CONFIG_FILE as D, FALLBACK_OUTPUT_DIR as F, type ResolvedCssOptions as R, type TokenValue as T, type ColorValue as a, DEFAULT_CONTEXTS as b, DEFAULT_CONTEXT_NAME as c, DEFAULT_NAME_EXTENSION as d, DEFAULT_OUTPUT_DIR as e, type DimensionValue as f, type DtcgNode as g, type FlatToken as h, type FontDef as i,
|
|
236
|
+
export { tokensToCss as A, unappliedOperations as B, type CssOptions as C, DEFAULT_CONFIG_FILE as D, FALLBACK_OUTPUT_DIR as F, type JsonPatchOperation as J, LOCKFILE_NAME as L, type ParseLockfileResult as P, type ResolvedCssOptions as R, SYNC_STAGING_PATH as S, type TokenValue as T, type ColorValue as a, DEFAULT_CONTEXTS as b, DEFAULT_CONTEXT_NAME as c, DEFAULT_NAME_EXTENSION as d, DEFAULT_OUTPUT_DIR as e, type DimensionValue as f, type DtcgNode as g, type FlatToken as h, type FontDef as i, LOCKFILE_VERSION as j, type LockfileProblem as k, type PatchOperationLike as l, type TokensLockfile as m, buildLockfile as n, emitCss as o, formatContextsModule as p, formatFontsModule as q, getContexts as r, getFonts as s, isOperationApplied as t, isPatchApplied as u, jsonEqual as v, parseLockfile as w, resolveCssOptions as x, serializeLockfile as y, serializeTokensFile as z };
|