@motion-proto/live-tokens 0.74.0 → 0.76.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.
Files changed (171) hide show
  1. package/.claude/skills/live-tokens-check-compliance/SKILL.md +33 -38
  2. package/.claude/skills/live-tokens-create-component/SKILL copy.md +196 -0
  3. package/.claude/skills/live-tokens-create-component/SKILL.md +198 -146
  4. package/.claude/skills/live-tokens-create-component/references/contract-tests.md +95 -52
  5. package/.claude/skills/live-tokens-create-component/references/intrinsics.md +2 -2
  6. package/.claude/skills/live-tokens-create-component/references/linked-siblings.md +2 -2
  7. package/.claude/skills/live-tokens-create-component/references/sketch-mode.md +12 -12
  8. package/.claude/skills/live-tokens-create-component/references/token-naming.md +2 -1
  9. package/.claude/skills/live-tokens-create-page/SKILL.md +187 -0
  10. package/.claude/skills/live-tokens-create-page/references/interaction-sources.md +66 -0
  11. package/.claude/skills/live-tokens-create-page/references/layout-sources.md +87 -0
  12. package/.claude/skills/live-tokens-create-theme/SKILL.md +52 -48
  13. package/.claude/skills/live-tokens-create-theme/references/design-directions.md +1 -1
  14. package/.claude/skills/live-tokens-fix-findings/SKILL.md +69 -60
  15. package/.claude/skills/live-tokens-pick-component/SKILL.md +64 -79
  16. package/.claude/skills/live-tokens-set-colors/SKILL.md +47 -38
  17. package/.claude/skills/live-tokens-set-geometry/SKILL.md +58 -35
  18. package/.claude/skills/live-tokens-set-geometry/references/geometry-anchors.md +5 -3
  19. package/.claude/skills/live-tokens-set-type/SKILL.md +30 -30
  20. package/CHANGELOG.md +138 -0
  21. package/README.md +17 -7
  22. package/bin/check-component.mjs +91 -19
  23. package/bin/check-page.mjs +102 -21
  24. package/bin/cli.mjs +87 -113
  25. package/bin/contractRunner.mjs +945 -0
  26. package/bin/create.mjs +1 -1
  27. package/bin/lib/catalogue.mjs +37 -30
  28. package/bin/lib/findings.mjs +46 -15
  29. package/bin/lib/report.mjs +3 -3
  30. package/bin/lib/tokenVocabulary.mjs +4 -4
  31. package/bin/migrate-routes.mjs +5 -5
  32. package/bin/migrate.mjs +4 -4
  33. package/bin/save-theme.mjs +8 -9
  34. package/bin/set-colors.mjs +9 -11
  35. package/bin/set-geometry.mjs +7 -7
  36. package/bin/set-type.mjs +5 -7
  37. package/bin/setup-claude.mjs +110 -0
  38. package/dist-plugin/{chunk-W6Y4BWFB.js → chunk-6WGFOJXO.js} +22 -0
  39. package/dist-plugin/{chunk-7VRTBGJT.js → chunk-PDNL4NC5.js} +9 -2
  40. package/dist-plugin/{chunk-V3YF6CGT.js → chunk-SWXRVZKT.js} +43 -1
  41. package/dist-plugin/{dataPaths-BhWzd5cL.d.cts → dataPaths-BpIK_Obx.d.cts} +1 -0
  42. package/dist-plugin/{dataPaths-BhWzd5cL.d.ts → dataPaths-BpIK_Obx.d.ts} +1 -0
  43. package/dist-plugin/index.cjs +310 -147
  44. package/dist-plugin/index.d.cts +1 -1
  45. package/dist-plugin/index.d.ts +1 -1
  46. package/dist-plugin/index.js +218 -122
  47. package/dist-plugin/migrateData/index.cjs +66 -2
  48. package/dist-plugin/migrateData/index.d.cts +1 -1
  49. package/dist-plugin/migrateData/index.d.ts +1 -1
  50. package/dist-plugin/migrateData/index.js +3 -3
  51. package/dist-plugin/setColors/index.cjs +61 -4
  52. package/dist-plugin/setColors/index.d.cts +1 -1
  53. package/dist-plugin/setColors/index.d.ts +1 -1
  54. package/dist-plugin/setColors/index.js +5 -5
  55. package/dist-plugin/setGeometry/index.cjs +107 -44
  56. package/dist-plugin/setGeometry/index.d.cts +5 -5
  57. package/dist-plugin/setGeometry/index.d.ts +5 -5
  58. package/dist-plugin/setGeometry/index.js +51 -45
  59. package/dist-plugin/setType/index.cjs +15 -0
  60. package/dist-plugin/setType/index.d.cts +1 -1
  61. package/dist-plugin/setType/index.d.ts +1 -1
  62. package/dist-plugin/setType/index.js +1 -1
  63. package/dist-plugin/tokensCssMigrations/index.d.cts +1 -1
  64. package/dist-plugin/tokensCssMigrations/index.d.ts +1 -1
  65. package/dist-plugin/tokensCssMigrations/index.js +1 -1
  66. package/package.json +35 -8
  67. package/src/app/site.css +19 -9
  68. package/src/editor/bootstrap.ts +2 -0
  69. package/src/editor/component-editor/CollapsibleSectionEditor.svelte +4 -4
  70. package/src/editor/component-editor/DialogEditor.svelte +4 -4
  71. package/src/editor/component-editor/MenuSelectEditor.svelte +4 -1
  72. package/src/editor/component-editor/SegmentedControlEditor.svelte +6 -1
  73. package/src/editor/component-editor/TabBarEditor.svelte +1 -1
  74. package/src/editor/component-editor/TableEditor.svelte +2 -2
  75. package/src/editor/component-editor/scaffolding/TokenLayout.svelte +6 -3
  76. package/src/editor/component-editor/scaffolding/VariantGroup.svelte +41 -20
  77. package/src/editor/core/components/adjustAliases.ts +59 -45
  78. package/src/editor/core/components/aliasKinds.ts +9 -5
  79. package/src/editor/core/preview/themePreview.ts +9 -2
  80. package/src/editor/core/sketch/sketchLayer.ts +22 -0
  81. package/src/editor/core/store/editorStore.ts +10 -1
  82. package/src/editor/core/themes/buildColors.ts +3 -3
  83. package/src/editor/core/themes/liveStateStream.ts +26 -0
  84. package/src/editor/core/themes/migrations/2026-09-07-stroke-role-renames.ts +52 -0
  85. package/src/editor/core/themes/migrations/index.ts +2 -0
  86. package/src/editor/core/themes/themeDocumentSync.ts +22 -11
  87. package/src/editor/core/themes/themeService.ts +9 -2
  88. package/src/editor/pages/ComponentEditorPage.svelte +17 -1
  89. package/src/editor/pages/liveTokensEditorHandle.ts +23 -0
  90. package/src/editor/skill-atlas/SkillAtlas.svelte +75 -573
  91. package/src/editor/skill-atlas/TreeCanvas.svelte +263 -0
  92. package/src/editor/skill-atlas/TreeNodeCard.svelte +136 -53
  93. package/src/editor/skill-atlas/edges.ts +31 -0
  94. package/src/editor/skill-atlas/skillSources.generated.ts +20 -19
  95. package/src/editor/skill-atlas/skillTrees.ts +19 -3840
  96. package/src/editor/skill-atlas/trees/check-compliance.ts +183 -0
  97. package/src/editor/skill-atlas/trees/create-component.ts +275 -0
  98. package/src/editor/skill-atlas/trees/create-page.ts +320 -0
  99. package/src/editor/skill-atlas/trees/create-theme.ts +255 -0
  100. package/src/editor/skill-atlas/trees/fix-findings.ts +469 -0
  101. package/src/editor/skill-atlas/trees/pick-component.ts +300 -0
  102. package/src/editor/skill-atlas/trees/set-colors.ts +148 -0
  103. package/src/editor/skill-atlas/trees/set-geometry.ts +136 -0
  104. package/src/editor/skill-atlas/trees/set-type.ts +142 -0
  105. package/src/editor/skill-atlas/types.ts +3 -4
  106. package/src/editor/skill-atlas/wireLayout.ts +287 -0
  107. package/src/live-tokens/data/themes/autumn.json +15 -15
  108. package/src/live-tokens/data/themes/halloween.json +15 -15
  109. package/src/live-tokens/data/themes/midnight-study.json +15 -15
  110. package/src/live-tokens/data/themes/ocean.json +15 -15
  111. package/src/live-tokens/data/themes/royal-velvet.json +15 -15
  112. package/src/live-tokens/data/themes/sketchy.json +15 -15
  113. package/src/live-tokens/data/themes/spring-meadow.json +15 -15
  114. package/src/live-tokens/data/themes/sunset.json +15 -15
  115. package/src/system/components/Badge.svelte +7 -0
  116. package/src/system/components/Button.svelte +7 -0
  117. package/src/system/components/Callout.svelte +10 -6
  118. package/src/system/components/Card.svelte +23 -4
  119. package/src/system/components/CodeSnippet.svelte +4 -3
  120. package/src/system/components/CollapsibleSection.svelte +23 -8
  121. package/src/system/components/CornerBadge.svelte +6 -0
  122. package/src/system/components/Dialog.svelte +13 -6
  123. package/src/system/components/IconButton.svelte +9 -0
  124. package/src/system/components/Image.svelte +8 -0
  125. package/src/system/components/ImageLightbox.svelte +6 -0
  126. package/src/system/components/InlineEditActions.svelte +7 -0
  127. package/src/system/components/Input.svelte +7 -0
  128. package/src/system/components/MenuSelect.svelte +7 -0
  129. package/src/system/components/Notification.svelte +7 -0
  130. package/src/system/components/Panel.svelte +6 -0
  131. package/src/system/components/ProgressBar.svelte +5 -0
  132. package/src/system/components/RadioButton.svelte +11 -5
  133. package/src/system/components/SectionDivider.svelte +8 -0
  134. package/src/system/components/SegmentedControl.svelte +6 -0
  135. package/src/system/components/SideNavigation.svelte +6 -0
  136. package/src/system/components/Slider.svelte +7 -4
  137. package/src/system/components/TabBar.svelte +15 -9
  138. package/src/system/components/Table.svelte +8 -3
  139. package/src/system/components/Toggle.svelte +4 -4
  140. package/src/system/components/Tooltip.svelte +6 -0
  141. package/src/testing-js/chunk-AO7EZHYV.js +776 -0
  142. package/src/testing-js/chunk-AO7EZHYV.js.map +1 -0
  143. package/src/testing-js/chunk-FAFOAWYL.js +39 -0
  144. package/src/testing-js/chunk-FAFOAWYL.js.map +1 -0
  145. package/src/testing-js/chunk-L73N4NSO.js +23 -0
  146. package/src/testing-js/chunk-L73N4NSO.js.map +1 -0
  147. package/src/testing-js/chunk-LXR3MN6N.js +3063 -0
  148. package/src/testing-js/chunk-LXR3MN6N.js.map +1 -0
  149. package/src/testing-js/chunk-ZMSX6CXR.js +53 -0
  150. package/src/testing-js/chunk-ZMSX6CXR.js.map +1 -0
  151. package/src/testing-js/component-alias.contract.js +81 -0
  152. package/src/testing-js/component-alias.contract.js.map +1 -0
  153. package/src/testing-js/component-editor.contract.js +62 -0
  154. package/src/testing-js/component-editor.contract.js.map +1 -0
  155. package/src/testing-js/component-render.contract.js +568 -0
  156. package/src/testing-js/component-render.contract.js.map +1 -0
  157. package/src/testing-js/index.d.ts +293 -0
  158. package/src/testing-js/index.js +222 -0
  159. package/src/testing-js/index.js.map +1 -0
  160. package/src/testing-js/registry.contract.js +39 -0
  161. package/src/testing-js/registry.contract.js.map +1 -0
  162. package/src/testing-js/vitest-BE6uGF31.d.ts +73 -0
  163. package/src/testing-js/vitest.d.ts +3 -0
  164. package/src/testing-js/vitest.js +13 -0
  165. package/src/testing-js/vitest.js.map +1 -0
  166. package/template/README.md +13 -0
  167. package/template/_gitignore +6 -0
  168. package/template/package.json +3 -1
  169. package/template/src/pages/Home.svelte +4 -18
  170. package/.claude/skills/live-tokens-build-page/SKILL.md +0 -103
  171. package/.claude/skills/live-tokens-build-page/references/layout-sources.md +0 -48
