skilld 0.15.0 → 0.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -59,33 +59,21 @@ If you need to re-configure skilld, just run `npx -y skilld config` to update yo
59
59
  - **LLM is optional** - Skills work without any LLM, but enhancing with one makes them significantly better.
60
60
  - **Multi-agent** - Run `skilld install --agent gemini-cli` to sync skills to another agent. The doc cache is shared.
61
61
 
62
- ## FAQ
62
+ ## Installation
63
63
 
64
- ### Why don't the skills run?
64
+ ### Global
65
65
 
66
- Try this in your project/user prompt:
66
+ Install globally to use `skilld` across all projects without `npx`:
67
67
 
68
- ```md
69
- Before modifying code, evaluate each installed skill against the current task.
70
- For each skill, determine YES/NO relevance and invoke all YES skills before proceeding.
68
+ ```bash
69
+ npm install -g skilld
70
+ # or
71
+ pnpm add -g skilld
71
72
  ```
72
73
 
73
- ### How is this different from Context7?
74
-
75
- Context7 is an MCP that fetches raw doc chunks at query time. You get different results each prompt, no curation, and it requires their server. Skilld is local-first: it generates a SKILL.md that lives in your project, tied to your actual package versions. No MCP dependency, no per-prompt latency, and it goes further with LLM-enhanced sections, prompt injection sanitization, and semantic search.
74
+ Then run `skilld` in any project directory.
76
75
 
77
- ### Will I be prompt injected?
78
-
79
- Skilld pulls issues from GitHub which could be abused for potential prompt injection.
80
-
81
- Skilld treats all data as untrusted, running in permissioned environments and using best practices to avoid injections.
82
- However, always be cautious when using skills from untrusted sources.
83
-
84
- ### Do skills update when my deps update?
85
-
86
- Yes. Run `skilld update` to regenerate outdated skills, or add `skilld update -b` to your prepare script and they regenerate in the background whenever you install packages.
87
-
88
- ## Installation
76
+ ### Per-Project
89
77
 
90
78
  If you'd like to install skilld and track the lock file references, add it as a dev dependency:
91
79
 
@@ -109,6 +97,32 @@ Add to `package.json` to keep skills fresh on install:
109
97
  }
110
98
  ```
111
99
 
100
+ ## FAQ
101
+
102
+ ### Why don't the skills run?
103
+
104
+ Try this in your project/user prompt:
105
+
106
+ ```md
107
+ Before modifying code, evaluate each installed skill against the current task.
108
+ For each skill, determine YES/NO relevance and invoke all YES skills before proceeding.
109
+ ```
110
+
111
+ ### How is this different from Context7?
112
+
113
+ Context7 is an MCP that fetches raw doc chunks at query time. You get different results each prompt, no curation, and it requires their server. Skilld is local-first: it generates a SKILL.md that lives in your project, tied to your actual package versions. No MCP dependency, no per-prompt latency, and it goes further with LLM-enhanced sections, prompt injection sanitization, and semantic search.
114
+
115
+ ### Will I be prompt injected?
116
+
117
+ Skilld pulls issues from GitHub which could be abused for potential prompt injection.
118
+
119
+ Skilld treats all data as untrusted, running in permissioned environments and using best practices to avoid injections.
120
+ However, always be cautious when using skills from untrusted sources.
121
+
122
+ ### Do skills update when my deps update?
123
+
124
+ Yes. Run `skilld update` to regenerate outdated skills, or add `skilld update -b` to your prepare script and they regenerate in the background whenever you install packages.
125
+
112
126
  ## CLI Usage
113
127
 
