cli-five 0.2.7 → 0.2.8
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 +2 -2
- package/src/steps/skills.mjs +59 -22
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cli-five",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
4
4
|
"description": "Code Like I'm Five — scaffold a 5-agent VS Code Copilot team into any repo.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"LICENSE"
|
|
17
17
|
],
|
|
18
18
|
"scripts": {
|
|
19
|
-
"test": "node --test tests
|
|
19
|
+
"test": "node --test tests/*.test.mjs",
|
|
20
20
|
"smoke": "node bin/cli-five.mjs --help"
|
|
21
21
|
},
|
|
22
22
|
"engines": {
|
package/src/steps/skills.mjs
CHANGED
|
@@ -9,6 +9,7 @@ import { log } from '../util/log.mjs';
|
|
|
9
9
|
// ── Known-good skill repos (verified working) ────────────────────────
|
|
10
10
|
// awesome-copilot skills are discovered dynamically via `skills find`.
|
|
11
11
|
const AWESOME_COPILOT_REPO = 'github/awesome-copilot';
|
|
12
|
+
const BREADCRUMB_BOX_WIDTH = 66;
|
|
12
13
|
|
|
13
14
|
// Well-known skill repos matched by stack term → repo + suggested skill names (skills.sh)
|
|
14
15
|
const SKILL_CATALOG = [
|
|
@@ -56,20 +57,17 @@ function projectUsesPnpm(cwd) {
|
|
|
56
57
|
*/
|
|
57
58
|
function detectEnv(cwd) {
|
|
58
59
|
const bundledBin = resolveSkillsBin();
|
|
60
|
+
const npmVer = whichVersion('npm');
|
|
59
61
|
const pnpmVer = whichVersion('pnpm');
|
|
60
62
|
const npxVer = whichVersion('npx');
|
|
61
63
|
const projectPnpm = projectUsesPnpm(cwd);
|
|
62
64
|
|
|
63
|
-
// ── Terse status lines ────────────────────────────────────────────
|
|
64
|
-
log.info(`skills CLI (bundled) ${bundledBin ? '✓' : '✗ not resolved'}`);
|
|
65
|
-
log.info(`pnpm ${pnpmVer ? `✓ ${pnpmVer}` : '✗ not found'}${projectPnpm ? ' (project uses pnpm)' : ''}`);
|
|
66
|
-
log.info(`npx ${npxVer ? `✓ ${npxVer}` : '✗ not found'}`);
|
|
67
|
-
|
|
68
65
|
// ── Priority: bundled > pnpm (if project or system) > npx ─────────
|
|
69
66
|
if (bundledBin) {
|
|
70
67
|
return {
|
|
71
68
|
label: 'bundled skills CLI',
|
|
72
69
|
runner: (skillsArgs) => ({ cmd: process.execPath, args: [bundledBin, ...skillsArgs] }),
|
|
70
|
+
npmVer,
|
|
73
71
|
pnpmVer,
|
|
74
72
|
npxVer,
|
|
75
73
|
projectPnpm,
|
|
@@ -79,6 +77,7 @@ function detectEnv(cwd) {
|
|
|
79
77
|
return {
|
|
80
78
|
label: 'pnpm dlx',
|
|
81
79
|
runner: (skillsArgs) => ({ cmd: 'pnpm', args: ['dlx', 'skills', ...skillsArgs] }),
|
|
80
|
+
npmVer,
|
|
82
81
|
pnpmVer,
|
|
83
82
|
npxVer,
|
|
84
83
|
projectPnpm,
|
|
@@ -88,6 +87,7 @@ function detectEnv(cwd) {
|
|
|
88
87
|
return {
|
|
89
88
|
label: 'npx',
|
|
90
89
|
runner: (skillsArgs) => ({ cmd: 'npx', args: ['-y', 'skills', ...skillsArgs] }),
|
|
90
|
+
npmVer,
|
|
91
91
|
pnpmVer,
|
|
92
92
|
npxVer,
|
|
93
93
|
projectPnpm,
|
|
@@ -109,7 +109,7 @@ export async function skillDiscovery({ cwd, answers, args }) {
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
// ── Environment checks ──────────────────────────────────────────────
|
|
112
|
-
|
|
112
|
+
let env = detectEnv(cwd);
|
|
113
113
|
|
|
114
114
|
if (!env) {
|
|
115
115
|
log.warn('Cannot run skills CLI: no bundled binary, pnpm, or npx found.');
|
|
@@ -119,7 +119,7 @@ export async function skillDiscovery({ cwd, answers, args }) {
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
// Offer pnpm if the user doesn't have it
|
|
122
|
-
if (
|
|
122
|
+
if (shouldOfferPnpmInstall(env)) {
|
|
123
123
|
const { wantPnpm } = await prompts({
|
|
124
124
|
type: 'confirm',
|
|
125
125
|
name: 'wantPnpm',
|
|
@@ -130,10 +130,13 @@ export async function skillDiscovery({ cwd, answers, args }) {
|
|
|
130
130
|
try {
|
|
131
131
|
execFileSync('npm', ['install', '-g', 'pnpm'], { stdio: 'inherit' });
|
|
132
132
|
log.ok('pnpm installed.');
|
|
133
|
+
env = detectEnv(cwd) || env;
|
|
133
134
|
} catch (err) {
|
|
134
135
|
log.warn(`pnpm install failed: ${err.message}`);
|
|
135
136
|
}
|
|
136
137
|
}
|
|
138
|
+
} else if (env.projectPnpm && !env.pnpmVer) {
|
|
139
|
+
log.dim(`pnpm not found. Using ${env.label} for skill discovery.`);
|
|
137
140
|
}
|
|
138
141
|
|
|
139
142
|
log.ok(`Running skills via ${env.label}`);
|
|
@@ -345,21 +348,9 @@ function printInstallSummary(results) {
|
|
|
345
348
|
|
|
346
349
|
function printBreadcrumbs() {
|
|
347
350
|
log.raw('');
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
log.raw(kleur.bold().green(' │') + ' ' + kleur.bold().green('│'));
|
|
352
|
-
log.raw(kleur.bold().green(' │') + ' Add awesome-copilot MCP for ongoing search: ' + kleur.bold().green('│'));
|
|
353
|
-
log.raw(kleur.bold().green(' │') + kleur.white(' Add to .vscode/mcp.json: ') + kleur.bold().green('│'));
|
|
354
|
-
log.raw(kleur.bold().green(' │') + kleur.dim(' "awesome-copilot": { ') + kleur.bold().green('│'));
|
|
355
|
-
log.raw(kleur.bold().green(' │') + kleur.dim(' "command": "npx", ') + kleur.bold().green('│'));
|
|
356
|
-
log.raw(kleur.bold().green(' │') + kleur.dim(' "args": ["-y", "awesome-copilot-mcp"] ') + kleur.bold().green('│'));
|
|
357
|
-
log.raw(kleur.bold().green(' │') + kleur.dim(' } ') + kleur.bold().green('│'));
|
|
358
|
-
log.raw(kleur.bold().green(' │') + ' ' + kleur.bold().green('│'));
|
|
359
|
-
log.raw(kleur.bold().green(' │') + ' Browse skills anytime: ' + kleur.bold().green('│'));
|
|
360
|
-
log.raw(kleur.bold().green(' │') + kleur.white(' npx skills find ') + kleur.bold().green('│'));
|
|
361
|
-
log.raw(kleur.bold().green(' │') + ' ' + kleur.bold().green('│'));
|
|
362
|
-
log.raw(kleur.bold().green(' └──────────────────────────────────────────────────────────────────┘'));
|
|
351
|
+
for (const line of buildBreadcrumbBox()) {
|
|
352
|
+
log.raw(line);
|
|
353
|
+
}
|
|
363
354
|
log.raw('');
|
|
364
355
|
}
|
|
365
356
|
|
|
@@ -539,6 +530,44 @@ function pad(s, n) {
|
|
|
539
530
|
return (s || '').padEnd(n);
|
|
540
531
|
}
|
|
541
532
|
|
|
533
|
+
/**
|
|
534
|
+
* Offer pnpm installation only for pnpm workspaces that are currently missing pnpm
|
|
535
|
+
* and can bootstrap it via npm on PATH.
|
|
536
|
+
*/
|
|
537
|
+
function shouldOfferPnpmInstall(env) {
|
|
538
|
+
return Boolean(env && env.projectPnpm && !env.pnpmVer && env.npmVer);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
function buildBreadcrumbBox() {
|
|
542
|
+
const horizontalDivider = kleur.bold().green(` ├${'─'.repeat(BREADCRUMB_BOX_WIDTH + 2)}┤`);
|
|
543
|
+
const lines = [
|
|
544
|
+
formatBoxLine(kleur.bold(' KEEP DISCOVERING -- paste into VS Code / Copilot Chat:'), BREADCRUMB_BOX_WIDTH),
|
|
545
|
+
horizontalDivider,
|
|
546
|
+
formatBoxLine('', BREADCRUMB_BOX_WIDTH),
|
|
547
|
+
formatBoxLine(' Add awesome-copilot MCP for ongoing search:', BREADCRUMB_BOX_WIDTH),
|
|
548
|
+
formatBoxLine(kleur.white(' Add to .vscode/mcp.json:'), BREADCRUMB_BOX_WIDTH),
|
|
549
|
+
formatBoxLine(kleur.dim(' "awesome-copilot": {'), BREADCRUMB_BOX_WIDTH),
|
|
550
|
+
formatBoxLine(kleur.dim(' "command": "npx",'), BREADCRUMB_BOX_WIDTH),
|
|
551
|
+
formatBoxLine(kleur.dim(' "args": ["-y", "awesome-copilot-mcp"]'), BREADCRUMB_BOX_WIDTH),
|
|
552
|
+
formatBoxLine(kleur.dim(' }'), BREADCRUMB_BOX_WIDTH),
|
|
553
|
+
formatBoxLine('', BREADCRUMB_BOX_WIDTH),
|
|
554
|
+
formatBoxLine(' Browse skills anytime:', BREADCRUMB_BOX_WIDTH),
|
|
555
|
+
formatBoxLine(kleur.white(' npx skills find'), BREADCRUMB_BOX_WIDTH),
|
|
556
|
+
formatBoxLine('', BREADCRUMB_BOX_WIDTH),
|
|
557
|
+
];
|
|
558
|
+
|
|
559
|
+
return [
|
|
560
|
+
kleur.bold().green(` ┌${'─'.repeat(BREADCRUMB_BOX_WIDTH + 2)}┐`),
|
|
561
|
+
...lines,
|
|
562
|
+
kleur.bold().green(` └${'─'.repeat(BREADCRUMB_BOX_WIDTH + 2)}┘`),
|
|
563
|
+
];
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
function formatBoxLine(content = '', width = BREADCRUMB_BOX_WIDTH) {
|
|
567
|
+
const paddingNeeded = Math.max(0, width - stripAnsi(content).length);
|
|
568
|
+
return `${kleur.bold().green(' │ ')}${content}${' '.repeat(paddingNeeded)}${kleur.bold().green(' │')}`;
|
|
569
|
+
}
|
|
570
|
+
|
|
542
571
|
function runInteractive(cmd, args, cwd) {
|
|
543
572
|
return new Promise((resolve) => {
|
|
544
573
|
const proc = spawn(cmd, args, { cwd, stdio: 'inherit' });
|
|
@@ -567,3 +596,11 @@ function parseSkillRefs(output) {
|
|
|
567
596
|
}
|
|
568
597
|
return results;
|
|
569
598
|
}
|
|
599
|
+
|
|
600
|
+
export const __testables = {
|
|
601
|
+
buildBreadcrumbBox,
|
|
602
|
+
detectEnv,
|
|
603
|
+
formatBoxLine,
|
|
604
|
+
shouldOfferPnpmInstall,
|
|
605
|
+
stripAnsi,
|
|
606
|
+
};
|