@astryxdesign/cli 0.0.15 → 0.1.0-canary.0b5b49f

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/CHANGELOG.md CHANGED
@@ -1,5 +1,93 @@
1
1
  # @xds/cli
2
2
 
3
+ # 0.1.0
4
+
5
+ #### Breaking Changes
6
+
7
+ - Read project config from `astryx.config.mjs` (was `xds.config.mjs`)
8
+ The CLI now resolves its optional project config from `astryx.config.mjs`
9
+ instead of `xds.config.mjs` — a hard cut, no fallback. Consumers with an
10
+ `xds.config.mjs` must rename it to `astryx.config.mjs` (the config shape and
11
+ all fields are unchanged). Part of removing `xds` naming from the public API.
12
+ - Rename the CLI command/bin from `xds` to `astryx`
13
+ The CLI binary is now `astryx` (was `xds`); `bin/xds.mjs` is renamed to
14
+ `bin/astryx.mjs`, the dual `xds`+`astryx` bin entries collapse to a single
15
+ `astryx`, and the program/manifest name is `astryx`. Invoke the CLI as
16
+ `npx astryx <command>` (e.g. `npx astryx component Button`). The swizzle
17
+ default output dir moves from `./components/xds` to `./components/astryx`.
18
+ Consumers using `npx xds`, an `xds` npm-script alias, or the `xds` MCP server
19
+ name should switch to `astryx`. Part of removing `xds` naming from the public API.
20
+ - Rename the exported `XDSError` class to `AstryxError`
21
+ The CLI's programmatic API error class is renamed `XDSError` -> `AstryxError`
22
+ (exported from `@xds/cli` + declared in its types). Consumers that catch or
23
+ reference `XDSError` from the CLI's API should switch to `AstryxError`. Part of
24
+ removing `xds` naming from the public API.
25
+ - Remove the XDS-prefix compatibility layer — astryx is now the only public surface
26
+ This release erases all `xds` naming from the public API; there is no compatibility
27
+ window. Consumers must migrate (we own all consumers pre-OSS):
28
+ - Remove the daily, brutalist, and default themes; neutral is the new baseline
29
+ Three theme packages are removed from the repo and will no longer be published:
30
+
31
+ #### Fixes
32
+
33
+ - `theme build` generates valid bare type imports (IconRegistry/DefinedTheme)
34
+ `astryx theme build` emitted `.d.ts` files importing `XDSIconRegistry` /
35
+ `XDSDefinedTheme` from `@xds/core`, but those aliases were removed — the
36
+ generated types failed to resolve. Generate `IconRegistry` / `DefinedTheme`
37
+ (the bare names `@xds/core` now exports) instead.
38
+
39
+ #### Documentation
40
+
41
+ - Update CLI theme docs to the current theme set
42
+ Refreshes the `astryx docs theme`, `getting-started`, `styling`,
43
+ `styling-libraries`, and `migration` reference docs to reflect the published
44
+ themes: `neutral`, `butter`, `chocolate`, `gothic`, `matcha`, `stone`, and
45
+ `y2k`. The removed `theme-default`, `theme-brutalist`, and `theme-daily`
46
+ packages are dropped from the docs, and install/import examples now use
47
+ `@astryxdesign/theme-neutral` as the recommended starting theme.
48
+
49
+ #### Other Changes
50
+
51
+ - **Component names:** the `XDS*` aliases are gone — use bare names (`Button` not
52
+ `XDSButton`, `useTheme` not `useXDSTheme`, `ButtonProps` not `XDSButtonProps`). The
53
+ `drop-xds-prefix-imports` codemod automates this.
54
+ - **CSS classes:** components emit only `.astryx-*` (the dual `.xds-*` class is gone).
55
+ Update custom CSS selectors `.xds-button` -> `.astryx-button` (prop/state value classes
56
+ like `.primary`/`.sm` are unchanged).
57
+ - **data attributes:** only `data-astryx-theme` / `data-astryx-media` are written; update
58
+ custom selectors and SSR root attributes off `data-xds-*`.
59
+ - **CSS layers:** `@layer xds-base` / `xds-theme` are renamed to `astryx-base` /
60
+ `astryx-theme`; update your `@layer` order line and any PostCSS `layersBefore` config.
61
+ `@astryxdesign/build`'s default library layer is now `astryx-base`.
62
+ - **Pre-compiled stylesheet:** the `@astryxdesign/core/xds.css` export is removed — import
63
+ `@astryxdesign/core/astryx.css`.
64
+ - **CSS custom properties:** the `--xds-*` padding fallback is gone; set `--astryx-*`.
65
+ - **CLI config key:** `@astryxdesign/cli` reads the package.json `"astryx"` field (was `"xds"`).
66
+ Rename the block; a stale `"xds"` key silently drops the package from discovery.
67
+ - `@astryxdesign/theme-daily`
68
+ - `@astryxdesign/theme-brutalist`
69
+ - `@astryxdesign/theme-default`
70
+ - import {defaultTheme} from '@astryxdesign/theme-default/built';
71
+ - import {neutralTheme} from '@astryxdesign/theme-neutral/built';
72
+ - <Theme theme={defaultTheme}>...</Theme>
73
+ - <Theme theme={neutralTheme}>...</Theme>
74
+ ```
75
+
76
+ ```
77
+ - Remove the internal `drop-xds-meta-prefix` codemod from the OSS repo (#2970)
78
+ This codemod has been moved to its own package's tooling, where it belongs. It was registered as an optional, version-independent transform and is not part of any standard upgrade path, so removing it does not affect the public `0.0.13 → 0.0.15` migration.
79
+ - Rename the npm package scope from `@xds/*` to `@astryxdesign/*`
80
+ All published packages move to the new `@astryxdesign` scope (e.g. `@xds/core` → `@astryxdesign/core`), along with the workspace lockfile, build/runtime scope-directory scans, and docsite slug derivation. Consumers must update their imports and dependency names. The internal ESLint plugin namespace (`@xds/*` rules) is intentionally untouched and tracked separately. Existing `@xds/*` codemods continue to target the old scope so projects still on `@xds/*` can migrate.
81
+
82
+ #### Contributors
83
+
84
+ Thanks to everyone who contributed to this release:
85
+
86
+ - @cixzhang
87
+ - @ejhammond
88
+
89
+ ---
90
+
3
91
  # 0.0.15
4
92
 
5
93
  #### Breaking Changes
package/README.md CHANGED
@@ -341,7 +341,7 @@ astryx doctor — diagnosing your setup
341
341
  @astryxdesign/core v0.0.14 is in step with @astryxdesign/cli v0.0.14.
342
342
  ⚠ Theme packages
343
343
  No @astryxdesign/theme-* packages are installed.
344
- → fix: Install a theme, e.g. `npm install @astryxdesign/theme-default`, then import its CSS or set xds.theme.
344
+ → fix: Install a theme, e.g. `npm install @astryxdesign/theme-neutral`, then import its CSS or set xds.theme.
345
345
  ℹ astryx.config.mjs
346
346
  No astryx.config.mjs found — using defaults.
347
347
  ℹ AI agent docs
@@ -21,7 +21,7 @@ export const docs = {
21
21
  type: 'code',
22
22
  lang: 'text',
23
23
  label: 'Paste this into your AI',
24
- code: 'Install @astryxdesign/core, @astryxdesign/theme-default, and @astryxdesign/cli in this project. Run `npx astryx init` to set up agent docs. Read the generated files to learn the conventions.',
24
+ code: 'Install @astryxdesign/core, @astryxdesign/theme-neutral, and @astryxdesign/cli in this project. Run `npx astryx init` to set up agent docs. Read the generated files to learn the conventions.',
25
25
  },
26
26
  ],
