skilld 0.4.1 → 0.5.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/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![npm downloads](https://img.shields.io/npm/dm/skilld?color=yellow)](https://npm.chart.dev/skilld)
5
5
  [![license](https://img.shields.io/npm/l/skilld?color=yellow)](https://github.com/harlan-zw/skilld/blob/main/LICENSE)
6
6
 
7
- > Expert SKILL.md knowledge for your NPM dependencies.
7
+ > Generate AI agent skills from your NPM dependencies.
8
8
 
9
9
  ## Why?
10
10
 
@@ -54,9 +54,9 @@ If you need to re-configure skilld, just run `npx -y skilld config` to update yo
54
54
 
55
55
  ### Tips
56
56
 
57
- - **Be selective** only add skills for packages your agent already struggles with or that you're actively debugging. Not every dependency needs a skill.
58
- - **LLM enhancement is optional** skilld generates a useful SKILL.md without any LLM, but enhancing with one makes them significantly better. This costs tokens, so be mindful.
59
- - **Multi-agent support** if you switch between agents (e.g. Claude Code and Gemini CLI), run `skilld install --agent gemini-cli` to sync your existing skills to the other agent. The doc cache is shared, so nothing is re-downloaded.
57
+ - **Be selective** - Only add skills for packages your agent struggles with. Not every dependency needs one.
58
+ - **LLM is optional** - Skills work without any LLM, but enhancing with one makes them significantly better.
59
+ - **Multi-agent** - Run `skilld install --agent gemini-cli` to sync skills to another agent. The doc cache is shared.
60
60
 
61
61
  ## Installation
62
62
 
@@ -85,7 +85,7 @@ Add to `package.json` to keep skills fresh on install:
85
85
  ## CLI Usage
86
86
 
87
87
  ```bash
88
- # Interactive mode auto-discover from package.json
88
+ # Interactive mode - auto-discover from package.json
89
89
  skilld
90
90
 
91
91
  # Add skills for specific package(s)
@@ -147,6 +147,20 @@ skilld config
147
147
  | `--prepare` | | `false` | Non-interactive sync for prepare hook (outdated only) |
148
148
  | `--background` | `-b` | `false` | Run `--prepare` in a detached background process |
149
149
 
150
+ ## FAQ
151
+
152
+ ### How is this different from Context7?
153
+
154
+ 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.
155
+
156
+ ### Aren't these just AI convention files?
157
+
158
+ Similar idea, but instead of hand-writing them, skilld generates them from the latest package docs, issues, and releases. This makes them considerably more accurate at a low token cost. They also auto-update when your dependencies ship new versions.
159
+
160
+ ### Do skills update when my deps update?
161
+
162
+ Yes. Run `skilld update` to regenerate outdated skills, or add `skilld --prepare -b` to your prepare script and they regenerate in the background whenever you install packages.
163
+
150
164
  ## Related
151
165
 
152
166
  - [skills-npm](https://github.com/antfu/skills-npm) - Convention for shipping agent skills in npm packages
@@ -77,6 +77,7 @@ const amp = defineTarget({
77
77
  detectInstalled: () => existsSync(join(configHome$2, "amp")),
78
78
  detectEnv: () => !!process.env.AMP_SESSION,
79
79
  detectProject: (cwd) => existsSync(join(cwd, ".agents", "AGENTS.md")),
80
+ instructionFile: "AGENTS.md",
80
81
  skillsDir: ".agents/skills",
81
82
  globalSkillsDir: join(configHome$2, "agents/skills"),
82
83
  additionalSkillsDirs: [
@@ -111,6 +112,7 @@ const claudeCode = defineTarget({
111
112
  detectEnv: () => !!(process.env.CLAUDE_CODE || process.env.CLAUDE_CONFIG_DIR),
112
113
  detectProject: (cwd) => existsSync(join(cwd, ".claude")) || existsSync(join(cwd, "CLAUDE.md")),
113
114
  cli: "claude",
115
+ instructionFile: "CLAUDE.md",
114
116
  skillsDir: ".claude/skills",
115
117
  globalSkillsDir: join(claudeHome, "skills"),
116
118
  frontmatter: [
@@ -190,6 +192,7 @@ const cline = defineTarget({
190
192
  detectInstalled: () => existsSync(join(home$5, ".cline")),
191
193
  detectEnv: () => !!process.env.CLINE_TASK_ID,
192
194
  detectProject: (cwd) => existsSync(join(cwd, ".cline")),
195
+ instructionFile: ".clinerules",
193
196
  skillsDir: ".cline/skills",
194
197
  globalSkillsDir: join(home$5, ".cline/skills"),
195
198
  additionalSkillsDirs: [".clinerules/skills", ".claude/skills"],
@@ -220,6 +223,7 @@ const codex = defineTarget({
220
223
  detectEnv: () => !!(process.env.CODEX_HOME || process.env.CODEX_SESSION),
221
224
  detectProject: (cwd) => existsSync(join(cwd, ".codex")),
222
225
  cli: "codex",
226
+ instructionFile: "AGENTS.md",
223
227
  skillsDir: ".agents/skills",
224
228
  globalSkillsDir: join(homedir(), ".agents/skills"),
225
229
  additionalSkillsDirs: ["~/.codex/skills", "/etc/codex/skills"],
@@ -263,6 +267,7 @@ const cursor = defineTarget({
263
267
  detectInstalled: () => existsSync(join(home$4, ".cursor")),
264
268
  detectEnv: () => !!(process.env.CURSOR_SESSION || process.env.CURSOR_TRACE_ID),
265
269
  detectProject: (cwd) => existsSync(join(cwd, ".cursor")) || existsSync(join(cwd, ".cursorrules")),
270
+ instructionFile: ".cursorrules",
266
271
  skillsDir: ".cursor/skills",
267
272
  globalSkillsDir: join(home$4, ".cursor/skills"),
268
273
  additionalSkillsDirs: [
@@ -306,6 +311,7 @@ const geminiCli = defineTarget({
306
311
  detectEnv: () => !!(process.env.GEMINI_API_KEY && process.env.GEMINI_SESSION),
307
312
  detectProject: (cwd) => existsSync(join(cwd, ".gemini")) || existsSync(join(cwd, "AGENTS.md")),
308
313
  cli: "gemini",
314
+ instructionFile: "GEMINI.md",
309
315
  skillsDir: ".gemini/skills",
310
316
  globalSkillsDir: join(home$3, ".gemini/skills"),
311
317
  frontmatter: [
@@ -337,6 +343,7 @@ const githubCopilot = defineTarget({
337
343
  detectInstalled: () => existsSync(join(home$2, ".copilot")),
338
344
  detectEnv: () => !!process.env.GITHUB_COPILOT_SESSION,
339
345
  detectProject: (cwd) => existsSync(join(cwd, ".github", "copilot-instructions.md")),
346
+ instructionFile: ".github/copilot-instructions.md",
340
347
  skillsDir: ".github/skills",
341
348
  globalSkillsDir: join(home$2, ".copilot/skills"),
342
349
  additionalSkillsDirs: [".claude/skills", "~/.claude/skills"],
@@ -375,6 +382,7 @@ const goose = defineTarget({
375
382
  detectEnv: () => !!process.env.GOOSE_SESSION,
376
383
  detectProject: (cwd) => existsSync(join(cwd, ".goose")),
377
384
  cli: "goose",
385
+ instructionFile: ".goosehints",
378
386
  skillsDir: ".goose/skills",
379
387
  globalSkillsDir: join(configHome$1, "goose/skills"),
380
388
  additionalSkillsDirs: [
@@ -407,6 +415,7 @@ const opencode = defineTarget({
407
415
  detectInstalled: () => existsSync(join(configHome, "opencode")),
408
416
  detectEnv: () => !!process.env.OPENCODE_SESSION,
409
417
  detectProject: (cwd) => existsSync(join(cwd, ".opencode")),
418
+ instructionFile: "AGENTS.md",
410
419
  skillsDir: ".opencode/skills",
411
420
  globalSkillsDir: join(configHome, "opencode/skills"),
412
421
  additionalSkillsDirs: [
@@ -447,6 +456,7 @@ const roo = defineTarget({
447
456
  detectInstalled: () => existsSync(join(home$1, ".roo")),
448
457
  detectEnv: () => !!process.env.ROO_SESSION,
449
458
  detectProject: (cwd) => existsSync(join(cwd, ".roo")),
459
+ instructionFile: ".roorules",
450
460
  skillsDir: ".roo/skills",
451
461
  globalSkillsDir: join(home$1, ".roo/skills"),
452
462
  frontmatter: [{
@@ -478,6 +488,7 @@ const windsurf = defineTarget({
478
488
  detectInstalled: () => existsSync(join(home, ".codeium/windsurf")),
479
489
  detectEnv: () => !!process.env.WINDSURF_SESSION,
480
490
  detectProject: (cwd) => existsSync(join(cwd, ".windsurf")) || existsSync(join(cwd, ".windsurfrules")),
491
+ instructionFile: ".windsurfrules",
481
492
  skillsDir: ".windsurf/skills",
482
493
  globalSkillsDir: join(home, ".codeium/windsurf/skills"),
483
494
  frontmatter: [{
@@ -1002,6 +1013,7 @@ function generateFrontmatter({ name, version, description: pkgDescription, globs
1002
1013
  const patterns = globs ?? FILE_PATTERN_MAP[name];
1003
1014
  const globHint = patterns?.length ? ` or working with ${patterns.join(", ")} files` : "";
1004
1015
  const descSuffix = pkgDescription ? ` (${pkgDescription.replace(/\.?\s*$/, "")})` : "";
1016
+ const editHint = globHint ? `editing${globHint} or code importing` : "writing code importing";
1005
1017
  let desc;
1006
1018
  if (packages && packages.length > 1) {
1007
1019
  const importList = packages.map((p) => `"${p.name}"`).join(", ");
@@ -1010,13 +1022,13 @@ function generateFrontmatter({ name, version, description: pkgDescription, globs
1010
1022
  allKeywords.add(pkg.name);
1011
1023
  for (const kw of expandPackageName(pkg.name)) allKeywords.add(kw);
1012
1024
  }
1013
- desc = `Using code importing from ${importList}${globHint}. Researching or debugging ${[...allKeywords].join(", ")}.${descSuffix}`;
1025
+ desc = `ALWAYS use when ${editHint} ${importList}. Consult for debugging, best practices, or modifying ${[...allKeywords].join(", ")}.${descSuffix}`;
1014
1026
  } else {
1015
1027
  const allKeywords = /* @__PURE__ */ new Set();
1016
1028
  allKeywords.add(name);
1017
1029
  for (const kw of expandPackageName(name)) allKeywords.add(kw);
1018
1030
  if (repoUrl) for (const kw of expandRepoName(repoUrl)) allKeywords.add(kw);
1019
- desc = `Using code importing from "${name}"${globHint}. Researching or debugging ${[...allKeywords].join(", ")}.${descSuffix}`;
1031
+ desc = `ALWAYS use when ${editHint} "${name}". Consult for debugging, best practices, or modifying ${[...allKeywords].join(", ")}.${descSuffix}`;
1020
1032
  }
1021
1033
  const lines = [
1022
1034
  "---",