114
128
  ```bash
package/dist/cli.mjs CHANGED
@@ -1304,7 +1304,8 @@ async function fetchAndCacheResources(opts) {
1304
1304
  hasDiscussions: features.discussions && existsSync(discussionsDir),
1305
1305
  hasReleases: features.releases && existsSync(releasesPath),
1306
1306
  warnings,
1307
- repoInfo
1307
+ repoInfo,
1308
+ usedCache: useCache
1308
1309
  };
1309
1310
  }
1310
1311
  async function indexResources(opts) {
@@ -1527,7 +1528,7 @@ async function selectSkillSections(message = "Generate SKILL.md with LLM") {
1527
1528
  cancelled: false
1528
1529
  };
1529
1530
  }
1530
- async function selectLlmConfig(presetModel, message) {
1531
+ async function selectLlmConfig(presetModel, message, usedCache) {
1531
1532
  if (presetModel) return {
1532
1533
  model: presetModel,
1533
1534
  sections: DEFAULT_SECTIONS
@@ -1535,6 +1536,10 @@ async function selectLlmConfig(presetModel, message) {
1535
1536
  if (!isInteractive()) return null;
1536
1537
  const defaultModel = await selectModel(true);
1537
1538
  if (!defaultModel) return null;
1539
+ if (usedCache) return {
1540
+ model: defaultModel,
1541
+ sections: DEFAULT_SECTIONS
1542
+ };
1538
1543
  const defaultModelName = getModelName(defaultModel);
1539
1544
  const choice = await p.select({
1540
1545
  message: "Generate enhanced SKILL.md?",
@@ -1943,8 +1948,9 @@ async function syncPackagesParallel(config) {
1943
1948
  for (const [, data] of skillData) for (const w of data.warnings) p.log.warn(`\x1B[33m${w}\x1B[0m`);
1944
1949
  if (errors.length > 0) for (const { pkg, reason } of errors) p.log.error(` ${pkg}: ${reason}`);
1945
1950
  const globalConfig = readConfig();
1951
+ const allCached = successfulPkgs.every((pkg) => skillData.get(pkg)?.usedCache);
1946
1952
  if (successfulPkgs.length > 0 && !globalConfig.skipLlm && !(config.yes && !config.model)) {
1947
- const llmConfig = await selectLlmConfig(config.model);
1953
+ const llmConfig = await selectLlmConfig(config.model, void 0, allCached);
1948
1954
  if (llmConfig) {
1949
1955
  p.log.step(getModelLabel(llmConfig.model));
1950
1956
  for (const pkg of successfulPkgs) states.set(pkg, {
@@ -2089,7 +2095,8 @@ async function syncBaseSkill(packageSpec, config, cwd, update) {
2089
2095
  relatedSkills,
2090
2096
  packages: allPackages.length > 1 ? allPackages : void 0,
2091
2097
  warnings: resources.warnings,
2092
- features
2098
+ features,
2099
+ usedCache: resources.usedCache
2093
2100
  };
2094
2101
  }
2095
2102
  async function enhanceWithLLM(packageName, data, config, cwd, update, sections, customPrompt) {
@@ -2470,7 +2477,7 @@ async function syncSinglePackage(packageSpec, config) {
2470
2477
  if (resources.hasIssues) resParts.push("issues");
2471
2478
  if (resources.hasDiscussions) resParts.push("discussions");
2472
2479
  if (resources.hasReleases) resParts.push("releases");
2473
- resSpin.stop(`Fetched ${resParts.length > 0 ? resParts.join(", ") : "resources"}`);
2480
+ resSpin.stop(resources.usedCache ? `Loaded ${resParts.length > 0 ? resParts.join(", ") : "resources"} (cached)` : `Fetched ${resParts.length > 0 ? resParts.join(", ") : "resources"}`);
2474
2481
  for (const w of resources.warnings) p.log.warn(`\x1B[33m${w}\x1B[0m`);
2475
2482
  linkAllReferences(skillDir, packageName, cwd, version, resources.docsType, void 0, features, resources.repoInfo);
2476
2483
  if (features.search) {
@@ -2526,7 +2533,7 @@ async function syncSinglePackage(packageSpec, config) {
2526
2533
  writeFileSync(join(skillDir, "SKILL.md"), baseSkillMd);
2527
2534
  p.log.success(config.mode === "update" ? `Updated skill: ${relative(cwd, skillDir)}` : `Created base skill: ${relative(cwd, skillDir)}`);
2528
2535
  if (!readConfig().skipLlm && (!config.yes || config.model)) {
2529
- const llmConfig = await selectLlmConfig(config.model);
2536
+ const llmConfig = await selectLlmConfig(config.model, void 0, resources.usedCache);
2530
2537
  if (llmConfig) {
2531
2538
  p.log.step(getModelLabel(llmConfig.model));
2532
2539
  await enhanceSkillWithLLM({