27
27
  },
@@ -36,7 +36,7 @@ export const docs = {
36
36
  type: 'code',
37
37
  lang: 'bash',
38
38
  label: 'Terminal',
39
- code: `npm install @astryxdesign/core @astryxdesign/theme-default @astryxdesign/cli`,
39
+ code: `npm install @astryxdesign/core @astryxdesign/theme-neutral @astryxdesign/cli`,
40
40
  },
41
41
  {
42
42
  type: 'prose',
@@ -63,11 +63,11 @@ export const docs = {
63
63
  label: 'globals.css',
64
64
  code: `@import '@astryxdesign/core/reset.css';
65
65
  @import '@astryxdesign/core/astryx.css';
66
- @import '@astryxdesign/theme-default/theme.css';`,
66
+ @import '@astryxdesign/theme-neutral/theme.css';`,
67
67
  },
68
68
  {
69
69
  type: 'prose',
70
- text: 'Available themes: @astryxdesign/theme-default (blue accent), @astryxdesign/theme-neutral (grayscale), @astryxdesign/theme-brutalist (zero radius, monospace). See `npx astryx docs theme` for the full theming guide.',
70
+ text: 'Available themes: @astryxdesign/theme-neutral (muted minimal, a good starting point), @astryxdesign/theme-butter, @astryxdesign/theme-chocolate, @astryxdesign/theme-gothic (dark-only), @astryxdesign/theme-matcha, @astryxdesign/theme-stone, and @astryxdesign/theme-y2k. See `npx astryx docs theme` for the full theming guide.',
71
71
  },
72
72
  ],
73
73
  },
@@ -88,7 +88,7 @@ import {VStack} from '@astryxdesign/core/Layout';
88
88
  export default function Page() {
89
89
  return (
90
90
  <VStack gap={2}>
91
- <Button label="Hello XDS" onClick={() => alert('Hi!')} />
91
+ <Button label="Hello Astryx" onClick={() => alert('Hi!')} />
92
92
  </VStack>
93
93
  );
94
94
  }`,
@@ -96,11 +96,11 @@ export default function Page() {
96
96
  ],
97
97
  },
98
98
  {
99
- title: 'Customize with xstyle',
99
+ title: 'Customize with StyleX',
100
100
  content: [
101
101
  {
102
102
  type: 'prose',
103
- text: 'Every component accepts an `xstyle` prop for StyleX style overrides created via `stylex.create()`.',
103
+ text: 'Astryx components support various styling solutions, from plain CSS and `className` to Tailwind and CSS-in-JS. See the [styling docs](/docs/styling) for the full guide. Astryx also has a deep integration with [StyleX](https://stylexjs.com/), an atomic CSS-in-JS library: create styles with `stylex.create()` and pass them to components with the `xstyle` prop.',
104
104
  },
105
105
  {
106
106
  type: 'code',
@@ -127,19 +127,19 @@ const overrides = stylex.create({
127
127
  type: 'table',
128
128
  headers: ['Example', 'Stack', 'Path'],
129
129
  rows: [
130
- ['Next.js', 'Next.js + theme CSS', 'apps/example-nextjs'],
131
- ['Next.js + StyleX', 'Next.js + StyleX for custom styles', 'apps/example-nextjs-stylex'],
132
- ['Next.js + Tailwind', 'Next.js + Tailwind bridge', 'apps/example-nextjs-tailwind'],
133
- ['Next.js Source', 'Next.js importing from source', 'apps/example-nextjs-source'],
134
- ['Vite', 'Vite', 'apps/example-vite'],
130
+ ['Next.js', 'Next.js + theme CSS', '[apps/example-nextjs](https://github.com/facebook/astryx/tree/main/apps/example-nextjs)'],
131
+ ['Next.js + StyleX', 'Next.js + StyleX for custom styles', '[apps/example-nextjs-stylex](https://github.com/facebook/astryx/tree/main/apps/example-nextjs-stylex)'],
132
+ ['Next.js + Tailwind', 'Next.js + Tailwind bridge', '[apps/example-nextjs-tailwind](https://github.com/facebook/astryx/tree/main/apps/example-nextjs-tailwind)'],
133
+ ['Next.js Source', 'Next.js importing from source', '[apps/example-nextjs-source](https://github.com/facebook/astryx/tree/main/apps/example-nextjs-source)'],
134
+ ['Vite', 'Vite', '[apps/example-vite](https://github.com/facebook/astryx/tree/main/apps/example-vite)'],
135
135
  ],
136
136
  },
137
137
  {
138
138
  type: 'code',
139
139
  lang: 'bash',
140
140
  label: 'Clone and run an example',
141
- code: `git clone https://github.com/facebookexperimental/xds.git
142
- cd xds/apps/example-nextjs
141
+ code: `git clone https://github.com/facebook/astryx.git
142
+ cd astryx/apps/example-nextjs
143
143
  pnpm install
144
144
  pnpm dev`,
145
145
  },
@@ -157,7 +157,7 @@ pnpm dev`,
157
157
  lang: 'json',
158
158
  label: 'package.json',
159
159
  code: `"scripts": {
160
- "xds": "node node_modules/@astryxdesign/cli/bin/astryx.mjs"
160
+ "astryx": "node node_modules/@astryxdesign/cli/bin/astryx.mjs"
161
161
  }`,
162
162
  },
163
163
  {
@@ -91,15 +91,15 @@ npx astryx component Button --json`,
91
91
  lang: 'tsx',
92
92
  label: 'Root provider with explicit mode',
93
93
  code: `import {Theme} from '@astryxdesign/core/theme';
94
- import {defaultTheme} from '@astryxdesign/theme-default/built';
94
+ import {neutralTheme} from '@astryxdesign/theme-neutral/built';
95
95
  import {useState} from 'react';
96
- import '@astryxdesign/theme-default/theme.css';
96
+ import '@astryxdesign/theme-neutral/theme.css';
97
97
 
98
98
  export function AppRoot({children}: {children: React.ReactNode}) {
99
99
  const [mode, setMode] = useState<'system' | 'light' | 'dark'>('system');
100
100
 
101
101
  return (
102
- <Theme theme={defaultTheme} mode={mode}>
102
+ <Theme theme={neutralTheme} mode={mode}>
103
103
  <SettingsContext.Provider value={{mode, setMode}}>
104
104
  {children}
105
105
  </SettingsContext.Provider>
@@ -121,7 +121,7 @@ export function AppRoot({children}: {children: React.ReactNode}) {
121
121
  @import "tailwindcss/preflight.css" layer(base);
122
122
  @import "@astryxdesign/core/reset.css";
123
123
  @import "@astryxdesign/core/astryx.css";
124
- @import "@astryxdesign/theme-default/theme.css";
124
+ @import "@astryxdesign/theme-neutral/theme.css";
125
125
  @import "@astryxdesign/core/tailwind-theme.css";
126
126
  @import "tailwindcss/utilities.css" layer(utilities);`,
127
127
  },
@@ -162,7 +162,7 @@ const styles = stylex.create({
162
162
  @import "tailwindcss/preflight.css" layer(base);
163
163
  @import "@astryxdesign/core/reset.css";
164
164
  @import "@astryxdesign/core/astryx.css";
165
- @import "@astryxdesign/theme-default/theme.css";
165
+ @import "@astryxdesign/theme-neutral/theme.css";
166
166
  @import "@astryxdesign/core/tailwind-theme.css";
167
167
  @import "tailwindcss/utilities.css" layer(utilities);`,
168
168
  },
@@ -374,9 +374,9 @@ tokens: {
374
374
  lang: 'ts',
375
375
  label: 'Resolve tokens without React context',
376
376
  code: `import {resolveThemeTokens} from '@astryxdesign/core/theme/tokens';
377
- import {defaultTheme} from '@astryxdesign/theme-default';
377
+ import {neutralTheme} from '@astryxdesign/theme-neutral';
378
378
 
379
- const tokens = resolveThemeTokens(defaultTheme, {mode: 'light'});
379
+ const tokens = resolveThemeTokens(neutralTheme, {mode: 'light'});
380
380
 
381
381
  const chartOptions = {
382
382
  textColor: tokens['--color-text-primary'],
@@ -22,9 +22,8 @@ export const docs = {
22
22
  type: 'table',
23
23
  headers: ['Approach', 'Use for', 'Example'],
24
24
  rows: [
25
- ['xstyle prop', 'Overriding a specific component', 'xstyle={styles.override}'],
25
+ ['StyleX', 'Component-specific overrides, reusable styles, pseudo-classes, and typed tokens', 'const styles = stylex.create(...); <Button xstyle={styles.save} />'],
26
26
  ['Tailwind utilities', 'Layout, wrappers, and utility styling', 'className="flex gap-3 p-4"'],
27
- ['stylex.create', 'Reusable styles, pseudo-classes, typed tokens', 'stylex.create({ card: { ... } })'],
28
27
  ['className', 'Integrating with external CSS or Tailwind on components', 'className="my-card shadow-lg"'],
29
28
  ['Styling-library token aliases', 'Keeping Panda, Chakra, MUI, Emotion, styled-components, UnoCSS, CSS Modules, or Sass in sync with the system', "colors.surface = 'var(--color-background-surface)'"],
30
29
  ],
@@ -104,7 +103,7 @@ const overrides = stylex.create({
104
103
  @import "tailwindcss/preflight.css" layer(base);
105
104
  @import "@astryxdesign/core/reset.css";
106
105
  @import "@astryxdesign/core/astryx.css";
107
- @import "@astryxdesign/theme-default/theme.css";
106
+ @import "@astryxdesign/theme-neutral/theme.css";
108
107
  @import "@astryxdesign/core/tailwind-theme.css";
109
108
  @import "tailwindcss/utilities.css" layer(utilities);`,
110
109
  },
@@ -6,7 +6,7 @@ export const docsDense = {
6
6
  description: 'Theme provider, custom themes, light/dark, component overrides',
7
7
  sections: [
8
8
  { title: 'Quick Start', content: [null, null, { type: 'prose', text: 'default import = runtime injection. /built import = pre-compiled CSS (pair with theme.css).' }] },
9
- { title: 'Themes', content: [null, { type: 'prose', text: '@astryxdesign/theme-{name} = source (runtime). @astryxdesign/theme-{name}/built = optimized (+ theme.css).' }] },
9
+ { title: 'Themes', content: [null, { type: 'prose', text: 'published: neutral (start here), butter, chocolate, gothic (dark-only), matcha, stone, y2k. @astryxdesign/theme-{name} = source (runtime). @astryxdesign/theme-{name}/built = optimized (+ theme.css).' }] },
10
10
  { title: 'Props', content: [null] },
11
11
  { title: 'Custom Theme', content: [{ type: 'prose', text: 'CLI wizard or manual defineTheme. only override tokens that differ.' }, null] },
12
12
  { title: 'defineTheme', content: [{ type: 'prose', text: 'scale configs (color, typography, radius, motion) + explicit token overrides + component overrides. color derives full palette from accent hex via HCT.' }, null, null] },
@@ -19,11 +19,11 @@ export const docs = {
19
19
  lang: 'tsx',
20
20
  label: 'Basic theme setup (runtime injection)',
21
21
  code: `import {Theme} from '@astryxdesign/core';
22
- import {defaultTheme} from '@astryxdesign/theme-default';
22
+ import {neutralTheme} from '@astryxdesign/theme-neutral';
23
23
 
24
24
  function App() {
25
25
  return (
26
- <Theme theme={defaultTheme}>
26
+ <Theme theme={neutralTheme}>
27
27
  <YourApp />
28
28
  </Theme>
29
29
  );
@@ -34,12 +34,12 @@ function App() {
34
34
  lang: 'tsx',
35
35
  label: 'Optimized setup (pre-built CSS)',
36
36
  code: `import {Theme} from '@astryxdesign/core';
37
- import {defaultTheme} from '@astryxdesign/theme-default/built';
38
- import '@astryxdesign/theme-default/theme.css';
37
+ import {neutralTheme} from '@astryxdesign/theme-neutral/built';
38
+ import '@astryxdesign/theme-neutral/theme.css';
39
39
 
40
40
  function App() {
41
41
  return (
42
- <Theme theme={defaultTheme}>
42
+ <Theme theme={neutralTheme}>
43
43
  <YourApp />
44
44
  </Theme>
45
45
  );
@@ -59,20 +59,40 @@ function App() {
59
59
  type: 'table',
60
60
  headers: ['Theme', 'Import', 'Description'],
61
61
  rows: [
62
- [
63
- 'Default',
64
- "import {defaultTheme} from '@astryxdesign/theme-default'",
65
- 'Blue accent, system fonts, light/dark',
66
- ],
67
62
  [
68
63
  'Neutral',
69
64
  "import {neutralTheme} from '@astryxdesign/theme-neutral'",
70
- 'Grayscale, shadcn-inspired',
65
+ 'Muted, minimal aesthetic with system fonts. A good starting point.',
66
+ ],
67
+ [
68
+ 'Butter',
69
+ "import {butterTheme} from '@astryxdesign/theme-butter'",
70
+ 'Golden, buttery surfaces with blue accents; Sarina + Outfit type.',
71
+ ],
72
+ [
73
+ 'Chocolate',
74
+ "import {chocolateTheme} from '@astryxdesign/theme-chocolate'",
75
+ 'Warm brown tones and cozy beige; Fraunces + Albert Sans type.',
76
+ ],
77
+ [
78
+ 'Gothic',
79
+ "import {gothicTheme} from '@astryxdesign/theme-gothic'",
80
+ 'Dark-only atmospheric theme; deep blue-gray surfaces, distressed display type.',
81
+ ],
82
+ [
83
+ 'Matcha',
84
+ "import {matchaTheme} from '@astryxdesign/theme-matcha'",
85
+ 'Earthy green theme with Figtree typography.',
86
+ ],
87
+ [
88
+ 'Stone',
89
+ "import {stoneTheme} from '@astryxdesign/theme-stone'",
90
+ 'Warm stone and slate tones; Montserrat + Figtree type.',
71
91
  ],
72
92
  [
73
- 'Brutalist',
74
- "import {brutalistTheme} from '@astryxdesign/theme-brutalist'",
75
- 'Zero radius, monospace, heavy borders',
93
+ 'Y2K',
94
+ "import {y2kTheme} from '@astryxdesign/theme-y2k'",
95
+ 'Playful Y2K pop; periwinkle body, holographic accents, Poppins + Crimson Text.',
76
96
  ],
77
97
  ],
78
98
  },
@@ -194,14 +214,14 @@ const myTheme = defineTheme({
194
214
  {
195
215
  type: 'code',
196
216
  lang: 'tsx',
197
- label: 'Extending the default theme',
217
+ label: 'Extending the neutral theme',
198
218
  code: `import {defineTheme} from '@astryxdesign/core/theme';
199
- import {defaultTheme} from '@astryxdesign/theme-default';
219
+ import {neutralTheme} from '@astryxdesign/theme-neutral';
200
220
  import {myIcons} from './icons';
201
221
 
202
222
  const brandTheme = defineTheme({
203
223
  name: 'brand',
204
- extends: defaultTheme,
224
+ extends: neutralTheme,
205
225
  icons: myIcons,
206
226
  tokens: {
207
227
  '--color-accent': ['#7B61FF', '#9B85FF'],
@@ -525,9 +545,9 @@ const pandaOrEmotionTheme = {
525
545
  lang: 'ts',
526
546
  label: 'Resolve token values without a hook',
527
547
  code: `import {resolveThemeTokens} from '@astryxdesign/core/theme/tokens';
528
- import {defaultTheme} from '@astryxdesign/theme-default';
548
+ import {neutralTheme} from '@astryxdesign/theme-neutral';
529
549
 
530
- const lightTokens = resolveThemeTokens(defaultTheme, {mode: 'light'});
550
+ const lightTokens = resolveThemeTokens(neutralTheme, {mode: 'light'});
531
551
  const chartTheme = {
532
552
  textColor: lightTokens['--color-text-primary'],
533
553
  seriesColor: lightTokens['--color-data-categorical-blue'],
@@ -6,7 +6,7 @@ export const docsZh = {
6
6
  description: 'Theme 提供者、自定义主题、亮/暗模式和组件样式覆盖。',
7
7
  sections: [
8
8
  { title: '快速开始', content: [null, null, { type: 'prose', text: '默认导入使用运行时样式注入。/built 导入使用预编译 CSS(需配合 theme.css)。' }] },
9
- { title: '可用主题', content: [null, { type: 'prose', text: '@astryxdesign/theme-{name} = 源码版(运行时注入)。@astryxdesign/theme-{name}/built = 优化版(配合 theme.css)。' }] },
9
+ { title: '可用主题', content: [null, { type: 'prose', text: '已发布主题:neutral(推荐起点)、butter、chocolate、gothic(仅暗色)、matcha、stone、y2k。@astryxdesign/theme-{name} = 源码版(运行时注入)。@astryxdesign/theme-{name}/built = 优化版(配合 theme.css)。' }] },
10
10
  { title: 'Theme 属性', content: [null] },
11
11
  { title: '创建自定义主题', content: [{ type: 'prose', text: '使用 CLI 向导(推荐)或手动 defineTheme。只覆盖与默认值不同的令牌。' }, null] },
12
12
  { title: 'defineTheme', content: [{ type: 'prose', text: '支持比例配置(typography、radius、motion)+ 显式令牌覆盖 + 组件覆盖。' }, null, null] },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astryxdesign/cli",
3
- "version": "0.0.15",
3
+ "version": "0.1.0-canary.0b5b49f",
4
4
  "displayName": "CLI",
5
5
  "description": "Scaffold projects, browse templates, generate themes, and get agent-ready docs from the command line.",
6
6
  "author": "Meta Open Source",
@@ -50,13 +50,13 @@
50
50
  "dependencies": {
51
51
  "@clack/prompts": "^1.5.1",
52
52
  "commander": "^12.1.0",
53
- "jiti": "^2.7.0"
53
+ "jiti": "^2.7.0",
54
+ "jscodeshift": "^17.3.0"
54
55
  },
55
56
  "peerDependencies": {
56
- "@astryxdesign/core": "*",
57
- "@astryxdesign/lab": "*",
58
- "@astryxdesign/theme-default": "*",
59
- "@astryxdesign/theme-neutral": "*"
57
+ "@astryxdesign/core": "0.1.0-canary.0b5b49f",
58
+ "@astryxdesign/lab": "0.1.0-canary.0b5b49f",
59
+ "@astryxdesign/theme-neutral": "0.1.0-canary.0b5b49f"
60
60
  },
61
61
  "peerDependenciesMeta": {
62
62
  "@astryxdesign/core": {
@@ -65,18 +65,14 @@
65
65
  "@astryxdesign/lab": {
66
66
  "optional": true
67
67
  },
68
- "@astryxdesign/theme-default": {
69
- "optional": true
70
- },
71
68
  "@astryxdesign/theme-neutral": {
72
69
  "optional": true
73
70
  }
74
71
  },
75
72
  "devDependencies": {
76
- "@astryxdesign/core": "*",
77
- "@astryxdesign/lab": "*",
78
- "@astryxdesign/theme-default": "*",
79
- "@astryxdesign/theme-neutral": "*"
73
+ "@astryxdesign/core": "0.1.0-canary.0b5b49f",
74
+ "@astryxdesign/lab": "0.1.0-canary.0b5b49f",
75
+ "@astryxdesign/theme-neutral": "0.1.0-canary.0b5b49f"
80
76
  },
81
77
  "scripts": {
82
78
  "astryx": "node bin/astryx.mjs",
@@ -240,7 +240,7 @@ export function checkThemes(ctx) {
240
240
  label: 'Theme packages',
241
241
  status: 'warn',
242
242
  message: 'No @astryxdesign/theme-* packages are installed.',
243
- fix: 'Install a theme, e.g. `npm install @astryxdesign/theme-default`, then import its CSS or set xds.theme.',
243
+ fix: 'Install a theme, e.g. `npm install @astryxdesign/theme-neutral`, then import its CSS or set xds.theme.',
244
244
  };
245
245
  }
246
246
 
@@ -355,8 +355,8 @@ export function checkAgentDocs(ctx) {
355
355
  try {
356
356
  const content = fs.readFileSync(path.join(ctx.cwd, rel), 'utf-8');
357
357
  return (
358
- content.includes('<!-- XDS:START -->') &&
359
- content.includes('<!-- XDS:END -->')
358
+ (content.includes('<!-- ASTRYX:START -->') || content.includes('<!-- XDS:START -->')) &&
359
+ (content.includes('<!-- ASTRYX:END -->') || content.includes('<!-- XDS:END -->'))
360
360
  );
361
361
  } catch {
362
362
  return false;
@@ -368,7 +368,7 @@ export function checkAgentDocs(ctx) {
368
368
  id: 'agent-docs',
369
369
  label: 'AI agent docs',
370
370
  status: 'warn',
371
- message: `Agent docs present (${present.join(', ')}) but no XDS section markers found.`,
371
+ message: `Agent docs present (${present.join(', ')}) but no Astryx section markers found.`,
372
372
  fix: 'Add the XDS section to your agent docs with `astryx init --features agents`.',
373
373
  };
374
374
  }
@@ -31,8 +31,11 @@ const AGENTS_MD = 'AGENTS.md';
31
31
  const CLAUDE_MD = 'CLAUDE.md';
32
32
  const CLAUDE_DIR_MD = path.join('.claude', 'CLAUDE.md');
33
33
 
34
- const XDS_MARKER_START = '<!-- XDS:START -->';
35
- const XDS_MARKER_END = '<!-- XDS:END -->';
34
+ const MARKER_START = '<!-- ASTRYX:START -->';
35
+ const MARKER_END = '<!-- ASTRYX:END -->';
36
+ // Legacy markers — read during migration so the script finds existing XDS blocks
37
+ const LEGACY_MARKER_START = '<!-- XDS:START -->';
38
+ const LEGACY_MARKER_END = '<!-- XDS:END -->';
36
39
 
37
40
  /**
38
41
  * Agent tool presets — maps tool names to their file search paths.
@@ -99,7 +102,7 @@ export function resolveAgentPaths(targetDir, agent) {
99
102
  */
100
103
  export function generateCompressedIndex(version, {coreDir, runPrefix = getRunPrefix()} = {}) {
101
104
  const run = `${runPrefix} astryx`;
102
- const lines = [XDS_MARKER_START];
105
+ const lines = [MARKER_START];
103
106
 
104
107
  // Component count from live discovery
105
108
  let componentCount = '90+';
@@ -177,7 +180,7 @@ export function generateCompressedIndex(version, {coreDir, runPrefix = getRunPre
177
180
  lines.push(`${run} swizzle <Name> eject source (--gap to report why)`);
178
181
  lines.push(`${run} upgrade --apply codemods after version bump`);
179
182
  lines.push(`after @astryxdesign/core bump, always run ${run} upgrade --apply`);
180
- lines.push(XDS_MARKER_END);
183
+ lines.push(MARKER_END);
181
184
 
182
185
  return lines.join('\n');
183
186
  }
@@ -218,14 +221,21 @@ export function injectXdsBlock(filePath, compressedIndex, {createIfMissing = fal
218
221
  if (fs.existsSync(filePath)) {
219
222
  content = fs.readFileSync(filePath, 'utf-8');
220
223
 
221
- const startIdx = content.indexOf(XDS_MARKER_START);
222
- const endIdx = content.indexOf(XDS_MARKER_END);
224
+ // Find existing section — try new markers first, fall back to legacy XDS markers
225
+ let startIdx = content.indexOf(MARKER_START);
226
+ let endIdx = content.indexOf(MARKER_END);
227
+ let markerEndLength = MARKER_END.length;
228
+ if (startIdx === -1) {
229
+ startIdx = content.indexOf(LEGACY_MARKER_START);
230
+ endIdx = content.indexOf(LEGACY_MARKER_END);
231
+ markerEndLength = LEGACY_MARKER_END.length;
232
+ }
223
233
 
224
234
  if (startIdx !== -1 && endIdx !== -1) {
225
235
  content =
226
236
  content.slice(0, startIdx) +
227
237
  compressedIndex +
228
- content.slice(endIdx + XDS_MARKER_END.length);
238
+ content.slice(endIdx + markerEndLength);
229
239
  } else if (onlyReplace) {
230
240
  // File exists but has no Astryx markers — skip it
231
241
  return false;
@@ -277,13 +287,20 @@ export function removeXdsBlock(filePath, {deleteIfEmpty = false} = {}) {
277
287
  if (!fs.existsSync(filePath)) return false;
278
288
 
279
289
  let content = fs.readFileSync(filePath, 'utf-8');
280
- const startIdx = content.indexOf(XDS_MARKER_START);
281
- const endIdx = content.indexOf(XDS_MARKER_END);
290
+ // Find existing section — try new markers first, fall back to legacy
291
+ let startIdx = content.indexOf(MARKER_START);
292
+ let endIdx = content.indexOf(MARKER_END);
293
+ let markerEndLen = MARKER_END.length;
294
+ if (startIdx === -1) {
295
+ startIdx = content.indexOf(LEGACY_MARKER_START);
296
+ endIdx = content.indexOf(LEGACY_MARKER_END);
297
+ markerEndLen = LEGACY_MARKER_END.length;
298
+ }
282
299
 
283
300
  if (startIdx === -1 || endIdx === -1) return false;
284
301
 
285
302
  const before = content.slice(0, startIdx).trimEnd();
286
- const after = content.slice(endIdx + XDS_MARKER_END.length).trimStart();
303
+ const after = content.slice(endIdx + markerEndLen).trimStart();
287
304
  content = before + (after ? '\n\n' + after : '') + '\n';
288
305
 
289
306
  if (deleteIfEmpty) {