@@ -1,21 +1,26 @@
1
1
  ---
2
2
  name: live-tokens-set-geometry
3
- description: Adjust corner radius, padding, gap, and border width across live-tokens components by moving each token alias along the shipped scales. Use when the user asks for pill or capsule buttons; rounded, rounder, sharp, sharper, square, softer, or harder corners; thicker or thinner borders; or density: space it out, tighter, denser, more compact, airier, more breathing room. Also invoked by live-tokens-create-theme, which supplies the geometry intent for a whole look. Changes shape and space aliases per component, never color, fonts, or tokens.css. Not for editing a single token (use the editor) or for a whole look (see live-tokens-create-theme).
3
+ description: Set a live-tokens theme's geometry: corner radius, padding, gap, and border width. Each moves per component along its shipped scale. Called with an anchor and a geometry intent by live-tokens-create-theme, or with the user's request directly. Use when the user asks for pill or capsule buttons. Use when the user asks for rounded, sharp, square, softer, or harder corners. Use when the user asks for thicker or thinner borders. Use when the user asks for density: space it out, tighter, denser, airier. Changes geometry only. For a request that also names color or type, read live-tokens-create-theme.
4
4
  ---
5
5
 
6
- # Adjusting geometry
6
+ # Setting a theme's geometry
7
7
 
