webclaw 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -6
- package/bin/webclaw.js +284 -31
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,11 +8,12 @@ Official CLI for WebClaw. It initializes a new project by cloning the WebClaw re
|
|
|
8
8
|
npx webclaw
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
You will be prompted for:
|
|
12
|
+
- project name
|
|
13
|
+
- environment keys (`CLAWDBOT_GATEWAY_URL`, token/password)
|
|
14
|
+
- local dev port
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
npx webclaw init my-webclaw
|
|
15
|
-
```
|
|
16
|
+
Then the CLI creates the project folder, installs dependencies, and starts WebClaw.
|
|
16
17
|
|
|
17
18
|
Run project commands from a WebClaw project directory:
|
|
18
19
|
|
|
@@ -26,6 +27,6 @@ webclaw lint
|
|
|
26
27
|
|
|
27
28
|
## Commands
|
|
28
29
|
|
|
29
|
-
- `webclaw` -
|
|
30
|
-
- `webclaw init [dir]` - initialize a project in `dir`
|
|
30
|
+
- `webclaw` - create and start a new project
|
|
31
|
+
- `webclaw init [dir]` - initialize a project in `dir` (legacy)
|
|
31
32
|
- `webclaw doctor` - validate local prerequisites
|
package/bin/webclaw.js
CHANGED
|
@@ -9,6 +9,7 @@ import readline from 'node:readline/promises'
|
|
|
9
9
|
|
|
10
10
|
const __filename = fileURLToPath(import.meta.url)
|
|
11
11
|
const __dirname = path.dirname(__filename)
|
|
12
|
+
const LOCAL_TEMPLATE_ROOT = path.resolve(__dirname, '..', '..', '..')
|
|
12
13
|
const REPO_URL = 'https://github.com/ibelick/webclaw'
|
|
13
14
|
|
|
14
15
|
function printBanner() {
|
|
@@ -17,14 +18,15 @@ function printBanner() {
|
|
|
17
18
|
process.stdout.write(`██ ██ ▄█▀█▄ ████▄ ▄████ ██ ▀▀█▄ ██ ██ \n`)
|
|
18
19
|
process.stdout.write(`██ █ ██ ██▄█▀ ██ ██ ██ ██ ▄█▀██ ██ █ ██ \n`)
|
|
19
20
|
process.stdout.write(` ██▀██ ▀█▄▄▄ ████▀ ▀████ ██ ▀█▄██ ██▀██ \n\n`)
|
|
20
|
-
process.stdout.write(`Fast web client for OpenClaw\n
|
|
21
|
+
process.stdout.write(`Fast web client for OpenClaw\n`)
|
|
22
|
+
process.stdout.write(`https://webclaw.dev/\n\n`)
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
function printHelp() {
|
|
24
26
|
process.stdout.write(`webclaw CLI\n\n`)
|
|
25
27
|
process.stdout.write(`Usage:\n`)
|
|
26
|
-
process.stdout.write(` webclaw
|
|
27
|
-
process.stdout.write(` webclaw init [dir] Initialize a new project\n`)
|
|
28
|
+
process.stdout.write(` webclaw Create and start a new project\n`)
|
|
29
|
+
process.stdout.write(` webclaw init [dir] Initialize a new project (legacy)\n`)
|
|
28
30
|
process.stdout.write(` webclaw dev Run development server\n`)
|
|
29
31
|
process.stdout.write(` webclaw build Build project\n`)
|
|
30
32
|
process.stdout.write(` webclaw preview Preview production build\n`)
|
|
@@ -32,11 +34,68 @@ function printHelp() {
|
|
|
32
34
|
process.stdout.write(` webclaw lint Run lint\n`)
|
|
33
35
|
process.stdout.write(` webclaw doctor Validate local setup\n`)
|
|
34
36
|
process.stdout.write(`\nOptions:\n`)
|
|
37
|
+
process.stdout.write(` --project-name <name> Project directory name\n`)
|
|
38
|
+
process.stdout.write(` --gateway-url <url> CLAWDBOT_GATEWAY_URL value\n`)
|
|
39
|
+
process.stdout.write(` --gateway-token <token> CLAWDBOT_GATEWAY_TOKEN value\n`)
|
|
40
|
+
process.stdout.write(` --gateway-password <pw> CLAWDBOT_GATEWAY_PASSWORD value\n`)
|
|
41
|
+
process.stdout.write(` --port <port> Dev server port\n`)
|
|
42
|
+
process.stdout.write(` --yes Accept defaults (non-interactive)\n`)
|
|
43
|
+
process.stdout.write(` --no-start Do not auto-run install + dev\n`)
|
|
35
44
|
process.stdout.write(` --force Allow init in non-empty directory\n`)
|
|
36
45
|
process.stdout.write(` --skip-env Skip .env.local setup prompts\n`)
|
|
37
46
|
process.stdout.write(` -h, --help Show help\n`)
|
|
38
47
|
}
|
|
39
48
|
|
|
49
|
+
function parseCliArgs(args) {
|
|
50
|
+
const flags = new Set()
|
|
51
|
+
const values = new Map()
|
|
52
|
+
const positionals = []
|
|
53
|
+
const optionsWithValues = new Set([
|
|
54
|
+
'--project-name',
|
|
55
|
+
'--gateway-url',
|
|
56
|
+
'--gateway-token',
|
|
57
|
+
'--gateway-password',
|
|
58
|
+
'--port',
|
|
59
|
+
])
|
|
60
|
+
|
|
61
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
62
|
+
const arg = args[index]
|
|
63
|
+
if (!arg.startsWith('-')) {
|
|
64
|
+
positionals.push(arg)
|
|
65
|
+
continue
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (arg === '-h' || arg === '--help') {
|
|
69
|
+
flags.add(arg)
|
|
70
|
+
continue
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!arg.startsWith('--')) {
|
|
74
|
+
flags.add(arg)
|
|
75
|
+
continue
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const equalIndex = arg.indexOf('=')
|
|
79
|
+
if (equalIndex !== -1) {
|
|
80
|
+
const key = arg.slice(0, equalIndex)
|
|
81
|
+
const value = arg.slice(equalIndex + 1)
|
|
82
|
+
values.set(key, value)
|
|
83
|
+
continue
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const nextArg = args[index + 1]
|
|
87
|
+
if (optionsWithValues.has(arg) && nextArg && !nextArg.startsWith('-')) {
|
|
88
|
+
values.set(arg, nextArg)
|
|
89
|
+
index += 1
|
|
90
|
+
continue
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
flags.add(arg)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return { flags, values, positionals }
|
|
97
|
+
}
|
|
98
|
+
|
|
40
99
|
function runCommand(command, args, cwd) {
|
|
41
100
|
const result = spawnSync(command, args, {
|
|
42
101
|
cwd,
|
|
@@ -74,7 +133,7 @@ function runProjectScript(scriptName) {
|
|
|
74
133
|
const detected = detectProjectRoot(process.cwd())
|
|
75
134
|
if (!detected) {
|
|
76
135
|
process.stderr.write(
|
|
77
|
-
`No WebClaw project found in this directory. Run \`webclaw
|
|
136
|
+
`No WebClaw project found in this directory. Run \`npx webclaw\` first.\n`,
|
|
78
137
|
)
|
|
79
138
|
process.exit(1)
|
|
80
139
|
}
|
|
@@ -132,6 +191,55 @@ function cloneRepo(targetDir) {
|
|
|
132
191
|
runCommand('git', ['clone', '--depth', '1', REPO_URL, targetDir], process.cwd())
|
|
133
192
|
}
|
|
134
193
|
|
|
194
|
+
function getLocalTemplateSource() {
|
|
195
|
+
const rootPackage = path.join(LOCAL_TEMPLATE_ROOT, 'package.json')
|
|
196
|
+
const appPackage = path.join(LOCAL_TEMPLATE_ROOT, 'apps', 'webclaw', 'package.json')
|
|
197
|
+
if (!fs.existsSync(rootPackage) || !fs.existsSync(appPackage)) {
|
|
198
|
+
return null
|
|
199
|
+
}
|
|
200
|
+
return LOCAL_TEMPLATE_ROOT
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function populateTemplate(targetDir, isCurrentDir) {
|
|
204
|
+
const localTemplateSource = getLocalTemplateSource()
|
|
205
|
+
if (localTemplateSource) {
|
|
206
|
+
if (!isCurrentDir) {
|
|
207
|
+
copyDir(localTemplateSource, targetDir)
|
|
208
|
+
return
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
copyDir(localTemplateSource, targetDir)
|
|
212
|
+
return
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (!isCurrentDir) {
|
|
216
|
+
cloneRepo(targetDir)
|
|
217
|
+
return
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'webclaw-'))
|
|
221
|
+
const tempCloneDir = path.join(tempRoot, 'repo')
|
|
222
|
+
cloneRepo(tempCloneDir)
|
|
223
|
+
copyDir(tempCloneDir, targetDir)
|
|
224
|
+
fs.rmSync(tempRoot, { recursive: true, force: true })
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function ensureGitRepository(targetDir) {
|
|
228
|
+
if (fs.existsSync(path.join(targetDir, '.git'))) {
|
|
229
|
+
return
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const result = spawnSync('git', ['init'], {
|
|
233
|
+
cwd: targetDir,
|
|
234
|
+
stdio: 'ignore',
|
|
235
|
+
env: process.env,
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
if (result.status === 0) {
|
|
239
|
+
process.stdout.write('Initialized git repository\n')
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
135
243
|
function resolveEnvFile(targetDir) {
|
|
136
244
|
const monorepoEnv = path.join(targetDir, 'apps', 'webclaw', '.env.local')
|
|
137
245
|
if (fs.existsSync(path.join(targetDir, 'apps', 'webclaw'))) {
|
|
@@ -145,8 +253,61 @@ async function askQuestion(rl, question) {
|
|
|
145
253
|
return answer.trim()
|
|
146
254
|
}
|
|
147
255
|
|
|
148
|
-
|
|
256
|
+
function parsePort(value, fallback) {
|
|
257
|
+
const parsed = Number(value)
|
|
258
|
+
if (!Number.isInteger(parsed) || parsed < 1 || parsed > 65535) {
|
|
259
|
+
return fallback
|
|
260
|
+
}
|
|
261
|
+
return parsed
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function setDevPort(targetDir, port) {
|
|
265
|
+
const appPackagePath = fs.existsSync(path.join(targetDir, 'apps', 'webclaw'))
|
|
266
|
+
? path.join(targetDir, 'apps', 'webclaw', 'package.json')
|
|
267
|
+
: path.join(targetDir, 'package.json')
|
|
268
|
+
|
|
269
|
+
if (!fs.existsSync(appPackagePath)) return
|
|
270
|
+
|
|
271
|
+
const packageJson = JSON.parse(fs.readFileSync(appPackagePath, 'utf8'))
|
|
272
|
+
if (!packageJson.scripts || typeof packageJson.scripts.dev !== 'string') return
|
|
273
|
+
|
|
274
|
+
if (packageJson.scripts.dev.includes('--port')) {
|
|
275
|
+
packageJson.scripts.dev = packageJson.scripts.dev.replace(
|
|
276
|
+
/--port\s+\d+/,
|
|
277
|
+
`--port ${port}`,
|
|
278
|
+
)
|
|
279
|
+
} else {
|
|
280
|
+
packageJson.scripts.dev = `${packageJson.scripts.dev} --port ${port}`
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
fs.writeFileSync(appPackagePath, `${JSON.stringify(packageJson, null, 2)}\n`)
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function writeEnvFile(targetDir, envValues) {
|
|
287
|
+
const envFile = resolveEnvFile(targetDir)
|
|
288
|
+
ensureDir(path.dirname(envFile))
|
|
289
|
+
|
|
290
|
+
const lines = [
|
|
291
|
+
`CLAWDBOT_GATEWAY_URL=${envValues.gatewayUrl}`,
|
|
292
|
+
`CLAWDBOT_GATEWAY_TOKEN=${envValues.gatewayToken}`,
|
|
293
|
+
]
|
|
294
|
+
|
|
295
|
+
if (envValues.gatewayPassword.length > 0) {
|
|
296
|
+
lines.push(`CLAWDBOT_GATEWAY_PASSWORD=${envValues.gatewayPassword}`)
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
fs.writeFileSync(envFile, `${lines.join('\n')}\n`)
|
|
300
|
+
process.stdout.write(`Wrote ${envFile}\n\n`)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
async function maybeSetupEnv(targetDir, options, envValues) {
|
|
149
304
|
if (options.has('--skip-env')) return
|
|
305
|
+
|
|
306
|
+
if (envValues) {
|
|
307
|
+
writeEnvFile(targetDir, envValues)
|
|
308
|
+
return
|
|
309
|
+
}
|
|
310
|
+
|
|
150
311
|
if (!process.stdin.isTTY || !process.stdout.isTTY) return
|
|
151
312
|
|
|
152
313
|
const envFile = resolveEnvFile(targetDir)
|
|
@@ -191,19 +352,35 @@ async function maybeSetupEnv(targetDir, options) {
|
|
|
191
352
|
const gatewayUrl = await askQuestion(rl, 'CLAWDBOT_GATEWAY_URL: ')
|
|
192
353
|
const gatewayToken = await askQuestion(rl, 'CLAWDBOT_GATEWAY_TOKEN: ')
|
|
193
354
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
)
|
|
199
|
-
process.stdout.write(`Wrote ${envFile}\n\n`)
|
|
355
|
+
writeEnvFile(targetDir, {
|
|
356
|
+
gatewayUrl,
|
|
357
|
+
gatewayToken,
|
|
358
|
+
gatewayPassword: '',
|
|
359
|
+
})
|
|
200
360
|
} finally {
|
|
201
361
|
rl.close()
|
|
202
362
|
}
|
|
203
363
|
}
|
|
204
364
|
|
|
205
|
-
|
|
206
|
-
|
|
365
|
+
function installDependencies(targetDir) {
|
|
366
|
+
const packageManager = detectPackageManager(targetDir)
|
|
367
|
+
if (packageManager === 'yarn') {
|
|
368
|
+
runCommand('yarn', ['install'], targetDir)
|
|
369
|
+
return
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
runCommand(packageManager, ['install'], targetDir)
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
function startProject(targetDir) {
|
|
376
|
+
const packageManager = detectPackageManager(targetDir)
|
|
377
|
+
runCommand(packageManager, ['run', 'dev'], targetDir)
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
async function initProject(rawTarget, options, bootstrapConfig) {
|
|
381
|
+
if (!bootstrapConfig) {
|
|
382
|
+
printBanner()
|
|
383
|
+
}
|
|
207
384
|
const targetDir = path.resolve(process.cwd(), rawTarget ?? '.')
|
|
208
385
|
const force = options.has('--force')
|
|
209
386
|
const isCurrentDir = targetDir === process.cwd()
|
|
@@ -231,26 +408,103 @@ async function initProject(rawTarget, options) {
|
|
|
231
408
|
}
|
|
232
409
|
|
|
233
410
|
if (!fs.existsSync(path.join(targetDir, '.git')) && isDirEmpty(targetDir)) {
|
|
234
|
-
|
|
235
|
-
cloneRepo(targetDir)
|
|
236
|
-
} else {
|
|
237
|
-
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'webclaw-'))
|
|
238
|
-
const tempCloneDir = path.join(tempRoot, 'repo')
|
|
239
|
-
cloneRepo(tempCloneDir)
|
|
240
|
-
copyDir(tempCloneDir, targetDir)
|
|
241
|
-
fs.rmSync(tempRoot, { recursive: true, force: true })
|
|
242
|
-
}
|
|
411
|
+
populateTemplate(targetDir, isCurrentDir)
|
|
243
412
|
}
|
|
244
413
|
|
|
245
|
-
|
|
414
|
+
ensureGitRepository(targetDir)
|
|
415
|
+
|
|
416
|
+
if (bootstrapConfig) {
|
|
417
|
+
setDevPort(targetDir, bootstrapConfig.port)
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
await maybeSetupEnv(targetDir, options, bootstrapConfig?.envValues)
|
|
246
421
|
|
|
247
422
|
process.stdout.write(`\nWebClaw project created at ${targetDir}\n\n`)
|
|
423
|
+
|
|
424
|
+
if (bootstrapConfig && bootstrapConfig.autoStart) {
|
|
425
|
+
process.stdout.write(`Installing dependencies...\n`)
|
|
426
|
+
installDependencies(targetDir)
|
|
427
|
+
process.stdout.write(`Starting WebClaw on port ${bootstrapConfig?.port ?? 3000}...\n\n`)
|
|
428
|
+
startProject(targetDir)
|
|
429
|
+
return
|
|
430
|
+
}
|
|
431
|
+
|
|
248
432
|
process.stdout.write(`Next steps:\n`)
|
|
249
433
|
process.stdout.write(` cd ${path.relative(process.cwd(), targetDir) || '.'}\n`)
|
|
250
434
|
process.stdout.write(` pnpm install\n`)
|
|
251
435
|
process.stdout.write(` pnpm dev\n\n`)
|
|
252
436
|
}
|
|
253
437
|
|
|
438
|
+
async function askBootstrapConfig(defaultProjectName, parsedArgs) {
|
|
439
|
+
const nonInteractive =
|
|
440
|
+
parsedArgs.flags.has('--yes') || !process.stdin.isTTY || !process.stdout.isTTY
|
|
441
|
+
|
|
442
|
+
const initialProjectName =
|
|
443
|
+
parsedArgs.values.get('--project-name') || defaultProjectName || 'webclaw'
|
|
444
|
+
const initialGatewayUrl =
|
|
445
|
+
parsedArgs.values.get('--gateway-url') || 'ws://127.0.0.1:18789'
|
|
446
|
+
const initialGatewayToken = parsedArgs.values.get('--gateway-token') || ''
|
|
447
|
+
const initialGatewayPassword = parsedArgs.values.get('--gateway-password') || ''
|
|
448
|
+
const initialPort = parsePort(parsedArgs.values.get('--port') || 3000, 3000)
|
|
449
|
+
|
|
450
|
+
if (nonInteractive) {
|
|
451
|
+
return {
|
|
452
|
+
projectName: initialProjectName,
|
|
453
|
+
envValues: {
|
|
454
|
+
gatewayUrl: initialGatewayUrl,
|
|
455
|
+
gatewayToken: initialGatewayToken,
|
|
456
|
+
gatewayPassword: initialGatewayPassword,
|
|
457
|
+
},
|
|
458
|
+
port: initialPort,
|
|
459
|
+
autoStart: !parsedArgs.flags.has('--no-start'),
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
const rl = readline.createInterface({
|
|
464
|
+
input: process.stdin,
|
|
465
|
+
output: process.stdout,
|
|
466
|
+
})
|
|
467
|
+
|
|
468
|
+
try {
|
|
469
|
+
const projectNameInput = await askQuestion(
|
|
470
|
+
rl,
|
|
471
|
+
`Project name [${initialProjectName}]: `,
|
|
472
|
+
)
|
|
473
|
+
const projectName = projectNameInput || initialProjectName
|
|
474
|
+
|
|
475
|
+
const gatewayUrlInput = await askQuestion(
|
|
476
|
+
rl,
|
|
477
|
+
`CLAWDBOT_GATEWAY_URL [${initialGatewayUrl}]: `,
|
|
478
|
+
)
|
|
479
|
+
const gatewayUrl = gatewayUrlInput || initialGatewayUrl
|
|
480
|
+
|
|
481
|
+
const gatewayTokenInput = await askQuestion(
|
|
482
|
+
rl,
|
|
483
|
+
'CLAWDBOT_GATEWAY_TOKEN (optional): ',
|
|
484
|
+
)
|
|
485
|
+
const gatewayPasswordInput = await askQuestion(
|
|
486
|
+
rl,
|
|
487
|
+
'CLAWDBOT_GATEWAY_PASSWORD (optional): ',
|
|
488
|
+
)
|
|
489
|
+
|
|
490
|
+
const portInput = await askQuestion(rl, `Port [${initialPort}]: `)
|
|
491
|
+
const port = parsePort(portInput || initialPort, initialPort)
|
|
492
|
+
|
|
493
|
+
return {
|
|
494
|
+
projectName,
|
|
495
|
+
envValues: {
|
|
496
|
+
gatewayUrl,
|
|
497
|
+
gatewayToken: gatewayTokenInput || initialGatewayToken,
|
|
498
|
+
gatewayPassword: gatewayPasswordInput || initialGatewayPassword,
|
|
499
|
+
},
|
|
500
|
+
port,
|
|
501
|
+
autoStart: !parsedArgs.flags.has('--no-start'),
|
|
502
|
+
}
|
|
503
|
+
} finally {
|
|
504
|
+
rl.close()
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
254
508
|
function doctor() {
|
|
255
509
|
const nodeMajor = Number(process.versions.node.split('.')[0] || 0)
|
|
256
510
|
const hasPnpm = spawnSync('pnpm', ['--version'], { stdio: 'ignore' }).status === 0
|
|
@@ -276,8 +530,9 @@ function doctor() {
|
|
|
276
530
|
|
|
277
531
|
async function main() {
|
|
278
532
|
const args = process.argv.slice(2)
|
|
279
|
-
const
|
|
280
|
-
const
|
|
533
|
+
const parsedArgs = parseCliArgs(args)
|
|
534
|
+
const options = parsedArgs.flags
|
|
535
|
+
const command = parsedArgs.positionals[0]
|
|
281
536
|
|
|
282
537
|
if (options.has('-h') || options.has('--help')) {
|
|
283
538
|
printHelp()
|
|
@@ -285,16 +540,14 @@ async function main() {
|
|
|
285
540
|
}
|
|
286
541
|
|
|
287
542
|
if (!command) {
|
|
288
|
-
|
|
543
|
+
printBanner()
|
|
544
|
+
const bootstrapConfig = await askBootstrapConfig(null, parsedArgs)
|
|
545
|
+
await initProject(bootstrapConfig.projectName, options, bootstrapConfig)
|
|
289
546
|
return
|
|
290
547
|
}
|
|
291
548
|
|
|
292
549
|
if (command === 'init') {
|
|
293
|
-
const target =
|
|
294
|
-
if (arg.startsWith('-')) return false
|
|
295
|
-
const previous = args[index - 1]
|
|
296
|
-
return previous === 'init'
|
|
297
|
-
})
|
|
550
|
+
const target = parsedArgs.positionals[1]
|
|
298
551
|
await initProject(target, options)
|
|
299
552
|
return
|
|
300
553
|
}
|