cli-five 0.2.9 → 0.2.11
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
CHANGED
|
@@ -116,7 +116,9 @@ cli-five searches **two sources** for skills matching your detected stack:
|
|
|
116
116
|
| **awesome-copilot** | Skills, instructions, agents, plugins from the GitHub community | 30k+ |
|
|
117
117
|
| **skills.sh** | Curated skill repos (Vercel, Anthropic, Microsoft, etc.) | — |
|
|
118
118
|
|
|
119
|
-
Recommendations show with source attribution
|
|
119
|
+
Recommendations show with source attribution. Only cli-five core skills are pre-selected; suggested skills from skills.sh and awesome-copilot require manual selection (press Space) before install. After installation, you get breadcrumbs for ongoing discovery:
|
|
120
|
+
|
|
121
|
+
Take time to read each installed skill so you understand what it does and can catch overlap or conflicts before they affect your workflow.
|
|
120
122
|
|
|
121
123
|
- **Suggest skill** — `copilot plugin install awesome-copilot@suggest` (AI-driven repo analysis)
|
|
122
124
|
- **MCP server** — `awesome-copilot-mcp` for programmatic search from any agent
|
package/package.json
CHANGED
package/src/steps/interview.mjs
CHANGED
|
@@ -2,66 +2,55 @@ import kleur from 'kleur';
|
|
|
2
2
|
import prompts from 'prompts';
|
|
3
3
|
|
|
4
4
|
// ── Preset stacks ─────────────────────────────────────────────────────
|
|
5
|
-
//
|
|
6
|
-
// copy-paste quickstart, broad hosting support.
|
|
7
|
-
// Research via Context7: Next.js, Vite+React, Express, Hono all score
|
|
8
|
-
// 80+ benchmark with high snippet counts and well-indexed docs.
|
|
5
|
+
// Curated defaults for fast project bootstrap with optional freeform mode.
|
|
9
6
|
const STACK_PRESETS = [
|
|
10
7
|
{
|
|
11
|
-
title: '
|
|
12
|
-
value: '
|
|
13
|
-
description: '
|
|
14
|
-
stack: ['
|
|
15
|
-
frameworks: ['
|
|
16
|
-
quickstart: '
|
|
8
|
+
title: 'SPA: Vanilla HTML/CSS/JS + CDN',
|
|
9
|
+
value: 'spa-vanilla-cdn',
|
|
10
|
+
description: 'No build step. Browser-native app with CDN-loaded libraries.',
|
|
11
|
+
stack: ['HTML + CSS + JavaScript'],
|
|
12
|
+
frameworks: ['CDN (no bundler)'],
|
|
13
|
+
quickstart: 'mkdir -p public && printf "<!doctype html><html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>SPA</title></head><body><div id=\"app\"></div><script src=\"./app.js\"></script></body></html>" > public/index.html && printf "document.getElementById(\"app\").textContent = \"Hello SPA\";" > public/app.js',
|
|
17
14
|
},
|
|
18
15
|
{
|
|
19
|
-
title: '
|
|
20
|
-
value: '
|
|
21
|
-
description: '
|
|
22
|
-
stack: ['Node +
|
|
23
|
-
frameworks: ['
|
|
24
|
-
quickstart: '
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
title: 'Vite + React (TypeScript)',
|
|
28
|
-
value: 'vite-react',
|
|
29
|
-
description: 'SPA frontend. Lightning-fast HMR. `npm create vite`',
|
|
30
|
-
stack: ['Node + TypeScript'],
|
|
31
|
-
frameworks: ['Vite', 'React', 'TypeScript'],
|
|
32
|
-
quickstart: 'npm create vite@latest . -- --template react-ts && npm i && npm run dev',
|
|
16
|
+
title: 'SPA: React + Vite',
|
|
17
|
+
value: 'spa-react-vite',
|
|
18
|
+
description: 'React single-page app powered by Vite.',
|
|
19
|
+
stack: ['Node + JavaScript'],
|
|
20
|
+
frameworks: ['React', 'Vite'],
|
|
21
|
+
quickstart: 'pnpm create vite@latest . --template react && pnpm install && pnpm dev',
|
|
33
22
|
},
|
|
34
23
|
{
|
|
35
|
-
title: '
|
|
36
|
-
value: '
|
|
37
|
-
description: '
|
|
38
|
-
stack: ['
|
|
39
|
-
frameworks: ['
|
|
40
|
-
quickstart: '
|
|
24
|
+
title: 'Web+DB: Python Flask + SQLite',
|
|
25
|
+
value: 'webdb-flask-sqlite',
|
|
26
|
+
description: 'Server-rendered web app with Flask and local SQLite storage.',
|
|
27
|
+
stack: ['Python'],
|
|
28
|
+
frameworks: ['Flask', 'SQLite'],
|
|
29
|
+
quickstart: 'python -m venv .venv && source .venv/bin/activate && pip install flask && python app.py',
|
|
41
30
|
},
|
|
42
31
|
{
|
|
43
|
-
title: '
|
|
44
|
-
value: '
|
|
45
|
-
description: '
|
|
46
|
-
stack: ['Node +
|
|
47
|
-
frameworks: ['
|
|
48
|
-
quickstart: '
|
|
32
|
+
title: 'Web+DB: Node.js + Express + SQLite',
|
|
33
|
+
value: 'webdb-express-sqlite',
|
|
34
|
+
description: 'Node web app with Express and SQLite.',
|
|
35
|
+
stack: ['Node + JavaScript'],
|
|
36
|
+
frameworks: ['Express', 'SQLite'],
|
|
37
|
+
quickstart: 'pnpm init && pnpm add express sqlite3 && node server.js',
|
|
49
38
|
},
|
|
50
39
|
{
|
|
51
|
-
title: '
|
|
52
|
-
value: '
|
|
53
|
-
description: '
|
|
40
|
+
title: 'Stack: Next.js + Prisma + SQLite',
|
|
41
|
+
value: 'stack-next-prisma-sqlite',
|
|
42
|
+
description: 'Full-stack Next.js with Prisma ORM and SQLite.',
|
|
54
43
|
stack: ['Node + TypeScript'],
|
|
55
|
-
frameworks: ['
|
|
56
|
-
quickstart: '
|
|
44
|
+
frameworks: ['Next.js', 'Prisma', 'SQLite', 'React'],
|
|
45
|
+
quickstart: 'pnpm create next-app@latest . --ts --eslint --app --src-dir --import-alias "@/*" && pnpm add prisma @prisma/client && pnpm prisma init --datasource-provider sqlite && pnpm dev',
|
|
57
46
|
},
|
|
58
47
|
{
|
|
59
|
-
title: '
|
|
60
|
-
value: 'fastapi',
|
|
61
|
-
description: '
|
|
62
|
-
stack: ['Python'],
|
|
63
|
-
frameworks: ['FastAPI', '
|
|
64
|
-
quickstart: 'pip install fastapi uvicorn &&
|
|
48
|
+
title: 'Stack: FastAPI + React/Vite',
|
|
49
|
+
value: 'stack-fastapi-react-vite',
|
|
50
|
+
description: 'FastAPI backend paired with a React/Vite frontend.',
|
|
51
|
+
stack: ['Python', 'Node + JavaScript'],
|
|
52
|
+
frameworks: ['FastAPI', 'React', 'Vite'],
|
|
53
|
+
quickstart: 'python -m venv .venv && source .venv/bin/activate && pip install fastapi uvicorn && pnpm create vite@latest web --template react && cd web && pnpm install && pnpm dev',
|
|
65
54
|
},
|
|
66
55
|
{
|
|
67
56
|
title: 'Custom (freeform)',
|
|
@@ -200,10 +189,10 @@ export async function interview(detected, args, docHints = {}) {
|
|
|
200
189
|
});
|
|
201
190
|
}
|
|
202
191
|
|
|
203
|
-
/** Default stack is
|
|
192
|
+
/** Default stack is first preset when nothing is detected and --yes is used. */
|
|
204
193
|
function defaults(detected, docHints = {}) {
|
|
205
194
|
const hasDetected = detected.stacks.length > 0;
|
|
206
|
-
const fallback = STACK_PRESETS[0];
|
|
195
|
+
const fallback = STACK_PRESETS[0];
|
|
207
196
|
return {
|
|
208
197
|
projectName: docHints.projectName || detected.projectName,
|
|
209
198
|
oneLiner: docHints.oneLiner || '',
|
package/src/steps/skills.mjs
CHANGED
|
@@ -10,6 +10,7 @@ import { log } from '../util/log.mjs';
|
|
|
10
10
|
// awesome-copilot skills are discovered dynamically via `skills find`.
|
|
11
11
|
const AWESOME_COPILOT_REPO = 'github/awesome-copilot';
|
|
12
12
|
const BREADCRUMB_BOX_WIDTH = 66;
|
|
13
|
+
const PNPM_INSTALL_DOCS_URL = 'https://pnpm.io/installation';
|
|
13
14
|
|
|
14
15
|
// Well-known skill repos matched by stack term → repo + suggested skill names (skills.sh)
|
|
15
16
|
const SKILL_CATALOG = [
|
|
@@ -22,6 +23,15 @@ const SKILL_CATALOG = [
|
|
|
22
23
|
{ terms: ['rust'], repo: 'anthropics/skills', skills: ['code-review'] },
|
|
23
24
|
];
|
|
24
25
|
|
|
26
|
+
// Core skills are the always-on baseline curated by cli-five.
|
|
27
|
+
// Stack-specific and discovered skills are suggestions and must be opted-in.
|
|
28
|
+
const CORE_CATALOG_SKILLS = new Set([
|
|
29
|
+
'anthropics/skills@frontend-design',
|
|
30
|
+
'anthropics/skills@skill-creator',
|
|
31
|
+
'vercel-labs/agent-skills@vercel-react-best-practices',
|
|
32
|
+
'vercel-labs/agent-skills@web-design-guidelines',
|
|
33
|
+
]);
|
|
34
|
+
|
|
25
35
|
// ── Environment detection ─────────────────────────────────────────────
|
|
26
36
|
|
|
27
37
|
function resolveSkillsBin() {
|
|
@@ -113,18 +123,24 @@ export async function skillDiscovery({ cwd, answers, args }) {
|
|
|
113
123
|
|
|
114
124
|
if (!env) {
|
|
115
125
|
log.warn('Cannot run skills CLI: no bundled binary, pnpm, or npx found.');
|
|
116
|
-
log.warn(
|
|
126
|
+
log.warn(`Install Node.js (includes npx) or pnpm, then re-run. ${PNPM_INSTALL_DOCS_URL}`);
|
|
117
127
|
printBreadcrumbs();
|
|
118
128
|
return;
|
|
119
129
|
}
|
|
120
130
|
|
|
131
|
+
if (env.pnpmVer) {
|
|
132
|
+
log.ok(`pnpm detected (${env.pnpmVer}).`);
|
|
133
|
+
} else {
|
|
134
|
+
log.dim('Tip: pnpm is recommended for faster installs and stricter dependency resolution.');
|
|
135
|
+
}
|
|
136
|
+
|
|
121
137
|
// Offer pnpm if the user doesn't have it
|
|
122
138
|
if (shouldOfferPnpmInstall(env)) {
|
|
123
139
|
const { wantPnpm } = await prompts({
|
|
124
140
|
type: 'confirm',
|
|
125
141
|
name: 'wantPnpm',
|
|
126
|
-
message: 'pnpm not found. Install it? (
|
|
127
|
-
initial:
|
|
142
|
+
message: 'pnpm not found. Install it now? (recommended)',
|
|
143
|
+
initial: true,
|
|
128
144
|
});
|
|
129
145
|
if (wantPnpm) {
|
|
130
146
|
try {
|
|
@@ -133,10 +149,9 @@ export async function skillDiscovery({ cwd, answers, args }) {
|
|
|
133
149
|
env = detectEnv(cwd) || env;
|
|
134
150
|
} catch (err) {
|
|
135
151
|
log.warn(`pnpm install failed: ${err.message}`);
|
|
152
|
+
log.warn(`Install pnpm manually: ${PNPM_INSTALL_DOCS_URL}`);
|
|
136
153
|
}
|
|
137
154
|
}
|
|
138
|
-
} else if (env.projectPnpm && !env.pnpmVer) {
|
|
139
|
-
log.dim(`pnpm not found. Using ${env.label} for skill discovery.`);
|
|
140
155
|
}
|
|
141
156
|
|
|
142
157
|
log.ok(`Running skills via ${env.label}`);
|
|
@@ -189,19 +204,20 @@ export async function skillDiscovery({ cwd, answers, args }) {
|
|
|
189
204
|
choices.push({
|
|
190
205
|
title: `${kleur.cyan('⬡')} ${r.skill} ${kleur.dim(`(${r.installs})`)} ${kleur.cyan('← awesome-copilot')}`,
|
|
191
206
|
value: { source: 'awesome', repo: r.repo, skill: r.skill, ref: r.ref },
|
|
192
|
-
selected:
|
|
207
|
+
selected: false,
|
|
193
208
|
});
|
|
194
209
|
}
|
|
195
210
|
|
|
196
211
|
// Static catalog recs (verified repos)
|
|
197
212
|
for (const r of catalogRecs) {
|
|
198
213
|
const ref = `${r.repo}@${r.skill}`;
|
|
214
|
+
const core = isCoreCatalogSkill(r.repo, r.skill);
|
|
199
215
|
if (seen.has(ref)) continue;
|
|
200
216
|
seen.add(ref);
|
|
201
217
|
choices.push({
|
|
202
|
-
title: `${kleur.yellow('◆')} ${r.skill} ${kleur.dim(`(${r.repo})`)} ${kleur.yellow('← skills.sh')}`,
|
|
218
|
+
title: `${kleur.yellow('◆')} ${r.skill} ${kleur.dim(`(${r.repo})`)} ${kleur.yellow(core ? '← core' : '← skills.sh (suggested)')}`,
|
|
203
219
|
value: { source: 'catalog', ref, repo: r.repo, skill: r.skill },
|
|
204
|
-
selected:
|
|
220
|
+
selected: core,
|
|
205
221
|
});
|
|
206
222
|
}
|
|
207
223
|
|
|
@@ -222,6 +238,8 @@ export async function skillDiscovery({ cwd, answers, args }) {
|
|
|
222
238
|
|
|
223
239
|
if (choices.length > 0) {
|
|
224
240
|
log.raw('');
|
|
241
|
+
log.dim('Suggested skills are not pre-selected. Press Space to install only what you need.');
|
|
242
|
+
log.dim('Read every installed skill so you understand behavior and catch potential conflicts early.');
|
|
225
243
|
const { toInstall } = await prompts({
|
|
226
244
|
type: 'multiselect',
|
|
227
245
|
name: 'toInstall',
|
|
@@ -490,6 +508,10 @@ function buildRecommendations(a) {
|
|
|
490
508
|
return out;
|
|
491
509
|
}
|
|
492
510
|
|
|
511
|
+
function isCoreCatalogSkill(repo, skill) {
|
|
512
|
+
return CORE_CATALOG_SKILLS.has(`${repo}@${skill}`);
|
|
513
|
+
}
|
|
514
|
+
|
|
493
515
|
function suggestSearches(a) {
|
|
494
516
|
const out = new Set();
|
|
495
517
|
for (const s of a.stack || []) {
|
|
@@ -535,7 +557,7 @@ function pad(s, n) {
|
|
|
535
557
|
* and can bootstrap it via npm on PATH.
|
|
536
558
|
*/
|
|
537
559
|
function shouldOfferPnpmInstall(env) {
|
|
538
|
-
return Boolean(env &&
|
|
560
|
+
return Boolean(env && !env.pnpmVer && env.npmVer);
|
|
539
561
|
}
|
|
540
562
|
|
|
541
563
|
function buildBreadcrumbBox() {
|
|
@@ -601,6 +623,7 @@ export const __testables = {
|
|
|
601
623
|
buildBreadcrumbBox,
|
|
602
624
|
detectEnv,
|
|
603
625
|
formatBoxLine,
|
|
626
|
+
isCoreCatalogSkill,
|
|
604
627
|
shouldOfferPnpmInstall,
|
|
605
628
|
stripAnsi,
|
|
606
629
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: Designer
|
|
3
3
|
description: "Handles all UI/UX design tasks. Use when: creating screens, layouts, theming, navigation flows, design systems."
|
|
4
|
-
model:
|
|
4
|
+
model: Gemini 3.1 Pro (Preview) (copilot)
|
|
5
5
|
tools: ['read', 'edit', 'search', 'web', 'io.github.upstash/context7/*', 'vscode/memory']
|
|
6
6
|
agents: []
|
|
7
7
|
---
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: Planner
|
|
3
3
|
description: "Creates implementation plans by researching the codebase, consulting documentation, and identifying edge cases. Use when: planning features, architectural decisions, or complex multi-file changes."
|
|
4
|
-
model: Claude
|
|
4
|
+
model: Claude Sonnet 4.6 (copilot)
|
|
5
5
|
tools: ['read', 'search', 'web', 'io.github.upstash/context7/*', 'vscode/memory']
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: Reviewer
|
|
3
3
|
description: "Reviews code and agent output for correctness, convention compliance, and architectural alignment. Use when: code review, auditing agent work, validating against specs."
|
|
4
|
-
model: Claude
|
|
4
|
+
model: Claude Sonnet 4.6 (copilot)
|
|
5
5
|
tools: ['read', 'search', 'web', 'vscode/memory']
|
|
6
6
|
agents: []
|
|
7
7
|
---
|