8
- You translate the request into a small ops file; the CLI resolves each matching alias on its token ladder, writes the result into each component's unsaved buffer, and prints a report card. Never hand-edit the data tree.
8
+ Write the request as an ops file. The CLI moves each matching alias along its scale, writes the result to each component's buffer, and prints a report. Never hand-edit the data tree.
9
+
10
+ The result is on screen as soon as the run finishes. The three set skills write the same buffer, so color, type, and geometry compose in any order. When the user accepts the result, run `save-theme` to keep it as a theme. Loading a theme in the editor discards it.
9
11
 
10
12
  ## Workflow
11
13
 
12
- 1. Read the geometry intent. When it names an anchor (a feeling, an idiom, or a genre), read `references/geometry-anchors.md` for that entry; it overrides the Idioms table below. Write the ops file to `scratch/geometry-ops.json`.
13
- 2. Run `npx live-tokens set-geometry scratch/geometry-ops.json`. It writes `component-configs/<id>/_working.json` for every component the ops change, which is the buffer the page already runs. `--dry-run` prints the report without writing.
14
- 3. Read the report card: every changed alias old → new, plus skips (raw value, off the ladder, already at the ladder end, pill preserved). Exit 1 means the run was rejected; the message names the offending op or the missing input, so fix it and re-run. Read where the controls landed, not only that the run succeeded: a button, badge, input, or tab padding sitting at `--space-6` is on its floor, and one that also carries `--radius-full` wants a targeted lift.
15
- 4. Report back in a line: every alias that moved, and any skip or clamp worth naming.
16
- 5. Tell the user to reload the page before saving. The editor keeps the look in the browser and writes the buffers from that copy, so a Save in a tab that was open during the run puts the pre-run shape back and the report you just showed them becomes a lie. After the reload, offer the inverse op as the undo and say the edit is unsaved until they save the open theme.
14
+ 1. Read the geometry intent and the anchor, when live-tokens-create-theme passed one. When the intent or the anchor names a feeling, an idiom, or a genre, read its entry in `references/geometry-anchors.md`.
15
+ 2. Write the ops file to `scratch/geometry-ops.json`.
16
+ 3. Run `npx live-tokens set-geometry scratch/geometry-ops.json`. It writes `component-configs/<id>/_working.json` for every component the ops change.
17
+ 4. Read the report. It lists every changed alias, old and new, and every skip with its reason.
18
+ 5. When the CLI exits 1, fix the op or the input the message names, then re-run.
19
+ 6. Reply with every alias that moved and any skip worth naming.
20
+
21
+ `--dry-run` prints the report without writing.
17
22
 
18
- Each run reads the LIVE config (buffer, else the open theme, else the shipped default), so "a bit more" and "back one" compound naturally.
23
+ Each run reads the live config, so "a bit more" and "back one" compound. The live config is the buffer, else the open theme. With no theme loaded, the open theme is the shipped default.
19
24
 
20
25
  ## The ops file
21
26
 
@@ -31,39 +36,55 @@ Targeted, absolute:
31
36
  { "ops": [{ "target": "button", "kind": "radius", "set": "--radius-full" }] }
32
37
  ```
33
38
 
34
- - `name`: ignored. Buffers are fixed slots, so a name names no file, and the CLI says it dropped one. Leave it out.
35
- - `target` (optional): a component id (the folder names under `src/live-tokens/data/component-configs/`, which the Catalogue in **live-tokens-pick-component** also names in full). A named component targets its id: "windows" or "modals" is `dialog`, "cards" is `card`, "tabs" is `tabbar`; an unknown target is a hard error. "The UI", "everything", or no noun at all means global, so omit it.
36
- - `kind`: `radius | padding | gap | border-width`.
37
- - `set` or `shift`, exactly one of the two. `set` takes an existing token on that kind's ladder. `shift` is a whole number of steps, clamped at the ladder ends.
38
- - `full` (radius shifts only): admits `--radius-full` as the ladder's top rung. `set` plus `full` is an error, so a pill request is `set: "--radius-full"` with no `full` flag.
39
+ - `target` (optional): a component id, one of the folder names under `src/live-tokens/data/component-configs/`. "Windows" or "modals" is `dialog`, "cards" is `card`, "tabs" is `tabbar`. "The UI", "everything", or no noun means global, so omit `target`.
40
+ - `kind`: `radius | padding | gap | border-width | divider-width | accent-width`. `border-width` moves `-border-width` aliases. `divider-width` moves dividers, hairline rules, and `-thickness` aliases. `accent-width` moves accent bars and indicators.
41
+ - `set` or `shift`, one of the two. `set` takes a token on that kind's scale. `shift` is a whole number of steps and stops at the ends of the scale.
42
+ - `full` (radius shifts only): admits `--radius-full` as the top of the scale. A pill request is `set: "--radius-full"` with no `full` flag.
39
43
 
40
44
  ## Idioms
41
45
 
42
- This table covers an intent that names no anchor. When the intent names one, `references/geometry-anchors.md` has the row and it wins.
46
+ The table covers an intent that names no anchor. An anchor's entry in `references/geometry-anchors.md` overrides the table.
43
47
 
44
48
  | The intent says | Ops |
45
49
  |---|---|
46
- | pill, capsule | radius `set: "--radius-full"`, plus the padding the pill needs (see below) |
50
+ | pill, capsule | radius `set: "--radius-full"`, plus the padding the pill needs (see Compact containers before controls) |
47
51
  | sharp, square corners | radius `set: "--radius-none"`, or `--radius-sm` for "mostly sharp" |
48
52
  | rounded (a named component) | radius `shift: 2` |
49
53
  | softer, rounder (global) | radius `shift: 1` to `2`, no `full` |
50
54
  | harder, sharper | radius `shift: -1` to `-2` |
51
- | increase the radius, less round, more round | radius `shift: 1` or `-1` with `"full": true`, so repeated pushes reach pill and a pill can come back down |
55
+ | increase the radius, less round, more round | radius `shift: 1` or `-1` with `"full": true` |
52
56
  | space it out, airier, breathing room | padding and gap `shift: 1` |
53
57
  | tighter, denser, more compact | padding and gap `shift: -1` |
54
58
  | thicker, thinner borders | border-width `shift: 1` or `-1` |
55
59
 
56
- A whole-look intent often arrives as a direction rather than an op. Playful, friendly, or soft is rounder and a step airier, with pill buttons when the direction is warm. Luxurious, elegant, or editorial is sharper corners, airier padding, thin borders. Technical, dense, or systematic is tighter spacing, a small radius, and square corners on containers. Calm or minimal leaves geometry alone.
60
+ A theme intent names a direction.
61
+
62
+ | The direction is | Geometry |
63
+ |---|---|
64
+ | playful, friendly, soft | rounder and a step airier. Warm adds pill buttons. |
65
+ | luxurious, elegant, editorial | sharper corners, airier padding, thin borders |
66
+ | technical, dense, systematic | tighter spacing, a small radius, square corners on containers |
67
+ | calm, minimal | unchanged |
57
68
 
58
- Magnitude words: "slightly" or "a bit" is 1 step, unqualified is 1 to 2, "much", "way", or "really" is 2 to 3. Mood words often mean both axes: "softer" is rounder plus airier, "compact" is tighter padding plus smaller gaps.
69
+ Magnitude follows the qualifier. "Slightly" or "a bit" is 1 step. No qualifier is 1 to 2 steps. "Much", "way", or "really" is 2 to 3 steps. A mood word often means both axes: "softer" is rounder plus airier, "compact" is tighter padding plus smaller gaps.
59
70
 
60
- ## Controls squeeze before containers
71
+ ## Compact containers before controls
61
72
 
62
- A global op spends the same number of steps everywhere, but a step costs a control far more than a container. `padding shift: -2` takes a card from a 16px inset to 10px and it is still a card. It takes a button from 8 to 4, doubled to 8px at each end, around an 18px line. The button stops reading as a button.
73
+ A global op spends the same number of steps everywhere, but a step costs a control more than a container. `padding shift: -2` takes a card from a 16px inset to 10px and it is still a card. The same op takes a button from 8px to its 6px floor, 12px at each end around an 18px line, and the floor stops it there. Below the floor the button stops reading as a button.
63
74
 
64
- So a global compaction is `shift: -1`. When the request wants more, spend the extra steps on the containers by name (`card`, `dialog`, `panel`, `collapsiblesection`, `sidenavigation`, `table`, `codesnippet`) and leave the controls alone. Loosening is not symmetric: airier is safe globally, because nothing breaks by growing.
75
+ So a global compaction is `shift: -1`. When the request wants more, spend the extra steps on the containers by name and leave the controls alone. The containers are:
65
76
 
66
- A pill needs the room most. `--radius-full` bends the corner in over the first and last glyph, so a capsule wants more horizontal inset than a square-cornered control, never less. `--space-8` is the floor for a large-text pill, which is where compact Midnight Study sits; the roomier pill presets (Ocean, Sunset, Royal Velvet) run `--space-10` to `--space-12`. Pair the radius op with a padding `set` on the same target, placed after any global compaction so it wins outright:
77
+ - `card`
78
+ - `dialog`
79
+ - `panel`
80
+ - `collapsiblesection`
81
+ - `sidenavigation`
82
+ - `table`
83
+ - `codesnippet`
84
+
85
+ Airier is safe globally, because nothing breaks by growing.
86
+
87
+ A pill needs the most room. `--radius-full` bends the corner in over the first and last glyph, so a capsule wants more horizontal inset than a square-cornered control. `--space-8` is the floor for a large-text pill. Compact Midnight Study sits there. The roomier pill presets, Ocean, Sunset, and Royal Velvet, run `--space-10` to `--space-12`. Pair the radius op with a padding `set` on the same target. In the ops list, place the padding `set` after any global padding shift. The later op wins:
67
88
 
68
89
  ```json
