@astryxdesign/cli 0.1.0-canary.9ad489c → 0.1.0-canary.a95a267
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astryxdesign/cli",
|
|
3
|
-
"version": "0.1.0-canary.
|
|
3
|
+
"version": "0.1.0-canary.a95a267",
|
|
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",
|
|
@@ -54,9 +54,9 @@
|
|
|
54
54
|
"jscodeshift": "^17.3.0"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
|
-
"@astryxdesign/core": "0.1.0-canary.
|
|
58
|
-
"@astryxdesign/lab": "0.1.0-canary.
|
|
59
|
-
"@astryxdesign/theme-neutral": "0.1.0-canary.
|
|
57
|
+
"@astryxdesign/core": "0.1.0-canary.a95a267",
|
|
58
|
+
"@astryxdesign/lab": "0.1.0-canary.a95a267",
|
|
59
|
+
"@astryxdesign/theme-neutral": "0.1.0-canary.a95a267"
|
|
60
60
|
},
|
|
61
61
|
"peerDependenciesMeta": {
|
|
62
62
|
"@astryxdesign/core": {
|
|
@@ -70,9 +70,9 @@
|
|
|
70
70
|
}
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
|
-
"@astryxdesign/core": "0.1.0-canary.
|
|
74
|
-
"@astryxdesign/lab": "0.1.0-canary.
|
|
75
|
-
"@astryxdesign/theme-neutral": "0.1.0-canary.
|
|
73
|
+
"@astryxdesign/core": "0.1.0-canary.a95a267",
|
|
74
|
+
"@astryxdesign/lab": "0.1.0-canary.a95a267",
|
|
75
|
+
"@astryxdesign/theme-neutral": "0.1.0-canary.a95a267"
|
|
76
76
|
},
|
|
77
77
|
"scripts": {
|
|
78
78
|
"astryx": "node bin/astryx.mjs",
|
package/src/api/doctor.mjs
CHANGED
|
@@ -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
|
-
|
|
359
|
-
|
|
358
|
+
content.includes('<!-- XDS:START -->') &&
|
|
359
|
+
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
|
|
371
|
+
message: `Agent docs present (${present.join(', ')}) but no XDS section markers found.`,
|
|
372
372
|
fix: 'Add the XDS section to your agent docs with `astryx init --features agents`.',
|
|
373
373
|
};
|
|
374
374
|
}
|
|
@@ -31,11 +31,8 @@ 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
|
|
35
|
-
const
|
|
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 -->';
|
|
34
|
+
const XDS_MARKER_START = '<!-- XDS:START -->';
|
|
35
|
+
const XDS_MARKER_END = '<!-- XDS:END -->';
|
|
39
36
|
|
|
40
37
|
/**
|
|
41
38
|
* Agent tool presets — maps tool names to their file search paths.
|
|
@@ -102,7 +99,7 @@ export function resolveAgentPaths(targetDir, agent) {
|
|
|
102
99
|
*/
|
|
103
100
|
export function generateCompressedIndex(version, {coreDir, runPrefix = getRunPrefix()} = {}) {
|
|
104
101
|
const run = `${runPrefix} astryx`;
|
|
105
|
-
const lines = [
|
|
102
|
+
const lines = [XDS_MARKER_START];
|
|
106
103
|
|
|
107
104
|
// Component count from live discovery
|
|
108
105
|
let componentCount = '90+';
|
|
@@ -180,7 +177,7 @@ export function generateCompressedIndex(version, {coreDir, runPrefix = getRunPre
|
|
|
180
177
|
lines.push(`${run} swizzle <Name> eject source (--gap to report why)`);
|
|
181
178
|
lines.push(`${run} upgrade --apply codemods after version bump`);
|
|
182
179
|
lines.push(`after @astryxdesign/core bump, always run ${run} upgrade --apply`);
|
|
183
|
-
lines.push(
|
|
180
|
+
lines.push(XDS_MARKER_END);
|
|
184
181
|
|
|
185
182
|
return lines.join('\n');
|
|
186
183
|
}
|
|
@@ -221,21 +218,14 @@ export function injectXdsBlock(filePath, compressedIndex, {createIfMissing = fal
|
|
|
221
218
|
if (fs.existsSync(filePath)) {
|
|
222
219
|
content = fs.readFileSync(filePath, 'utf-8');
|
|
223
220
|
|
|
224
|
-
|
|
225
|
-
|
|
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
|
-
}
|
|
221
|
+
const startIdx = content.indexOf(XDS_MARKER_START);
|
|
222
|
+
const endIdx = content.indexOf(XDS_MARKER_END);
|
|
233
223
|
|
|
234
224
|
if (startIdx !== -1 && endIdx !== -1) {
|
|
235
225
|
content =
|
|
236
226
|
content.slice(0, startIdx) +
|
|
237
227
|
compressedIndex +
|
|
238
|
-
content.slice(endIdx +
|
|
228
|
+
content.slice(endIdx + XDS_MARKER_END.length);
|
|
239
229
|
} else if (onlyReplace) {
|
|
240
230
|
// File exists but has no Astryx markers — skip it
|
|
241
231
|
return false;
|
|
@@ -287,20 +277,13 @@ export function removeXdsBlock(filePath, {deleteIfEmpty = false} = {}) {
|
|
|
287
277
|
if (!fs.existsSync(filePath)) return false;
|
|
288
278
|
|
|
289
279
|
let content = fs.readFileSync(filePath, 'utf-8');
|
|
290
|
-
|
|
291
|
-
|
|
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
|
-
}
|
|
280
|
+
const startIdx = content.indexOf(XDS_MARKER_START);
|
|
281
|
+
const endIdx = content.indexOf(XDS_MARKER_END);
|
|
299
282
|
|
|
300
283
|
if (startIdx === -1 || endIdx === -1) return false;
|
|
301
284
|
|
|
302
285
|
const before = content.slice(0, startIdx).trimEnd();
|
|
303
|
-
const after = content.slice(endIdx +
|
|
286
|
+
const after = content.slice(endIdx + XDS_MARKER_END.length).trimStart();
|
|
304
287
|
content = before + (after ? '\n\n' + after : '') + '\n';
|
|
305
288
|
|
|
306
289
|
if (deleteIfEmpty) {
|
|
@@ -32,8 +32,8 @@ describe('generateCompressedIndex', () => {
|
|
|
32
32
|
it('includes the version number', () => {
|
|
33
33
|
const result = generateCompressedIndex('1.2.3');
|
|
34
34
|
expect(result).toContain('Astryx v1.2.3');
|
|
35
|
-
expect(result).toContain('<!--
|
|
36
|
-
expect(result).toContain('<!--
|
|
35
|
+
expect(result).toContain('<!-- XDS:START -->');
|
|
36
|
+
expect(result).toContain('<!-- XDS:END -->');
|
|
37
37
|
});
|
|
38
38
|
|
|
39
39
|
it('includes theme nudge rule', () => {
|
|
@@ -82,19 +82,19 @@ describe('injectXdsBlock', () => {
|
|
|
82
82
|
const filePath = path.join(tmpDir, 'test.md');
|
|
83
83
|
fs.writeFileSync(filePath, '# Existing content\n');
|
|
84
84
|
|
|
85
|
-
const result = injectXdsBlock(filePath, '<!--
|
|
85
|
+
const result = injectXdsBlock(filePath, '<!-- XDS:START -->\nnew\n<!-- XDS:END -->');
|
|
86
86
|
|
|
87
87
|
expect(result).toBe(true);
|
|
88
88
|
const content = fs.readFileSync(filePath, 'utf-8');
|
|
89
89
|
expect(content).toContain('# Existing content');
|
|
90
|
-
expect(content).toContain('<!--
|
|
90
|
+
expect(content).toContain('<!-- XDS:START -->');
|
|
91
91
|
});
|
|
92
92
|
|
|
93
93
|
it('replaces existing markers', () => {
|
|
94
94
|
const filePath = path.join(tmpDir, 'test.md');
|
|
95
95
|
fs.writeFileSync(filePath, 'before\n<!-- XDS:START -->\nold\n<!-- XDS:END -->\nafter\n');
|
|
96
96
|
|
|
97
|
-
injectXdsBlock(filePath, '<!--
|
|
97
|
+
injectXdsBlock(filePath, '<!-- XDS:START -->\nnew\n<!-- XDS:END -->');
|
|
98
98
|
|
|
99
99
|
const content = fs.readFileSync(filePath, 'utf-8');
|
|
100
100
|
expect(content).toContain('new');
|
|
@@ -106,7 +106,7 @@ describe('injectXdsBlock', () => {
|
|
|
106
106
|
it('returns false and does not create file when createIfMissing is false', () => {
|
|
107
107
|
const filePath = path.join(tmpDir, 'nonexistent.md');
|
|
108
108
|
|
|
109
|
-
const result = injectXdsBlock(filePath, '<!--
|
|
109
|
+
const result = injectXdsBlock(filePath, '<!-- XDS:START -->\ncontent\n<!-- XDS:END -->');
|
|
110
110
|
|
|
111
111
|
expect(result).toBe(false);
|
|
112
112
|
expect(fs.existsSync(filePath)).toBe(false);
|
|
@@ -116,11 +116,11 @@ describe('injectXdsBlock', () => {
|
|
|
116
116
|
const filePath = path.join(tmpDir, 'test.md');
|
|
117
117
|
fs.writeFileSync(filePath, '# Existing content\n\nNo XDS markers here.\n');
|
|
118
118
|
|
|
119
|
-
const result = injectXdsBlock(filePath, '<!--
|
|
119
|
+
const result = injectXdsBlock(filePath, '<!-- XDS:START -->\nnew\n<!-- XDS:END -->', {onlyReplace: true});
|
|
120
120
|
|
|
121
121
|
expect(result).toBe(false);
|
|
122
122
|
const content = fs.readFileSync(filePath, 'utf-8');
|
|
123
|
-
expect(content).not.toContain('<!--
|
|
123
|
+
expect(content).not.toContain('<!-- XDS:START -->');
|
|
124
124
|
expect(content).toBe('# Existing content\n\nNo XDS markers here.\n');
|
|
125
125
|
});
|
|
126
126
|
|
|
@@ -128,7 +128,7 @@ describe('injectXdsBlock', () => {
|
|
|
128
128
|
const filePath = path.join(tmpDir, 'test.md');
|
|
129
129
|
fs.writeFileSync(filePath, 'before\n<!-- XDS:START -->\nold\n<!-- XDS:END -->\nafter\n');
|
|
130
130
|
|
|
131
|
-
const result = injectXdsBlock(filePath, '<!--
|
|
131
|
+
const result = injectXdsBlock(filePath, '<!-- XDS:START -->\nnew\n<!-- XDS:END -->', {onlyReplace: true});
|
|
132
132
|
|
|
133
133
|
expect(result).toBe(true);
|
|
134
134
|
const content = fs.readFileSync(filePath, 'utf-8');
|
|
@@ -139,7 +139,7 @@ describe('injectXdsBlock', () => {
|
|
|
139
139
|
it('creates file when createIfMissing is true', () => {
|
|
140
140
|
const filePath = path.join(tmpDir, 'new.md');
|
|
141
141
|
|
|
142
|
-
const result = injectXdsBlock(filePath, '<!--
|
|
142
|
+
const result = injectXdsBlock(filePath, '<!-- XDS:START -->\ncontent\n<!-- XDS:END -->', {
|
|
143
143
|
createIfMissing: true,
|
|
144
144
|
header: '# Header',
|
|
145
145
|
});
|
|
@@ -147,7 +147,7 @@ describe('injectXdsBlock', () => {
|
|
|
147
147
|
expect(result).toBe(true);
|
|
148
148
|
const content = fs.readFileSync(filePath, 'utf-8');
|
|
149
149
|
expect(content).toContain('# Header');
|
|
150
|
-
expect(content).toContain('<!--
|
|
150
|
+
expect(content).toContain('<!-- XDS:START -->');
|
|
151
151
|
});
|
|
152
152
|
});
|
|
153
153
|
|
|
@@ -157,9 +157,9 @@ describe('injectAgentsMd', () => {
|
|
|
157
157
|
|
|
158
158
|
const content = fs.readFileSync(path.join(tmpDir, 'AGENTS.md'), 'utf-8');
|
|
159
159
|
expect(content).toContain('# AGENTS.md');
|
|
160
|
-
expect(content).toContain('<!--
|
|
160
|
+
expect(content).toContain('<!-- XDS:START -->');
|
|
161
161
|
expect(content).toContain('Astryx v1.0.0');
|
|
162
|
-
expect(content).toContain('<!--
|
|
162
|
+
expect(content).toContain('<!-- XDS:END -->');
|
|
163
163
|
});
|
|
164
164
|
|
|
165
165
|
it('updates existing AGENTS.md by replacing XDS markers', () => {
|
|
@@ -195,7 +195,7 @@ Existing agent docs.
|
|
|
195
195
|
|
|
196
196
|
const content = fs.readFileSync(path.join(tmpDir, 'AGENTS.md'), 'utf-8');
|
|
197
197
|
expect(content).toContain('Existing agent docs.');
|
|
198
|
-
expect(content).toContain('<!--
|
|
198
|
+
expect(content).toContain('<!-- XDS:START -->');
|
|
199
199
|
expect(content).toContain('Astryx v1.0.0');
|
|
200
200
|
});
|
|
201
201
|
});
|
|
@@ -210,7 +210,7 @@ describe('injectClaudeMd', () => {
|
|
|
210
210
|
const content = fs.readFileSync(path.join(tmpDir, 'CLAUDE.md'), 'utf-8');
|
|
211
211
|
expect(content).toContain('# Claude Config');
|
|
212
212
|
expect(content).toContain('Existing rules.');
|
|
213
|
-
expect(content).toContain('<!--
|
|
213
|
+
expect(content).toContain('<!-- XDS:START -->');
|
|
214
214
|
expect(content).toContain('Astryx v1.0.0');
|
|
215
215
|
});
|
|
216
216
|
|
|
@@ -322,7 +322,7 @@ describe('installAgentDocs', () => {
|
|
|
322
322
|
expect(fs.existsSync(path.join(tmpDir, '.claude', 'CLAUDE.md'))).toBe(true);
|
|
323
323
|
expect(fs.existsSync(path.join(tmpDir, 'AGENTS.md'))).toBe(false);
|
|
324
324
|
const content = fs.readFileSync(path.join(tmpDir, '.claude', 'CLAUDE.md'), 'utf-8');
|
|
325
|
-
expect(content).toContain('<!--
|
|
325
|
+
expect(content).toContain('<!-- XDS:START -->');
|
|
326
326
|
});
|
|
327
327
|
|
|
328
328
|
it('injects into CLAUDE.md at root when it exists', () => {
|
|
@@ -334,7 +334,7 @@ describe('installAgentDocs', () => {
|
|
|
334
334
|
expect(written).toEqual(['CLAUDE.md']);
|
|
335
335
|
expect(fs.existsSync(path.join(tmpDir, 'AGENTS.md'))).toBe(false);
|
|
336
336
|
const claudeContent = fs.readFileSync(path.join(tmpDir, 'CLAUDE.md'), 'utf-8');
|
|
337
|
-
expect(claudeContent).toContain('<!--
|
|
337
|
+
expect(claudeContent).toContain('<!-- XDS:START -->');
|
|
338
338
|
expect(claudeContent).toContain('Project rules.');
|
|
339
339
|
});
|
|
340
340
|
|
|
@@ -349,8 +349,8 @@ describe('installAgentDocs', () => {
|
|
|
349
349
|
expect(written).toContain('CLAUDE.md');
|
|
350
350
|
const agentsContent = fs.readFileSync(path.join(tmpDir, 'AGENTS.md'), 'utf-8');
|
|
351
351
|
const claudeContent = fs.readFileSync(path.join(tmpDir, 'CLAUDE.md'), 'utf-8');
|
|
352
|
-
expect(agentsContent).toContain('<!--
|
|
353
|
-
expect(claudeContent).toContain('<!--
|
|
352
|
+
expect(agentsContent).toContain('<!-- XDS:START -->');
|
|
353
|
+
expect(claudeContent).toContain('<!-- XDS:START -->');
|
|
354
354
|
});
|
|
355
355
|
|
|
356
356
|
it('updates existing .claude/CLAUDE.md', () => {
|
|
@@ -363,7 +363,7 @@ describe('installAgentDocs', () => {
|
|
|
363
363
|
expect(written).toEqual(['.claude/CLAUDE.md']);
|
|
364
364
|
const content = fs.readFileSync(path.join(tmpDir, '.claude', 'CLAUDE.md'), 'utf-8');
|
|
365
365
|
expect(content).toContain('Existing content.');
|
|
366
|
-
expect(content).toContain('<!--
|
|
366
|
+
expect(content).toContain('<!-- XDS:START -->');
|
|
367
367
|
});
|
|
368
368
|
|
|
369
369
|
it('respects --agent claude preset: finds existing CLAUDE.md', () => {
|
|
@@ -410,7 +410,7 @@ describe('installAgentDocs', () => {
|
|
|
410
410
|
|
|
411
411
|
expect(written).toEqual([]);
|
|
412
412
|
const content = fs.readFileSync(path.join(tmpDir, 'CLAUDE.md'), 'utf-8');
|
|
413
|
-
expect(content).not.toContain('<!--
|
|
413
|
+
expect(content).not.toContain('<!-- XDS:START -->');
|
|
414
414
|
expect(content).toBe('# Claude\n\nProject rules only.\n');
|
|
415
415
|
});
|
|
416
416
|
|
package/src/commands/init.mjs
CHANGED
|
@@ -248,7 +248,7 @@ export function registerInit(program) {
|
|
|
248
248
|
humanLog(' 2. Optionally add a theme:');
|
|
249
249
|
humanLog(" import { neutralTheme } from '@astryxdesign/theme-neutral'");
|
|
250
250
|
humanLog(' <Theme theme={neutralTheme}>...</Theme>');
|
|
251
|
-
humanLog(` 3. ${run}
|
|
251
|
+
humanLog(` 3. ${run} xds --help for all commands`);
|
|
252
252
|
humanLog('');
|
|
253
253
|
});
|
|
254
254
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @file Detect the project's package manager from lockfiles.
|
|
5
5
|
*
|
|
6
6
|
* Returns the correct command prefix for running package binaries
|
|
7
|
-
* (e.g. 'npx
|
|
7
|
+
* (e.g. 'npx xds', 'yarn xds', 'pnpm exec xds').
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import * as fs from 'node:fs';
|