@archetypeai/ds-cli 0.3.10 → 0.3.12

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/bin.js CHANGED
@@ -31,12 +31,16 @@ Create flags:
31
31
  --fonts / --no-fonts Install internal fonts (default: prompt)
32
32
  --no-components Skip component installation (default: install all)
33
33
  --codeagent <cursor|claude|none> Agent configuration (default: prompt)
34
+ --defaults Skip prompts, use sensible defaults
34
35
 
35
36
  Init flags:
36
37
  --pm <npm|pnpm|bun|yarn> Package manager (default: auto-detect)
37
38
  --fonts / --no-fonts Install internal fonts (default: prompt)
38
39
  --no-components Skip component installation (default: install all)
39
40
  --codeagent <cursor|claude|none> Agent configuration (default: prompt)
41
+ --defaults Skip prompts, use sensible defaults
42
+
43
+ Non-interactive shells (no TTY) automatically use defaults.
40
44
 
41
45
  Add targets:
42
46
  ds-ui-svelte Install all design system components
@@ -8,10 +8,12 @@ import {
8
8
  installTokens,
9
9
  initShadcn,
10
10
  configureCss,
11
+ installLinting,
11
12
  installComponents,
12
13
  createDemoPage,
13
14
  installAgentConfig
14
15
  } from '../lib/scaffold-ds-svelte-project.js';
16
+ import { isInteractive, DEFAULTS, logDefaultsNotice } from '../lib/is-interactive.js';
15
17
 
16
18
  // parse flags