69
90
  { "ops": [
@@ -73,26 +94,28 @@ A pill needs the room most. `--radius-full` bends the corner in over the first a
73
94
  ] }
74
95
  ```
75
96
 
76
- ## Ladders
97
+ ## Scales
98
+
99
+ Radius runs `none, sm, md, lg, xl, 2xl, 3xl, 4xl`, with `full` as the gated ninth step. Space (padding and gap) is the editor picker's subset, `0, 2, 4, 6, 8, 10, 12, 16, 20, 24, 32, 48`, so the editor can select every value the CLI writes. Border width is the `--border-width-*` scale from `1` to `24`. A shift never reaches `--border-width-0`, and an alias at 0 is skipped. "No borders" is `set: "--border-width-0"`.
77
100
 
78
- Radius runs `none, sm, md, lg, xl, 2xl, 3xl, 4xl`, with `full` as the gated ninth rung. Space (padding and gap) is the editor picker's subset: `0, 2, 4, 6, 8, 10, 12, 16, 20, 24, 32, 48`, so every written value stays re-editable by hand. Border width is the full `--border-width-*` scale. `set` values must be on the ladder (`--space-64` is rejected).
101
+ An alias off the subset spends its first step reaching the subset, so `--space-2` with `shift: 1` lands on `--space-4`.
79
102
 
80
- Content insets stop at `--space-4`. Below it the text sits against its own edge, so `--space-0` and `--space-2` are destinations a person picks on purpose, not ones a relative "tighter" hands you. Both stay available through the editor picker and through `set`. An alias already below the floor still moves up, and a shift that would push one under `--space-4` reports as clamped and writes nothing.
103
+ ## Floors
81
104
 
82
- Padding that wraps a line of type stops a rung higher, at `--space-6`. The engine spots it in the config itself: a variant that also declares a `-text-font-size` is holding text, and the components that hold text double their padding horizontally, so `--space-4` there is 4px over an 18px line and 8px at each end. No shipped default puts text below `--space-6`.
105
+ Content insets stop at `--space-4`. Below `--space-4` the text sits against its own edge, so `--space-0` and `--space-2` are values a person picks on purpose, through the editor picker or `set`. An alias below the floor still moves up. A shift that would push one under `--space-4` lands on `--space-4`. An alias already at `--space-4` is skipped, and the report says so.
83
106
 
84
- The floor guards `-padding` only. Outer space is exempt, because a 2px gap between an icon and its label, or a 2px margin under a bar, is ordinary design rather than a mistake. Note that `-margin` rides the `padding` kind, so a padding op moves margins too; it just does not floor them.
107
+ Padding around a line of type stops at `--space-6`. A variant that declares a `-text-font-size` holds text. A component that holds text doubles its padding horizontally, so `--space-4` there is 4px over an 18px line and 8px at each end. No shipped default puts text below `--space-6`.
85
108
 
86
- An alias sitting off the subset spends its first step reaching the rung the shift points at, so `--space-2` with `shift: 1` lands on `--space-4` rather than jumping past it.
109
+ The floor guards `-padding` only. A 2px gap between an icon and its label, or a 2px margin under a bar, is ordinary design. `-margin` belongs to the `padding` kind, so a padding op moves margins too, without the floor.
87
110
 
88
111
  ## Scope
89
112
 
90
- Every value written is an existing token; nothing new is minted. `tokens.css`, saved themes, colors, and fonts are never touched, so any theme composes with any shape state. An adjustment is an unsaved edit: Save the open theme in the editor to keep it, and Adopt to ship it. Both stay human actions.
113
+ Geometry only. Color, type, saved themes, and `tokens.css` are untouched: `set-geometry` writes existing tokens into each component's buffer and creates no new ones. `save-theme` keeps the result; Adopt ships it.
91
114
 
92
115
  ## Verify
93
116
 
94
- - The CLI exits 0 and the report card lists the changes you expected, with no surprising skips.
95
- - The app (dev server running) shows the new shape on each changed component after a reload.
96
- - Buttons still read as buttons: the label has room at both ends, and a pill has more of it than a square-cornered control had.
97
- - `component-configs/<id>/_working.json` exists for every component the report listed. That buffer is the whole change: it stays until the open theme is saved or another theme is loaded.
98
- - To revert, run the inverse ops, or load a theme in the Theme panel to discard every unsaved edit.
117
+ - The CLI exits 0 and the report lists the expected changes, with no unexpected skips.
118
+ - The app shows the new shape on each changed component.
119
+ - Buttons still read as buttons: the label has room at both ends, and a pill has more than a square-cornered control. A control whose padding sits at `--space-6` is on its floor. A control that also carries `--radius-full` needs a targeted lift.
120
+ - `component-configs/<id>/_working.json` exists for every component the report listed.
121
+ - To revert, run the inverse ops, or load the open theme to discard the buffer.
@@ -4,9 +4,11 @@ Read this when the geometry intent names one of these. An anchor overrides the
4
4
  Idioms table in SKILL.md, because it is tuned to the same direction the color
5
5
  came from, and a style's geometry is often targeted rather than global.
6
6
 
7
- Entries are written in the ops vocabulary: "radius +2" is a radius shift of 2,
8
- "borders +1" a border-width shift of 1, "padding +1" a padding and gap shift of
9
- 1. A named component means a targeted op. Controls squeeze before containers,
7
+ Entries are written in the ops vocabulary. "radius +2" is a radius shift of 2.
8
+ "borders +1" is a border-width shift of 1. "padding +1" is a padding and gap
9
+ shift of 1. "hairline borders" is border-width `set: "--border-width-1"`, and
10
+ "no borders" is `set: "--border-width-0"`. "hairline rules" is divider-width
11
+ `set: "--border-width-1"`. A named component means a targeted op. Controls squeeze before containers,
10
12
  so a compaction of more than one step still spends its extra steps on
11
13
  containers by name.
12
14
 
@@ -1,23 +1,23 @@
1
1
  ---
2
2
  name: live-tokens-set-type
3
- description: Choose and apply a Google Fonts pairing for a live-tokens theme, binding families to the shipped --font-* stacks. Use whenever the user asks to pair fonts, pick a typeface, change or set the fonts, or describes type by voice: what font should the headings use, make the type more editorial, friendlier, more technical, more elegant, a serif for headings, a display font for this theme, less generic type, match the fonts to the theme. Also invoked by live-tokens-create-theme, which supplies the type intent for a whole look. Changes type only, never color. Not for a single token (use the editor) or for a whole look (see live-tokens-create-theme).
3
+ description: Set a live-tokens theme's type: a Google Fonts pairing for the shipped --font-* stacks. The CLI verifies each family for the weights it ships. Called with an anchor and a type intent by live-tokens-create-theme, or with the user's request directly. Use when the user asks to pair fonts, pick a typeface, or set the fonts. Use when the user describes type by voice: editorial, friendlier, technical, elegant, less generic. Use when the user names a face for a role: a serif for headings, a display font. Changes type only. For a request that also names color or geometry, read live-tokens-create-theme.
4
4
  ---
5
5
 
6
- # Setting a theme's fonts
6
+ # Setting a theme's type
7
7
 
8
- You choose the families; the CLI verifies each against Google Fonts, builds the URL from the weights the family actually has, and writes the result into the unsaved buffer. Never hand-author font JSON and never edit the data tree directly. Google Fonts is the pool because it is freely licensable and loads by URL; other sources go in by hand through the editor's Project fonts section.
8
+ Choose the families. The CLI verifies each against Google Fonts, builds the URL from the weights the family has, and writes the result to the buffer. Never hand-author font JSON or edit the data tree. Google Fonts is the pool because it is freely licensable and loads by URL. Other sources go in through the editor's Project fonts section.
9
9
 
10
- ## Workflow
10
+ The result is on screen as soon as the run finishes. The three set skills write the same buffer, so color, type, and geometry compose in any order. When the user accepts the result, run `save-theme` to keep it as a theme. Loading a theme in the editor discards it.
11
11
 
12
- 1. Read the type intent. When it names an anchor (a feeling, an idiom, or a genre), read `references/type-anchors.md` for that entry; it overrides the Voice table below. Choose the pairing with the framework here and write the pairing file to `scratch/font-pairing.json`.
13
- 2. Run `npx live-tokens set-type scratch/font-pairing.json`. It prints each stack that moved, each family's real weights and URL, and the weights your typography tokens ask for that the family lacks.
14
- 3. Read the report. A weight gap is a quality note: name it and offer an alternative only if it matters (a body face without 400, 700, or italic matters; a display face without 300 does not). A family not on Google Fonts fails the run; fix the spelling and re-run.
15
- 4. Report back in a line: the two families, the form model behind each, and any weight gap worth naming.
16
- 5. Tell the user to reload the editor page before saving. A running editor holds its own copy of the buffer this CLI just wrote and never re-reads it, so a Save without a reload writes the stale copy back and the pairing vanishes with a success report still on screen. After the reload the type is on the page, and unsaved until they save the open theme.
12
+ ## Workflow
17
13
 
18
- State your reasoning when you propose the pairing: each face's form model and the matrix verdict, in one sentence, so the user can argue with the argument rather than only the result.
14
+ 1. Read the type intent and any anchor live-tokens-create-theme passed. When either names an anchor (a feeling, an idiom, or a genre), read its entry in `references/type-anchors.md`; it overrides the Voice table below.
15
+ 2. Choose the pairing and write it to `scratch/font-pairing.json`.
16
+ 3. Run `npx live-tokens set-type scratch/font-pairing.json`. It prints each stack that moved, each family's weights and URL, and, under Weight coverage, the weights the typography tokens ask for that the family lacks.
17
+ 4. Read the report. Name a missing weight and offer an alternative only when it matters: a body face without 400, 700, or italic matters, and a display face without 300 does not. A family not on Google Fonts fails the run. Fix the spelling and re-run. A pairing the stacks already hold prints "Nothing to change" and writes nothing. A pairing equal to the open theme's discards the buffer, and the report says so.
18
+ 5. Reply with the two families, the form model behind each, the matrix verdict, and any missing weight worth naming.
19
19
 
20
- Flags: `--dry-run` reports without writing. `--no-verify` skips the network and requires an explicit URL per family; use it only offline with a URL in hand.
20
+ Flags: `--dry-run` reports without writing. `--no-verify` skips the network and requires a URL per family; use it only offline.
21
21
 
22
22
  ## The pairing file
23
23
 
@@ -25,17 +25,17 @@ Flags: `--dry-run` reports without writing. `--no-verify` skips the network and
25
25
  { "display": "Fraunces", "body": "Nunito Sans" }
26
26
  ```
