@opencangjie/skills 0.0.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/dist/cli.js ADDED
@@ -0,0 +1,674 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import chalk from 'chalk';
4
+ import ora from 'ora';
5
+ import inquirer from 'inquirer';
6
+ import fs from 'fs-extra';
7
+ import path from 'path';
8
+ import { createClient, handleApiError, RuntimeManager } from './index.js';
9
+ const program = new Command();
10
+ const getClient = () => {
11
+ return createClient({
12
+ baseUrl: process.env.SKILL_RUNTIME_API_URL
13
+ });
14
+ };
15
+ const spinner = (text) => ora(text);
16
+ const printSuccess = (message) => {
17
+ console.log(chalk.green('✓'), message);
18
+ };
19
+ const printError = (message) => {
20
+ console.error(chalk.red('✗'), message);
21
+ };
22
+ const printSkill = (skill) => {
23
+ console.log(chalk.bold.cyan(`\n${skill.name}`) + chalk.gray(` (${skill.version})`));
24
+ console.log(chalk.gray(' Description:'), skill.description);
25
+ console.log(chalk.gray(' Author:'), skill.author);
26
+ if (skill.source_path) {
27
+ console.log(chalk.gray(' Path:'), skill.source_path);
28
+ }
29
+ };
30
+ const printSkillShort = (skill) => {
31
+ console.log(` ${chalk.cyan(skill.name)} ${chalk.gray(`(${skill.version})`)} - ${skill.description}`);
32
+ };
33
+ program
34
+ .name('skills')
35
+ .description('AgentSkills Runtime CLI - Install, manage, and execute AI agent skills')
36
+ .version('0.0.1')
37
+ .option('-u, --api-url <url>', 'API server URL', process.env.SKILL_RUNTIME_API_URL || 'http://127.0.0.1:8080')
38
+ .option('--json', 'Output as JSON', false);
39
+ program
40
+ .command('find [query]')
41
+ .description('Search for skills interactively or by keyword')
42
+ .option('-l, --limit <number>', 'Maximum number of results', '10')
43
+ .action(async (query, options) => {
44
+ const spin = spinner('Searching for skills...');
45
+ try {
46
+ const client = getClient();
47
+ let searchQuery = query;
48
+ if (!searchQuery) {
49
+ spin.stop();
50
+ const answer = await inquirer.prompt([{
51
+ type: 'input',
52
+ name: 'query',
53
+ message: 'What kind of skill are you looking for?',
54
+ default: ''
55
+ }]);
56
+ searchQuery = answer.query;
57
+ }
58
+ if (!searchQuery) {
59
+ spin.stop();
60
+ console.log(chalk.yellow('No search query provided. Showing all installed skills...\n'));
61
+ const result = await client.listSkills({ limit: parseInt(options.limit) });
62
+ if (result.skills.length === 0) {
63
+ console.log(chalk.gray('No skills found.'));
64
+ return;
65
+ }
66
+ result.skills.forEach(printSkillShort);
67
+ return;
68
+ }
69
+ spin.start();
70
+ const result = await client.searchSkills(searchQuery);
71
+ spin.stop();
72
+ if (result.skills.length === 0) {
73
+ console.log(chalk.yellow(`No skills found matching "${searchQuery}".`));
74
+ console.log(chalk.gray('\nTry different keywords or check if the skill exists at https://skills.sh/'));
75
+ return;
76
+ }
77
+ console.log(chalk.bold(`\nFound ${result.total} skill(s) matching "${searchQuery}":\n`));
78
+ result.skills.forEach(printSkillShort);
79
+ console.log(chalk.gray('\nInstall with: skills add <owner/repo@skill>'));
80
+ console.log(chalk.gray('Browse more at: https://skills.sh/'));
81
+ }
82
+ catch (error) {
83
+ spin.fail('Search failed');
84
+ printError(handleApiError(error).errmsg);
85
+ process.exit(1);
86
+ }
87
+ });
88
+ program
89
+ .command('add <source>')
90
+ .description('Install a skill from GitHub or local path')
91
+ .option('-g, --global', 'Install globally (user-level)', false)
92
+ .option('-p, --path <path>', 'Local path to skill')
93
+ .option('-b, --branch <branch>', 'Git branch name')
94
+ .option('-t, --tag <tag>', 'Git tag name')
95
+ .option('-c, --commit <commit>', 'Git commit ID')
96
+ .option('-n, --name <name>', 'Skill name override')
97
+ .option('--validate', 'Validate skill before installation', true)
98
+ .option('--no-validate', 'Skip validation')
99
+ .option('-y, --yes', 'Skip confirmation prompts', false)
100
+ .action(async (source, options) => {
101
+ const spin = spinner('Installing skill...');
102
+ try {
103
+ const client = getClient();
104
+ const installOptions = {
105
+ source: options.path || source,
106
+ validate: options.validate,
107
+ branch: options.branch,
108
+ tag: options.tag,
109
+ commit: options.commit
110
+ };
111
+ if (!options.yes) {
112
+ spin.stop();
113
+ console.log(chalk.bold('\nAbout to install:'), chalk.cyan(source));
114
+ const answer = await inquirer.prompt([{
115
+ type: 'confirm',
116
+ name: 'proceed',
117
+ message: 'Continue?',
118
+ default: true
119
+ }]);
120
+ if (!answer.proceed) {
121
+ console.log(chalk.gray('Installation cancelled.'));
122
+ return;
123
+ }
124
+ spin.start();
125
+ }
126
+ spin.text = 'Installing skill...';
127
+ const result = await client.installSkill(installOptions);
128
+ spin.succeed(chalk.green(result.message));
129
+ console.log(chalk.gray('\nSkill ID:'), result.id);
130
+ console.log(chalk.gray('Status:'), result.status);
131
+ console.log(chalk.gray('Installed at:'), result.created_at);
132
+ }
133
+ catch (error) {
134
+ spin.fail('Installation failed');
135
+ printError(handleApiError(error).errmsg);
136
+ process.exit(1);
137
+ }
138
+ });
139
+ program
140
+ .command('list')
141
+ .description('List installed skills')
142
+ .option('-l, --limit <number>', 'Maximum number of results', '20')
143
+ .option('-p, --page <number>', 'Page number', '0')
144
+ .option('--json', 'Output as JSON', false)
145
+ .action(async (options) => {
146
+ const spin = spinner('Loading skills...');
147
+ try {
148
+ const client = getClient();
149
+ const result = await client.listSkills({
150
+ limit: parseInt(options.limit),
151
+ page: parseInt(options.page)
152
+ });
153
+ spin.stop();
154
+ if (options.json) {
155
+ console.log(JSON.stringify(result, null, 2));
156
+ return;
157
+ }
158
+ if (result.skills.length === 0) {
159
+ console.log(chalk.yellow('No skills installed.'));
160
+ console.log(chalk.gray('\nInstall a skill with: skills add <source>'));
161
+ console.log(chalk.gray('Find skills with: skills find <query>'));
162
+ return;
163
+ }
164
+ console.log(chalk.bold(`\nInstalled Skills (${result.total_count} total):\n`));
165
+ result.skills.forEach(printSkillShort);
166
+ if (result.total_page > 1) {
167
+ console.log(chalk.gray(`\nPage ${result.current_page + 1} of ${result.total_page}`));
168
+ console.log(chalk.gray('Use --page to see more results'));
169
+ }
170
+ }
171
+ catch (error) {
172
+ spin.fail('Failed to list skills');
173
+ printError(handleApiError(error).errmsg);
174
+ process.exit(1);
175
+ }
176
+ });
177
+ program
178
+ .command('run <skillId>')
179
+ .description('Execute a skill')
180
+ .option('-t, --tool <name>', 'Tool name to execute')
181
+ .option('-p, --params <json>', 'Parameters as JSON string')
182
+ .option('-f, --params-file <file>', 'Parameters from JSON file')
183
+ .option('-i, --interactive', 'Interactive parameter input', false)
184
+ .action(async (skillId, options) => {
185
+ const spin = spinner('Executing skill...');
186
+ try {
187
+ const client = getClient();
188
+ let params = {};
189
+ if (options.params) {
190
+ params = JSON.parse(options.params);
191
+ }
192
+ else if (options.paramsFile) {
193
+ params = await fs.readJson(options.paramsFile);
194
+ }
195
+ else if (options.interactive) {
196
+ spin.stop();
197
+ const skill = await client.getSkill(skillId);
198
+ console.log(chalk.bold(`\nExecuting: ${skill.name}`));
199
+ console.log(chalk.gray(skill.description));
200
+ if (skill.tools && skill.tools.length > 0) {
201
+ const toolAnswer = await inquirer.prompt([{
202
+ type: 'list',
203
+ name: 'tool',
204
+ message: 'Select a tool:',
205
+ choices: skill.tools.map((t) => ({ name: `${t.name} - ${t.description}`, value: t.name }))
206
+ }]);
207
+ options.tool = toolAnswer.tool;
208
+ const tool = skill.tools.find((t) => t.name === options.tool);
209
+ if (tool && tool.parameters.length > 0) {
210
+ for (const param of tool.parameters) {
211
+ const answer = await inquirer.prompt([{
212
+ type: param.paramType === 'boolean' ? 'confirm' : 'input',
213
+ name: param.name,
214
+ message: param.description,
215
+ default: param.defaultValue,
216
+ }]);
217
+ params[param.name] = answer[param.name];
218
+ }
219
+ }
220
+ }
221
+ spin.start();
222
+ }
223
+ let result;
224
+ if (options.tool) {
225
+ spin.text = `Executing tool: ${options.tool}...`;
226
+ result = await client.executeSkillTool(skillId, options.tool, params);
227
+ }
228
+ else {
229
+ spin.text = 'Executing skill...';
230
+ result = await client.executeSkill(skillId, params);
231
+ }
232
+ if (result.success) {
233
+ spin.succeed('Execution completed');
234
+ console.log('\n' + chalk.bold('Result:'));
235
+ console.log(result.output);
236
+ if (result.data) {
237
+ console.log(chalk.gray('\nData:'));
238
+ console.log(JSON.stringify(result.data, null, 2));
239
+ }
240
+ }
241
+ else {
242
+ spin.fail('Execution failed');
243
+ printError(result.errorMessage || 'Unknown error');
244
+ process.exit(1);
245
+ }
246
+ }
247
+ catch (error) {
248
+ spin.fail('Execution failed');
249
+ printError(handleApiError(error).errmsg);
250
+ process.exit(1);
251
+ }
252
+ });
253
+ program
254
+ .command('remove <skillId>')
255
+ .alias('rm')
256
+ .alias('uninstall')
257
+ .description('Remove an installed skill')
258
+ .option('-y, --yes', 'Skip confirmation prompt', false)
259
+ .action(async (skillId, options) => {
260
+ try {
261
+ const client = getClient();
262
+ if (!options.yes) {
263
+ const skill = await client.getSkill(skillId);
264
+ console.log(chalk.bold('\nAbout to remove:'));
265
+ printSkill(skill);
266
+ const answer = await inquirer.prompt([{
267
+ type: 'confirm',
268
+ name: 'proceed',
269
+ message: 'Are you sure you want to remove this skill?',
270
+ default: false
271
+ }]);
272
+ if (!answer.proceed) {
273
+ console.log(chalk.gray('Removal cancelled.'));
274
+ return;
275
+ }
276
+ }
277
+ const spin = spinner('Removing skill...');
278
+ const result = await client.uninstallSkill(skillId);
279
+ spin.succeed(result.message);
280
+ }
281
+ catch (error) {
282
+ printError(handleApiError(error).errmsg);
283
+ process.exit(1);
284
+ }
285
+ });
286
+ program
287
+ .command('info <skillId>')
288
+ .description('Show detailed information about a skill')
289
+ .action(async (skillId) => {
290
+ try {
291
+ const client = getClient();
292
+ const skill = await client.getSkill(skillId);
293
+ printSkill(skill);
294
+ if (skill.tools && skill.tools.length > 0) {
295
+ console.log(chalk.bold('\n Tools:'));
296
+ skill.tools.forEach((tool) => {
297
+ console.log(chalk.cyan(` • ${tool.name}`));
298
+ console.log(chalk.gray(` ${tool.description}`));
299
+ if (tool.parameters.length > 0) {
300
+ tool.parameters.forEach(param => {
301
+ const required = param.required ? chalk.red('*') : '';
302
+ console.log(chalk.gray(` - ${param.name}${required}: ${param.description}`));
303
+ });
304
+ }
305
+ });
306
+ }
307
+ if (skill.dependencies && skill.dependencies.length > 0) {
308
+ console.log(chalk.bold('\n Dependencies:'));
309
+ skill.dependencies.forEach((dep) => {
310
+ console.log(chalk.gray(` • ${dep}`));
311
+ });
312
+ }
313
+ }
314
+ catch (error) {
315
+ printError(handleApiError(error).errmsg);
316
+ process.exit(1);
317
+ }
318
+ });
319
+ program
320
+ .command('init [name]')
321
+ .description('Initialize a new skill project')
322
+ .option('-d, --directory <dir>', 'Target directory', '.')
323
+ .option('-t, --template <template>', 'Skill template', 'basic')
324
+ .action(async (name, options) => {
325
+ try {
326
+ let skillName = name;
327
+ if (!skillName) {
328
+ const answer = await inquirer.prompt([{
329
+ type: 'input',
330
+ name: 'name',
331
+ message: 'Skill name:',
332
+ validate: (input) => input.length > 0 || 'Name is required'
333
+ }]);
334
+ skillName = answer.name;
335
+ }
336
+ const targetDir = path.join(options.directory, skillName);
337
+ if (await fs.exists(targetDir)) {
338
+ const answer = await inquirer.prompt([{
339
+ type: 'confirm',
340
+ name: 'overwrite',
341
+ message: `Directory "${targetDir}" already exists. Overwrite?`,
342
+ default: false
343
+ }]);
344
+ if (!answer.overwrite) {
345
+ console.log(chalk.gray('Init cancelled.'));
346
+ return;
347
+ }
348
+ }
349
+ const spin = spinner('Creating skill project...');
350
+ await fs.ensureDir(targetDir);
351
+ const skillContent = `---
352
+ name: ${skillName}
353
+ description: A new agent skill
354
+ version: 1.0.0
355
+ author: Your Name
356
+ license: MIT
357
+ ---
358
+
359
+ # ${skillName}
360
+
361
+ This is a new agent skill created with the skills CLI.
362
+
363
+ ## Usage
364
+
365
+ Describe how to use this skill here.
366
+
367
+ ## Tools
368
+
369
+ ### tool-name
370
+
371
+ Description of what this tool does.
372
+
373
+ **Parameters:**
374
+
375
+ - \`param1\` (string, required): Description of parameter
376
+
377
+ **Example:**
378
+
379
+ \`\`\`
380
+ skills run ${skillName} --tool tool-name -p '{"param1": "value"}'
381
+ \`\`\`
382
+
383
+ ## Installation
384
+
385
+ \`\`\`
386
+ skills add ./path/to/${skillName}
387
+ \`\`\`
388
+ `;
389
+ await fs.writeFile(path.join(targetDir, 'SKILL.md'), skillContent);
390
+ const readmeContent = `# ${skillName}
391
+
392
+ An agent skill for [description].
393
+
394
+ ## Installation
395
+
396
+ \`\`\`bash
397
+ skills add ./path/to/${skillName}
398
+ \`\`\`
399
+
400
+ ## Usage
401
+
402
+ \`\`\`bash
403
+ skills run ${skillName} --tool <tool-name> -p '{"param": "value"}'
404
+ \`\`\`
405
+
406
+ ## License
407
+
408
+ MIT
409
+ `;
410
+ await fs.writeFile(path.join(targetDir, 'README.md'), readmeContent);
411
+ spin.succeed(`Skill project created at ${targetDir}`);
412
+ console.log(chalk.bold('\nNext steps:'));
413
+ console.log(chalk.gray(` 1. Edit ${targetDir}/SKILL.md to define your skill`));
414
+ console.log(chalk.gray(` 2. Add any additional files or resources`));
415
+ console.log(chalk.gray(` 3. Install with: skills add ${targetDir}`));
416
+ }
417
+ catch (error) {
418
+ printError(error instanceof Error ? error.message : 'Unknown error');
419
+ process.exit(1);
420
+ }
421
+ });
422
+ program
423
+ .command('check')
424
+ .description('Check for skill updates')
425
+ .action(async () => {
426
+ const spin = spinner('Checking for updates...');
427
+ try {
428
+ const client = getClient();
429
+ const result = await client.listSkills({ limit: 100 });
430
+ spin.stop();
431
+ if (result.skills.length === 0) {
432
+ console.log(chalk.yellow('No skills installed.'));
433
+ return;
434
+ }
435
+ console.log(chalk.bold(`\nChecking ${result.skills.length} skill(s) for updates...\n`));
436
+ let updatesAvailable = 0;
437
+ for (const skill of result.skills) {
438
+ console.log(chalk.gray(` ${skill.name} (${skill.version}) - No updates available`));
439
+ }
440
+ if (updatesAvailable === 0) {
441
+ console.log(chalk.green('\n✓ All skills are up to date'));
442
+ }
443
+ else {
444
+ console.log(chalk.yellow(`\n${updatesAvailable} skill(s) have updates available`));
445
+ console.log(chalk.gray('Run `skills update` to update all skills'));
446
+ }
447
+ }
448
+ catch (error) {
449
+ spin.fail('Check failed');
450
+ printError(handleApiError(error).errmsg);
451
+ process.exit(1);
452
+ }
453
+ });
454
+ program
455
+ .command('update [skillId]')
456
+ .description('Update skills to their latest versions')
457
+ .option('-a, --all', 'Update all installed skills', false)
458
+ .action(async (skillId, options) => {
459
+ const spin = spinner('Updating skills...');
460
+ try {
461
+ const client = getClient();
462
+ if (options.all) {
463
+ const result = await client.listSkills({ limit: 100 });
464
+ spin.stop();
465
+ if (result.skills.length === 0) {
466
+ console.log(chalk.yellow('No skills installed.'));
467
+ return;
468
+ }
469
+ console.log(chalk.bold(`\nUpdating ${result.skills.length} skill(s)...\n`));
470
+ for (const skill of result.skills) {
471
+ const updateSpin = spinner(`Updating ${skill.name}...`);
472
+ try {
473
+ await client.updateSkill(skill.id, {});
474
+ updateSpin.succeed(`${skill.name} updated`);
475
+ }
476
+ catch {
477
+ updateSpin.fail(`Failed to update ${skill.name}`);
478
+ }
479
+ }
480
+ console.log(chalk.green('\n✓ Update complete'));
481
+ }
482
+ else if (skillId) {
483
+ spin.text = `Updating ${skillId}...`;
484
+ await client.updateSkill(skillId, {});
485
+ spin.succeed(`${skillId} updated`);
486
+ }
487
+ else {
488
+ spin.stop();
489
+ printError('Please specify a skill ID or use --all to update all skills');
490
+ process.exit(1);
491
+ }
492
+ }
493
+ catch (error) {
494
+ spin.fail('Update failed');
495
+ printError(handleApiError(error).errmsg);
496
+ process.exit(1);
497
+ }
498
+ });
499
+ program
500
+ .command('config <skillId>')
501
+ .description('Manage skill configuration')
502
+ .option('-s, --set <key=value>', 'Set a configuration value')
503
+ .option('-g, --get <key>', 'Get a configuration value')
504
+ .option('-l, --list', 'List all configuration', false)
505
+ .action(async (skillId, options) => {
506
+ try {
507
+ const client = getClient();
508
+ if (options.list) {
509
+ const config = await client.getSkillConfig(skillId);
510
+ console.log(chalk.bold(`\nConfiguration for ${skillId}:\n`));
511
+ console.log(JSON.stringify(config, null, 2));
512
+ return;
513
+ }
514
+ if (options.get) {
515
+ const config = await client.getSkillConfig(skillId);
516
+ console.log(config[options.get] || chalk.gray('(not set)'));
517
+ return;
518
+ }
519
+ if (options.set) {
520
+ const [key, value] = options.set.split('=');
521
+ if (!key || value === undefined) {
522
+ printError('Invalid format. Use: --set key=value');
523
+ process.exit(1);
524
+ }
525
+ const config = await client.getSkillConfig(skillId);
526
+ config[key] = value;
527
+ await client.setSkillConfig(skillId, config);
528
+ printSuccess(`Set ${key} = ${value}`);
529
+ return;
530
+ }
531
+ printError('Please specify an action: --set, --get, or --list');
532
+ }
533
+ catch (error) {
534
+ printError(handleApiError(error).errmsg);
535
+ process.exit(1);
536
+ }
537
+ });
538
+ program
539
+ .command('status')
540
+ .description('Check the status of the skills runtime server')
541
+ .action(async () => {
542
+ try {
543
+ const client = getClient();
544
+ const runtimeStatus = await client.runtime.status();
545
+ if (runtimeStatus.running) {
546
+ console.log(chalk.green('✓'), 'Skills runtime is running');
547
+ console.log(chalk.gray(' API URL:'), client.getBaseUrl());
548
+ console.log(chalk.gray(' Version:'), runtimeStatus.version || 'unknown');
549
+ const skills = await client.listSkills({ limit: 1 });
550
+ console.log(chalk.gray(' Skills installed:'), skills.total_count);
551
+ }
552
+ else {
553
+ console.log(chalk.red('✗'), 'Skills runtime is not running');
554
+ console.log(chalk.gray(' API URL:'), client.getBaseUrl());
555
+ console.log(chalk.gray('\nStart the runtime with: skills start'));
556
+ console.log(chalk.gray('Install runtime with: skills install-runtime'));
557
+ }
558
+ }
559
+ catch (error) {
560
+ console.log(chalk.red('✗'), 'Skills runtime is not responding');
561
+ console.log(chalk.gray(' Error:'), handleApiError(error).errmsg);
562
+ }
563
+ });
564
+ program
565
+ .command('install-runtime')
566
+ .description('Download and install the AgentSkills runtime binary')
567
+ .option('-v, --version <version>', 'Runtime version to install', '0.0.1')
568
+ .action(async (options) => {
569
+ const runtime = new RuntimeManager();
570
+ if (runtime.isInstalled()) {
571
+ console.log(chalk.yellow('Runtime is already installed at:'), runtime.getRuntimePath());
572
+ const answer = await inquirer.prompt([{
573
+ type: 'confirm',
574
+ name: 'reinstall',
575
+ message: 'Do you want to reinstall?',
576
+ default: false
577
+ }]);
578
+ if (!answer.reinstall) {
579
+ return;
580
+ }
581
+ }
582
+ const spin = spinner(`Downloading runtime v${options.version}...`);
583
+ try {
584
+ const success = await runtime.downloadRuntime(options.version);
585
+ if (success) {
586
+ spin.succeed('Runtime installed successfully');
587
+ console.log(chalk.gray('\nLocation:'), runtime.getRuntimePath());
588
+ console.log(chalk.bold('\nNext steps:'));
589
+ console.log(chalk.gray(' 1. Start the runtime: skills start'));
590
+ console.log(chalk.gray(' 2. Install a skill: skills add <source>'));
591
+ }
592
+ else {
593
+ spin.fail('Failed to download runtime');
594
+ process.exit(1);
595
+ }
596
+ }
597
+ catch (error) {
598
+ spin.fail('Installation failed');
599
+ printError(error instanceof Error ? error.message : 'Unknown error');
600
+ process.exit(1);
601
+ }
602
+ });
603
+ program
604
+ .command('start')
605
+ .description('Start the AgentSkills runtime server')
606
+ .option('-p, --port <port>', 'Port to listen on', '8080')
607
+ .option('-h, --host <host>', 'Host to bind to', '127.0.0.1')
608
+ .option('-d, --detached', 'Run in background', false)
609
+ .action(async (options) => {
610
+ const runtime = new RuntimeManager();
611
+ if (!runtime.isInstalled()) {
612
+ printError('Runtime is not installed.');
613
+ console.log(chalk.gray('\nInstall with: skills install-runtime'));
614
+ process.exit(1);
615
+ }
616
+ const status = await runtime.status();
617
+ if (status.running) {
618
+ console.log(chalk.yellow('Runtime is already running'));
619
+ console.log(chalk.gray(' Version:'), status.version || 'unknown');
620
+ return;
621
+ }
622
+ console.log(chalk.bold('Starting AgentSkills runtime...'));
623
+ console.log(chalk.gray(` Host: ${options.host}`));
624
+ console.log(chalk.gray(` Port: ${options.port}`));
625
+ console.log(chalk.gray(` Mode: ${options.detached ? 'background' : 'foreground'}`));
626
+ const proc = runtime.start({
627
+ port: parseInt(options.port),
628
+ host: options.host,
629
+ detached: options.detached
630
+ });
631
+ if (proc) {
632
+ if (options.detached) {
633
+ await new Promise(resolve => setTimeout(resolve, 1000));
634
+ const newStatus = await runtime.status();
635
+ if (newStatus.running) {
636
+ console.log(chalk.green('\n✓ Runtime started in background'));
637
+ console.log(chalk.gray(' PID file:'), runtime.getRuntimePath().replace(/[^/\\]+$/, 'runtime.pid'));
638
+ }
639
+ else {
640
+ printError('Runtime failed to start');
641
+ process.exit(1);
642
+ }
643
+ }
644
+ else {
645
+ console.log(chalk.green('\n✓ Runtime started'));
646
+ console.log(chalk.gray('Press Ctrl+C to stop'));
647
+ }
648
+ }
649
+ else {
650
+ printError('Failed to start runtime');
651
+ process.exit(1);
652
+ }
653
+ });
654
+ program
655
+ .command('stop')
656
+ .description('Stop the AgentSkills runtime server')
657
+ .action(async () => {
658
+ const runtime = new RuntimeManager();
659
+ const status = await runtime.status();
660
+ if (!status.running) {
661
+ console.log(chalk.yellow('Runtime is not running'));
662
+ return;
663
+ }
664
+ const success = runtime.stop();
665
+ if (success) {
666
+ console.log(chalk.green('✓ Runtime stopped'));
667
+ }
668
+ else {
669
+ printError('Failed to stop runtime');
670
+ process.exit(1);
671
+ }
672
+ });
673
+ program.parse();
674
+ //# sourceMappingURL=cli.js.map