17
19
  export function parseFlags(args) {
@@ -20,7 +22,8 @@ export function parseFlags(args) {
20
22
  framework: null,
21
23
  pm: null,
22
24
  components: true,
23
- agent: null
25
+ agent: null,
26
+ defaults: false
24
27
  };
25
28
 
26
29
  for (let i = 0; i < args.length; i++) {
@@ -33,6 +36,8 @@ export function parseFlags(args) {
33
36
  flags.components = false;
34
37
  } else if (arg === '--codeagent' && args[i + 1]) {
35
38
  flags.agent = args[++i];
39
+ } else if (arg === '--defaults') {
40
+ flags.defaults = true;
36
41
  } else if (!arg.startsWith('--') && !flags.name) {
37
42
  flags.name = arg;
38
43
  }
@@ -44,12 +49,17 @@ export function parseFlags(args) {
44
49
  // create a new project
45
50
  export async function create(args) {
46
51
  const flags = parseFlags(args);
52
+ const interactive = isInteractive(flags);
47
53
 
48
54
  p.intro('Create a new project using Archetype AI Design System.');
49
55
 
50
56
  // specify project name
51
57
  let name = flags.name;
52
58
  if (!name) {
59
+ if (!interactive) {
60
+ p.log.error('Project name is required. Usage: ds create <project-name>');
61
+ process.exit(1);
62
+ }
53
63
  name = await p.text({
54
64
  message: 'What is your project name?',
55
65
  placeholder: 'my-app',
@@ -87,26 +97,38 @@ export async function create(args) {
87
97
  // specify framework
88
98
  let framework = flags.framework;
89
99
  if (!framework) {
90
- framework = await p.select({
91
- message: 'Which framework?',
92
- options: [{ value: 'svelte', label: 'SvelteKit', hint: 'Svelte 5 + Tailwind v4' }]
93
- });
94
- if (p.isCancel(framework)) {
95
- p.cancel('Setup cancelled.');
96
- process.exit(0);
100
+ if (!interactive) {
101
+ framework = DEFAULTS.framework;
102
+ } else {
103
+ framework = await p.select({
104
+ message: 'Which framework?',
105
+ options: [{ value: 'svelte', label: 'SvelteKit', hint: 'Svelte 5 + Tailwind v4, default' }]
106
+ });
107
+ if (p.isCancel(framework)) {
108
+ p.cancel('Setup cancelled.');
109
+ process.exit(0);
110
+ }
97
111
  }
98
112
  }
99
113
 
100
114
  // specify package manager
101
115
  let pmName = flags.pm;
102
116
  if (!pmName) {
103
- pmName = await p.select({
104
- message: 'Which package manager?',
105
- options: pmNames.map((n) => ({ value: n, label: n }))
106
- });
107
- if (p.isCancel(pmName)) {
108
- p.cancel('Setup cancelled.');
109
- process.exit(0);
117
+ if (!interactive) {
118
+ pmName = DEFAULTS.pm;
119
+ } else {
120
+ pmName = await p.select({
121
+ message: 'Which package manager?',
122
+ options: pmNames.map((n) => ({
123
+ value: n,
124
+ label: n,
125
+ ...(n === DEFAULTS.pm && { hint: 'default' })
126
+ }))
127
+ });
128
+ if (p.isCancel(pmName)) {
129
+ p.cancel('Setup cancelled.');
130
+ process.exit(0);
131
+ }
110
132
  }
111
133
  }
112
134
  const pm = getPm(pmName);
@@ -122,13 +144,17 @@ export async function create(args) {
122
144
  const projectPath = resolve(targetDir, name);
123
145
 
124
146
  if (existsSync(projectPath)) {
125
- const overwrite = await p.confirm({
126
- message: `Directory "${name}" already exists. Continue anyway?`,
127
- initialValue: false
128
- });
129
- if (p.isCancel(overwrite) || !overwrite) {
130
- p.cancel('Setup cancelled.');
131
- process.exit(0);
147
+ if (!interactive) {
148
+ p.log.warn(`Directory "${name}" already exists. Proceeding (non-interactive mode).`);
149
+ } else {
150
+ const overwrite = await p.confirm({
151
+ message: `Directory "${name}" already exists. Continue anyway?`,
152
+ initialValue: false
153
+ });
154
+ if (p.isCancel(overwrite) || !overwrite) {
155
+ p.cancel('Setup cancelled.');
156
+ process.exit(0);
157
+ }
132
158
  }
133
159
  }
134
160
 
@@ -151,6 +177,9 @@ export async function create(args) {
151
177
  const includeFonts = false;
152
178
  configureCss(projectPath, includeFonts);
153
179
 
180
+ // set up linting and formatting
181
+ await installLinting(pm, projectPath);
182
+
154
183
  // install components
155
184
  if (flags.components) {
156
185
  try {
@@ -169,20 +198,33 @@ export async function create(args) {
169
198
  // specify agent config
170
199
  let agent = flags.agent;
171
200
  if (!agent) {
172
- agent = await p.select({
173
- message: 'Install AI agent configuration?',
174
- options: [
175
- { value: 'none', label: 'None' },
176
- { value: 'cursor', label: 'Cursor', hint: 'AGENTS.md + skills + rules' },
177
- { value: 'claude', label: 'Claude Code', hint: 'CLAUDE.md + skills + rules' }
178
- ]
179
- });
180
- if (p.isCancel(agent)) {
181
- p.cancel('Setup cancelled.');
182
- process.exit(0);
201
+ if (!interactive) {
202
+ agent = DEFAULTS.agent;
203
+ } else {
204
+ agent = await p.select({
205
+ message: 'Install AI agent configuration?',
206
+ options: [
207
+ { value: 'none', label: 'None' },
208
+ { value: 'cursor', label: 'Cursor', hint: 'AGENTS.md + skills + rules' },
209
+ { value: 'claude', label: 'Claude Code', hint: 'CLAUDE.md + skills + rules, default' }
210
+ ]
211
+ });
212
+ if (p.isCancel(agent)) {
213
+ p.cancel('Setup cancelled.');
214
+ process.exit(0);
215
+ }
183
216
  }
184
217
  }
185
218
 
219
+ // log defaults notice
220
+ if (!interactive) {
221
+ const applied = {};
222
+ if (!flags.framework) applied.framework = framework;
223
+ if (!flags.pm) applied.pm = pmName;
224
+ if (!flags.agent) applied.codeagent = agent;
225
+ logDefaultsNotice(applied);
226
+ }
227
+
186
228
  const validAgents = ['cursor', 'claude', 'none'];
187
229
  if (!validAgents.includes(agent)) {
188
230
  p.log.error(`Invalid --codeagent value "${agent}". Must be one of: ${validAgents.join(', ')}`);
@@ -203,6 +245,7 @@ export async function create(args) {
203
245
  `Framework: ${framework}`,
204
246
  `Package Manager: ${pm.name}`,
205
247
  `Fonts: ${includeFonts ? 'installed' : 'skipped'}`,
248
+ `Linting: configured`,
206
249
  `Components: ${flags.components ? 'all' : 'skipped'}`,
207
250
  `Agent Configuration: ${agent}`
208
251
  ].join('\n');
package/commands/init.js CHANGED
@@ -8,16 +8,19 @@ import {
8
8
  installTokens,
9
9
  initShadcn,
10
10
  prependCss,
11
+ installLinting,
11
12
  installComponents,
12
13
  installAgentConfig
13
14
  } from '../lib/scaffold-ds-svelte-project.js';
15
+ import { isInteractive, DEFAULTS, logDefaultsNotice } from '../lib/is-interactive.js';
14
16
 
15
17
  // parse flags
16
18
  export function parseFlags(args) {
17
19
  const flags = {
18
20
  pm: null,
19
21
  components: true,
20
- agent: null
22
+ agent: null,
23
+ defaults: false
21
24
  };
22
25
 
23
26
  for (let i = 0; i < args.length; i++) {
@@ -28,6 +31,8 @@ export function parseFlags(args) {
28
31
  flags.components = false;
29
32
  } else if (arg === '--codeagent' && args[i + 1]) {
30
33
  flags.agent = args[++i];
34
+ } else if (arg === '--defaults') {
35
+ flags.defaults = true;
31
36
  }
32
37
  }
33
38
 
@@ -48,6 +53,7 @@ function hasTailwind(projectPath) {
48
53
  // initialize the design system in an existing project
49
54
  export async function init(args) {
50
55
  const flags = parseFlags(args);
56
+ const interactive = isInteractive(flags);
51
57
  const projectPath = process.cwd();
52
58
 
53
59
  // validate --pm flag
@@ -81,17 +87,33 @@ export async function init(args) {
81
87
  }
82
88
  }
83
89
  if (!pmName) {
84
- pmName = await p.select({
85
- message: 'Which package manager?',
86
- options: pmNames.map((n) => ({ value: n, label: n }))
87
- });
88
- if (p.isCancel(pmName)) {
89
- p.cancel('Setup cancelled.');
90
- process.exit(0);
90
+ if (!interactive) {
91
+ pmName = DEFAULTS.pm;
92
+ } else {
93
+ pmName = await p.select({
94
+ message: 'Which package manager?',
95
+ options: pmNames.map((n) => ({
96
+ value: n,
97
+ label: n,
98
+ ...(n === DEFAULTS.pm && { hint: 'default' })
99
+ }))
100
+ });
101
+ if (p.isCancel(pmName)) {
102
+ p.cancel('Setup cancelled.');
103
+ process.exit(0);
104
+ }
91
105
  }
92
106
  }
93
107
  const pm = getPm(pmName);
94
108
 
109
+ // log defaults notice
110
+ if (!interactive) {
111
+ const applied = {};
112
+ if (!flags.pm) applied.pm = pmName;
113
+ if (!flags.agent) applied.codeagent = DEFAULTS.agent;
114
+ logDefaultsNotice(applied);
115
+ }
116
+
95
117
  // verify package manager is installed
96
118
  if (!isPmInstalled(pmName)) {
97
119
  p.log.error(`${pmName} is not installed. Please install it first and try again.`);
@@ -120,6 +142,9 @@ export async function init(args) {
120
142
  const includeFonts = false;
121
143
  prependCss(projectPath, includeFonts);
122
144
 
145
+ // set up linting and formatting
146
+ await installLinting(pm, projectPath);
147
+
123
148
  // install components
124
149
  if (flags.components) {
125
150
  try {
@@ -138,17 +163,21 @@ export async function init(args) {
138
163
  // specify agent config
139
164
  let agent = flags.agent;
140
165
  if (!agent) {
141
- agent = await p.select({
142
- message: 'Install AI agent configuration?',
143
- options: [
144
- { value: 'none', label: 'None' },
145
- { value: 'cursor', label: 'Cursor', hint: 'AGENTS.md + skills + rules' },
146
- { value: 'claude', label: 'Claude Code', hint: 'CLAUDE.md + skills + rules' }
147
- ]
148
- });
149
- if (p.isCancel(agent)) {
150
- p.cancel('Setup cancelled.');
151
- process.exit(0);
166
+ if (!interactive) {
167
+ agent = DEFAULTS.agent;
168
+ } else {
169
+ agent = await p.select({
170
+ message: 'Install AI agent configuration?',
171
+ options: [
172
+ { value: 'none', label: 'None' },
173
+ { value: 'cursor', label: 'Cursor', hint: 'AGENTS.md + skills + rules' },
174
+ { value: 'claude', label: 'Claude Code', hint: 'CLAUDE.md + skills + rules, default' }
175
+ ]
176
+ });
177
+ if (p.isCancel(agent)) {
178
+ p.cancel('Setup cancelled.');
179
+ process.exit(0);
180
+ }
152
181
  }
153
182
  }
154
183
 
@@ -167,6 +196,7 @@ export async function init(args) {
167
196
  `Location: ${projectPath}`,
168
197
  `Package Manager: ${pm.name}`,
169
198
  `Fonts: ${includeFonts ? 'installed' : 'skipped'}`,
199
+ `Linting: configured`,
170
200
  `Components: ${flags.components ? 'all' : 'skipped'}`,
171
201
  `Agent Config: ${agent}`
172
202
  ].join('\n');
@@ -98,17 +98,9 @@ Identify structural opportunities to use DS composition patterns:
98
98
 
99
99
  Import patterns from `$lib/components/ui/` as needed.
100
100
 
101
- ## Step 5: Set Up Linting and Formatting
101
+ ## Step 5: Lint and Format
102
102
 
103
- Run the `scripts/setup.sh` script located in this skill's directory from the project root. The script:
104
-
105
- - Installs `eslint`, `prettier`, `eslint-plugin-svelte`, `eslint-config-prettier`, `prettier-plugin-svelte`, `prettier-plugin-tailwindcss`, and `globals`
106
- - Creates `eslint.config.js` (flat config v9+) if it doesn't exist
107
- - Creates `.prettierrc` with Svelte + Tailwind plugin config if it doesn't exist
108
- - Creates `.prettierignore` if it doesn't exist
109
- - Adds `lint`, `lint:fix`, `format`, and `format:check` scripts to `package.json`
110
-
111
- After setup, run linting and formatting:
103
+ Run linting and formatting to clean up the migrated code:
112
104
 
113
105
  ```bash
114
106
  npm run lint:fix && npm run format
@@ -120,12 +120,16 @@ Usage:
120
120
  } else if (isClaude) {
121
121
  agent = 'claude';
122
122
  } else {
123
+ if (!process.stdin.isTTY) {
124
+ p.log.error('Specify --cursor or --claude in non-interactive mode.');
125
+ process.exit(1);
126
+ }
123
127
  // interactive prompt when no flag is passed
124
128
  agent = await p.select({
125
129
  message: 'Which agent configuration?',
126
130
  options: [
127
131
  { value: 'cursor', label: 'Cursor', hint: 'AGENTS.md + skills + rules' },
128
- { value: 'claude', label: 'Claude Code', hint: 'CLAUDE.md + skills + rules' }
132
+ { value: 'claude', label: 'Claude Code', hint: 'CLAUDE.md + skills + rules, default' }
129
133
  ]
130
134
  });
131
135
  if (p.isCancel(agent)) {
@@ -0,0 +1,19 @@
1
+ import * as p from '@clack/prompts';
2
+
3
+ export const DEFAULTS = {
4
+ framework: 'svelte',
5
+ pm: 'npm',
6
+ agent: 'claude'
7
+ };
8
+
9
+ export function isInteractive(flags) {
10
+ if (flags.defaults) return false;
11
+ return !!process.stdin.isTTY;
12
+ }
13
+
14
+ export function logDefaultsNotice(applied) {
15
+ const parts = Object.entries(applied).map(([k, v]) => `${k}=${v}`);
16
+ if (parts.length > 0) {
17
+ p.log.info(`Non-interactive mode: using defaults (${parts.join(', ')})`);
18
+ }
19
+ }
@@ -259,6 +259,123 @@ export function createDemoPage(projectPath) {
259
259
  p.log.success('Demo page created');
260
260
  }
261
261
 
262
+ // install linting and formatting
263
+ export async function installLinting(pm, projectPath) {
264
+ const s = p.spinner();
265
+ s.start('Setting up linting and formatting');
266
+ try {
267
+ // install dev dependencies
268
+ const [cmd, ...baseArgs] = splitCmd(pm.install);
269
+ await run(
270
+ cmd,
271
+ [
272
+ ...baseArgs,
273
+ '-D',
274
+ '@eslint/js',
275
+ 'eslint',
276
+ 'prettier',
277
+ 'eslint-plugin-svelte',
278
+ 'eslint-config-prettier',
279
+ 'prettier-plugin-svelte',
280
+ 'prettier-plugin-tailwindcss',
281
+ 'globals'
282
+ ],
283
+ { cwd: projectPath }
284
+ );
285
+
286
+ // detect CSS file for Prettier Tailwind plugin
287
+ let cssFile = '';
288
+ for (const candidate of ['src/app.css', 'src/routes/layout.css', 'src/app.pcss']) {
289
+ if (existsSync(join(projectPath, candidate))) {
290
+ cssFile = candidate;
291
+ break;
292
+ }
293
+ }
294
+
295
+ // create eslint.config.js
296
+ const eslintPath = join(projectPath, 'eslint.config.js');
297
+ if (!existsSync(eslintPath)) {
298
+ writeFile(
299
+ eslintPath,
300
+ `import js from '@eslint/js';
301
+ import svelte from 'eslint-plugin-svelte';
302
+ import globals from 'globals';
303
+ import svelteConfig from './svelte.config.js';
304
+
305
+ export default [
306
+ \tjs.configs.recommended,
307
+ \t...svelte.configs.recommended,
308
+ \t...svelte.configs['flat/prettier'],
309
+ \t{
310
+ \t\tlanguageOptions: {
311
+ \t\t\tglobals: { ...globals.browser, ...globals.node }
312
+ \t\t}
313
+ \t},
314
+ \t{
315
+ \t\tfiles: ['**/*.svelte', '**/*.svelte.js'],
316
+ \t\tlanguageOptions: {
317
+ \t\t\tparserOptions: { svelteConfig }
318
+ \t\t}
319
+ \t},
320
+ \t{
321
+ \t\tignores: ['.svelte-kit/', 'build/', 'dist/', 'node_modules/']
322
+ \t}
323
+ ];
324
+ `
325
+ );
326
+ }
327
+
328
+ // create .prettierrc
329
+ const prettierrcPath = join(projectPath, '.prettierrc');
330
+ if (!existsSync(prettierrcPath)) {
331
+ const prettierrc = {
332
+ useTabs: true,
333
+ singleQuote: true,
334
+ trailingComma: 'none',
335
+ printWidth: 100,
336
+ plugins: ['prettier-plugin-svelte', 'prettier-plugin-tailwindcss']
337
+ };
338
+ if (cssFile) {
339
+ prettierrc.tailwindStylesheet = `./${cssFile}`;
340
+ }
341
+ writeFile(prettierrcPath, JSON.stringify(prettierrc, null, '\t') + '\n');
342
+ }
343
+
344
+ // create .prettierignore
345
+ const prettierignorePath = join(projectPath, '.prettierignore');
346
+ if (!existsSync(prettierignorePath)) {
347
+ writeFile(
348
+ prettierignorePath,
349
+ `.svelte-kit
350
+ .claude
351
+ .cursor
352
+ build
353
+ dist
354
+ node_modules
355
+ package-lock.json
356
+ `
357
+ );
358
+ }
359
+
360
+ // add lint/format scripts to package.json
361
+ const pkgPath = join(projectPath, 'package.json');
362
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
363
+ pkg.scripts = pkg.scripts || {};
364
+ pkg.scripts.lint = 'eslint .';
365
+ pkg.scripts['lint:fix'] = 'eslint . --fix';
366
+ pkg.scripts.format = 'prettier --write .';
367
+ pkg.scripts['format:check'] = 'prettier --check .';
368
+ writeFileSync(pkgPath, JSON.stringify(pkg, null, '\t') + '\n');
369
+
370
+ s.stop('Linting and formatting configured');
371
+ return true;
372
+ } catch (error) {
373
+ s.stop('Failed to set up linting');
374
+ p.log.error(error.stderr?.toString() || error.message);
375
+ return false;
376
+ }
377
+ }
378
+
262
379
  // install agent configuration
263
380
  export function installAgentConfig(projectPath, agentType) {
264
381
  const s = p.spinner();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@archetypeai/ds-cli",
3
- "version": "0.3.10",
3
+ "version": "0.3.12",
4
4
  "description": "Archetype AI Design System CLI Tool",
5
5
  "type": "module",
6
6
  "bin": {