27
27
 
28
- Every slot is optional and an omitted slot is left exactly as it is. `display` is `--font-display`, `body` is `--font-sans`; `serif`, `mono` and `editorial` exist when a theme needs them. `editorial` is `--font-editorial`, the long-reading face behind the `--editorial-*` text styles: it tracks the body face until a theme repoints it, so set it only when essays and articles should not carry the body face. A slot may be `{ "name": "...", "url": "..." }` to pin an exact URL. Spell families as Google does; the CLI reports the canonical spelling back.
28
+ Every slot is optional; an omitted slot keeps its family. `display` is `--font-display` and `body` is `--font-sans`. `serif`, `mono`, and `editorial` exist when a theme needs them. `editorial` is `--font-editorial`, the long-reading face behind the `--editorial-*` text styles. An omitted `editorial` keeps its family, so set it only when essays and articles need a face of their own. Weight coverage is reported for `display`, `body`, `serif`, and `mono`. A family bound to `editorial` gets no coverage line. A slot may be `{ "name": "...", "url": "..." }` to pin a URL. A pinned URL is not probed, so the report shows no weights for it and coverage skips it. Spell families as Google does; the CLI reports the canonical spelling.
29
29
 
30
30
  ## Choose the body face first
31
31
 
32
- The body face is the anchor. It carries most of the words, and text faces survive small sizes where display faces do not. Pick it against the type intent, then pick the display face against it. A body face must have regular, bold, and italic; low to moderate stroke contrast; open apertures; and a large x-height. A face failing any of these is a display face whatever its name says. Single-weight families are fine for `display` and disqualifying for `body`.
32
+ The body face is the anchor. It carries most of the words, and text faces survive small sizes where display faces do not. Pick it against the type intent, then pick the display face against it. A body face has regular, bold, and italic; low to moderate stroke contrast; open apertures; and a large x-height. A face missing any of these is a display face, whatever its name says.
33
33
 
