rafters 0.0.51 → 0.0.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +409 -116
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -241,6 +241,18 @@ var registryClient = new RegistryClient();
241
241
  import { existsSync } from "fs";
242
242
  import { readFile } from "fs/promises";
243
243
  import { join } from "path";
244
+ var SELECTABLE_FRAMEWORKS = [
245
+ "next",
246
+ "vite",
247
+ "remix",
248
+ "react-router",
249
+ "astro",
250
+ "wc",
251
+ "vanilla"
252
+ ];
253
+ function isSelectableFramework(value2) {
254
+ return SELECTABLE_FRAMEWORKS.includes(value2);
255
+ }
244
256
  var CONFIG_FILE_FRAMEWORKS = [
245
257
  { files: ["astro.config.mjs", "astro.config.ts", "astro.config.js"], framework: "astro" },
246
258
  { files: ["next.config.mjs", "next.config.ts", "next.config.js"], framework: "next" },
@@ -313,6 +325,7 @@ async function detectShadcn(cwd) {
313
325
  }
314
326
  function frameworkToTarget(framework) {
315
327
  if (framework === "astro") return "astro";
328
+ if (framework === "wc") return "wc";
316
329
  return "react";
317
330
  }
318
331
  function targetToExtension(target) {
@@ -320,7 +333,8 @@ function targetToExtension(target) {
320
333
  react: ".tsx",
321
334
  astro: ".astro",
322
335
  vue: ".vue",
323
- svelte: ".svelte"
336
+ svelte: ".svelte",
337
+ wc: ".element.ts"
324
338
  };
325
339
  return map[target];
326
340
  }
@@ -7100,8 +7114,8 @@ var require_util = __commonJS({
7100
7114
  }
7101
7115
  function fn() {
7102
7116
  var promiseResolve, promiseReject;
7103
- var promise = new Promise(function(resolve7, reject) {
7104
- promiseResolve = resolve7;
7117
+ var promise = new Promise(function(resolve8, reject) {
7118
+ promiseResolve = resolve8;
7105
7119
  promiseReject = reject;
7106
7120
  });
7107
7121
  var args = [];
@@ -10212,8 +10226,8 @@ var require_path = __commonJS({
10212
10226
  var win323 = {};
10213
10227
  function win32SplitPath(filename) {
10214
10228
  var result = splitDeviceRe.exec(filename), device = (result[1] || "") + (result[2] || ""), tail = result[3] || "";
10215
- var result2 = splitTailRe.exec(tail), dir = result2[1], basename3 = result2[2], ext2 = result2[3];
10216
- return [device, dir, basename3, ext2];
10229
+ var result2 = splitTailRe.exec(tail), dir = result2[1], basename5 = result2[2], ext2 = result2[3];
10230
+ return [device, dir, basename5, ext2];
10217
10231
  }
10218
10232
  function win32StatPath(path2) {
10219
10233
  var result = splitDeviceRe.exec(path2), device = result[1] || "", isUnc = !!device && device[1] !== ":";
@@ -11065,7 +11079,7 @@ var require_events = __commonJS({
11065
11079
  return ret;
11066
11080
  }
11067
11081
  function once(emitter, name2) {
11068
- return new Promise(function(resolve7, reject) {
11082
+ return new Promise(function(resolve8, reject) {
11069
11083
  function errorListener(err) {
11070
11084
  emitter.removeListener(name2, resolver);
11071
11085
  reject(err);
@@ -11074,7 +11088,7 @@ var require_events = __commonJS({
11074
11088
  if (typeof emitter.removeListener === "function") {
11075
11089
  emitter.removeListener("error", errorListener);
11076
11090
  }
11077
- resolve7([].slice.call(arguments));
11091
+ resolve8([].slice.call(arguments));
11078
11092
  }
11079
11093
  ;
11080
11094
  eventTargetAgnosticAddListener(emitter, name2, resolver, { once: true });
@@ -11784,11 +11798,11 @@ var require_util3 = __commonJS({
11784
11798
  var queueMicrotask_1 = require_queueMicrotask();
11785
11799
  exports.isWin = process2.platform === "win32";
11786
11800
  function promisify(fs22, fn, getResult = (input) => input) {
11787
- return (...args) => new Promise((resolve7, reject) => {
11801
+ return (...args) => new Promise((resolve8, reject) => {
11788
11802
  fs22[fn].bind(fs22)(...args, (error3, result) => {
11789
11803
  if (error3)
11790
11804
  return reject(error3);
11791
- return resolve7(getResult(result));
11805
+ return resolve8(getResult(result));
11792
11806
  });
11793
11807
  });
11794
11808
  }
@@ -11944,9 +11958,9 @@ var require_util3 = __commonJS({
11944
11958
  }
11945
11959
  function streamToBuffer(stream2) {
11946
11960
  const chunks = [];
11947
- return new Promise((resolve7, reject) => {
11961
+ return new Promise((resolve8, reject) => {
11948
11962
  stream2.on("data", (chunk) => chunks.push(chunk));
11949
- stream2.on("end", () => resolve7(buffer_1.Buffer.concat(chunks)));
11963
+ stream2.on("end", () => resolve8(buffer_1.Buffer.concat(chunks)));
11950
11964
  stream2.on("error", reject);
11951
11965
  });
11952
11966
  }
@@ -12327,11 +12341,11 @@ function __metadata(metadataKey, metadataValue) {
12327
12341
  }
12328
12342
  function __awaiter(thisArg, _arguments, P, generator) {
12329
12343
  function adopt(value2) {
12330
- return value2 instanceof P ? value2 : new P(function(resolve7) {
12331
- resolve7(value2);
12344
+ return value2 instanceof P ? value2 : new P(function(resolve8) {
12345
+ resolve8(value2);
12332
12346
  });
12333
12347
  }
12334
- return new (P || (P = Promise))(function(resolve7, reject) {
12348
+ return new (P || (P = Promise))(function(resolve8, reject) {
12335
12349
  function fulfilled(value2) {
12336
12350
  try {
12337
12351
  step(generator.next(value2));
@@ -12347,7 +12361,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
12347
12361
  }
12348
12362
  }
12349
12363
  function step(result) {
12350
- result.done ? resolve7(result.value) : adopt(result.value).then(fulfilled, rejected);
12364
+ result.done ? resolve8(result.value) : adopt(result.value).then(fulfilled, rejected);
12351
12365
  }
12352
12366
  step((generator = generator.apply(thisArg, _arguments || [])).next());
12353
12367
  });
@@ -12530,14 +12544,14 @@ function __asyncValues(o) {
12530
12544
  }, i);
12531
12545
  function verb(n2) {
12532
12546
  i[n2] = o[n2] && function(v) {
12533
- return new Promise(function(resolve7, reject) {
12534
- v = o[n2](v), settle(resolve7, reject, v.done, v.value);
12547
+ return new Promise(function(resolve8, reject) {
12548
+ v = o[n2](v), settle(resolve8, reject, v.done, v.value);
12535
12549
  });
12536
12550
  };
12537
12551
  }
12538
- function settle(resolve7, reject, d2, v) {
12552
+ function settle(resolve8, reject, d2, v) {
12539
12553
  Promise.resolve(v).then(function(v2) {
12540
- resolve7({ value: v2, done: d2 });
12554
+ resolve8({ value: v2, done: d2 });
12541
12555
  }, reject);
12542
12556
  }
12543
12557
  }
@@ -12756,13 +12770,13 @@ var require_util4 = __commonJS({
12756
12770
  return Object.assign({ separator: "/", syncHandleAllowed: false, mode: "read" }, partial);
12757
12771
  };
12758
12772
  exports.ctx = ctx;
12759
- var basename3 = (path2, separator) => {
12773
+ var basename5 = (path2, separator) => {
12760
12774
  if (path2[path2.length - 1] === separator)
12761
12775
  path2 = path2.slice(0, -1);
12762
12776
  const lastSlashIndex = path2.lastIndexOf(separator);
12763
12777
  return lastSlashIndex === -1 ? path2 : path2.slice(lastSlashIndex + 1);
12764
12778
  };
12765
- exports.basename = basename3;
12779
+ exports.basename = basename5;
12766
12780
  var nameRegex = /^(\.{1,2})$|^(.*([\/\\]).*)$/;
12767
12781
  var assertName = (name2, method, klass) => {
12768
12782
  const isInvalid = !name2 || nameRegex.test(name2);
@@ -12955,12 +12969,12 @@ var require_Dir = __commonJS({
12955
12969
  return typeof x === "function";
12956
12970
  }
12957
12971
  promisify(obj, fn) {
12958
- return (...args) => new Promise((resolve7, reject) => {
12972
+ return (...args) => new Promise((resolve8, reject) => {
12959
12973
  if (this.isFunction(obj[fn])) {
12960
12974
  obj[fn].bind(obj)(...args, (error3, result) => {
12961
12975
  if (error3)
12962
12976
  reject(error3);
12963
- resolve7(result);
12977
+ resolve8(result);
12964
12978
  });
12965
12979
  } else {
12966
12980
  reject("Not a function");
@@ -13084,7 +13098,7 @@ var require_volume = __commonJS({
13084
13098
  var Dir_1 = require_Dir();
13085
13099
  var resolveCrossPlatform = pathModule.resolve;
13086
13100
  var { O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_EXCL, O_TRUNC, O_APPEND, O_DIRECTORY, O_SYMLINK, F_OK, COPYFILE_EXCL, COPYFILE_FICLONE_FORCE } = constants_1.constants;
13087
- var { sep: sep2, relative: relative4, join: join15, dirname: dirname5 } = pathModule.posix ? pathModule.posix : pathModule;
13101
+ var { sep: sep2, relative: relative4, join: join16, dirname: dirname6 } = pathModule.posix ? pathModule.posix : pathModule;
13088
13102
  var kMinPoolSpace = 128;
13089
13103
  var EPERM = "EPERM";
13090
13104
  var ENOENT2 = "ENOENT";
@@ -13099,13 +13113,13 @@ var require_volume = __commonJS({
13099
13113
  var ENOSYS = "ENOSYS";
13100
13114
  var ERR_FS_EISDIR = "ERR_FS_EISDIR";
13101
13115
  var ERR_OUT_OF_RANGE = "ERR_OUT_OF_RANGE";
13102
- var resolve7 = (filename, base = process_1.default.cwd()) => resolveCrossPlatform(base, filename);
13116
+ var resolve8 = (filename, base = process_1.default.cwd()) => resolveCrossPlatform(base, filename);
13103
13117
  if (util_1.isWin) {
13104
- const _resolve = resolve7;
13105
- resolve7 = (filename, base) => (0, util_1.unixify)(_resolve(filename, base));
13118
+ const _resolve = resolve8;
13119
+ resolve8 = (filename, base) => (0, util_1.unixify)(_resolve(filename, base));
13106
13120
  }
13107
13121
  function filenameToSteps(filename, base) {
13108
- const fullPath = resolve7(filename, base);
13122
+ const fullPath = resolve8(filename, base);
13109
13123
  const fullPathSansSlash = fullPath.substring(1);
13110
13124
  if (!fullPathSansSlash)
13111
13125
  return [];
@@ -13150,7 +13164,7 @@ var require_volume = __commonJS({
13150
13164
  function flatten(pathPrefix, node) {
13151
13165
  for (const path2 in node) {
13152
13166
  const contentOrNode = node[path2];
13153
- const joinedPath = join15(pathPrefix, path2);
13167
+ const joinedPath = join16(pathPrefix, path2);
13154
13168
  if (typeof contentOrNode === "string" || contentOrNode instanceof buffer_1.Buffer) {
13155
13169
  flatJSON[joinedPath] = contentOrNode;
13156
13170
  } else if (typeof contentOrNode === "object" && contentOrNode !== null && Object.keys(contentOrNode).length > 0) {
@@ -13307,7 +13321,7 @@ var require_volume = __commonJS({
13307
13321
  return null;
13308
13322
  node = curr === null || curr === void 0 ? void 0 : curr.getNode();
13309
13323
  if (resolveSymlinks && node.isSymlink()) {
13310
- const resolvedPath = pathModule.isAbsolute(node.symlink) ? node.symlink : join15(pathModule.dirname(curr.getPath()), node.symlink);
13324
+ const resolvedPath = pathModule.isAbsolute(node.symlink) ? node.symlink : join16(pathModule.dirname(curr.getPath()), node.symlink);
13311
13325
  steps2 = filenameToSteps(resolvedPath).concat(steps2.slice(i + 1));
13312
13326
  curr = this.root;
13313
13327
  i = 0;
@@ -13466,9 +13480,9 @@ var require_volume = __commonJS({
13466
13480
  fromJSON(json2, cwd = process_1.default.cwd()) {
13467
13481
  for (let filename in json2) {
13468
13482
  const data = json2[filename];
13469
- filename = resolve7(filename, cwd);
13483
+ filename = resolve8(filename, cwd);
13470
13484
  if (typeof data === "string" || data instanceof buffer_1.Buffer) {
13471
- const dir = dirname5(filename);
13485
+ const dir = dirname6(filename);
13472
13486
  this.mkdirpBase(
13473
13487
  dir,
13474
13488
  511
@@ -19947,10 +19961,10 @@ var Minipass = class extends EventEmitter {
19947
19961
  * Return a void Promise that resolves once the stream ends.
19948
19962
  */
19949
19963
  async promise() {
19950
- return new Promise((resolve7, reject) => {
19964
+ return new Promise((resolve8, reject) => {
19951
19965
  this.on(DESTROYED, () => reject(new Error("stream destroyed")));
19952
19966
  this.on("error", (er) => reject(er));
19953
- this.on("end", () => resolve7());
19967
+ this.on("end", () => resolve8());
19954
19968
  });
19955
19969
  }
19956
19970
  /**
@@ -19974,7 +19988,7 @@ var Minipass = class extends EventEmitter {
19974
19988
  return Promise.resolve({ done: false, value: res });
19975
19989
  if (this[EOF])
19976
19990
  return stop();
19977
- let resolve7;
19991
+ let resolve8;
19978
19992
  let reject;
19979
19993
  const onerr = (er) => {
19980
19994
  this.off("data", ondata);
@@ -19988,19 +20002,19 @@ var Minipass = class extends EventEmitter {
19988
20002
  this.off("end", onend);
19989
20003
  this.off(DESTROYED, ondestroy);
19990
20004
  this.pause();
19991
- resolve7({ value: value2, done: !!this[EOF] });
20005
+ resolve8({ value: value2, done: !!this[EOF] });
19992
20006
  };
19993
20007
  const onend = () => {
19994
20008
  this.off("error", onerr);
19995
20009
  this.off("data", ondata);
19996
20010
  this.off(DESTROYED, ondestroy);
19997
20011
  stop();
19998
- resolve7({ done: true, value: void 0 });
20012
+ resolve8({ done: true, value: void 0 });
19999
20013
  };
20000
20014
  const ondestroy = () => onerr(new Error("stream destroyed"));
20001
20015
  return new Promise((res2, rej) => {
20002
20016
  reject = rej;
20003
- resolve7 = res2;
20017
+ resolve8 = res2;
20004
20018
  this.once(DESTROYED, ondestroy);
20005
20019
  this.once("error", onerr);
20006
20020
  this.once("end", onend);
@@ -20972,9 +20986,9 @@ var PathBase = class {
20972
20986
  if (this.#asyncReaddirInFlight) {
20973
20987
  await this.#asyncReaddirInFlight;
20974
20988
  } else {
20975
- let resolve7 = () => {
20989
+ let resolve8 = () => {
20976
20990
  };
20977
- this.#asyncReaddirInFlight = new Promise((res) => resolve7 = res);
20991
+ this.#asyncReaddirInFlight = new Promise((res) => resolve8 = res);
20978
20992
  try {
20979
20993
  for (const e of await this.#fs.promises.readdir(fullpath, {
20980
20994
  withFileTypes: true
@@ -20987,7 +21001,7 @@ var PathBase = class {
20987
21001
  children.provisional = 0;
20988
21002
  }
20989
21003
  this.#asyncReaddirInFlight = void 0;
20990
- resolve7();
21004
+ resolve8();
20991
21005
  }
20992
21006
  return children.slice(0, children.provisional);
20993
21007
  }
@@ -24242,7 +24256,7 @@ function toBase64(buffer) {
24242
24256
  if (isNode) {
24243
24257
  return buffer.toString("base64");
24244
24258
  } else {
24245
- return new Promise((resolve7, reject) => {
24259
+ return new Promise((resolve8, reject) => {
24246
24260
  const blob = new Blob([buffer], { type: "application/octet-stream" });
24247
24261
  const reader = new FileReader();
24248
24262
  reader.onloadend = () => {
@@ -24250,7 +24264,7 @@ function toBase64(buffer) {
24250
24264
  /** @type {string } */
24251
24265
  reader.result.split(",")[1]
24252
24266
  );
24253
- resolve7(base64String);
24267
+ resolve8(base64String);
24254
24268
  };
24255
24269
  reader.onerror = reject;
24256
24270
  reader.readAsDataURL(blob);
@@ -27863,7 +27877,7 @@ var AESDecryptionStream = class extends TransformStream {
27863
27877
  super({
27864
27878
  start() {
27865
27879
  Object.assign(this, {
27866
- ready: new Promise((resolve7) => this.resolveReady = resolve7),
27880
+ ready: new Promise((resolve8) => this.resolveReady = resolve8),
27867
27881
  password: encodePassword(password2, rawPassword),
27868
27882
  signed,
27869
27883
  strength: encryptionStrength - 1,
@@ -27931,7 +27945,7 @@ var AESEncryptionStream = class extends TransformStream {
27931
27945
  super({
27932
27946
  start() {
27933
27947
  Object.assign(this, {
27934
- ready: new Promise((resolve7) => this.resolveReady = resolve7),
27948
+ ready: new Promise((resolve8) => this.resolveReady = resolve8),
27935
27949
  password: encodePassword(password2, rawPassword),
27936
27950
  strength: encryptionStrength - 1,
27937
27951
  pending: new Uint8Array()
@@ -35929,21 +35943,21 @@ async function registryToCompiled(registry, options = {}) {
35929
35943
  const { minify = true, includeImport = true } = options;
35930
35944
  const themeCss = registryToTailwind(registry, { includeImport });
35931
35945
  const { execFileSync } = await import("child_process");
35932
- const { mkdtempSync, writeFileSync, readFileSync, rmSync } = await import("fs");
35933
- const { join: join15, dirname: dirname5 } = await import("path");
35946
+ const { mkdtempSync, writeFileSync, readFileSync: readFileSync2, rmSync } = await import("fs");
35947
+ const { join: join16, dirname: dirname6 } = await import("path");
35934
35948
  const { createRequire: createRequire2 } = await import("module");
35935
35949
  const require2 = createRequire2(import.meta.url);
35936
35950
  let pkgDir;
35937
35951
  try {
35938
35952
  const pkgJsonPath = require2.resolve("@tailwindcss/cli/package.json");
35939
- pkgDir = dirname5(pkgJsonPath);
35953
+ pkgDir = dirname6(pkgJsonPath);
35940
35954
  } catch {
35941
35955
  throw new Error("Failed to resolve @tailwindcss/cli");
35942
35956
  }
35943
- const binPath = join15(pkgDir, "dist", "index.mjs");
35944
- const tempDir = mkdtempSync(join15(pkgDir, ".tmp-compile-"));
35945
- const tempInput = join15(tempDir, "input.css");
35946
- const tempOutput = join15(tempDir, "output.css");
35957
+ const binPath = join16(pkgDir, "dist", "index.mjs");
35958
+ const tempDir = mkdtempSync(join16(pkgDir, ".tmp-compile-"));
35959
+ const tempInput = join16(tempDir, "input.css");
35960
+ const tempOutput = join16(tempDir, "output.css");
35947
35961
  try {
35948
35962
  writeFileSync(tempInput, themeCss);
35949
35963
  const args = [binPath, "-i", tempInput, "-o", tempOutput];
@@ -35951,7 +35965,7 @@ async function registryToCompiled(registry, options = {}) {
35951
35965
  args.push("--minify");
35952
35966
  }
35953
35967
  execFileSync("node", args, { stdio: "pipe", timeout: 3e4 });
35954
- return readFileSync(tempOutput, "utf-8");
35968
+ return readFileSync2(tempOutput, "utf-8");
35955
35969
  } catch (error3) {
35956
35970
  const message = error3 instanceof Error ? error3.message : String(error3);
35957
35971
  throw new Error(`Failed to compile CSS: ${message}`);
@@ -46273,6 +46287,8 @@ var CSS_LOCATIONS = {
46273
46287
  vite: ["src/index.css", "src/main.css", "src/styles.css", "src/app.css"],
46274
46288
  remix: ["app/styles/global.css", "app/globals.css", "app/root.css"],
46275
46289
  "react-router": ["app/app.css", "app/root.css", "app/styles.css", "app/globals.css"],
46290
+ wc: ["src/index.css", "src/main.css", "src/styles.css", "styles/global.css"],
46291
+ vanilla: ["src/index.css", "src/main.css", "src/styles.css", "styles/global.css"],
46276
46292
  unknown: ["src/styles/global.css", "src/index.css", "styles/globals.css"]
46277
46293
  };
46278
46294
  var COMPONENT_PATHS = {
@@ -46297,8 +46313,27 @@ var COMPONENT_PATHS = {
46297
46313
  primitives: "app/lib/primitives",
46298
46314
  composites: "app/composites"
46299
46315
  },
46316
+ wc: {
46317
+ components: "src/components/ui",
46318
+ primitives: "src/lib/primitives",
46319
+ composites: "src/composites"
46320
+ },
46321
+ vanilla: {
46322
+ components: "src/components/ui",
46323
+ primitives: "src/lib/primitives",
46324
+ composites: "src/composites"
46325
+ },
46300
46326
  unknown: { components: "components/ui", primitives: "lib/primitives", composites: "composites" }
46301
46327
  };
46328
+ var FRAMEWORK_PROMPT_LABELS = {
46329
+ next: "Next.js",
46330
+ vite: "Vite",
46331
+ remix: "Remix",
46332
+ "react-router": "React Router v7",
46333
+ astro: "Astro",
46334
+ wc: "Web Components (custom elements, shadow DOM)",
46335
+ vanilla: "Vanilla (plain HTML/TS, no framework)"
46336
+ };
46302
46337
  async function findMainCssFile(cwd, framework) {
46303
46338
  const locations = CSS_LOCATIONS[framework] || CSS_LOCATIONS.unknown;
46304
46339
  for (const location of locations) {
@@ -46340,6 +46375,26 @@ ${cssContent}`;
46340
46375
  function isInteractive() {
46341
46376
  return Boolean(process.stdin.isTTY && process.stdout.isTTY);
46342
46377
  }
46378
+ async function resolveFramework(detected, flag, agentMode) {
46379
+ if (flag) {
46380
+ if (!isSelectableFramework(flag)) {
46381
+ throw new Error(
46382
+ `Unknown --framework "${flag}". Valid values: ${SELECTABLE_FRAMEWORKS.join(", ")}.`
46383
+ );
46384
+ }
46385
+ return flag;
46386
+ }
46387
+ if (detected !== "unknown") return detected;
46388
+ if (agentMode || !isInteractive()) return "unknown";
46389
+ const picked = await select({
46390
+ message: "Couldn't auto-detect your framework. Which one is this?",
46391
+ choices: SELECTABLE_FRAMEWORKS.map((value2) => ({
46392
+ name: FRAMEWORK_PROMPT_LABELS[value2],
46393
+ value: value2
46394
+ }))
46395
+ });
46396
+ return picked;
46397
+ }
46343
46398
  async function promptExportFormats(existingConfig) {
46344
46399
  if (!isInteractive()) {
46345
46400
  return existingConfig ?? DEFAULT_EXPORTS;
@@ -46677,13 +46732,26 @@ async function init(options) {
46677
46732
  const cwd = process.cwd();
46678
46733
  const paths = getRaftersPaths(cwd);
46679
46734
  log({ event: "init:start", cwd });
46680
- const { framework, shadcn, tailwindVersion } = await detectProject(cwd);
46735
+ const { framework: detectedFramework, shadcn, tailwindVersion } = await detectProject(cwd);
46681
46736
  log({
46682
46737
  event: "init:detected",
46683
- framework,
46738
+ framework: detectedFramework,
46684
46739
  tailwindVersion,
46685
46740
  hasShadcn: !!shadcn
46686
46741
  });
46742
+ const framework = await resolveFramework(
46743
+ detectedFramework,
46744
+ options.framework,
46745
+ isAgentMode2
46746
+ );
46747
+ if (framework !== detectedFramework) {
46748
+ log({
46749
+ event: "init:framework_resolved",
46750
+ detected: detectedFramework,
46751
+ resolved: framework,
46752
+ source: options.framework ? "flag" : "prompt"
46753
+ });
46754
+ }
46687
46755
  if (isTailwindV3(tailwindVersion)) {
46688
46756
  throw new Error("Tailwind v3 detected. Rafters requires Tailwind v4.");
46689
46757
  }
@@ -46867,8 +46935,8 @@ async function maybeOnboardExisting(cwd, importPendingPath) {
46867
46935
  }
46868
46936
 
46869
46937
  // src/commands/mcp.ts
46870
- import { existsSync as existsSync6 } from "fs";
46871
- import { join as join13, resolve as resolve5 } from "path";
46938
+ import { existsSync as existsSync7 } from "fs";
46939
+ import { basename as basename4, join as join14, resolve as resolve6 } from "path";
46872
46940
 
46873
46941
  // src/mcp/server.ts
46874
46942
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
@@ -46877,7 +46945,7 @@ import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprot
46877
46945
 
46878
46946
  // src/mcp/tools.ts
46879
46947
  import { readdir as readdir3 } from "fs/promises";
46880
- import { join as join11 } from "path";
46948
+ import { join as join13 } from "path";
46881
46949
 
46882
46950
  // ../composites/src/built-in-rules/email.ts
46883
46951
  var email = external_exports.string().email();
@@ -46989,14 +47057,181 @@ function search(query) {
46989
47057
  }).filter((entry) => entry.score > 0).sort((a2, b2) => b2.score - a2.score).map((entry) => entry.c);
46990
47058
  }
46991
47059
 
47060
+ // src/utils/workspaces.ts
47061
+ import { existsSync as existsSync6, readdirSync as readdirSync2, readFileSync, statSync } from "fs";
47062
+ import { basename as basename3, dirname as dirname5, join as join12, resolve as resolve5 } from "path";
47063
+
47064
+ // src/utils/discover.ts
47065
+ import { existsSync as existsSync5 } from "fs";
47066
+ import { dirname as dirname4, join as join11, resolve as resolve4 } from "path";
47067
+ function discoverProjectRoot(startDir) {
47068
+ let current = resolve4(startDir);
47069
+ for (; ; ) {
47070
+ const configPath = join11(current, ".rafters", "config.rafters.json");
47071
+ if (existsSync5(configPath)) {
47072
+ return current;
47073
+ }
47074
+ const parent = dirname4(current);
47075
+ if (parent === current) {
47076
+ return null;
47077
+ }
47078
+ current = parent;
47079
+ }
47080
+ }
47081
+
47082
+ // src/utils/workspaces.ts
47083
+ function findMonorepoRoot(startDir, boundary) {
47084
+ let current = resolve5(startDir);
47085
+ const stopAt = boundary ? resolve5(boundary) : null;
47086
+ for (; ; ) {
47087
+ const pnpmWorkspace = join12(current, "pnpm-workspace.yaml");
47088
+ if (existsSync6(pnpmWorkspace)) {
47089
+ const patterns = parsePnpmWorkspaceYaml(readFileSync(pnpmWorkspace, "utf-8"));
47090
+ if (patterns.length > 0) {
47091
+ return { root: current, patterns };
47092
+ }
47093
+ }
47094
+ const pkgJson = join12(current, "package.json");
47095
+ if (existsSync6(pkgJson)) {
47096
+ const patterns = parsePackageJsonWorkspaces(readFileSync(pkgJson, "utf-8"));
47097
+ if (patterns.length > 0) {
47098
+ return { root: current, patterns };
47099
+ }
47100
+ }
47101
+ if (stopAt && current === stopAt) return null;
47102
+ const parent = dirname5(current);
47103
+ if (parent === current) return null;
47104
+ current = parent;
47105
+ }
47106
+ }
47107
+ function parsePnpmWorkspaceYaml(content) {
47108
+ const lines = content.split("\n");
47109
+ const patterns = [];
47110
+ let inPackages = false;
47111
+ for (const rawLine of lines) {
47112
+ const line = rawLine.replace(/#.*$/, "").trimEnd();
47113
+ if (!line.trim()) continue;
47114
+ if (/^packages\s*:/.test(line)) {
47115
+ inPackages = true;
47116
+ continue;
47117
+ }
47118
+ if (inPackages) {
47119
+ const itemMatch = line.match(/^\s*-\s*(?:["']?)([^"'\s]+)(?:["']?)\s*$/);
47120
+ if (itemMatch?.[1]) {
47121
+ patterns.push(itemMatch[1]);
47122
+ continue;
47123
+ }
47124
+ if (!/^\s/.test(line)) {
47125
+ inPackages = false;
47126
+ }
47127
+ }
47128
+ }
47129
+ return patterns;
47130
+ }
47131
+ function parsePackageJsonWorkspaces(content) {
47132
+ try {
47133
+ const pkg = JSON.parse(content);
47134
+ const ws = pkg.workspaces;
47135
+ if (Array.isArray(ws)) {
47136
+ return ws.filter((p2) => typeof p2 === "string");
47137
+ }
47138
+ if (ws && typeof ws === "object" && Array.isArray(ws.packages)) {
47139
+ return ws.packages.filter((p2) => typeof p2 === "string");
47140
+ }
47141
+ return [];
47142
+ } catch {
47143
+ return [];
47144
+ }
47145
+ }
47146
+ function expandPattern(monorepoRoot, pattern) {
47147
+ const trimmed = pattern.replace(/\/+$/, "");
47148
+ if (trimmed.endsWith("/*")) {
47149
+ const parentRel = trimmed.slice(0, -2);
47150
+ const parent = join12(monorepoRoot, parentRel);
47151
+ if (!existsSync6(parent)) return [];
47152
+ return readdirSync2(parent).map((entry) => join12(parent, entry)).filter((path2) => {
47153
+ try {
47154
+ return statSync(path2).isDirectory();
47155
+ } catch {
47156
+ return false;
47157
+ }
47158
+ });
47159
+ }
47160
+ const literal = join12(monorepoRoot, trimmed);
47161
+ if (existsSync6(literal)) {
47162
+ try {
47163
+ if (statSync(literal).isDirectory()) return [literal];
47164
+ } catch {
47165
+ return [];
47166
+ }
47167
+ }
47168
+ return [];
47169
+ }
47170
+ function discoverWorkspaces(startDir = process.cwd(), options = {}) {
47171
+ const layout = findMonorepoRoot(startDir, options.boundary);
47172
+ if (!layout) {
47173
+ const single = discoverProjectRoot(startDir);
47174
+ if (!single) return [];
47175
+ if (options.boundary && !single.startsWith(resolve5(options.boundary))) return [];
47176
+ return [{ name: basename3(single), root: single }];
47177
+ }
47178
+ const seen = /* @__PURE__ */ new Set();
47179
+ const workspaces = [];
47180
+ for (const pattern of layout.patterns) {
47181
+ for (const dir of expandPattern(layout.root, pattern)) {
47182
+ if (seen.has(dir)) continue;
47183
+ seen.add(dir);
47184
+ const config2 = join12(dir, ".rafters", "config.rafters.json");
47185
+ if (existsSync6(config2)) {
47186
+ workspaces.push({ name: basename3(dir), root: dir });
47187
+ }
47188
+ }
47189
+ }
47190
+ const rootConfig = join12(layout.root, ".rafters", "config.rafters.json");
47191
+ if (existsSync6(rootConfig) && !seen.has(layout.root)) {
47192
+ workspaces.unshift({ name: basename3(layout.root), root: layout.root });
47193
+ }
47194
+ return workspaces;
47195
+ }
47196
+ function pickDefaultWorkspace(workspaces, startDir = process.cwd()) {
47197
+ if (workspaces.length === 0) return null;
47198
+ const cwd = resolve5(startDir);
47199
+ const containing = workspaces.find((ws) => cwd === ws.root || cwd.startsWith(`${ws.root}/`));
47200
+ if (containing) return containing;
47201
+ if (workspaces.length === 1) return workspaces[0] ?? null;
47202
+ return null;
47203
+ }
47204
+ function resolveWorkspace(workspaces, defaultWorkspace, name2) {
47205
+ if (name2) {
47206
+ return workspaces.find((ws) => ws.name === name2) ?? null;
47207
+ }
47208
+ return defaultWorkspace;
47209
+ }
47210
+
46992
47211
  // src/mcp/tools.ts
47212
+ var WORKSPACE_PARAM = {
47213
+ workspace: {
47214
+ type: "string",
47215
+ description: "Workspace name (directory basename). Required when the MCP session has multiple workspaces and none matches cwd. Call rafters_workspaces to list options."
47216
+ }
47217
+ };
46993
47218
  var TOOL_DEFINITIONS = [
47219
+ {
47220
+ name: "rafters_workspaces",
47221
+ description: "List rafters workspaces visible to this MCP session. Returns name, path, and which one is the default for unscoped tool calls. Call this first when the project might be a monorepo.",
47222
+ inputSchema: {
47223
+ type: "object",
47224
+ properties: {},
47225
+ required: []
47226
+ }
47227
+ },
46994
47228
  {
46995
47229
  name: "rafters_composite",
46996
47230
  description: "Query composites by ID, search term, or category. Returns designer intent (solves, appliesWhen, do/never), I/O rules for chaining, and block structure.",
46997
47231
  inputSchema: {
46998
47232
  type: "object",
46999
47233
  properties: {
47234
+ ...WORKSPACE_PARAM,
47000
47235
  id: { type: "string", description: "Get a specific composite by ID" },
47001
47236
  query: { type: "string", description: "Fuzzy search by name/keywords" },
47002
47237
  category: { type: "string", description: "Filter by category" }
@@ -47010,6 +47245,7 @@ var TOOL_DEFINITIONS = [
47010
47245
  inputSchema: {
47011
47246
  type: "object",
47012
47247
  properties: {
47248
+ ...WORKSPACE_PARAM,
47013
47249
  name: { type: "string", description: "Get a specific rule by name" },
47014
47250
  query: { type: "string", description: "Search rules by name/description" },
47015
47251
  create: {
@@ -47032,6 +47268,7 @@ var TOOL_DEFINITIONS = [
47032
47268
  inputSchema: {
47033
47269
  type: "object",
47034
47270
  properties: {
47271
+ ...WORKSPACE_PARAM,
47035
47272
  solves: {
47036
47273
  type: "string",
47037
47274
  description: "What problem the pattern solves (searches composite solves field)"
@@ -47050,6 +47287,7 @@ var TOOL_DEFINITIONS = [
47050
47287
  inputSchema: {
47051
47288
  type: "object",
47052
47289
  properties: {
47290
+ ...WORKSPACE_PARAM,
47053
47291
  name: {
47054
47292
  type: "string",
47055
47293
  description: 'Component name (e.g., "button", "dialog", "card")'
@@ -47060,13 +47298,20 @@ var TOOL_DEFINITIONS = [
47060
47298
  }
47061
47299
  ];
47062
47300
  var RaftersToolHandler = class {
47063
- projectRoot;
47064
- compositesLoaded = false;
47065
- constructor(projectRoot) {
47066
- this.projectRoot = projectRoot;
47301
+ workspaces;
47302
+ defaultWorkspace;
47303
+ /** Tracks per-workspace composite loading so we only read from disk once. */
47304
+ compositesLoadedFor = /* @__PURE__ */ new Set();
47305
+ /** Tracks built-in composite loading separately (loaded once globally). */
47306
+ builtInCompositesLoaded = false;
47307
+ constructor(workspaces, defaultWorkspace) {
47308
+ this.workspaces = workspaces;
47309
+ this.defaultWorkspace = defaultWorkspace;
47067
47310
  }
47068
47311
  async handleToolCall(name2, args) {
47069
47312
  switch (name2) {
47313
+ case "rafters_workspaces":
47314
+ return this.handleWorkspaces();
47070
47315
  case "rafters_composite":
47071
47316
  return this.handleComposite(args);
47072
47317
  case "rafters_rule":
@@ -47076,7 +47321,7 @@ var RaftersToolHandler = class {
47076
47321
  case "rafters_component":
47077
47322
  return this.handleComponent(args.name);
47078
47323
  default: {
47079
- const suggestion = name2 === "rafters_onboard" ? "rafters_onboard was removed. Token import is now a CLI operation: run `rafters init` (auto-detects and prompts) or `rafters import` (standalone)." : "Available tools: rafters_composite, rafters_rule, rafters_pattern, rafters_component.";
47324
+ const suggestion = name2 === "rafters_onboard" ? "rafters_onboard was removed. Token import is now a CLI operation: run `rafters init` (auto-detects and prompts) or `rafters import` (standalone)." : "Available tools: rafters_workspaces, rafters_composite, rafters_rule, rafters_pattern, rafters_component.";
47080
47325
  return {
47081
47326
  content: [
47082
47327
  { type: "text", text: JSON.stringify({ error: `Unknown tool: ${name2}`, suggestion }) }
@@ -47085,6 +47330,54 @@ var RaftersToolHandler = class {
47085
47330
  }
47086
47331
  }
47087
47332
  }
47333
+ /**
47334
+ * Resolve the requested workspace, returning a structured error result when
47335
+ * the agent didn't pick one and there's no default. Returns the default
47336
+ * workspace (which may itself be null when no `.rafters/` exists at all)
47337
+ * for tools that read agent-shipped data and can degrade gracefully.
47338
+ */
47339
+ resolve(name2) {
47340
+ return resolveWorkspace(this.workspaces, this.defaultWorkspace, name2);
47341
+ }
47342
+ /**
47343
+ * Build a structured error response listing the available workspaces.
47344
+ * Use this when a tool requires a workspace and the agent didn't pick one.
47345
+ */
47346
+ workspaceRequiredError() {
47347
+ return {
47348
+ content: [
47349
+ {
47350
+ type: "text",
47351
+ text: JSON.stringify({
47352
+ error: "workspace parameter required",
47353
+ suggestion: "Multiple workspaces are available. Pass `workspace` with one of the names below.",
47354
+ workspaces: this.workspaces.map((w) => ({ name: w.name, root: w.root }))
47355
+ })
47356
+ }
47357
+ ]
47358
+ };
47359
+ }
47360
+ async handleWorkspaces() {
47361
+ return {
47362
+ content: [
47363
+ {
47364
+ type: "text",
47365
+ text: JSON.stringify(
47366
+ {
47367
+ workspaces: this.workspaces.map((w) => ({
47368
+ name: w.name,
47369
+ root: w.root,
47370
+ isDefault: w.name === this.defaultWorkspace?.name
47371
+ })),
47372
+ defaultWorkspace: this.defaultWorkspace?.name ?? null
47373
+ },
47374
+ null,
47375
+ 2
47376
+ )
47377
+ }
47378
+ ]
47379
+ };
47380
+ }
47088
47381
  async loadCompositesFromDir(dir) {
47089
47382
  try {
47090
47383
  const entries = await readdir3(dir);
@@ -47092,7 +47385,7 @@ var RaftersToolHandler = class {
47092
47385
  for (const file of files) {
47093
47386
  try {
47094
47387
  const { readFile: readFile9 } = await import("fs/promises");
47095
- const raw = await readFile9(join11(dir, file), "utf-8");
47388
+ const raw = await readFile9(join13(dir, file), "utf-8");
47096
47389
  const parsed = JSON.parse(raw);
47097
47390
  const result = CompositeFileSchema.safeParse(parsed);
47098
47391
  if (result.success) {
@@ -47107,23 +47400,29 @@ var RaftersToolHandler = class {
47107
47400
  } catch {
47108
47401
  }
47109
47402
  }
47110
- async ensureCompositesLoaded() {
47111
- if (this.compositesLoaded) return;
47112
- const builtInDirs = ["typography"];
47113
- for (const dir of builtInDirs) {
47114
- await this.loadCompositesFromDir(
47115
- join11(process.cwd(), "node_modules/@rafters/composites/src", dir)
47116
- );
47403
+ async ensureCompositesLoaded(workspace) {
47404
+ if (!this.builtInCompositesLoaded) {
47405
+ const builtInDirs = ["typography"];
47406
+ for (const dir of builtInDirs) {
47407
+ await this.loadCompositesFromDir(
47408
+ join13(process.cwd(), "node_modules/@rafters/composites/src", dir)
47409
+ );
47410
+ }
47411
+ this.builtInCompositesLoaded = true;
47117
47412
  }
47118
- if (this.projectRoot) {
47119
- const paths = getRaftersPaths(this.projectRoot);
47120
- await this.loadCompositesFromDir(join11(paths.root, "composites"));
47413
+ if (workspace && !this.compositesLoadedFor.has(workspace.root)) {
47414
+ const paths = getRaftersPaths(workspace.root);
47415
+ await this.loadCompositesFromDir(join13(paths.root, "composites"));
47416
+ this.compositesLoadedFor.add(workspace.root);
47121
47417
  }
47122
- this.compositesLoaded = true;
47123
47418
  }
47124
47419
  async handleComposite(args) {
47125
- await this.ensureCompositesLoaded();
47126
- const { id, query, category } = args;
47420
+ const { id, query, category, workspace } = args;
47421
+ const resolved = this.resolve(workspace);
47422
+ if (workspace && !resolved) {
47423
+ return this.workspaceRequiredError();
47424
+ }
47425
+ await this.ensureCompositesLoaded(resolved);
47127
47426
  let composites2;
47128
47427
  if (id) {
47129
47428
  const c4 = get2(id);
@@ -47190,8 +47489,12 @@ var RaftersToolHandler = class {
47190
47489
  return { content: [{ type: "text", text: JSON.stringify({ rules }, null, 2) }] };
47191
47490
  }
47192
47491
  async handlePattern(args) {
47193
- await this.ensureCompositesLoaded();
47194
- const { solves, query } = args;
47492
+ const { solves, query, workspace } = args;
47493
+ const resolved = this.resolve(workspace);
47494
+ if (workspace && !resolved) {
47495
+ return this.workspaceRequiredError();
47496
+ }
47497
+ await this.ensureCompositesLoaded(resolved);
47195
47498
  let composites2;
47196
47499
  if (solves) {
47197
47500
  const all = getAll2();
@@ -47268,8 +47571,8 @@ var RaftersToolHandler = class {
47268
47571
  };
47269
47572
 
47270
47573
  // src/mcp/server.ts
47271
- async function startMcpServer(projectRoot) {
47272
- const toolHandler = new RaftersToolHandler(projectRoot);
47574
+ async function startMcpServer(workspaces, defaultWorkspace) {
47575
+ const toolHandler = new RaftersToolHandler(workspaces, defaultWorkspace);
47273
47576
  const server = new Server(
47274
47577
  {
47275
47578
  name: "rafters",
@@ -47309,52 +47612,39 @@ async function startMcpServer(projectRoot) {
47309
47612
  });
47310
47613
  }
47311
47614
 
47312
- // src/utils/discover.ts
47313
- import { existsSync as existsSync5 } from "fs";
47314
- import { dirname as dirname4, join as join12, resolve as resolve4 } from "path";
47315
- function discoverProjectRoot(startDir) {
47316
- let current = resolve4(startDir);
47317
- for (; ; ) {
47318
- const configPath = join12(current, ".rafters", "config.rafters.json");
47319
- if (existsSync5(configPath)) {
47320
- return current;
47321
- }
47322
- const parent = dirname4(current);
47323
- if (parent === current) {
47324
- return null;
47325
- }
47326
- current = parent;
47327
- }
47328
- }
47329
-
47330
47615
  // src/commands/mcp.ts
47331
47616
  async function mcp(options) {
47332
- let projectRoot;
47617
+ let workspaces;
47618
+ let defaultWorkspace;
47333
47619
  if (options.projectRoot) {
47334
- const explicit = resolve5(options.projectRoot);
47335
- const configPath = join13(explicit, ".rafters", "config.rafters.json");
47336
- if (!existsSync6(configPath)) {
47620
+ const explicit = resolve6(options.projectRoot);
47621
+ const configPath = join14(explicit, ".rafters", "config.rafters.json");
47622
+ if (!existsSync7(configPath)) {
47337
47623
  process.stderr.write(
47338
47624
  `--project-root ${explicit} does not contain .rafters/config.rafters.json
47339
47625
  `
47340
47626
  );
47341
- projectRoot = null;
47627
+ workspaces = [];
47628
+ defaultWorkspace = null;
47342
47629
  } else {
47343
- projectRoot = explicit;
47630
+ const ws = { name: basename4(explicit), root: explicit };
47631
+ workspaces = [ws];
47632
+ defaultWorkspace = ws;
47344
47633
  }
47345
47634
  } else {
47346
- projectRoot = discoverProjectRoot(process.cwd());
47635
+ workspaces = discoverWorkspaces(process.cwd());
47636
+ defaultWorkspace = pickDefaultWorkspace(workspaces, process.cwd());
47347
47637
  }
47348
- await startMcpServer(projectRoot);
47638
+ await startMcpServer(workspaces, defaultWorkspace);
47349
47639
  }
47350
47640
 
47351
47641
  // src/commands/studio.ts
47352
- import { existsSync as existsSync7 } from "fs";
47353
- import { resolve as resolve6 } from "path";
47642
+ import { existsSync as existsSync8 } from "fs";
47643
+ import { resolve as resolve7 } from "path";
47354
47644
 
47355
47645
  // ../studio/src/api/vite-plugin.ts
47356
47646
  import { writeFile as writeFile5 } from "fs/promises";
47357
- import { join as join14 } from "path";
47647
+ import { join as join15 } from "path";
47358
47648
  var TokenResponseSchema = external_exports.object({
47359
47649
  ok: external_exports.literal(true),
47360
47650
  token: TokenSchema
@@ -47378,7 +47668,7 @@ var ColorBuildOptionsSchema = external_exports.object({
47378
47668
  states: external_exports.record(external_exports.string(), external_exports.string()).optional()
47379
47669
  });
47380
47670
  var projectPath = process.env.RAFTERS_PROJECT_PATH || process.cwd();
47381
- var outputPath = join14(projectPath, ".rafters", "output", "rafters.vars.css");
47671
+ var outputPath = join15(projectPath, ".rafters", "output", "rafters.vars.css");
47382
47672
  var SetTokenMessageSchema = external_exports.object({
47383
47673
  name: external_exports.string().min(1),
47384
47674
  value: external_exports.union([external_exports.string(), ColorValueSchema, ColorReferenceSchema]),
@@ -47497,7 +47787,7 @@ function getNamespacePatchSchema(namespace) {
47497
47787
  }
47498
47788
  var MAX_BODY_SIZE = 1024 * 1024;
47499
47789
  function readJsonBody(req) {
47500
- return new Promise((resolve7, reject) => {
47790
+ return new Promise((resolve8, reject) => {
47501
47791
  let body = "";
47502
47792
  let size = 0;
47503
47793
  req.on("data", (chunk) => {
@@ -47510,7 +47800,7 @@ function readJsonBody(req) {
47510
47800
  });
47511
47801
  req.on("end", () => {
47512
47802
  try {
47513
- resolve7(body ? JSON.parse(body) : {});
47803
+ resolve8(body ? JSON.parse(body) : {});
47514
47804
  } catch {
47515
47805
  reject(new Error("Invalid JSON body"));
47516
47806
  }
@@ -47963,7 +48253,7 @@ import { createServer } from "vite";
47963
48253
  async function studio() {
47964
48254
  const cwd = process.cwd();
47965
48255
  const paths = getRaftersPaths(cwd);
47966
- if (!existsSync7(paths.root)) {
48256
+ if (!existsSync8(paths.root)) {
47967
48257
  console.error('No .rafters/ directory found. Run "rafters init" first.');
47968
48258
  process.exit(1);
47969
48259
  }
@@ -47980,7 +48270,7 @@ async function studio() {
47980
48270
  },
47981
48271
  resolve: {
47982
48272
  alias: {
47983
- "@rafters-output": resolve6(cwd, ".rafters", "output")
48273
+ "@rafters-output": resolve7(cwd, ".rafters", "output")
47984
48274
  }
47985
48275
  }
47986
48276
  });
@@ -47991,7 +48281,10 @@ async function studio() {
47991
48281
  // src/index.ts
47992
48282
  var program = new Command();
47993
48283
  program.name("rafters").description("Design system CLI - scaffold tokens and serve MCP").version("0.0.1");
47994
- program.command("init").description("Initialize .rafters/ with default tokens and config").option("-r, --rebuild", "Regenerate output files from existing tokens").option("--reset", "Re-run generators fresh, replacing persisted tokens").option("--agent", "Output JSON for machine consumption").action(withErrorHandler(init));
48284
+ program.command("init").description("Initialize .rafters/ with default tokens and config").option("-r, --rebuild", "Regenerate output files from existing tokens").option("--reset", "Re-run generators fresh, replacing persisted tokens").option(
48285
+ "--framework <name>",
48286
+ "Override framework detection (next|vite|remix|react-router|astro|wc|vanilla)"
48287
+ ).option("--agent", "Output JSON for machine consumption").action(withErrorHandler(init));
47995
48288
  program.command("import").description("Import existing design tokens (Tailwind v4, shadcn, generic CSS)").option("--force", "Overwrite existing .rafters/import-pending.json").option("--importer <id>", "Force a specific importer (tailwind-v4, shadcn, generic-css)").option("--agent", "Output JSON for machine consumption").action(withErrorHandler(importCommand));
47996
48289
  program.command("add").description("Add rafters components to the project").argument("[components...]", "Component names to add").option("--list", "List available components").option("--overwrite", "Overwrite existing component files").option("--update", "Re-fetch named components from registry").option("--update-all", "Re-fetch all installed components from registry").option("--registry-url <url>", "Custom registry URL").option("--agent", "Output JSON for machine consumption").action(withErrorHandler(add));
47997
48290
  program.command("mcp").description("Start MCP server for AI agent access (stdio)").option("--project-root <path>", "Explicit project root (skips .rafters/ discovery)").action(mcp);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rafters",
3
- "version": "0.0.51",
3
+ "version": "0.0.53",
4
4
  "description": "CLI for Rafters design system - scaffold tokens and add components",
5
5
  "license": "MIT",
6
6
  "type": "module",