skilld 1.7.3 → 2.0.0
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/_chunks/add.mjs +66 -0
- package/dist/_chunks/add.mjs.map +1 -0
- package/dist/_chunks/agent-prompt.mjs +88 -0
- package/dist/_chunks/agent-prompt.mjs.map +1 -0
- package/dist/_chunks/agent.mjs +737 -619
- package/dist/_chunks/agent.mjs.map +1 -1
- package/dist/_chunks/args.mjs +42 -0
- package/dist/_chunks/args.mjs.map +1 -0
- package/dist/_chunks/assemble.mjs +11 -8
- package/dist/_chunks/assemble.mjs.map +1 -1
- package/dist/_chunks/author.mjs +77 -131
- package/dist/_chunks/author.mjs.map +1 -1
- package/dist/_chunks/cache.mjs +320 -54
- package/dist/_chunks/cache.mjs.map +1 -1
- package/dist/_chunks/cache2.mjs +7 -6
- package/dist/_chunks/cache2.mjs.map +1 -1
- package/dist/_chunks/client.mjs +117 -0
- package/dist/_chunks/client.mjs.map +1 -0
- package/dist/_chunks/core.mjs +7 -4
- package/dist/_chunks/detect.mjs +54 -44
- package/dist/_chunks/detect.mjs.map +1 -1
- package/dist/_chunks/eject.mjs +69 -0
- package/dist/_chunks/eject.mjs.map +1 -0
- package/dist/_chunks/embedding-cache2.mjs +2 -2
- package/dist/_chunks/env.mjs +19 -0
- package/dist/_chunks/env.mjs.map +1 -0
- package/dist/_chunks/install-many.mjs +376 -0
- package/dist/_chunks/install-many.mjs.map +1 -0
- package/dist/_chunks/install.mjs +86 -371
- package/dist/_chunks/install.mjs.map +1 -1
- package/dist/_chunks/intro.mjs +63 -0
- package/dist/_chunks/intro.mjs.map +1 -0
- package/dist/_chunks/list.mjs +2 -2
- package/dist/_chunks/list.mjs.map +1 -1
- package/dist/_chunks/lockfile.mjs +31 -7
- package/dist/_chunks/lockfile.mjs.map +1 -1
- package/dist/_chunks/login.mjs +233 -0
- package/dist/_chunks/login.mjs.map +1 -0
- package/dist/_chunks/logout.mjs +27 -0
- package/dist/_chunks/logout.mjs.map +1 -0
- package/dist/_chunks/map.mjs +11 -0
- package/dist/_chunks/map.mjs.map +1 -0
- package/dist/_chunks/markdown.mjs +79 -54
- package/dist/_chunks/markdown.mjs.map +1 -1
- package/dist/_chunks/menu.mjs +33 -0
- package/dist/_chunks/menu.mjs.map +1 -0
- package/dist/_chunks/model-picker.mjs +61 -0
- package/dist/_chunks/model-picker.mjs.map +1 -0
- package/dist/_chunks/monorepo.mjs +73 -0
- package/dist/_chunks/monorepo.mjs.map +1 -0
- package/dist/_chunks/package-json.mjs.map +1 -1
- package/dist/_chunks/paths.mjs +47 -0
- package/dist/_chunks/paths.mjs.map +1 -0
- package/dist/_chunks/pipeline.mjs +985 -0
- package/dist/_chunks/pipeline.mjs.map +1 -0
- package/dist/_chunks/pool2.mjs +2 -2
- package/dist/_chunks/portable.mjs +151 -0
- package/dist/_chunks/portable.mjs.map +1 -0
- package/dist/_chunks/prepare-hook.mjs +2 -0
- package/dist/_chunks/prepare-hook2.mjs +61 -0
- package/dist/_chunks/prepare-hook2.mjs.map +1 -0
- package/dist/_chunks/prepare.mjs +47 -3
- package/dist/_chunks/prepare.mjs.map +1 -1
- package/dist/_chunks/prepare2.mjs +9 -8
- package/dist/_chunks/prepare2.mjs.map +1 -1
- package/dist/_chunks/prompts.mjs +784 -26
- package/dist/_chunks/prompts.mjs.map +1 -1
- package/dist/_chunks/pull.mjs +219 -0
- package/dist/_chunks/pull.mjs.map +1 -0
- package/dist/_chunks/regex.mjs +19 -0
- package/dist/_chunks/regex.mjs.map +1 -0
- package/dist/_chunks/retriv.mjs +2 -171
- package/dist/_chunks/retriv2.mjs +159 -0
- package/dist/_chunks/retriv2.mjs.map +1 -0
- package/dist/_chunks/sanitize.mjs +12 -9
- package/dist/_chunks/sanitize.mjs.map +1 -1
- package/dist/_chunks/search-helpers.mjs +9 -8
- package/dist/_chunks/search-helpers.mjs.map +1 -1
- package/dist/_chunks/search-interactive.mjs +23 -20
- package/dist/_chunks/search-interactive.mjs.map +1 -1
- package/dist/_chunks/search.mjs +3 -4
- package/dist/_chunks/search.mjs.map +1 -1
- package/dist/_chunks/{sources.mjs → semver.mjs} +1128 -838
- package/dist/_chunks/semver.mjs.map +1 -0
- package/dist/_chunks/skill-installer.mjs +2 -0
- package/dist/_chunks/skill-installer2.mjs +154 -0
- package/dist/_chunks/skill-installer2.mjs.map +1 -0
- package/dist/_chunks/skills.mjs +12 -12
- package/dist/_chunks/skills.mjs.map +1 -1
- package/dist/_chunks/store.mjs +107 -0
- package/dist/_chunks/store.mjs.map +1 -0
- package/dist/_chunks/sync.mjs +761 -1349
- package/dist/_chunks/sync.mjs.map +1 -1
- package/dist/_chunks/sync2.mjs +2 -3
- package/dist/_chunks/telemetry.mjs +26 -0
- package/dist/_chunks/telemetry.mjs.map +1 -0
- package/dist/_chunks/uninstall.mjs +15 -13
- package/dist/_chunks/uninstall.mjs.map +1 -1
- package/dist/_chunks/update.mjs +171 -0
- package/dist/_chunks/update.mjs.map +1 -0
- package/dist/_chunks/upload.mjs +4 -4
- package/dist/_chunks/validate.mjs +1 -1
- package/dist/_chunks/version.mjs +16 -27
- package/dist/_chunks/version.mjs.map +1 -1
- package/dist/_chunks/whoami.mjs +21 -0
- package/dist/_chunks/whoami.mjs.map +1 -0
- package/dist/_chunks/wizard.mjs +2 -190
- package/dist/_chunks/wizard2.mjs +200 -0
- package/dist/_chunks/wizard2.mjs.map +1 -0
- package/dist/cli.mjs +77 -59
- package/dist/cli.mjs.map +1 -1
- package/dist/prepare.mjs +5 -4
- package/dist/prepare.mjs.map +1 -1
- package/dist/retriv/worker.d.mts +5 -1
- package/dist/retriv/worker.d.mts.map +1 -1
- package/dist/retriv/worker.mjs +1 -1
- package/package.json +20 -29
- package/dist/_chunks/author-group.mjs +0 -17
- package/dist/_chunks/author-group.mjs.map +0 -1
- package/dist/_chunks/cli-helpers.mjs +0 -335
- package/dist/_chunks/cli-helpers.mjs.map +0 -1
- package/dist/_chunks/cli-helpers2.mjs +0 -2
- package/dist/_chunks/config.mjs +0 -122
- package/dist/_chunks/config.mjs.map +0 -1
- package/dist/_chunks/index.d.mts +0 -151
- package/dist/_chunks/index.d.mts.map +0 -1
- package/dist/_chunks/index2.d.mts +0 -44
- package/dist/_chunks/index2.d.mts.map +0 -1
- package/dist/_chunks/index3.d.mts +0 -589
- package/dist/_chunks/index3.d.mts.map +0 -1
- package/dist/_chunks/prefix.mjs +0 -108
- package/dist/_chunks/prefix.mjs.map +0 -1
- package/dist/_chunks/retriv.mjs.map +0 -1
- package/dist/_chunks/setup.mjs +0 -17
- package/dist/_chunks/setup.mjs.map +0 -1
- package/dist/_chunks/shared.mjs +0 -503
- package/dist/_chunks/shared.mjs.map +0 -1
- package/dist/_chunks/skill.mjs +0 -329
- package/dist/_chunks/skill.mjs.map +0 -1
- package/dist/_chunks/sources.mjs.map +0 -1
- package/dist/_chunks/sync-registry.mjs +0 -59
- package/dist/_chunks/sync-registry.mjs.map +0 -1
- package/dist/_chunks/sync-shared.mjs +0 -2
- package/dist/_chunks/sync-shared2.mjs +0 -1020
- package/dist/_chunks/sync-shared2.mjs.map +0 -1
- package/dist/_chunks/types.d.mts +0 -88
- package/dist/_chunks/types.d.mts.map +0 -1
- package/dist/_chunks/wizard.mjs.map +0 -1
- package/dist/agent/index.d.mts +0 -346
- package/dist/agent/index.d.mts.map +0 -1
- package/dist/agent/index.mjs +0 -5
- package/dist/cache/index.d.mts +0 -2
- package/dist/cache/index.mjs +0 -4
- package/dist/index.d.mts +0 -5
- package/dist/index.mjs +0 -5
- package/dist/retriv/index.d.mts +0 -3
- package/dist/retriv/index.mjs +0 -2
- package/dist/sources/index.d.mts +0 -2
- package/dist/sources/index.mjs +0 -3
- package/dist/types.d.mts +0 -4
- package/dist/types.mjs +0 -1
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { a as targets } from "./detect.mjs";
|
|
2
|
+
import { a as getModelName, c as getOAuthProviderList, l as loginOAuthProvider, r as getAvailableModels } from "./agent.mjs";
|
|
3
|
+
import { m as updateConfig, o as defaultFeatures } from "./cache.mjs";
|
|
4
|
+
import { t as isInteractive } from "./env.mjs";
|
|
5
|
+
import { r as resolveAgent } from "./agent-prompt.mjs";
|
|
6
|
+
import { t as sharedArgs } from "./args.mjs";
|
|
7
|
+
import { n as OAUTH_NOTE, r as pickModel, t as NO_MODELS_MESSAGE } from "./model-picker.mjs";
|
|
8
|
+
import { styleText } from "node:util";
|
|
9
|
+
import * as p from "@clack/prompts";
|
|
10
|
+
import { defineCommand } from "citty";
|
|
11
|
+
import { execSync } from "node:child_process";
|
|
12
|
+
function hasGhCli() {
|
|
13
|
+
if (process.env.SKILLD_NO_GH) return false;
|
|
14
|
+
try {
|
|
15
|
+
execSync("gh --version", { stdio: "ignore" });
|
|
16
|
+
return true;
|
|
17
|
+
} catch {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
async function runWizard(opts = {}) {
|
|
22
|
+
if (!isInteractive()) return false;
|
|
23
|
+
const agentLabel = opts.agent ? targets[opts.agent].displayName : null;
|
|
24
|
+
const skillsDir = opts.agent ? targets[opts.agent].skillsDir : ".claude/skills";
|
|
25
|
+
const agentLine = agentLabel ? `\n${styleText("gray", `Target agent: ${agentLabel}`)}` : "";
|
|
26
|
+
p.note(`Your AI agent reads docs from its training data - but APIs change,
|
|
27
|
+
versions drift, and patterns go stale. Skilld fixes this.
|
|
28
|
+
|
|
29
|
+
It generates a ${styleText("bold", "SKILL.md")} - a markdown reference card built from\nthe ${styleText("bold", "actual docs, issues, and release notes")} for the exact\npackage versions in your project. Your agent reads this file\nevery session - no hallucinated APIs.\n\n${styleText("bold", "How it works:")}\n 1. Fetch docs, issues, and types for your packages\n 2. Optionally compress with an LLM into a concise cheat sheet\n\n${styleText("gray", `Example: \`skilld add vue\` creates ${skillsDir}/vue-skilld/SKILL.md\nYour agent then knows the right APIs, gotchas, and patterns\nfor your exact version.`)}${agentLine}`, "Welcome to skilld");
|
|
30
|
+
const ghInstalled = hasGhCli();
|
|
31
|
+
if (ghInstalled) p.log.success("GitHub CLI detected — will use it to pull issues and discussions.");
|
|
32
|
+
else p.log.info(`${styleText("gray", "GitHub CLI not installed — issues and discussions disabled.")}\n Install later to enable: ${styleText("cyan", "https://cli.github.com")}`);
|
|
33
|
+
const selected = await p.multiselect({
|
|
34
|
+
message: "What data sources should skills include?",
|
|
35
|
+
options: [
|
|
36
|
+
{
|
|
37
|
+
label: "Local search",
|
|
38
|
+
value: "search",
|
|
39
|
+
hint: "query engine for `skilld search` across all skill docs"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
label: "Release notes",
|
|
43
|
+
value: "releases",
|
|
44
|
+
hint: "changelogs and migration notes per version"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
label: "GitHub issues",
|
|
48
|
+
value: "issues",
|
|
49
|
+
hint: "common bugs, workarounds, and solutions",
|
|
50
|
+
disabled: !ghInstalled
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
label: "GitHub discussions",
|
|
54
|
+
value: "discussions",
|
|
55
|
+
hint: "community Q&A and usage examples",
|
|
56
|
+
disabled: !ghInstalled
|
|
57
|
+
}
|
|
58
|
+
],
|
|
59
|
+
initialValues: [...Object.entries(defaultFeatures).filter(([, v]) => v).map(([k]) => k), ...ghInstalled ? ["issues", "discussions"] : []],
|
|
60
|
+
required: false
|
|
61
|
+
});
|
|
62
|
+
if (p.isCancel(selected)) {
|
|
63
|
+
p.cancel("Setup cancelled");
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
const features = {
|
|
67
|
+
search: selected.includes("search"),
|
|
68
|
+
issues: selected.includes("issues"),
|
|
69
|
+
discussions: selected.includes("discussions"),
|
|
70
|
+
releases: selected.includes("releases")
|
|
71
|
+
};
|
|
72
|
+
p.note(`An LLM can optionally summarize raw docs into a focused reference
|
|
73
|
+
highlighting best practices, gotchas, and migrations.
|
|
74
|
+
|
|
75
|
+
${styleText("bold", "Without LLM:")} ~2 KB skill with package metadata, types, and links\n${styleText("bold", "With LLM:")} ~5 KB skill with curated gotchas, patterns, and migration notes\n\n${styleText("bold", "This is a one-time build step")} - it generates the SKILL.md, then your\ncoding agent reads the result every session. Can be a different model.\n\n${styleText("gray", "Works with API keys (ANTHROPIC_API_KEY, GEMINI_API_KEY, OPENAI_API_KEY)\nor CLI tools (claude, gemini, codex).")}`, "Enhancement model (optional)");
|
|
76
|
+
let modelId;
|
|
77
|
+
let skippedEnhancement = false;
|
|
78
|
+
let oauthJustConnected = false;
|
|
79
|
+
while (true) {
|
|
80
|
+
const allModels = process.env.SKILLD_NO_AGENTS ? [] : await getAvailableModels();
|
|
81
|
+
if (allModels.length === 0) p.log.warn(NO_MODELS_MESSAGE);
|
|
82
|
+
else if (oauthJustConnected) p.log.step(`${allModels.length} models now available. Select one below.`);
|
|
83
|
+
else {
|
|
84
|
+
const providers = /* @__PURE__ */ new Set();
|
|
85
|
+
for (const m of allModels) {
|
|
86
|
+
const vendor = m.vendorGroup ?? m.providerName;
|
|
87
|
+
if (!m.id.startsWith("pi:")) providers.add(`${vendor} via CLI`);
|
|
88
|
+
else if (m.hint?.includes("API key")) providers.add(`${vendor} via API key`);
|
|
89
|
+
else if (m.hint?.includes("OAuth")) providers.add(`${vendor} via OAuth`);
|
|
90
|
+
}
|
|
91
|
+
if (providers.size > 0) p.log.success(`Found: ${[...providers].join(", ")}`);
|
|
92
|
+
}
|
|
93
|
+
const afterOptions = getOAuthProviderList().length > 0 ? [{
|
|
94
|
+
label: "⚠ Connect OAuth provider...",
|
|
95
|
+
value: "_connect",
|
|
96
|
+
hint: "may violate provider ToS"
|
|
97
|
+
}, {
|
|
98
|
+
label: "Skip enhancement",
|
|
99
|
+
value: "_skip",
|
|
100
|
+
hint: "base skill with docs, issues, and types, add LLM later via `skilld config`"
|
|
101
|
+
}] : [{
|
|
102
|
+
label: "Skip enhancement",
|
|
103
|
+
value: "_skip",
|
|
104
|
+
hint: "base skill with docs, issues, and types, add LLM later via `skilld config`"
|
|
105
|
+
}];
|
|
106
|
+
const choice = await pickModel(allModels, {
|
|
107
|
+
before: allModels.length > 0 ? [{
|
|
108
|
+
label: "Auto",
|
|
109
|
+
value: "_auto",
|
|
110
|
+
hint: "picks best available model from connected providers"
|
|
111
|
+
}] : [],
|
|
112
|
+
after: afterOptions
|
|
113
|
+
});
|
|
114
|
+
if (choice === null) {
|
|
115
|
+
p.cancel("Setup cancelled");
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
if (choice === "_connect") {
|
|
119
|
+
await wizardConnectProvider();
|
|
120
|
+
oauthJustConnected = true;
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
if (choice === "_skip") {
|
|
124
|
+
skippedEnhancement = true;
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
if (choice === "_auto") break;
|
|
128
|
+
modelId = choice;
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
updateConfig({
|
|
132
|
+
features,
|
|
133
|
+
...modelId ? {
|
|
134
|
+
model: modelId,
|
|
135
|
+
skipLlm: false
|
|
136
|
+
} : {
|
|
137
|
+
model: void 0,
|
|
138
|
+
skipLlm: skippedEnhancement
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
const modelSummary = modelId ? getModelName(modelId) : skippedEnhancement ? "none (raw docs)" : "auto";
|
|
142
|
+
const featureList = Object.entries(features).filter(([, v]) => v).map(([k]) => k).join(", ") || "none";
|
|
143
|
+
p.log.success(`Model: ${modelSummary} · Features: ${featureList}`);
|
|
144
|
+
if (opts.showOutro !== false) p.note(`Run ${styleText("cyan", "skilld add <pkg>")} to generate skills for specific packages\nRun ${styleText("cyan", "skilld")} to scan your project and pick packages interactively\nRun ${styleText("cyan", "skilld config")} to change settings later`, "Setup complete");
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
async function wizardConnectProvider() {
|
|
148
|
+
p.note(OAUTH_NOTE, "How OAuth works");
|
|
149
|
+
const providers = getOAuthProviderList();
|
|
150
|
+
const provider = await p.select({
|
|
151
|
+
message: "Connect provider",
|
|
152
|
+
options: providers.map((pr) => ({
|
|
153
|
+
label: pr.name,
|
|
154
|
+
value: pr.id,
|
|
155
|
+
hint: pr.loggedIn ? "connected" : void 0
|
|
156
|
+
}))
|
|
157
|
+
});
|
|
158
|
+
if (p.isCancel(provider)) return;
|
|
159
|
+
const spinner = p.spinner();
|
|
160
|
+
spinner.start("Connecting...");
|
|
161
|
+
const success = await loginOAuthProvider(provider, {
|
|
162
|
+
onAuth: (url, instructions) => {
|
|
163
|
+
spinner.stop("Open this URL in your browser:");
|
|
164
|
+
p.log.info(` ${styleText("cyan", url)}`);
|
|
165
|
+
if (instructions) p.log.info(` ${styleText("gray", instructions)}`);
|
|
166
|
+
spinner.start("Waiting for authentication...");
|
|
167
|
+
},
|
|
168
|
+
onPrompt: async (message, placeholder) => {
|
|
169
|
+
const value = await p.text({
|
|
170
|
+
message,
|
|
171
|
+
placeholder
|
|
172
|
+
});
|
|
173
|
+
if (p.isCancel(value)) return "";
|
|
174
|
+
return value;
|
|
175
|
+
},
|
|
176
|
+
onProgress: (msg) => p.log.step(msg)
|
|
177
|
+
}).catch((err) => {
|
|
178
|
+
spinner.stop(`Login failed: ${err.message}`);
|
|
179
|
+
return false;
|
|
180
|
+
});
|
|
181
|
+
spinner.stop();
|
|
182
|
+
if (success) {
|
|
183
|
+
const name = providers.find((pr) => pr.id === provider)?.name ?? provider;
|
|
184
|
+
p.log.success(`Connected to ${name}`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
const setupCommandDef = defineCommand({
|
|
188
|
+
meta: {
|
|
189
|
+
name: "setup",
|
|
190
|
+
description: "Re-run the setup wizard to configure features and model"
|
|
191
|
+
},
|
|
192
|
+
args: { agent: sharedArgs.agent },
|
|
193
|
+
async run({ args }) {
|
|
194
|
+
const agent = resolveAgent(args.agent);
|
|
195
|
+
await runWizard({ agent: agent && agent !== "none" ? agent : void 0 });
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
export { setupCommandDef as n, runWizard as t };
|
|
199
|
+
|
|
200
|
+
//# sourceMappingURL=wizard2.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wizard2.mjs","names":["agents"],"sources":["../../src/commands/wizard.ts"],"sourcesContent":["import type { AgentType, OptimizeModel } from '../agent/index.ts'\nimport type { FeaturesConfig } from '../core/config.ts'\nimport { execSync } from 'node:child_process'\nimport { styleText } from 'node:util'\nimport * as p from '@clack/prompts'\nimport { defineCommand } from 'citty'\nimport { getOAuthProviderList, loginOAuthProvider } from '../agent/clis/pi-ai.ts'\nimport { agents, getAvailableModels, getModelName } from '../agent/index.ts'\nimport { resolveAgent } from '../cli/agent-prompt.ts'\nimport { sharedArgs } from '../cli/args.ts'\nimport { isInteractive } from '../cli/env.ts'\nimport { NO_MODELS_MESSAGE, OAUTH_NOTE, pickModel } from '../cli/model-picker.ts'\nimport { defaultFeatures, updateConfig } from '../core/config.ts'\n\nfunction hasGhCli(): boolean {\n if (process.env.SKILLD_NO_GH)\n return false\n try {\n execSync('gh --version', { stdio: 'ignore' })\n return true\n }\n catch {\n return false\n }\n}\n\nexport interface WizardOptions {\n /** Resolved target agent, if known */\n agent?: AgentType\n /** Show next-steps outro when done (default: true) */\n showOutro?: boolean\n}\n\nexport async function runWizard(opts: WizardOptions = {}): Promise<boolean> {\n if (!isInteractive())\n return false\n\n const agentLabel = opts.agent ? agents[opts.agent].displayName : null\n const skillsDir = opts.agent ? agents[opts.agent].skillsDir : '.claude/skills'\n const agentLine = agentLabel\n ? `\\n${styleText('gray', `Target agent: ${agentLabel}`)}`\n : ''\n\n p.note(\n `Your AI agent reads docs from its training data - but APIs change,\\n`\n + `versions drift, and patterns go stale. Skilld fixes this.\\n`\n + `\\n`\n + `It generates a ${styleText('bold', 'SKILL.md')} - a markdown reference card built from\\n`\n + `the ${styleText('bold', 'actual docs, issues, and release notes')} for the exact\\n`\n + `package versions in your project. Your agent reads this file\\n`\n + `every session - no hallucinated APIs.\\n`\n + `\\n`\n + `${styleText('bold', 'How it works:')}\\n`\n + ` 1. Fetch docs, issues, and types for your packages\\n`\n + ` 2. Optionally compress with an LLM into a concise cheat sheet\\n`\n + `\\n`\n + `${styleText('gray', `Example: \\`skilld add vue\\` creates ${skillsDir}/vue-skilld/SKILL.md\\nYour agent then knows the right APIs, gotchas, and patterns\\nfor your exact version.`)}${agentLine}`,\n 'Welcome to skilld',\n )\n\n const ghInstalled = hasGhCli()\n\n if (ghInstalled) {\n p.log.success(\n 'GitHub CLI detected — will use it to pull issues and discussions.',\n )\n }\n else {\n p.log.info(\n `${styleText('gray', 'GitHub CLI not installed — issues and discussions disabled.')}\\n`\n + ` Install later to enable: ${styleText('cyan', 'https://cli.github.com')}`,\n )\n }\n\n // Feature toggles\n const selected = await p.multiselect({\n message: 'What data sources should skills include?',\n options: [\n { label: 'Local search', value: 'search' as const, hint: 'query engine for `skilld search` across all skill docs' },\n { label: 'Release notes', value: 'releases' as const, hint: 'changelogs and migration notes per version' },\n { label: 'GitHub issues', value: 'issues' as const, hint: 'common bugs, workarounds, and solutions', disabled: !ghInstalled },\n { label: 'GitHub discussions', value: 'discussions' as const, hint: 'community Q&A and usage examples', disabled: !ghInstalled },\n ],\n initialValues: [\n ...Object.entries(defaultFeatures)\n .filter(([, v]) => v)\n .map(([k]) => k),\n ...(ghInstalled ? ['issues', 'discussions'] as const : []),\n ] as Array<keyof FeaturesConfig>,\n required: false,\n })\n\n if (p.isCancel(selected)) {\n p.cancel('Setup cancelled')\n return false\n }\n\n const features: FeaturesConfig = {\n search: selected.includes('search'),\n issues: selected.includes('issues'),\n discussions: selected.includes('discussions'),\n releases: selected.includes('releases'),\n }\n\n // Enhancement model - optional, independent of target agent\n p.note(\n `An LLM can optionally summarize raw docs into a focused reference\\n`\n + `highlighting best practices, gotchas, and migrations.\\n`\n + `\\n`\n + `${styleText('bold', 'Without LLM:')} ~2 KB skill with package metadata, types, and links\\n`\n + `${styleText('bold', 'With LLM:')} ~5 KB skill with curated gotchas, patterns, and migration notes\\n`\n + `\\n`\n + `${styleText('bold', 'This is a one-time build step')} - it generates the SKILL.md, then your\\n`\n + `coding agent reads the result every session. Can be a different model.\\n`\n + `\\n`\n + `${styleText('gray', 'Works with API keys (ANTHROPIC_API_KEY, GEMINI_API_KEY, OPENAI_API_KEY)\\nor CLI tools (claude, gemini, codex).')}`,\n 'Enhancement model (optional)',\n )\n\n let modelId: OptimizeModel | undefined\n let skippedEnhancement = false\n let oauthJustConnected = false\n\n // Loop so user can connect OAuth then come back to pick a model\n while (true) {\n const allModels = process.env.SKILLD_NO_AGENTS ? [] : await getAvailableModels()\n\n if (allModels.length === 0) {\n p.log.warn(NO_MODELS_MESSAGE)\n }\n else if (oauthJustConnected) {\n p.log.step(`${allModels.length} models now available. Select one below.`)\n }\n else {\n // Show which providers were found by name (e.g. \"Anthropic via CLI, OpenAI via API key\")\n const providers = new Set<string>()\n for (const m of allModels) {\n const vendor = m.vendorGroup ?? m.providerName\n if (!m.id.startsWith('pi:'))\n providers.add(`${vendor} via CLI`)\n else if (m.hint?.includes('API key'))\n providers.add(`${vendor} via API key`)\n else if (m.hint?.includes('OAuth'))\n providers.add(`${vendor} via OAuth`)\n }\n if (providers.size > 0)\n p.log.success(`Found: ${[...providers].join(', ')}`)\n }\n\n const oauthProviders = getOAuthProviderList()\n const afterOptions = oauthProviders.length > 0\n ? [\n { label: '⚠ Connect OAuth provider...', value: '_connect', hint: 'may violate provider ToS' },\n { label: 'Skip enhancement', value: '_skip', hint: 'base skill with docs, issues, and types, add LLM later via `skilld config`' },\n ]\n : [\n { label: 'Skip enhancement', value: '_skip', hint: 'base skill with docs, issues, and types, add LLM later via `skilld config`' },\n ]\n\n const choice = await pickModel(allModels, {\n before: allModels.length > 0\n ? [{ label: 'Auto', value: '_auto', hint: 'picks best available model from connected providers' }]\n : [],\n after: afterOptions,\n })\n\n if (choice === null) {\n p.cancel('Setup cancelled')\n return false\n }\n\n if (choice === '_connect') {\n await wizardConnectProvider()\n oauthJustConnected = true\n continue\n }\n\n if (choice === '_skip') {\n skippedEnhancement = true\n break\n }\n if (choice === '_auto')\n break\n\n modelId = choice as OptimizeModel\n break\n }\n\n updateConfig({\n features,\n ...(modelId\n ? { model: modelId, skipLlm: false }\n : { model: undefined, skipLlm: skippedEnhancement }),\n })\n\n // Summary of what was saved\n const modelSummary = modelId\n ? getModelName(modelId)\n : skippedEnhancement\n ? 'none (raw docs)'\n : 'auto'\n const featureList = Object.entries(features).filter(([, v]) => v).map(([k]) => k).join(', ') || 'none'\n p.log.success(`Model: ${modelSummary} · Features: ${featureList}`)\n\n if (opts.showOutro !== false) {\n p.note(\n `Run ${styleText('cyan', 'skilld add <pkg>')} to generate skills for specific packages\\n`\n + `Run ${styleText('cyan', 'skilld')} to scan your project and pick packages interactively\\n`\n + `Run ${styleText('cyan', 'skilld config')} to change settings later`,\n 'Setup complete',\n )\n }\n return true\n}\n\nasync function wizardConnectProvider(): Promise<void> {\n p.note(OAUTH_NOTE, 'How OAuth works')\n\n const providers = getOAuthProviderList()\n const provider = await p.select({\n message: 'Connect provider',\n options: providers.map(pr => ({\n label: pr.name,\n value: pr.id,\n hint: pr.loggedIn ? 'connected' : undefined,\n })),\n })\n\n if (p.isCancel(provider))\n return\n\n const spinner = p.spinner()\n spinner.start('Connecting...')\n\n const success = await loginOAuthProvider(provider as string, {\n onAuth: (url, instructions) => {\n spinner.stop('Open this URL in your browser:')\n p.log.info(` ${styleText('cyan', url)}`)\n if (instructions)\n p.log.info(` ${styleText('gray', instructions)}`)\n spinner.start('Waiting for authentication...')\n },\n onPrompt: async (message, placeholder) => {\n const value = await p.text({ message, placeholder })\n if (p.isCancel(value))\n return ''\n return value as string\n },\n onProgress: msg => p.log.step(msg),\n }).catch((err: Error) => {\n spinner.stop(`Login failed: ${err.message}`)\n return false\n })\n\n spinner.stop()\n\n if (success) {\n const name = providers.find(pr => pr.id === provider)?.name ?? provider\n p.log.success(`Connected to ${name}`)\n }\n}\n\nexport const setupCommandDef = defineCommand({\n meta: {\n name: 'setup',\n description: 'Re-run the setup wizard to configure features and model',\n },\n args: {\n agent: sharedArgs.agent,\n },\n async run({ args }) {\n const agent = resolveAgent(args.agent)\n await runWizard({\n agent: agent && agent !== 'none' ? agent as AgentType : undefined,\n })\n },\n})\n"],"mappings":"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"}
|
package/dist/cli.mjs
CHANGED
|
@@ -1,32 +1,40 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { c as getOAuthProviderList, i as getAvailableModels, l as loginOAuthProvider, o as getModelName, t as detectImportedPackages, u as logoutOAuthProvider } from "./_chunks/agent.mjs";
|
|
3
|
-
import { i as CACHE_DIR, s as getPackageDbPath, t as getCacheDir } from "./_chunks/version.mjs";
|
|
4
|
-
import { i as readPackageJsonSafe } from "./_chunks/package-json.mjs";
|
|
5
|
-
import "./_chunks/cache.mjs";
|
|
6
|
-
import { n as getSharedSkillsDir, o as semverGt, r as mapInsert } from "./_chunks/shared.mjs";
|
|
7
|
-
import { r as fetchNpmRegistryMeta, t as fetchLatestVersion } from "./_chunks/sources.mjs";
|
|
8
2
|
import { a as targets, i as getAgentVersion, r as detectTargetAgent, t as detectInstalledAgents } from "./_chunks/detect.mjs";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
3
|
+
import { a as getModelName, c as getOAuthProviderList, l as loginOAuthProvider, n as detectImportedPackages, r as getAvailableModels, u as logoutOAuthProvider } from "./_chunks/agent.mjs";
|
|
4
|
+
import { h as timedSpinner, m as timeAgo, o as unlinkSkillFromAgents, u as formatSource } from "./_chunks/prompts.mjs";
|
|
5
|
+
import { f as getSharedSkillsDir, m as skillInternalDir, n as CACHE_DIR, u as getPackageDbPath } from "./_chunks/paths.mjs";
|
|
6
|
+
import { h as VERSION_RANGE_PREFIX_RE, n as COMMA_OR_WHITESPACE_RE } from "./_chunks/regex.mjs";
|
|
7
|
+
import { s as getCacheDir } from "./_chunks/prepare.mjs";
|
|
8
|
+
import { i as readPackageJsonSafe } from "./_chunks/package-json.mjs";
|
|
9
|
+
import { d as readConfig, l as hasCompletedWizard, m as updateConfig, o as defaultFeatures, u as hasConfig } from "./_chunks/cache.mjs";
|
|
10
|
+
import { n as isRunningInsideAgent, r as requireInteractive, t as isInteractive } from "./_chunks/env.mjs";
|
|
11
|
+
import { n as promptForAgent, r as resolveAgent } from "./_chunks/agent-prompt.mjs";
|
|
12
|
+
import { t as sharedArgs } from "./_chunks/args.mjs";
|
|
13
|
+
import { t as version } from "./_chunks/version.mjs";
|
|
14
|
+
import { a as relativeTime, i as introLine, n as getInstalledGenerators, r as getRepoHint, t as formatStatus } from "./_chunks/intro.mjs";
|
|
15
|
+
import { n as menuLoop, t as guard } from "./_chunks/menu.mjs";
|
|
16
|
+
import { n as hasPrepareHook, r as suggestPrepareHook } from "./_chunks/prepare-hook2.mjs";
|
|
17
|
+
import { n as OAUTH_NOTE, r as pickModel, t as NO_MODELS_MESSAGE } from "./_chunks/model-picker.mjs";
|
|
18
|
+
import { c as resolveSkillName, f as fetchNpmRegistryMeta, l as toStoragePackageName, n as semverGt, u as fetchLatestVersion } from "./_chunks/semver.mjs";
|
|
19
|
+
import { t as mapInsert } from "./_chunks/map.mjs";
|
|
20
|
+
import { l as removeLockEntry, o as parsePackages } from "./_chunks/lockfile.mjs";
|
|
13
21
|
import { i as iterateSkills, n as getSkillsDir, r as isOutdated, t as getProjectState } from "./_chunks/skills.mjs";
|
|
14
|
-
import {
|
|
15
|
-
import { t as runWizard } from "./_chunks/wizard.mjs";
|
|
22
|
+
import { t as runWizard } from "./_chunks/wizard2.mjs";
|
|
16
23
|
import "./_chunks/core.mjs";
|
|
17
|
-
import { join, resolve } from "pathe";
|
|
18
24
|
import { existsSync, readFileSync, readdirSync, realpathSync, rmSync, statSync } from "node:fs";
|
|
19
|
-
import
|
|
25
|
+
import { styleText } from "node:util";
|
|
20
26
|
import * as p from "@clack/prompts";
|
|
21
27
|
import { defineCommand, runMain } from "citty";
|
|
28
|
+
import pLimit from "p-limit";
|
|
29
|
+
import { join, resolve } from "pathe";
|
|
22
30
|
import logUpdate from "log-update";
|
|
23
31
|
async function configCommand() {
|
|
24
32
|
const initConfig = readConfig();
|
|
25
33
|
const agentId = initConfig.agent || detectTargetAgent() || void 0;
|
|
26
|
-
const cyan = (s) =>
|
|
34
|
+
const cyan = (s) => styleText("cyan", s);
|
|
27
35
|
const modelLabel = initConfig.skipLlm ? "skip" : initConfig.model ? cyan(getModelName(initConfig.model)) : "auto";
|
|
28
36
|
const agentLabel = agentId && targets[agentId] ? cyan(targets[agentId].displayName) : "auto-detect";
|
|
29
|
-
p.note(
|
|
37
|
+
p.note(styleText("gray", `Fetch docs → Enhance with ${modelLabel} → Install to ${agentLabel}`), "How skilld works");
|
|
30
38
|
await menuLoop({
|
|
31
39
|
message: "Settings",
|
|
32
40
|
options: () => {
|
|
@@ -136,7 +144,7 @@ async function configureOAuth() {
|
|
|
136
144
|
return getOAuthProviderList().map((pr) => ({
|
|
137
145
|
label: pr.name,
|
|
138
146
|
value: pr.id,
|
|
139
|
-
hint: pr.loggedIn ? "
|
|
147
|
+
hint: pr.loggedIn ? styleText("green", "connected") : "not connected"
|
|
140
148
|
}));
|
|
141
149
|
},
|
|
142
150
|
onSelect: async (providerId) => {
|
|
@@ -163,8 +171,8 @@ async function configureOAuth() {
|
|
|
163
171
|
const success = await loginOAuthProvider(providerId, {
|
|
164
172
|
onAuth: (url, instructions) => {
|
|
165
173
|
spinner.stop("Open this URL in your browser:");
|
|
166
|
-
p.log.info(`
|
|
167
|
-
if (instructions) p.log.info(`
|
|
174
|
+
p.log.info(` ${styleText("cyan", url)}`);
|
|
175
|
+
if (instructions) p.log.info(` ${styleText("gray", instructions)}`);
|
|
168
176
|
spinner.start("Waiting for authentication...");
|
|
169
177
|
},
|
|
170
178
|
onPrompt: async (message, placeholder) => {
|
|
@@ -344,7 +352,7 @@ const removeCommandDef = defineCommand({
|
|
|
344
352
|
packages: args.package ? [...new Set([args.package, ...args._ || []].map((s) => s.trim()).filter(Boolean).map((s) => {
|
|
345
353
|
const name = resolveSkillName(s);
|
|
346
354
|
if (!name) {
|
|
347
|
-
p.log.warn(`Cannot remove
|
|
355
|
+
p.log.warn(`Cannot remove ${styleText("cyan", s)}: curator/collection inputs are not addressable here.`);
|
|
348
356
|
return null;
|
|
349
357
|
}
|
|
350
358
|
return name;
|
|
@@ -393,7 +401,7 @@ async function countEmbeddings(packageName, version) {
|
|
|
393
401
|
}
|
|
394
402
|
}
|
|
395
403
|
function countRefDocs(skillDir) {
|
|
396
|
-
const refsDir =
|
|
404
|
+
const refsDir = skillInternalDir(skillDir);
|
|
397
405
|
if (!existsSync(refsDir)) return 0;
|
|
398
406
|
let count = 0;
|
|
399
407
|
const walk = (dir, depth = 0) => {
|
|
@@ -410,9 +418,9 @@ function countRefDocs(skillDir) {
|
|
|
410
418
|
walk(refsDir);
|
|
411
419
|
return count;
|
|
412
420
|
}
|
|
413
|
-
const dim = (s) =>
|
|
414
|
-
const bold = (s) =>
|
|
415
|
-
const green = (s) =>
|
|
421
|
+
const dim = (s) => styleText("gray", s);
|
|
422
|
+
const bold = (s) => styleText("bold", s);
|
|
423
|
+
const green = (s) => styleText("green", s);
|
|
416
424
|
function getLastSynced() {
|
|
417
425
|
let latest = null;
|
|
418
426
|
for (const skill of iterateSkills()) if (skill.info?.syncedAt) {
|
|
@@ -582,8 +590,8 @@ function brandFrame(t, floor = 0, density = 0) {
|
|
|
582
590
|
async function brandLoader(work, minMs = 1500) {
|
|
583
591
|
if (process.env.SKILLD_EFFECT === "none") return work();
|
|
584
592
|
const name = "\x1B[1m\x1B[38;2;255;255;255mskilld\x1B[0m";
|
|
585
|
-
const verStr =
|
|
586
|
-
const status = "
|
|
593
|
+
const verStr = styleText("dim", `v${version}`);
|
|
594
|
+
const status = styleText("dim", "Setting up your environment");
|
|
587
595
|
const start = Date.now();
|
|
588
596
|
const sub = (raw) => raw.replace("%NAME%", name).replace("%VER%", verStr);
|
|
589
597
|
let done = false;
|
|
@@ -608,6 +616,7 @@ async function brandLoader(work, minMs = 1500) {
|
|
|
608
616
|
logUpdate.done();
|
|
609
617
|
return result;
|
|
610
618
|
}
|
|
619
|
+
const STATIC_REGEX_3 = /^[\^~>=<]/;
|
|
611
620
|
const _emit = process.emit;
|
|
612
621
|
process.emit = (event, ...args) => event === "warning" && args[0]?.name === "ExperimentalWarning" && args[0]?.message?.includes("SQLite") ? false : _emit.apply(process, [event, ...args]);
|
|
613
622
|
function deprecatedForwarder(oldName, newName, loader) {
|
|
@@ -620,7 +629,7 @@ function deprecatedForwarder(oldName, newName, loader) {
|
|
|
620
629
|
name: oldName
|
|
621
630
|
},
|
|
622
631
|
async run(ctx) {
|
|
623
|
-
console.warn(
|
|
632
|
+
console.warn(styleText("yellow", `⚠ \`skilld ${oldName}\` is deprecated. Use \`skilld ${newName}\` instead.`));
|
|
624
633
|
return original(ctx);
|
|
625
634
|
}
|
|
626
635
|
});
|
|
@@ -644,7 +653,11 @@ const SUBCOMMAND_NAMES = [
|
|
|
644
653
|
"prepare",
|
|
645
654
|
"author",
|
|
646
655
|
"publish",
|
|
647
|
-
"upload"
|
|
656
|
+
"upload",
|
|
657
|
+
"login",
|
|
658
|
+
"logout",
|
|
659
|
+
"whoami",
|
|
660
|
+
"pull"
|
|
648
661
|
];
|
|
649
662
|
runMain(defineCommand({
|
|
650
663
|
meta: {
|
|
@@ -654,8 +667,8 @@ runMain(defineCommand({
|
|
|
654
667
|
},
|
|
655
668
|
args: { agent: sharedArgs.agent },
|
|
656
669
|
subCommands: {
|
|
657
|
-
add: () => import("./_chunks/
|
|
658
|
-
update: () => import("./_chunks/
|
|
670
|
+
add: () => import("./_chunks/add.mjs").then((m) => m.addCommandDef),
|
|
671
|
+
update: () => import("./_chunks/update.mjs").then((m) => m.updateCommandDef),
|
|
659
672
|
info: () => infoCommandDef,
|
|
660
673
|
list: () => import("./_chunks/list.mjs").then((m) => m.listCommandDef),
|
|
661
674
|
config: () => configCommandDef,
|
|
@@ -665,9 +678,13 @@ runMain(defineCommand({
|
|
|
665
678
|
uninstall: () => import("./_chunks/uninstall.mjs").then((m) => m.uninstallCommandDef),
|
|
666
679
|
search: () => import("./_chunks/search.mjs").then((m) => m.searchCommandDef),
|
|
667
680
|
cache: () => import("./_chunks/cache2.mjs").then((m) => m.cacheCommandDef),
|
|
668
|
-
setup: () => import("./_chunks/
|
|
669
|
-
|
|
670
|
-
|
|
681
|
+
setup: () => import("./_chunks/wizard.mjs").then((m) => m.setupCommandDef),
|
|
682
|
+
login: () => import("./_chunks/login.mjs").then((m) => m.loginCommandDef),
|
|
683
|
+
logout: () => import("./_chunks/logout.mjs").then((m) => m.logoutCommandDef),
|
|
684
|
+
whoami: () => import("./_chunks/whoami.mjs").then((m) => m.whoamiCommandDef),
|
|
685
|
+
pull: () => import("./_chunks/pull.mjs").then((m) => m.pullCommandDef),
|
|
686
|
+
author: () => import("./_chunks/author.mjs").then((m) => m.authorGroupDef),
|
|
687
|
+
eject: deprecatedForwarder("eject", "author eject", () => import("./_chunks/eject.mjs").then((m) => m.ejectCommandDef)),
|
|
671
688
|
validate: deprecatedForwarder("validate", "author validate", () => import("./_chunks/validate.mjs").then((m) => m.validateCommandDef)),
|
|
672
689
|
assemble: deprecatedForwarder("assemble", "author assemble", () => import("./_chunks/assemble.mjs").then((m) => m.assembleCommandDef)),
|
|
673
690
|
publish: deprecatedForwarder("publish", "author publish", () => import("./_chunks/upload.mjs").then((m) => m.uploadCommandDef)),
|
|
@@ -693,7 +710,8 @@ runMain(defineCommand({
|
|
|
693
710
|
if (!hasCompletedWizard()) {
|
|
694
711
|
if (!await runWizard()) return;
|
|
695
712
|
}
|
|
696
|
-
p.log.info(
|
|
713
|
+
p.log.info(`No agent selected - skills export as portable PROMPT_*.md files.
|
|
714
|
+
Run ${styleText("cyan", "skilld add <pkg>")} to generate prompts for any package.\n Run ${styleText("cyan", "skilld config")} to set a target agent later.`);
|
|
697
715
|
return;
|
|
698
716
|
}
|
|
699
717
|
const agent = currentAgent;
|
|
@@ -734,9 +752,9 @@ runMain(defineCommand({
|
|
|
734
752
|
};
|
|
735
753
|
});
|
|
736
754
|
if (selfUpdate) {
|
|
737
|
-
const released = selfUpdate.releasedAt ?
|
|
755
|
+
const released = selfUpdate.releasedAt ? styleText("gray", ` · ${relativeTime(new Date(selfUpdate.releasedAt))}`) : "";
|
|
738
756
|
const cmd = `npx nypm add${realpathSync(process.argv[1]).startsWith(resolve(cwd, "node_modules")) ? "" : " -g"} skilld@${selfUpdate.latest}`;
|
|
739
|
-
p.note(
|
|
757
|
+
p.note(`${styleText("gray", version)} → ${styleText(["bold", "green"], selfUpdate.latest)}${released}\n${styleText("cyan", cmd)}`, styleText("yellow", "Update available"));
|
|
740
758
|
}
|
|
741
759
|
if (state.skills.length === 0) {
|
|
742
760
|
if (!hasCompletedWizard()) {
|
|
@@ -748,13 +766,13 @@ runMain(defineCommand({
|
|
|
748
766
|
const projectPkg = readPackageJsonSafe(join(cwd, "package.json"));
|
|
749
767
|
const hasPkgJson = !!projectPkg;
|
|
750
768
|
const projectName = projectPkg?.parsed.name;
|
|
751
|
-
const projectLabel = projectName ? `Generating skills for
|
|
769
|
+
const projectLabel = projectName ? `Generating skills for ${styleText("cyan", projectName)}` : "Generating skills for current directory";
|
|
752
770
|
p.log.step(projectLabel);
|
|
753
771
|
if (!hasPkgJson) p.log.warn("No package.json found - enter npm package names manually.\n For best results, run skilld inside a JS/TS project directory.");
|
|
754
772
|
if (state.shipped.length > 0) {
|
|
755
773
|
const totalShipped = state.shipped.reduce((sum, s) => sum + s.skills.length, 0);
|
|
756
774
|
const names = state.shipped.map((s) => s.packageName).join(", ");
|
|
757
|
-
p.log.info(
|
|
775
|
+
p.log.info(`${styleText("cyan", `${totalShipped} ready-to-use skill${totalShipped > 1 ? "s" : ""}`)} shipped by your dependencies: ${names}`);
|
|
758
776
|
}
|
|
759
777
|
p.log.info("Tip: Add skills for packages with complex APIs or frequent breaking changes - not every dependency needs one.");
|
|
760
778
|
let setupComplete = false;
|
|
@@ -762,7 +780,7 @@ runMain(defineCommand({
|
|
|
762
780
|
const shippedOption = state.shipped.length > 0 ? [{
|
|
763
781
|
label: "Install shipped skills",
|
|
764
782
|
value: "shipped",
|
|
765
|
-
hint:
|
|
783
|
+
hint: styleText("cyan", `${state.shipped.reduce((sum, s) => sum + s.skills.length, 0)} ready to use`)
|
|
766
784
|
}] : [];
|
|
767
785
|
const source = hasPkgJson ? await p.select({
|
|
768
786
|
message: "How should I find packages?",
|
|
@@ -794,13 +812,13 @@ runMain(defineCommand({
|
|
|
794
812
|
return;
|
|
795
813
|
}
|
|
796
814
|
if (source === "skip") {
|
|
797
|
-
p.log.info(
|
|
815
|
+
p.log.info(`Run ${styleText("cyan", "skilld add <pkg>")} or ${styleText("cyan", "skilld")} anytime to add skills.`);
|
|
798
816
|
return;
|
|
799
817
|
}
|
|
800
818
|
if (source === "shipped") {
|
|
801
|
-
const { handleShippedSkills: installShipped } = await import("./_chunks/
|
|
819
|
+
const { handleShippedSkills: installShipped } = await import("./_chunks/skill-installer.mjs");
|
|
802
820
|
for (const pkg of state.shipped) {
|
|
803
|
-
const version = state.deps.get(pkg.packageName)?.replace(
|
|
821
|
+
const version = state.deps.get(pkg.packageName)?.replace(VERSION_RANGE_PREFIX_RE, "") || "0.0.0";
|
|
804
822
|
installShipped(pkg.packageName, version, cwd, agent, false);
|
|
805
823
|
for (const sk of pkg.skills) p.log.success(`Installed shipped skill: ${sk.skillName}`);
|
|
806
824
|
}
|
|
@@ -824,7 +842,7 @@ runMain(defineCommand({
|
|
|
824
842
|
p.log.warn("No packages entered");
|
|
825
843
|
continue;
|
|
826
844
|
}
|
|
827
|
-
selected = input.split(
|
|
845
|
+
selected = input.split(COMMA_OR_WHITESPACE_RE).map((s) => s.trim()).filter(Boolean);
|
|
828
846
|
if (selected.length === 0) {
|
|
829
847
|
p.log.warn("No valid packages entered");
|
|
830
848
|
continue;
|
|
@@ -880,7 +898,7 @@ runMain(defineCommand({
|
|
|
880
898
|
const choice = await p.multiselect({
|
|
881
899
|
message: `Select packages (${packages.length} found)`,
|
|
882
900
|
options: packages.map((name) => {
|
|
883
|
-
const ver = state.deps.get(name)?.replace(
|
|
901
|
+
const ver = state.deps.get(name)?.replace(STATIC_REGEX_3, "") || "";
|
|
884
902
|
const repo = getRepoHint(name, cwd);
|
|
885
903
|
const hint = sourceMap.get(name) === "preset" ? "nuxt module" : void 0;
|
|
886
904
|
const pad = " ".repeat(maxLen - name.length + 2);
|
|
@@ -890,7 +908,7 @@ runMain(defineCommand({
|
|
|
890
908
|
repo
|
|
891
909
|
].filter(Boolean).join(" ");
|
|
892
910
|
return {
|
|
893
|
-
label: meta ? `${name}${pad}
|
|
911
|
+
label: meta ? `${name}${pad}${styleText("gray", meta)}` : name,
|
|
894
912
|
value: name
|
|
895
913
|
};
|
|
896
914
|
}),
|
|
@@ -921,7 +939,7 @@ runMain(defineCommand({
|
|
|
921
939
|
const previewContent = readFileSync(previewPath, "utf-8");
|
|
922
940
|
const previewLines = previewContent.split("\n").slice(0, 20).join("\n").replace(/\x1B\[[0-?]*[ -/]*[@-~]/g, "").replace(/\x1B\].*?(?:\x07|\x1B\\)/g, "");
|
|
923
941
|
const fileSize = (Buffer.byteLength(previewContent) / 1024).toFixed(1);
|
|
924
|
-
p.note(
|
|
942
|
+
p.note(styleText("gray", `${previewLines}\n...`), `${targets[agent].skillsDir}/${previewSkill.name}/SKILL.md (${fileSize} KB)`);
|
|
925
943
|
}
|
|
926
944
|
}
|
|
927
945
|
const agentName = targets[agent].displayName;
|
|
@@ -937,10 +955,10 @@ runMain(defineCommand({
|
|
|
937
955
|
"amp": "Start a new Amp session.\nReads skill descriptions at startup, full content on invocation.",
|
|
938
956
|
"opencode": "Start a new OpenCode session.\nSkills are discovered automatically at startup.",
|
|
939
957
|
"roo": "Restart your editor. Roo reads skill descriptions at startup."
|
|
940
|
-
}[agent] ?? "" : `Skills are ready in ${targets[agent].skillsDir}/.\n
|
|
958
|
+
}[agent] ?? "" : `Skills are ready in ${targets[agent].skillsDir}/.\n${styleText("gray", `${agentName} was not detected on this machine.\nInstall it to use these skills, or run \`skilld config\` to change agents.`)}`;
|
|
941
959
|
const firstPkg = previewSkill?.info?.packageName || previewSkill?.name;
|
|
942
|
-
const trySuggestion = firstPkg ? `\n\n
|
|
943
|
-
p.note(`${verifyLine}${trySuggestion}\n\nRun
|
|
960
|
+
const trySuggestion = firstPkg ? `\n\n${styleText("cyan", "Try it:")} ask your agent "What are the gotchas or breaking changes in ${firstPkg}?"` : "";
|
|
961
|
+
p.note(`${verifyLine}${trySuggestion}\n\nRun ${styleText("cyan", "skilld info")} to see installed skills.\nRun ${styleText("cyan", "skilld")} again to add more, update, or search.`, `${agentName} - next steps`);
|
|
944
962
|
try {
|
|
945
963
|
await suggestPrepareHook(cwd);
|
|
946
964
|
} catch (err) {
|
|
@@ -951,11 +969,11 @@ runMain(defineCommand({
|
|
|
951
969
|
const status = formatStatus(state.synced.length, state.outdated.length);
|
|
952
970
|
p.log.info(status);
|
|
953
971
|
let needsPrepareHook = !hasPrepareHook(cwd);
|
|
954
|
-
if (needsPrepareHook) p.log.warn(
|
|
972
|
+
if (needsPrepareHook) p.log.warn(`${styleText("yellow", "No prepare hook.")} Skills won't auto-restore on ${styleText("cyan", "npm install")}.`);
|
|
955
973
|
if (state.shipped.length > 0) {
|
|
956
974
|
const totalSkills = state.shipped.reduce((sum, s) => sum + s.skills.length, 0);
|
|
957
975
|
const names = state.shipped.map((s) => s.packageName).join(", ");
|
|
958
|
-
p.log.info(
|
|
976
|
+
p.log.info(`${styleText("cyan", `${totalSkills} ready-to-use skill${totalSkills > 1 ? "s" : ""}`)} shipped by your dependencies: ${names}`);
|
|
959
977
|
}
|
|
960
978
|
const refreshState = async () => {
|
|
961
979
|
state = await getProjectState(cwd);
|
|
@@ -969,7 +987,7 @@ runMain(defineCommand({
|
|
|
969
987
|
opts.push({
|
|
970
988
|
label: "Install shipped skills",
|
|
971
989
|
value: "shipped",
|
|
972
|
-
hint:
|
|
990
|
+
hint: styleText("cyan", `${total} available`)
|
|
973
991
|
});
|
|
974
992
|
}
|
|
975
993
|
opts.push({
|
|
@@ -979,12 +997,12 @@ runMain(defineCommand({
|
|
|
979
997
|
if (state.outdated.length > 0) opts.push({
|
|
980
998
|
label: "Update skills",
|
|
981
999
|
value: "update",
|
|
982
|
-
hint:
|
|
1000
|
+
hint: styleText("yellow", `${state.outdated.length} outdated`)
|
|
983
1001
|
});
|
|
984
1002
|
if (needsPrepareHook) opts.push({
|
|
985
1003
|
label: "Setup prepare hook",
|
|
986
1004
|
value: "prepare-hook",
|
|
987
|
-
hint: "
|
|
1005
|
+
hint: styleText("yellow", "recommended")
|
|
988
1006
|
});
|
|
989
1007
|
opts.push({
|
|
990
1008
|
label: "Remove skills",
|
|
@@ -1018,12 +1036,12 @@ runMain(defineCommand({
|
|
|
1018
1036
|
initialValues: allShipped
|
|
1019
1037
|
}));
|
|
1020
1038
|
if (selected.length === 0) return;
|
|
1021
|
-
const { handleShippedSkills: installShipped } = await import("./_chunks/
|
|
1039
|
+
const { handleShippedSkills: installShipped } = await import("./_chunks/skill-installer.mjs");
|
|
1022
1040
|
const seen = /* @__PURE__ */ new Set();
|
|
1023
1041
|
for (const s of selected) {
|
|
1024
1042
|
if (seen.has(s.packageName)) continue;
|
|
1025
1043
|
seen.add(s.packageName);
|
|
1026
|
-
const version = state.deps.get(s.packageName)?.replace(
|
|
1044
|
+
const version = state.deps.get(s.packageName)?.replace(VERSION_RANGE_PREFIX_RE, "") || "0.0.0";
|
|
1027
1045
|
installShipped(s.packageName, version, cwd, agent, false);
|
|
1028
1046
|
}
|
|
1029
1047
|
p.log.success(`Installed ${selected.length} shipped skill${selected.length > 1 ? "s" : ""}`);
|
|
@@ -1062,7 +1080,7 @@ runMain(defineCommand({
|
|
|
1062
1080
|
placeholder: "vue nuxt pinia"
|
|
1063
1081
|
}));
|
|
1064
1082
|
if (!input) return;
|
|
1065
|
-
selected = input.split(
|
|
1083
|
+
selected = input.split(COMMA_OR_WHITESPACE_RE).map((s) => s.trim()).filter(Boolean);
|
|
1066
1084
|
if (selected.length === 0) return;
|
|
1067
1085
|
} else {
|
|
1068
1086
|
let usages;
|
|
@@ -1118,7 +1136,7 @@ runMain(defineCommand({
|
|
|
1118
1136
|
const choice = guard(await p.multiselect({
|
|
1119
1137
|
message: `Select packages your agent struggles with or that are new to you (${packages.length} found)`,
|
|
1120
1138
|
options: packages.map((name) => {
|
|
1121
|
-
const ver = state.deps.get(name)?.replace(
|
|
1139
|
+
const ver = state.deps.get(name)?.replace(STATIC_REGEX_3, "") || "";
|
|
1122
1140
|
const repo = getRepoHint(name, cwd);
|
|
1123
1141
|
const hint = sourceMap.get(name) === "preset" ? "nuxt module" : frameworks.has(name) ? "framework" : (usageMap.get(name)?.count ?? 0) >= 5 ? `${usageMap.get(name).count} imports` : void 0;
|
|
1124
1142
|
const pad = " ".repeat(maxLen - name.length + 2);
|
|
@@ -1128,7 +1146,7 @@ runMain(defineCommand({
|
|
|
1128
1146
|
repo
|
|
1129
1147
|
].filter(Boolean).join(" ");
|
|
1130
1148
|
return {
|
|
1131
|
-
label: meta ? `${name}${pad}
|
|
1149
|
+
label: meta ? `${name}${pad}${styleText("gray", meta)}` : name,
|
|
1132
1150
|
value: name
|
|
1133
1151
|
};
|
|
1134
1152
|
}),
|