rafters 0.0.7 → 0.0.8

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 (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +22 -28
  3. package/dist/index.js +70 -17
  4. package/package.json +4 -2
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Ezmode Games
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -2,32 +2,28 @@
2
2
 
3
3
  Design Intelligence CLI. Scaffold tokens, add components, and serve an MCP server so AI agents build UIs with designer-level judgment instead of guessing.
4
4
 
5
- ## Install
5
+ ## Quick Start
6
6
 
7
7
  ```bash
8
- npx rafters init
8
+ pnpm dlx rafters init
9
9
  ```
10
10
 
11
- Or install globally:
12
-
13
- ```bash
14
- pnpm add -g rafters
15
- ```
11
+ This detects your framework, scaffolds `.rafters/` with a complete token system, and generates output files.
16
12
 
17
13
  ## Commands
18
14
 
19
15
  ### `rafters init`
20
16
 
21
- Initialize a project with design tokens. Detects your framework, scaffolds `.rafters/` with a complete token system, and generates output files.
17
+ Initialize a project with design tokens.
22
18
 
23
19
  ```bash
24
- rafters init # Interactive setup
25
- rafters init --rebuild # Regenerate output files from existing tokens
26
- rafters init --reset # Re-run generators fresh, replacing persisted tokens
27
- rafters init --agent # JSON output for CI/machine consumption
20
+ pnpm dlx rafters init # Interactive setup
21
+ pnpm dlx rafters init --rebuild # Regenerate output files from existing tokens
22
+ pnpm dlx rafters init --reset # Re-run generators fresh, replacing persisted tokens
23
+ pnpm dlx rafters init --agent # JSON output for CI/machine consumption
28
24
  ```
29
25
 
30
- **Supported frameworks:** Next.js, Vite, Remix, React Router, Astro
26
+ **Detected frameworks:** Next.js, Vite, Remix, React Router, Astro
31
27
 
32
28
  **Export formats** (configured during init):
33
29
 
@@ -45,29 +41,27 @@ Automatically detects and migrates existing shadcn/ui color values. Requires Tai
45
41
  Add components from the Rafters registry to your project.
46
42
 
47
43
  ```bash
48
- rafters add button dialog # Add specific components
49
- rafters add --list # List all available components
50
- rafters add --overwrite # Replace existing files
44
+ pnpm dlx rafters add button dialog # Add specific components
45
+ pnpm dlx rafters add --list # List all available components
46
+ pnpm dlx rafters add --overwrite # Replace existing files
51
47
  ```
52
48
 
53
49
  Components include embedded design intelligence: cognitive load ratings (1-7), accessibility requirements, do/never guidance, and trust-building patterns. Dependencies are resolved automatically.
54
50
 
55
- ### `rafters studio`
51
+ ### `rafters mcp`
56
52
 
57
- Launch Studio for visual token editing.
53
+ Start the MCP server for AI agent access via stdio transport.
58
54
 
59
55
  ```bash
60
- rafters studio
56
+ pnpm dlx rafters mcp
61
57
  ```
62
58
 
63
- Opens a Vite-powered UI where you design by doing: pick a primary color, explain why, watch the system paint your scale. Every decision is recorded with reasoning so AI agents read intent instead of guessing.
64
-
65
- ### `rafters mcp`
59
+ ### `rafters studio`
66
60
 
67
- Start the MCP server for AI agent access via stdio transport.
61
+ Launch Studio for visual token editing. Spawns a local Vite dev server from the `@rafters/studio` package.
68
62
 
69
63
  ```bash
70
- rafters mcp
64
+ pnpm dlx rafters studio
71
65
  ```
72
66
 
73
67
  ## MCP Tools
@@ -96,13 +90,13 @@ Token dependency graph, derivation rules, and human override context. Returns ho
96
90
 
97
91
  ## How It Works
98
92
 
99
- Rafters is a Design Intelligence Protocol. AI agents don't have taste - they guess at colors, spacing, hierarchy. Rafters encodes a designer's judgment into queryable data so AI reads decisions instead of guessing.
93
+ Rafters is a Design Intelligence Protocol. AI agents don't have taste -- they guess at colors, spacing, hierarchy. Rafters encodes a designer's judgment into queryable data so AI reads decisions instead of guessing.
100
94
 
101
95
  Three layers:
102
96
 
103
- - **What** (Components) - 55 React components with embedded intelligence metadata
104
- - **Where** (Tokens) - 240+ tokens with dependency graph and human override tracking
105
- - **Why** (Decisions) - Do/never patterns, cognitive load scores, trust patterns, accessibility requirements
97
+ - **What** (Components) -- 55 React components with embedded intelligence metadata
98
+ - **Where** (Tokens) -- 240+ tokens with dependency graph and human override tracking
99
+ - **Why** (Decisions) -- Do/never patterns, cognitive load scores, trust patterns, accessibility requirements
106
100
 
107
101
  The token system uses OKLCH color space, modular scales based on musical ratios, and a dependency engine that automatically derives related values. When a designer overrides a computed value, the system records the reason so AI agents respect the intent.
108
102
 
package/dist/index.js CHANGED
@@ -12735,6 +12735,9 @@ var context = {
12735
12735
  function setAgentMode(agent) {
12736
12736
  context.agent = agent;
12737
12737
  }
12738
+ function isAgentMode() {
12739
+ return context.agent;
12740
+ }
12738
12741
  function log(event) {
12739
12742
  if (context.agent) {
12740
12743
  console.log(JSON.stringify(event));
@@ -12888,6 +12891,20 @@ function error46(message) {
12888
12891
  context.spinner?.fail(message);
12889
12892
  context.spinner = null;
12890
12893
  }
12894
+ function withErrorHandler(action) {
12895
+ return async (...args) => {
12896
+ try {
12897
+ await action(...args);
12898
+ } catch (err) {
12899
+ const message = err instanceof Error ? err.message : String(err);
12900
+ error46(message);
12901
+ if (process.env.DEBUG && err instanceof Error && err.stack) {
12902
+ console.error(err.stack);
12903
+ }
12904
+ process.exitCode = 1;
12905
+ }
12906
+ };
12907
+ }
12891
12908
 
12892
12909
  // src/utils/update-dependencies.ts
12893
12910
  import { execa } from "execa";
@@ -13183,8 +13200,9 @@ async function add(components, options) {
13183
13200
  // src/commands/init.ts
13184
13201
  import { existsSync as existsSync2 } from "fs";
13185
13202
  import { copyFile, mkdir as mkdir3, readFile as readFile4, rm, writeFile as writeFile3 } from "fs/promises";
13203
+ import { createRequire } from "module";
13186
13204
  import { join as join8, relative } from "path";
13187
- import { checkbox } from "@inquirer/prompts";
13205
+ import { checkbox, confirm } from "@inquirer/prompts";
13188
13206
 
13189
13207
  // ../design-tokens/src/plugins/scale.ts
13190
13208
  function scale(registry2, tokenName, dependencies) {
@@ -46488,8 +46506,8 @@ async function registryToCompiled(registry2, options = {}) {
46488
46506
  const { execFileSync } = await import("child_process");
46489
46507
  const { mkdtempSync, writeFileSync, readFileSync, rmSync } = await import("fs");
46490
46508
  const { join: join11, dirname: dirname4 } = await import("path");
46491
- const { createRequire } = await import("module");
46492
- const require2 = createRequire(import.meta.url);
46509
+ const { createRequire: createRequire2 } = await import("module");
46510
+ const require2 = createRequire2(import.meta.url);
46493
46511
  let pkgDir;
46494
46512
  try {
46495
46513
  const pkgJsonPath = require2.resolve("@tailwindcss/cli/package.json");
@@ -50634,7 +50652,39 @@ async function promptExportFormats(existingConfig) {
50634
50652
  });
50635
50653
  return selectionsToConfig(selections);
50636
50654
  }
50637
- async function generateOutputs(paths, registry2, exports, shadcn) {
50655
+ function isTailwindCliInstalled() {
50656
+ const require2 = createRequire(import.meta.url);
50657
+ try {
50658
+ require2.resolve("@tailwindcss/cli/package.json");
50659
+ return true;
50660
+ } catch (err) {
50661
+ if (err instanceof Error && "code" in err && err.code === "MODULE_NOT_FOUND") {
50662
+ return false;
50663
+ }
50664
+ throw err;
50665
+ }
50666
+ }
50667
+ async function ensureTailwindCli(cwd) {
50668
+ if (!isInteractive() || isAgentMode()) {
50669
+ throw new Error(
50670
+ "Standalone CSS export requires @tailwindcss/cli. Install it as a dev dependency in your project."
50671
+ );
50672
+ }
50673
+ const shouldInstall = await confirm({
50674
+ message: "Standalone CSS requires @tailwindcss/cli. Install it now?",
50675
+ default: true
50676
+ });
50677
+ if (!shouldInstall) {
50678
+ throw new Error("Standalone CSS export requires @tailwindcss/cli.");
50679
+ }
50680
+ await updateDependencies([], ["@tailwindcss/cli"], { cwd });
50681
+ if (!isTailwindCliInstalled()) {
50682
+ throw new Error(
50683
+ "@tailwindcss/cli was installed but cannot be resolved. Try installing at the workspace root."
50684
+ );
50685
+ }
50686
+ }
50687
+ async function generateOutputs(cwd, paths, registry2, exports, shadcn) {
50638
50688
  const outputs = [];
50639
50689
  if (exports.tailwind) {
50640
50690
  const tailwindCss = registryToTailwind(registry2, { includeImport: !shadcn });
@@ -50652,6 +50702,9 @@ async function generateOutputs(paths, registry2, exports, shadcn) {
50652
50702
  outputs.push("rafters.json");
50653
50703
  }
50654
50704
  if (exports.compiled) {
50705
+ if (!isTailwindCliInstalled()) {
50706
+ await ensureTailwindCli(cwd);
50707
+ }
50655
50708
  log({ event: "init:compiling_css" });
50656
50709
  const compiledCss = await registryToCompiled(registry2, { includeImport: !shadcn });
50657
50710
  await writeFile3(join8(paths.output, "rafters.standalone.css"), compiledCss);
@@ -50659,7 +50712,7 @@ async function generateOutputs(paths, registry2, exports, shadcn) {
50659
50712
  }
50660
50713
  return outputs;
50661
50714
  }
50662
- async function regenerateFromExisting(cwd, paths, shadcn, isAgentMode) {
50715
+ async function regenerateFromExisting(cwd, paths, shadcn, isAgentMode2) {
50663
50716
  log({ event: "init:regenerate", cwd });
50664
50717
  let existingConfig = null;
50665
50718
  try {
@@ -50680,7 +50733,7 @@ async function regenerateFromExisting(cwd, paths, shadcn, isAgentMode) {
50680
50733
  });
50681
50734
  const registry2 = new TokenRegistry(allTokens);
50682
50735
  let exports;
50683
- if (isAgentMode) {
50736
+ if (isAgentMode2) {
50684
50737
  exports = existingConfig?.exports ?? DEFAULT_EXPORTS;
50685
50738
  log({ event: "init:exports_default", exports });
50686
50739
  } else {
@@ -50691,7 +50744,7 @@ async function regenerateFromExisting(cwd, paths, shadcn, isAgentMode) {
50691
50744
  log({ event: "init:exports_selected", exports });
50692
50745
  }
50693
50746
  await mkdir3(paths.output, { recursive: true });
50694
- const outputs = await generateOutputs(paths, registry2, exports, shadcn);
50747
+ const outputs = await generateOutputs(cwd, paths, registry2, exports, shadcn);
50695
50748
  if (existingConfig) {
50696
50749
  existingConfig.exports = exports;
50697
50750
  await writeFile3(paths.config, JSON.stringify(existingConfig, null, 2));
@@ -50702,7 +50755,7 @@ async function regenerateFromExisting(cwd, paths, shadcn, isAgentMode) {
50702
50755
  path: paths.output
50703
50756
  });
50704
50757
  }
50705
- async function resetToDefaults(cwd, paths, shadcn, isAgentMode) {
50758
+ async function resetToDefaults(cwd, paths, shadcn, isAgentMode2) {
50706
50759
  log({ event: "init:reset", cwd });
50707
50760
  let existingConfig = null;
50708
50761
  try {
@@ -50735,7 +50788,7 @@ async function resetToDefaults(cwd, paths, shadcn, isAgentMode) {
50735
50788
  });
50736
50789
  }
50737
50790
  let exports;
50738
- if (isAgentMode) {
50791
+ if (isAgentMode2) {
50739
50792
  exports = existingConfig?.exports ?? DEFAULT_EXPORTS;
50740
50793
  log({ event: "init:exports_default", exports });
50741
50794
  } else {
@@ -50768,7 +50821,7 @@ async function resetToDefaults(cwd, paths, shadcn, isAgentMode) {
50768
50821
  namespaceCount
50769
50822
  });
50770
50823
  await mkdir3(paths.output, { recursive: true });
50771
- const outputs = await generateOutputs(paths, registry2, exports, shadcn);
50824
+ const outputs = await generateOutputs(cwd, paths, registry2, exports, shadcn);
50772
50825
  if (existingConfig) {
50773
50826
  existingConfig.exports = exports;
50774
50827
  await writeFile3(paths.config, JSON.stringify(existingConfig, null, 2));
@@ -50781,7 +50834,7 @@ async function resetToDefaults(cwd, paths, shadcn, isAgentMode) {
50781
50834
  }
50782
50835
  async function init(options) {
50783
50836
  setAgentMode(options.agent ?? false);
50784
- const isAgentMode = options.agent ?? false;
50837
+ const isAgentMode2 = options.agent ?? false;
50785
50838
  const cwd = process.cwd();
50786
50839
  const paths = getRaftersPaths(cwd);
50787
50840
  log({ event: "init:start", cwd });
@@ -50800,7 +50853,7 @@ async function init(options) {
50800
50853
  throw new Error("Nothing to reset. No .rafters/ directory found.");
50801
50854
  }
50802
50855
  if (raftersExists && options.reset) {
50803
- await resetToDefaults(cwd, paths, shadcn, isAgentMode);
50856
+ await resetToDefaults(cwd, paths, shadcn, isAgentMode2);
50804
50857
  return;
50805
50858
  }
50806
50859
  if (raftersExists && !options.rebuild) {
@@ -50809,7 +50862,7 @@ async function init(options) {
50809
50862
  );
50810
50863
  }
50811
50864
  if (raftersExists && options.rebuild) {
50812
- await regenerateFromExisting(cwd, paths, shadcn, isAgentMode);
50865
+ await regenerateFromExisting(cwd, paths, shadcn, isAgentMode2);
50813
50866
  return;
50814
50867
  }
50815
50868
  let existingColors = null;
@@ -50833,7 +50886,7 @@ async function init(options) {
50833
50886
  }
50834
50887
  }
50835
50888
  let exports;
50836
- if (isAgentMode) {
50889
+ if (isAgentMode2) {
50837
50890
  exports = DEFAULT_EXPORTS;
50838
50891
  log({ event: "init:exports_default", exports });
50839
50892
  } else {
@@ -50899,7 +50952,7 @@ async function init(options) {
50899
50952
  path: paths.tokens,
50900
50953
  namespaceCount
50901
50954
  });
50902
- const outputs = await generateOutputs(paths, registry2, exports, shadcn);
50955
+ const outputs = await generateOutputs(cwd, paths, registry2, exports, shadcn);
50903
50956
  let detectedCssPath = null;
50904
50957
  if (!shadcn && exports.tailwind) {
50905
50958
  detectedCssPath = await findMainCssFile(cwd, framework);
@@ -51896,8 +51949,8 @@ async function studio() {
51896
51949
  // src/index.ts
51897
51950
  var program = new Command();
51898
51951
  program.name("rafters").description("Design system CLI - scaffold tokens and serve MCP").version("0.0.1");
51899
- 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(init);
51900
- 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("--registry-url <url>", "Custom registry URL").option("--agent", "Output JSON for machine consumption").action(add);
51952
+ 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));
51953
+ 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("--registry-url <url>", "Custom registry URL").option("--agent", "Output JSON for machine consumption").action(withErrorHandler(add));
51901
51954
  program.command("mcp").description("Start MCP server for AI agent access (stdio)").action(mcp);
51902
51955
  program.command("studio").description("Open Studio UI for visual token editing").action(studio);
51903
51956
  program.parse();
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "rafters",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "description": "CLI for Rafters design system - scaffold tokens and add components",
5
+ "license": "MIT",
5
6
  "type": "module",
6
7
  "bin": {
7
8
  "rafters": "./dist/index.js"
@@ -10,7 +11,8 @@
10
11
  ".": "./dist/index.js"
11
12
  },
12
13
  "files": [
13
- "dist"
14
+ "dist",
15
+ "LICENSE"
14
16
  ],
15
17
  "dependencies": {
16
18
  "@antfu/ni": "^28.1.0",