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.
- package/LICENSE +21 -0
- package/README.md +22 -28
- package/dist/index.js +70 -17
- 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
|
-
##
|
|
5
|
+
## Quick Start
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
|
|
8
|
+
pnpm dlx rafters init
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
|
|
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.
|
|
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
|
-
**
|
|
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
|
|
51
|
+
### `rafters mcp`
|
|
56
52
|
|
|
57
|
-
|
|
53
|
+
Start the MCP server for AI agent access via stdio transport.
|
|
58
54
|
|
|
59
55
|
```bash
|
|
60
|
-
rafters
|
|
56
|
+
pnpm dlx rafters mcp
|
|
61
57
|
```
|
|
62
58
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
### `rafters mcp`
|
|
59
|
+
### `rafters studio`
|
|
66
60
|
|
|
67
|
-
|
|
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
|
|
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
|
|
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)
|
|
104
|
-
- **Where** (Tokens)
|
|
105
|
-
- **Why** (Decisions)
|
|
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 =
|
|
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
|
-
|
|
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,
|
|
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 (
|
|
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,
|
|
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 (
|
|
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
|
|
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,
|
|
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,
|
|
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 (
|
|
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.
|
|
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",
|