34
- The shipped text styles ask the display face for 600, across all four heading levels, and the body face for 400; prose markup adds 700 and italic for `strong` and `em`. Screen candidates against those four before running, so the report confirms a decision instead of reporting a surprise.
34
+ The shipped text styles ask the display face for 600 and the body face for 400; `strong` and `em` add 700 and italic. Screen candidates against those four weights before running.
35
35
 
36
- ## The font matrix: the decision rule
36
+ ## The font matrix
37
37
 
38
- Classify each candidate on two layers. The **skeleton** is its form model; the **flesh** is its stroke contrast and serif treatment.
38
+ Classify each candidate by form model and by stroke contrast and serifs.
39
39
 
40
40
  | Form model | Construction | Reads as |
41
41
  |---|---|---|
@@ -43,11 +43,11 @@ Classify each candidate on two layers. The **skeleton** is its form model; the *
43
43
  | **Rational** | vertical stress, closed apertures, drawn not written | orderly, reserved, elegant, authoritative |
44
44
  | **Geometric** | monolinear, circle-and-line | technical, modern, systematic, sober |
45
45
 
46
- - **Same skeleton, different flesh: reliable.** Helvetica and Bodoni are both rational, one a linear sans and one a contrasting serif.
47
- - **Same flesh, different skeleton: the failure case.** The two look alike on the surface and fight underneath. This is why two arbitrary sans-serifs so often clash.
48
- - **Far apart on both: works, deliberately.** An unmistakable difference reads as a decision.
46
+ - One form model with different stroke contrast or serifs pairs reliably. Helvetica and Bodoni are both rational, one a linear sans and one a high-contrast serif.
47
+ - Different form models with the same stroke contrast and serifs fail. The two look alike and fight underneath. Two arbitrary sans serifs clash for this reason.
48
+ - Different on both counts works. An unmistakable difference reads as a decision.
49
49
 
50
- Many faces sit between columns. When one straddles, say so and lean on the voice table and the x-height check instead.
50
+ Many faces sit between columns. When one straddles, say so and lean on the Voice table and the x-height check.
51
51
 
52
52
  ## Voice
53
53
 
@@ -61,33 +61,33 @@ Many faces sit between columns. When one straddles, say so and lean on the voice
61
61
  | serious, institutional, trustworthy | rational sans body, rational serif display |
62
62
  | quiet, minimal, unbranded | one superfamily across both slots |
63
63
 
64
- This table covers an intent that names no anchor. When the intent names one, `references/type-anchors.md` has the row and it wins.
64
+ The table covers an intent that names no anchor. An anchor's row in `references/type-anchors.md` wins.
65
65
 
66
- Match the type to the same design direction the color came from. A warm autumn palette under a cold geometric sans reads as two projects.
66
+ Match the type to the design direction the color came from. A warm autumn palette under a cold geometric sans reads as two projects.
67
67
 
68
68
  ## Shortcuts
69
69
 
70
- These find an adequate pairing fast and skip the reasoning; use them when the request is vague or the type should stay quiet.
70
+ Use these when the request is vague or the type should stay quiet.
71
71
 
72
- - **A superfamily.** Google Fonts families with both sans and serif siblings, among them Alegreya, Ancizar, IBM Plex, Inria, Merriweather, Noto, PT, Roboto, Source. The catalogue moves and this list does not, so treat it as a starting set: `set-type` verifies every family against the API and fails loudly on one that is gone.
72
+ - **A superfamily.** A Google Fonts family with sans and serif siblings: Alegreya, Ancizar, IBM Plex, Inria, Merriweather, Noto, PT, Roboto, Source. The catalogue moves and this list does not; `set-type` fails on a family that is gone.
73
73
  - **One family across weights.**
74
74
  - **Same designer or foundry.**
75
75
  - **Serif display over sans body** when nothing else decides it.
76
76
 
77
77
  ## Watch for
78
78
 
79
- - **x-height parity.** Both faces are set from one size scale, so a small-x-height display face over a large-x-height body face gives a heading that looks weaker than its own body text. This is the one visual check that matters on screen; make it on the rendered page.
79
+ - **x-height parity.** Both faces share one size scale, so a small-x-height display face over a large-x-height body face gives a heading weaker than its own body text. Check it on the rendered page.
80
80
  - **Print faces at small sizes.** Delicate serifs and high stroke contrast turn to mud below 16px.
81
81
  - **Every family is a download.** Two is the target; three needs a reason.
82
- - **Sets of themes:** no two share a display face or a body face.
82
+ - **Sets of themes.** No two share a display face or a body face.
83
83
 
84
84
  ## Scope
85
85
 
86
- Type only. Color, component aliases, shape, and the type scale are untouched: `set-type` moves families between stacks and nothing else, writing only the font entries in the unsaved buffer. Save the theme to keep it, Adopt to ship it. Adopt is also what rewrites `fonts.css`, which is how a build with no editor in it loads the family at all.
86
+ Type only. Color, component aliases, shape, and the type scale are untouched: `set-type` writes the font entries in the buffer and carries every other value forward. `save-theme` keeps the result; Adopt ships it and rewrites `fonts.css`, which is how a build without the editor loads the family.
87
87
 
