@design-twin/dtwin 0.1.0-alpha.0 → 0.1.1
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 +47 -4
- package/figma-plugin/code.js +4289 -0
- package/figma-plugin/manifest.json +28 -0
- package/figma-plugin/ui.html +722 -0
- package/layer/cross-check.js +2746 -0
- package/layer/drift-lint.js +1526 -0
- package/layer/get-component.js +553 -0
- package/layer/map-bootstrap.js +1404 -0
- package/layer/map-validate.js +397 -0
- package/package.json +5 -1
- package/src/commands.ts +14 -1
- package/src/figma-mcp.ts +51 -20
- package/src/figma-pull.ts +5 -0
- package/src/init.ts +37 -12
package/README.md
CHANGED
|
@@ -7,13 +7,31 @@ The plugin's hidden UI iframe is a WebSocket **client**; these processes are the
|
|
|
7
7
|
(`127.0.0.1:8787`). Nothing touches the internet. See `../ARCHITECTURE.md` for the full design.
|
|
8
8
|
|
|
9
9
|
## Install (once)
|
|
10
|
-
|
|
10
|
+
It needs [Bun](https://bun.sh/install) ≥ 1.4.2 (`engines.bun`) on your PATH; Node is not supported. Install Bun
|
|
11
|
+
first (`curl -fsSL https://bun.sh/install | bash`, or `powershell -c "irm bun.sh/install.ps1 | iex"` on Windows), then
|
|
12
|
+
the package, `@design-twin/dtwin`, from npm:
|
|
13
|
+
```
|
|
14
|
+
bun add -g @design-twin/dtwin # puts `dtwin` in ~/.bun/bin (on your PATH via the Bun installer)
|
|
15
|
+
```
|
|
16
|
+
`npm i -g @design-twin/dtwin` installs the same thing, but `dtwin` still runs on Bun: without Bun on PATH it stops at
|
|
17
|
+
`env: bun: No such file or directory`. The package also carries the built Figma plugin (`figma-plugin/manifest.json`
|
|
18
|
+
inside it — `dtwin init` prints the full path to import) and the design-to-code bundles the MCP server's
|
|
19
|
+
`design_get_component` / `design_drift_lint` load (`layer/`).
|
|
20
|
+
|
|
21
|
+
Or with Homebrew (macOS, Linux), which installs Bun for you and keeps both up to date with `brew upgrade`:
|
|
22
|
+
```
|
|
23
|
+
brew install its-magdy/tap/dtwin
|
|
24
|
+
```
|
|
25
|
+
The formula installs the same npm package into Homebrew's prefix; every release updates it. Paths `dtwin init` writes
|
|
26
|
+
(the `.mcp.json` server entry, the plugin manifest it prints) are spelt through `$(brew --prefix)/opt/dtwin/…`, which
|
|
27
|
+
survives an upgrade — not the versioned `Cellar/dtwin/<version>/` folder the next `brew upgrade` deletes.
|
|
28
|
+
|
|
29
|
+
Or from a clone (to work on the code):
|
|
11
30
|
```
|
|
12
31
|
git clone https://github.com/its-magdy/design-twin.git && cd design-twin
|
|
13
32
|
bun install # @modelcontextprotocol/sdk (+ zod), for every workspace
|
|
14
33
|
cd bridge && bun link # puts `dtwin` in ~/.bun/bin (on your PATH); nothing to build
|
|
15
34
|
```
|
|
16
|
-
It needs [Bun](https://bun.sh/install) ≥ 1.4.2 (`engines.bun`); Node is not supported.
|
|
17
35
|
Or skip the link and run `bun --no-install --no-env-file /path/to/design-twin/bridge/src/figma-pull.ts` wherever
|
|
18
36
|
this README says `dtwin` (those two flags are what the bin's shebang adds: without them, Bun loads the `.env` of the
|
|
19
37
|
project you run it in and may fetch a missing package from the registry).
|
|
@@ -34,7 +52,7 @@ validated against them and exits rather than binding a port nothing could ever r
|
|
|
34
52
|
**Languages:** the whole bridge is **TypeScript** (ESM) under `src/` — `figma-pull.ts` (read CLI),
|
|
35
53
|
`server-core.ts` (WS core), `figma-mcp.ts` (MCP server), and the modules they share. From a checkout,
|
|
36
54
|
Bun runs it directly with **zero build** (`bun bridge/src/figma-pull.ts …`, `bun bridge/src/figma-mcp.ts`), and the
|
|
37
|
-
package ships the same TypeScript: its `dtwin` bin — what `bun link` puts on your PATH — is `src/figma-pull.ts`,
|
|
55
|
+
package ships the same TypeScript: its `dtwin` bin — what `bun add -g` or `bun link` puts on your PATH — is `src/figma-pull.ts`,
|
|
38
56
|
whose shebang is `#!/usr/bin/env -S bun --no-install --no-env-file` (so a `.env` or a missing package in the
|
|
39
57
|
project you run it from can neither change its environment nor make Bun fetch a module from the registry;
|
|
40
58
|
`env -S` needs GNU coreutils ≥ 8.30 or a BSD/macOS `env` — on BusyBox, call `bun --no-install --no-env-file` on
|
|
@@ -801,13 +819,38 @@ execution**, unlike some community servers; a `fill` / `color` must be a hex col
|
|
|
801
819
|
`#rrggbb` or `#rrggbbaa` with the `#`, never a name like `red` — and anything else is refused (by the
|
|
802
820
|
schema here, and by the plugin for a write from another client) instead of painted as a wrong colour; `dryRun: true` returns a preview of what each op would
|
|
803
821
|
create or overwrite without touching the file — there is no undo from the MCP side, so preview anything
|
|
804
|
-
that overwrites; refused outright when the file is in read-only Dev Mode
|
|
822
|
+
that overwrites; refused outright when the file is in read-only Dev Mode — and **refused unless the designer has
|
|
823
|
+
ticked "Allow edits"** in the plugin window, see below), and two that read the export already on disk and
|
|
805
824
|
need no Figma connection — `design_get_component` (one component's variant node trees) and
|
|
806
825
|
`design_drift_lint` (the component map vs the export; see below). The frame-walking export tools accept opt-in read flags
|
|
807
826
|
`css` / `measurements` / `pluginData` / `motion` / `sharedData`; `figma_export_design_system` doesn't
|
|
808
827
|
take them (it never walks a node — see below) but DOES take `variantVisuals`, since the component
|
|
809
828
|
catalog it builds is exactly what that flag enriches.
|
|
810
829
|
|
|
830
|
+
### "Allow edits" — the plugin changes nothing until the designer opts in
|
|
831
|
+
The plugin window has an **Allow edits** checkbox, **off by default**. While it is off the plugin only reads:
|
|
832
|
+
every `figma_write` batch is refused whole, before any op runs, and the tool returns this error (nothing in the
|
|
833
|
+
file changed):
|
|
834
|
+
|
|
835
|
+
> Edits are off in the Design Twin plugin — tick 'Allow edits' in the plugin window, then retry. Nothing in the file was changed.
|
|
836
|
+
|
|
837
|
+
That is not something an agent can fix. **Ask the user to tick "Allow edits" in the Design Twin plugin window,
|
|
838
|
+
then retry the same call.** The plugin's main thread holds the setting and checks it on every write; nothing on
|
|
839
|
+
the bridge side can turn it on.
|
|
840
|
+
|
|
841
|
+
- **Dry run still works while it is off.** `dryRun: true` previews the batch as before and adds `editsAllowed`
|
|
842
|
+
(read from the plugin's `whoami`): `false` → a real write would be refused right now (the preview also carries
|
|
843
|
+
`wouldRefuse` with the sentence above); `true` → it would be applied; `null` → unknown (no plugin connected,
|
|
844
|
+
several connected with no `client`, or a plugin built before the opt-in). Check it before asking the user to
|
|
845
|
+
review a preview, so the request to tick the box comes in the same breath.
|
|
846
|
+
- **The setting is per user, for every file.** It is saved in Figma's `clientStorage`, which is already scoped
|
|
847
|
+
to one user and this plugin. It is not per file: the plugin cannot reliably name a file (`fileKey` is only for
|
|
848
|
+
private plugins, and file names repeat), and a per-file flag stored in the document would itself be an edit.
|
|
849
|
+
Untick it when you are done.
|
|
850
|
+
- **No write is silent.** Each applied batch (and each refused one) shows a Figma toast and a line in the plugin
|
|
851
|
+
window, e.g. "Design Twin applied 3 edits to this file."
|
|
852
|
+
- `dtwin whoami` prints the state (`edits: off — …` / `edits: ALLOWED — …`) and `editsAllowed` is in its JSON.
|
|
853
|
+
|
|
811
854
|
### `writeToDisk` — the export path that doesn't go through the context window
|
|
812
855
|
Every export tool takes `writeToDisk: true` (plus an optional `outDir`). It writes the export through
|
|
813
856
|
the same `write-out.ts` the CLI uses — same layout, by construction — and returns a **compact index**
|