88
88
  ## Verify
89
89
 
90
90
  - The CLI exits 0 and names each stack that moved, before and after.
91
- - Each URL reflects the family's real weights: a range for a variable family, an enumeration for a static one, a bare URL for a single-weight face.
92
- - The app shows the new type after a reload, and the editor's Fonts section lists both families with their fallbacks intact.
93
- - To revert, run the inverse pairing file, or load the open theme again to discard the buffer.
91
+ - Each URL matches the family's weights: a range for a variable family, an enumeration for a static one, a bare URL for a single-weight face. A pinned URL is written as given.
92
+ - The app shows the new type, and the editor's Fonts section lists both families with their fallbacks.
93
+ - To revert, run the previous pairing file, or load the open theme to discard the buffer.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,143 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.76.0 — The skills directory matches the release
4
+
5
+ ### Changed (breaking)
6
+
7
+ - **`setup-claude --force` now makes `.claude/skills/` match the release.** It
8
+ replaced each bundled skill by merging over it, which left two kinds of stale
9
+ text behind: a skill a release renamed kept its old directory, where it
10
+ shadowed the replacement, and a reference file a release dropped survived
11
+ inside a skill that was otherwise current. Both are invisible until a model
12
+ reads them. A forced run now replaces each bundled directory outright and
13
+ removes any `live-tokens-` skill the release no longer ships, naming each one
14
+ it removed. A skill under any other name is the project's own and is never
15
+ touched, and an unforced run still deletes nothing. 0.75.0's rename of
16
+ `live-tokens-build-page` to `live-tokens-create-page` is the case that
17
+ prompted this; the changelog then told a reader to delete the directory by
18
+ hand.
19
+
20
+ Before a forced run, copy any bundled skill you edited in place to a name of
21
+ your own. A `live-tokens-` directory this release does not ship is deleted
22
+ without a prompt, and one it does ship is replaced rather than merged.
23
+
24
+ `setup-claude` moves out of `bin/cli.mjs` into `bin/setup-claude.mjs` as
25
+ `runSetupClaude` and `formatSetupResult`, matching `create.mjs`, and gains
26
+ `bin/setup-claude.test.ts`.
27
+
28
+ ### Changed
29
+
30
+ - **The `create` template installs the skills from `postinstall` and gitignores
31
+ them.** A scaffolded project no longer commits nine skill directories the
32
+ package owns, so a version bump stops showing twenty changed files that
33
+ nobody wrote. The skills instead refresh on every `npm install`. The
34
+ postinstall ends in `|| exit 0`: `setup-claude` refuses to run on Windows,
35
+ and a skills copy must never fail an install. A project created before this
36
+ release adds the two lines itself; the README carries them.
37
+
38
+ ## 0.75.0 — A component passes when the tests pass
39
+
40
+ ### Added
41
+
42
+ - **`check-component` gains `--tests`.** Beyond the static lint, it runs the
43
+ registry contract under vitest and the component contract suites under
44
+ Playwright, for one component or every authored one, and reports coverage
45
+ by rule: listed, persisted and reset, themed, previewed, and drawn in
46
+ Sketch mode. `@playwright/test`, `vitest`, and `happy-dom` are new optional
47
+ peer dependencies; a missing one is a `tests-not-installed` finding naming
48
+ the install command. The suites ship at
49
+ `@motion-proto/live-tokens/testing` and `/testing/vitest`, and run here
50
+ against the library's own demo app and in a consumer against the
51
+ consumer's own app.
52
+
53
+ **live-tokens-create-component now runs `--tests` as its Verification
54
+ step**, in place of the manual pass through `/live-tokens/components`.
55
+ Every line that step asked a reader to confirm by eye is now a contract
56
+ assertion: the component's listing, its controls and preview, persistence
57
+ and reset, theme projection, linked properties, and Sketch mode.
58
+ live-tokens-fix-findings maps the new rule ids to the create-component
59
+ section that fixes each one, and the `create` template's new
60
+ `test:design` script runs the checks once the three peers are installed.
61
+
62
+ ### Changed
63
+
64
+ - **Breaking: `tokens --scale` replaces `tokens --family`, and there is no
65
+ alias.** A token scale is the progression of one token across its range,
66
+ such as `space` or `radius`, and it is the one term for that grouping in the
67
+ CLI, the skills, and the skill atlas. "Family" now means a typeface only.
68
+ The `--json` output names the grouping `scales`, each with a `scale` and its
69
+ `tokens`. `bin/cliStrings.test.ts` bans "token family" and `--family`.
70
+ - **Dividers and accents name their stroke role.** Three stroke roles share
71
+ the `--border-width-*` scale: a border encloses, a divider separates, an
72
+ accent emphasises. `set-geometry` moves each role on its own and reads the
73
+ role off the suffix, so a divider named `-border` moved with the borders.
74
+ TabBar's indicator is `--tabbar-<state>-indicator-width`, CollapsibleSection's
75
+ divider is `--collapsiblesection-divider-<state>-hairline-color` and
76
+ `-hairline-thickness`, Dialog's header and footer rules are
77
+ `--dialog-<part>-divider` and `-divider-width`, and Table's header rule is
78
+ `--table-default-header-divider` and `-divider-width`. Component migration 27
79
+ renames the keys in a saved theme; values are unchanged.
80
+ - **CLI output uses the skills' vocabulary.** Every verb's help and report
81
+ lines say "the buffer" for edits a theme file does not hold yet, "load" for
82
+ making a theme the open one, "design token" and "semantic property" for the
83
+ two token classes, "shipped default", and "scale" and "step". The three set
84
+ verbs close with "The buffer holds this edit. Run save-theme to keep it as a
85
+ theme." Report lines print "old to new" in place of an arrow, and
86
+ `set-geometry` labels a skip "raw value", "off the scale", or "at the end of
87
+ the scale". `bin/cliStrings.test.ts` holds the line. The skills are corrected
88
+ where they described the CLI wrongly; the audit is
89
+ `docs/plans/cli-skill-alignment.md`.
90
+ - **`live-tokens-build-page` is renamed `live-tokens-create-page`.** The verb
91
+ now matches `create-theme` and `create-component`. A project that copied the
92
+ skill keeps the old directory until it deletes it.
93
+ - **The `create` template matches the skill.** `Home.svelte` drops the `h1`
94
+ and `p` rules `site.css` already types, the `0.9em` code size, and a `1.6`
95
+ line-height; its two Buttons take `--space-8`. `site.css` sets all five
96
+ axes from one text style on `p`, list items, `code`, and `pre`, and `ol li`
97
+ reads `--body-md-line-height` in place of `1.6`. A project created before
98
+ this release keeps its copied `site.css`.
99
+
100
+ - **A page's type comes from a text style, and the checker fails a page that
101
+ names a raw axis.** `raw-text-axis` is an error, and it now reads a `var()`
102
+ as well as a literal. A `--font-size-*`, `--line-height-*`,
103
+ `--letter-spacing-*`, or a family stack such as `--font-sans` on a text
104
+ property is a finding. A text style token such as `--body-md-font-size` is
105
+ not. A `--font-weight-*` alone is not either, because a weight cannot move
106
+ the scale or the fonts. Two warnings join it. `control-size` reports a
107
+ `size` prop on a shipped component in a page file. `multiple-primary`
108
+ reports a second `variant="primary"` Button in one page file. A project
109
+ retunes a component's default size once, in the components editor. The
110
+ package's own pages, the template, and the `create` starter are all clean
111
+ under `--strict`. The starter's bulleted lists now take the `--body-md-*`
112
+ bundle.
113
+
114
+ **Every shipped component carries a usage comment.** `npx live-tokens
115
+ components` prints it as the description. `report` checks the shipped
116
+ set as it checks a custom component. The comment
117
+ names what the component is, what it is for, and what to reach for instead.
118
+ It never mentions size.
119
+
120
+ - **Callout owns its box; the page owns the space around it.** `.callout` no
121
+ longer sets `margin: var(--space-24) 0`. A stack of callouts now takes its
122
+ spacing from the page's own gap, and a page that wants the old rhythm sets
123
+ `margin-block` on the container. The four `--callout-*-accent-width` defaults
124
+ point at `--border-width-1`, so the left edge matches the other three sides,
125
+ and the default theme follows. The token stays, so a theme can set the thick
126
+ left rule back, and the seven other presets keep the accents they were
127
+ authored with.
128
+
129
+ - **A CLI run shows up in the open editor, and a Save afterwards keeps it.**
130
+ The dev server now watches the unsaved buffers and the active-theme pointer
131
+ and streams every outside change to the page as one frame over
132
+ `GET /api/live-tokens/events`. The editor hydrates from that frame the way
133
+ it does from an Apply, so `set-colors`, `set-type`, `set-geometry`, and
134
+ `save-theme` land on screen as they finish, and a Save afterwards writes
135
+ what is on screen rather than the tab's stale copy. The four verbs no longer
136
+ ask for a reload, and neither do the skills that run them. The server leaves
137
+ its own writes out of the stream, so an editor Save does not hydrate itself.
138
+ A branch switch that moves a buffer or the pointer reaches the page the same
139
+ way; any other JSON changed from outside still needs a reload.
140
+
3
141
  ## 0.74.0 — A theme is three decisions and one document
4
142
 
5
143
  ### Changed
package/README.md CHANGED
@@ -322,12 +322,12 @@ npx @motion-proto/live-tokens <command>
322
322
  | Command | What it does |
323
323
  |---|---|
324
324
  | `create <dir> [--force]` | Scaffold a new Svelte + Vite app wired up with live-tokens. |
325
- | `setup-claude [--force]` | Install the bundled Claude Code skills into `./.claude/skills/`. |
325
+ | `setup-claude [--force]` | Install the bundled Claude Code skills into `./.claude/skills/`; `--force` makes the directory match this release. |
326
326
  | `components [id] [--json]` | List every component the project has, shipped and its own, with the props each takes; with an id, its props, variants, tokens, and defaults. |
327
- | `tokens [--family <name>] [--json]` | List every theme token the project's `tokens.css` declares, by family, with its value. |
327
+ | `tokens [--scale <name>] [--json]` | List every design token the project's `tokens.css` declares, by scale, with its value. |
328
328
  | `report [--json]` | The project as facts: pending migrations, tokens each component reads, which page renders which component, and both checkers' findings by rule. Always exits 0. |
329
329
  | `check-component [id]` | Validate a component's runtime, editor, and registration against the authoring contract; with no id, every component authored under `src/system/components`. |
330
- | `check-page [paths...]` | Validate pages against the build-page contract: catalogue components and their props, theme tokens over literals, route wiring. |
330
+ | `check-page [paths...]` | Validate pages against the create-page contract: catalogue components and their props, theme tokens over literals, route wiring. |
331
331
  | `set-colors <base-colors.json> [--dry-run]` | Build the theme's whole color identity from 10 OKLCH base colors, enforce AA contrast on the derived text tokens, and write the result to the unsaved colors-and-type buffer. |
332
332
  | `set-type <pairing.json> [--dry-run] [--no-verify]` | Bind Google Fonts families to the theme's font stacks, verified against the API. |
333
333
  | `set-geometry <ops.json> [--dry-run]` | Move radius, padding, gap, and border-width aliases along their token scales. |
@@ -346,10 +346,20 @@ The package bundles nine Claude Code skills. They encode the conventions this RE
346
346
  npx @motion-proto/live-tokens setup-claude
347
347
  ```
348
348
 
349
- This copies every bundled skill into `./.claude/skills/` in the current directory. Re-run it after upgrading the package to pick up new and changed skills, adding `--force` to overwrite. macOS and Linux only. The equivalent by hand:
349
+ This copies every bundled skill into `./.claude/skills/` in the current directory, leaving any that already exist. macOS and Linux only.
350
350
 
351
- ```bash
352
- mkdir -p .claude/skills && cp -R node_modules/@motion-proto/live-tokens/.claude/skills/. .claude/skills/
351
+ Re-run it with `--force` after upgrading. That makes the directory match the release: each bundled skill is replaced outright, so a reference file the release dropped goes with it, and a `live-tokens-` skill the release no longer ships is removed. A skill under any other name is the project's own and is never touched. Without `--force` nothing is deleted and an existing skill is left alone, so a renamed skill keeps shadowing its replacement until a forced run clears it.
352
+
353
+ A project created with `create` runs the forced form from `postinstall` and gitignores the copy, so the skills track the installed version with nothing to commit. To do the same in an existing project:
354
+
355
+ ```jsonc
356
+ // package.json
357
+ "postinstall": "live-tokens setup-claude --force || exit 0"
358
+ ```
359
+
360
+ ```
361
+ # .gitignore
362
+ .claude/skills/live-tokens-*/
353
363
  ```
354
364
 
355
365
  ### `live-tokens-pick-component`
@@ -358,7 +368,7 @@ Ask "TabBar or SegmentedControl?", "how do I let someone pick one of four option
358
368
 
359
369
  The skill holds the catalogue grouped by job (action, input, selection, containers, messaging, display) and a decision table for each confusable family: `SegmentedControl` vs `TabBar` vs `RadioButton` vs `MenuSelect`, `Card` vs `CollapsibleSection` vs `Dialog`, `Callout` vs `Notification` vs `Tooltip` vs `Badge`, `Button` vs `IconButton`, and the on/off case. It answers the question and writes nothing. Read it before authoring anything new.
360
370
 
361
- ### `live-tokens-build-page`
371
+ ### `live-tokens-create-page`
362
372
 
363
373
  Ask for a page, a route, or a screen: "build a pricing page", "add a /settings route", "put a hero at the top of Home".
364
374