skilld 0.5.0 → 0.6.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
@@ -37,7 +37,7 @@ Skilld leverages maintainers existing effort. Maintainers write great docs for u
37
37
  - 🌍 **Any Source: Opt-in** - Any NPM dependency or GitHub source, docs auto-resolved
38
38
  - 📦 **Bleeding Edge Context** - Latest issues, discussions, and releases synced on
39
39
  every update. Always use the latest best practices and avoid deprecated patterns.
40
- - 📚 **Opt-in LLM Sections** - Enhance skills with LLM-generated `Best practices`, `LLM Gaps`, `Doc Map`, or your own prompts
40
+ - 📚 **Opt-in LLM Sections** - Enhance skills with LLM-generated `Best practices`, `API Changes`, `Doc Map`, or your own prompts
41
41
  - 🔍 **Semantic Search** - Query indexed docs across all skills via [retriv](https://github.com/harlan-zw/retriv) embeddings
42
42
  - 🎯 **Safe & Versioned** - Prompt injection sanitization, version-aware caching, auto-updates on new releases
43
43
  - 🤝 **Ecosystem** - Compatible with [`npx skills`](https://skills.sh/) and [skills-npm](https://github.com/antfu/skills-npm)
@@ -50,6 +50,12 @@ Run skilld in a project to generate skills for your dependencies through a simpl
50
50
  npx -y skilld
51
51
  ```
52
52
 
53
+ Or add a specific package directly:
54
+
55
+ ```bash
56
+ npx -y skilld add vue
57
+ ```
58
+
53
59
  If you need to re-configure skilld, just run `npx -y skilld config` to update your agent, model, or preferences.
54
60
 
55
61
  ### Tips
@@ -58,6 +64,20 @@ If you need to re-configure skilld, just run `npx -y skilld config` to update yo
58
64
  - **LLM is optional** - Skills work without any LLM, but enhancing with one makes them significantly better.
59
65
  - **Multi-agent** - Run `skilld install --agent gemini-cli` to sync skills to another agent. The doc cache is shared.
60
66
 
67
+ ## FAQ
68
+
69
+ ### How is this different from Context7?
70
+
71
+ 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.
72
+
73
+ ### Aren't these just AI convention files?
74
+
75
+ 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.
76
+
77
+ ### Do skills update when my deps update?
78
+
79
+ 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.
80
+
61
81
  ## Installation
62
82
 
63
83
  If you'd like to install skilld and track the lock file references, add it as a dev dependency:
@@ -147,20 +167,6 @@ skilld config
147
167
  | `--prepare` | | `false` | Non-interactive sync for prepare hook (outdated only) |
148
168
  | `--background` | `-b` | `false` | Run `--prepare` in a detached background process |
149
169
 
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
-
164
170
  ## Related
165
171
 
166
172
  - [skills-npm](https://github.com/antfu/skills-npm) - Convention for shipping agent skills in npm packages
@@ -1,5 +1,5 @@
1
1
  import { _ as writeSections, b as sanitizeMarkdown, h as readCachedSection, y as repairMarkdown } from "./storage.mjs";
2
- import { t as yamlEscape } from "./yaml.mjs";
2
+ import { o as getFilePatterns, t as yamlEscape } from "./yaml.mjs";
3
3
  import { createRequire } from "node:module";
4
4
  import { homedir } from "node:os";
5
5
  import { dirname, join, relative } from "pathe";
@@ -554,50 +554,133 @@ function getAgentVersion(agentType) {
554
554
  return null;
555
555
  }
556
556
  }
557
- function apiSection({ packageName, hasReleases, hasChangelog }) {
558
- const searchHints = [`\`skilld search "added" -p ${packageName}\``, `\`skilld search "new" -p ${packageName}\``];
557
+ function apiChangesSection({ packageName, version, hasReleases, hasChangelog, hasIssues, hasDiscussions, features }) {
558
+ const [, major, minor] = version?.match(/^(\d+)\.(\d+)/) ?? [];
559
+ const searchHints = [];
560
+ if (features?.search !== false) {
561
+ searchHints.push(`\`npx -y skilld search "deprecated" -p ${packageName}\``, `\`npx -y skilld search "breaking" -p ${packageName}\``);
562
+ if (major && minor) {
563
+ const minorNum = Number(minor);
564
+ const majorNum = Number(major);
565
+ if (minorNum <= 2) {
566
+ searchHints.push(`\`npx -y skilld search "v${majorNum}.${minorNum}" -p ${packageName}\``);
567
+ if (minorNum > 0) searchHints.push(`\`npx -y skilld search "v${majorNum}.${minorNum - 1}" -p ${packageName}\``);
568
+ if (majorNum > 0) searchHints.push(`\`npx -y skilld search "v${majorNum - 1}" -p ${packageName}\``);
569
+ } else {
570
+ searchHints.push(`\`npx -y skilld search "v${majorNum}.${minorNum}" -p ${packageName}\``);
571
+ searchHints.push(`\`npx -y skilld search "v${majorNum}.${minorNum - 1}" -p ${packageName}\``);
572
+ searchHints.push(`\`npx -y skilld search "v${majorNum}.${minorNum - 2}" -p ${packageName}\``);
573
+ }
574
+ searchHints.push(`\`npx -y skilld search "Features" -p ${packageName}\``);
575
+ }
576
+ }
577
+ const referenceWeights = [];
578
+ if (hasReleases) referenceWeights.push({
579
+ name: "Releases",
580
+ path: "./.skilld/releases/_INDEX.md",
581
+ score: 9,
582
+ useFor: "Primary source — version headings list new/deprecated/renamed APIs"
583
+ });
584
+ if (hasChangelog) referenceWeights.push({
585
+ name: "Changelog",
586
+ path: `./.skilld/pkg/${hasChangelog}`,
587
+ score: 9,
588
+ useFor: "Features/Breaking Changes sections per version"
589
+ });
590
+ referenceWeights.push({
591
+ name: "Docs",
592
+ path: "./.skilld/docs/",
593
+ score: 4,
594
+ useFor: "Only migration guides or upgrade pages"
595
+ });
596
+ if (hasIssues) referenceWeights.push({
597
+ name: "Issues",
598
+ path: "./.skilld/issues/_INDEX.md",
599
+ score: 2,
600
+ useFor: "Skip unless searching a specific removed API"
601
+ });
602
+ if (hasDiscussions) referenceWeights.push({
603
+ name: "Discussions",
604
+ path: "./.skilld/discussions/_INDEX.md",
605
+ score: 2,
606
+ useFor: "Skip unless searching a specific removed API"
607
+ });
608
+ const releaseGuidance = hasReleases ? `\n\n**Scan release history:** Read \`./.skilld/releases/_INDEX.md\` for a timeline. Focus on [MAJOR] and [MINOR] releases — these contain breaking changes and renamed/deprecated APIs that LLMs trained on older data will get wrong.` : "";
609
+ const versionGuidance = major && minor ? `\n\n**New APIs in recent releases are the highest-priority gaps** — the LLM was trained on older data and will use outdated or non-existent APIs instead. Search for recent version tags and "Features" in releases/changelog to find new composables, components, hooks, or utilities added in recent major/minor versions.` : "";
559
610
  return {
560
- task: `**Generate a doc map — a compact index of exports the LLM wouldn't already know, linked to source files.** Focus on APIs added in recent versions, non-obvious exports, and anything with surprising behavior that isn't covered in LLM Gaps or Best Practices.
561
-
562
- Skip well-known, stable APIs the LLM was trained on. Skip self-explanatory utilities (\`isString\`, \`toArray\`). The value is navigational: function name → which file to Read for details.${hasReleases || hasChangelog ? `\n\nSearch ${hasReleases ? "releases" : "changelog"} for recently added APIs using ${searchHints.join(" and ")}. Prioritize exports the LLM likely doesn't know about — new in recent minor/major versions.` : ""}`,
563
- format: `\`\`\`
564
- ## Doc Map
611
+ referenceWeights,
612
+ task: `**Find new, deprecated, and renamed APIs from version history.** Focus exclusively on APIs that changed between versions — LLMs trained on older data will use the wrong names, wrong signatures, or non-existent functions.
565
613
 
566
- ### [Queries](./.skilld/docs/queries.md)
614
+ Find from releases/changelog:
615
+ - **New APIs added in recent major/minor versions** that the LLM will not know to use (new functions, composables, components, hooks)
616
+ - **Deprecated or removed APIs** that LLMs trained on older data will still use (search for "deprecated", "removed", "renamed")
617
+ - **Signature changes** where old code compiles but behaves wrong (changed parameter order, return types, default values)
618
+ - **Breaking changes** in recent versions (v2 → v3 migrations, major version bumps)
619
+ ${searchHints.length ? `\nSearch: ${searchHints.join(", ")}` : ""}${releaseGuidance}${versionGuidance}`,
620
+ format: `## API Changes
567
621
 
568
- createQueryKeyStore, queryOptions, infiniteQueryOptions
622
+ This section documents version-specific API changes — prioritize recent major/minor releases.
569
623
 
570
- ### [Hooks](./.skilld/docs/hooks.md) *(v5.0+)*
624
+ \`\`\`
625
+ ## API Changes
571
626
 
572
- useSuspenseQuery, usePrefetchQuery, useQueries
627
+ ⚠️ \`createClient(url, key)\` — v2 changed to \`createClient({ url, key })\`, old positional args silently ignored [source](./.skilld/releases/v2.0.0.md)
573
628
 
574
- ### [Composables](./.skilld/docs/composables.md)
629
+ \`useTemplateRef()\` — new in v3.5, replaces \`$refs\` pattern [source](./.skilld/releases/v3.5.0.md)
575
630
 
576
- useNuxtData, usePreviewMode, prerenderRoutes
631
+ ⚠️ \`db.query()\` — returns \`{ rows }\` not raw array since v4 [source](./.skilld/docs/migration.md)
577
632
  \`\`\`
578
633
 
579
- Comma-separated names per group. One line per doc page. Annotate version when APIs are recent additions. For single-doc packages, use a flat comma list.`,
634
+ Each item: ⚠️ (breaking/deprecated) or (new) + API name + what changed + source link.`,
580
635
  rules: [
581
- "- **Doc Map:** names only, grouped by doc page, MAX 25 lines",
582
- "- Skip entirely for packages with fewer than 5 exports or only 1 doc page",
583
- "- Prioritize new/recent exports over well-established APIs",
584
- "- No signatures, no descriptions the linked doc IS the description",
585
- "- Do not list functions already in LLM Gaps or Best Practices"
586
- ]
636
+ "- **API Changes:** 8-12 items from version history, MAX 80 lines",
637
+ "- Prioritize recent major/minor releases over old patch versions",
638
+ "- Focus on APIs that CHANGED, not general conventions or gotchas",
639
+ "- New APIs get ✨, deprecated/breaking get ⚠️",
640
+ hasReleases ? "- Start with `./.skilld/releases/_INDEX.md` to identify recent major/minor releases, then read specific release files" : "",
641
+ hasChangelog ? "- Scan CHANGELOG.md for version headings, focus on Features/Breaking Changes sections" : ""
642
+ ].filter(Boolean)
587
643
  };
588
644
  }
589
- function bestPracticesSection({ packageName, hasIssues, hasDiscussions }) {
590
- const searchHints = [`\`skilld search "recommended" -p ${packageName}\``, `\`skilld search "avoid" -p ${packageName}\``];
591
- const communityGuidance = [];
592
- if (hasDiscussions) communityGuidance.push("**Mine discussions for patterns:** Read `./.skilld/discussions/_INDEX.md` for an overview. Q&A discussions with accepted answers reveal the \"right way\" to do things — especially when the question implies a non-obvious pattern.");
593
- if (hasIssues) communityGuidance.push("**Mine questions from issues:** Issues tagged as questions (type: question) in `./.skilld/issues/_INDEX.md` reveal what users find confusing — address these patterns proactively.");
594
- const communityBlock = communityGuidance.length ? `\n\n${communityGuidance.join("\n\n")}` : "";
645
+ function bestPracticesSection({ packageName, hasIssues, hasDiscussions, hasReleases, hasChangelog, features }) {
646
+ const searchHints = [];
647
+ if (features?.search !== false) searchHints.push(`\`npx -y skilld search "recommended" -p ${packageName}\``, `\`npx -y skilld search "avoid" -p ${packageName}\``);
648
+ const referenceWeights = [{
649
+ name: "Docs",
650
+ path: "./.skilld/docs/",
651
+ score: 9,
652
+ useFor: "Primary source — recommended patterns, configuration, idiomatic usage"
653
+ }];
654
+ if (hasDiscussions) referenceWeights.push({
655
+ name: "Discussions",
656
+ path: "./.skilld/discussions/_INDEX.md",
657
+ score: 8,
658
+ useFor: "Q&A with accepted answers reveal \"the right way\""
659
+ });
660
+ if (hasIssues) referenceWeights.push({
661
+ name: "Issues",
662
+ path: "./.skilld/issues/_INDEX.md",
663
+ score: 7,
664
+ useFor: "Questions reveal what users find confusing"
665
+ });
666
+ if (hasReleases) referenceWeights.push({
667
+ name: "Releases",
668
+ path: "./.skilld/releases/_INDEX.md",
669
+ score: 3,
670
+ useFor: "Only for new patterns introduced in recent versions"
671
+ });
672
+ if (hasChangelog) referenceWeights.push({
673
+ name: "Changelog",
674
+ path: `./.skilld/pkg/${hasChangelog}`,
675
+ score: 3,
676
+ useFor: "Only for new patterns introduced in recent versions"
677
+ });
595
678
  return {
679
+ referenceWeights,
596
680
  task: `**Extract non-obvious best practices from the references.** Focus on recommended patterns Claude wouldn't already know: idiomatic usage, preferred configurations, performance tips, patterns that differ from what a developer would assume. Surface new patterns from recent minor releases that may post-date training data. Every item must link to a verified source file.
597
681
 
598
682
  Skip: obvious API usage, installation steps, general TypeScript/programming patterns, anything a developer would naturally write without reading the docs.
599
-
600
- Search for recommended patterns using ${searchHints.join(", ")}.${communityBlock}`,
683
+ ${searchHints.length ? `\nSearch: ${searchHints.join(", ")}` : ""}`,
601
684
  format: `\`\`\`
602
685
  ## Best Practices
603
686
 
@@ -620,10 +703,8 @@ Each item: ✅ + pattern name + why it's preferred + source link. Code block onl
620
703
  rules: [
621
704
  "- **5-10 best practice items**",
622
705
  "- **MAX 150 lines** for best practices section",
623
- "- **Only link files confirmed to exist** via Glob or Read — no guessed paths",
624
- hasDiscussions ? "- Check `./.skilld/discussions/_INDEX.md` for answered Q&A — these reveal idiomatic patterns" : "",
625
- hasIssues ? "- Check `./.skilld/issues/_INDEX.md` for common questions — address confusing patterns proactively" : ""
626
- ].filter(Boolean)
706
+ "- **Only link files confirmed to exist** via Glob or Read — no guessed paths"
707
+ ]
627
708
  };
628
709
  }
629
710
  function customSection({ heading, body }) {
@@ -638,59 +719,82 @@ Content addressing the user's instructions above, using concise examples and sou
638
719
  rules: [`- **Custom section "${heading}":** MAX 80 lines, use \`## ${heading}\` heading`]
639
720
  };
640
721
  }
641
- function llmGapsSection({ packageName, hasIssues, hasReleases, hasChangelog }) {
642
- const searchHints = [`\`skilld search "deprecated" -p ${packageName}\``, `\`skilld search "breaking" -p ${packageName}\``];
643
- const searchSources = [hasReleases && "releases", hasChangelog && "changelog"].filter(Boolean);
644
- const sourceHint = searchSources.length ? ` across ${searchSources.join(" and ")}` : "";
645
- const releaseGuidance = hasReleases ? `\n\n**Scan release history:** Read \`./.skilld/releases/_INDEX.md\` for a timeline. Focus on [MAJOR] and [MINOR] releases — these contain breaking changes and renamed/deprecated APIs that LLMs trained on older data will get wrong.` : "";
646
- const issueGuidance = hasIssues ? `\n\n**Mine issues for gotchas:** Read \`./.skilld/issues/_INDEX.md\` for an overview. Focus on bug reports (type: bug) with high reactions these reveal patterns users consistently get wrong. Closed bugs show resolved pitfalls worth warning about.` : "";
722
+ function apiSection({ hasReleases, hasChangelog, hasIssues, hasDiscussions }) {
723
+ const referenceWeights = [{
724
+ name: "Docs",
725
+ path: "./.skilld/docs/",
726
+ score: 10,
727
+ useFor: "Primary sourcescan all doc pages for export names"
728
+ }];
729
+ if (hasReleases) referenceWeights.push({
730
+ name: "Releases",
731
+ path: "./.skilld/releases/_INDEX.md",
732
+ score: 5,
733
+ useFor: "New APIs added in recent versions"
734
+ });
735
+ if (hasChangelog) referenceWeights.push({
736
+ name: "Changelog",
737
+ path: `./.skilld/pkg/${hasChangelog}`,
738
+ score: 5,
739
+ useFor: "New APIs added in recent versions"
740
+ });
741
+ referenceWeights.push({
742
+ name: "Package",
743
+ path: "./.skilld/pkg/",
744
+ score: 4,
745
+ useFor: "Check exports field and entry points"
746
+ });
747
+ if (hasIssues) referenceWeights.push({
748
+ name: "Issues",
749
+ path: "./.skilld/issues/_INDEX.md",
750
+ score: 1,
751
+ useFor: "Skip"
752
+ });
753
+ if (hasDiscussions) referenceWeights.push({
754
+ name: "Discussions",
755
+ path: "./.skilld/discussions/_INDEX.md",
756
+ score: 1,
757
+ useFor: "Skip"
758
+ });
647
759
  return {
648
- task: `**Identify patterns an LLM will get wrong on first attempt.** These are NOT best practices — they are constraints, conventions, and non-obvious behaviors that cause immediate errors when an AI generates code without knowing them.
760
+ referenceWeights,
761
+ task: `**Generate a doc map — a compact index of exports the LLM wouldn't already know, linked to source files.** Focus on APIs added in recent versions, non-obvious exports, and anything with surprising behavior that isn't covered in API Changes or Best Practices.
649
762
 
650
- Find:
651
- - Deprecated or renamed APIs that LLMs trained on older data will still use (search releases/changelog for "deprecated", "removed", "renamed")
652
- - Default values that changed between major/minor versions (old code "works" but behaves wrong)
653
- - File-location constraints (e.g. composable only works in specific directories)
654
- - Framework magic that isn't obvious from API signatures (auto-imports, file-based routing, macro transforms)
655
- - APIs that behave differently than similar packages (surprising argument order, return types, sync vs async)
656
- - Context-dependent availability (server-only, client-only, build-time only, must be called inside setup)
657
- - Implicit ordering or lifecycle requirements
658
- - Convention-over-configuration patterns where violating the convention silently fails
763
+ Skip well-known, stable APIs the LLM was trained on. Skip self-explanatory utilities (\`isString\`, \`toArray\`). The value is navigational: function name → which file to Read for details.`,
764
+ format: `\`\`\`
765
+ ## Doc Map
659
766
 
660
- Use ${searchHints.join(" and ")} to surface deprecations and breaking changes${sourceHint}.${releaseGuidance}${issueGuidance}`,
661
- format: `## LLM Gaps
767
+ ### [Queries](./.skilld/docs/queries.md)
662
768
 
663
- This section goes BEFORE best practices — it's higher priority.
769
+ createQueryKeyStore, queryOptions, infiniteQueryOptions
664
770
 
665
- \`\`\`
666
- ## LLM Gaps
771
+ ### [Hooks](./.skilld/docs/hooks.md) *(v5.0+)*
667
772
 
668
- ⚠️ \`createClient(url, key)\` — v2 changed to \`createClient({ url, key })\`, old positional args silently ignored [source](./.skilld/releases/v2.0.0.md)
773
+ useSuspenseQuery, usePrefetchQuery, useQueries
669
774
 
670
- ⚠️ \`definePageMeta()\` — only works in \`pages/**/*.vue\`, silently ignored elsewhere [source](./.skilld/docs/routing.md)
775
+ ### [Composables](./.skilld/docs/composables.md)
671
776
 
672
- ⚠️ \`db.query()\` — returns \`{ rows }\` not raw array since v4, destructure or code breaks silently [source](./.skilld/docs/queries.md)
777
+ useNuxtData, usePreviewMode, prerenderRoutes
673
778
  \`\`\`
674
779
 
675
- Each item: ⚠️ + API/pattern name + what goes wrong + where it works + source link.`,
780
+ Comma-separated names per group. One line per doc page. Annotate version when APIs are recent additions. For single-doc packages, use a flat comma list.`,
676
781
  rules: [
677
- "- **LLM Gaps:** 5-10 items that will prevent first-attempt errors, MAX 80 lines",
678
- "- Focus on \"silent failures\" and \"works but wrong\" over obvious runtime errors",
679
- "- Assume the LLM knows general programming but NOT this package's conventions",
680
- "- Prioritize deprecated/renamed APIs and changed defaults these cause the most first-attempt failures",
681
- hasReleases ? "- Start with `./.skilld/releases/_INDEX.md` scan [MAJOR]/[MINOR] releases for breaking changes, then read specific release files" : "",
682
- hasIssues ? "- Check `./.skilld/issues/_INDEX.md` for bug reports — high-reaction bugs often reveal non-obvious constraints" : ""
683
- ].filter(Boolean)
782
+ "- **Doc Map:** names only, grouped by doc page, MAX 25 lines",
783
+ "- Skip entirely for packages with fewer than 5 exports or only 1 doc page",
784
+ "- Prioritize new/recent exports over well-established APIs",
785
+ "- No signatures, no descriptions the linked doc IS the description",
786
+ "- Do not list functions already in API Changes or Best Practices"
787
+ ]
684
788
  };
685
789
  }
686
790
  const SECTION_OUTPUT_FILES = {
687
791
  "best-practices": "_BEST_PRACTICES.md",
688
- "llm-gaps": "_LLM_GAPS.md",
792
+ "api-changes": "_API_CHANGES.md",
689
793
  "api": "_DOC_MAP.md",
690
794
  "custom": "_CUSTOM.md"
691
795
  };
692
796
  const SECTION_MERGE_ORDER = [
693
- "llm-gaps",
797
+ "api-changes",
694
798
  "best-practices",
695
799
  "api",
696
800
  "custom"
@@ -703,7 +807,7 @@ function formatDocTree(files) {
703
807
  }
704
808
  return [...dirs.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([dir, count]) => `- \`${dir}/\` (${count} .md files)`).join("\n");
705
809
  }
706
- function generateImportantBlock({ packageName, hasIssues, hasDiscussions, hasReleases, hasChangelog, docsType, hasShippedDocs, skillDir }) {
810
+ function generateImportantBlock({ packageName, hasIssues, hasDiscussions, hasReleases, hasChangelog, docsType, hasShippedDocs, skillDir, features }) {
707
811
  const rows = [["Docs", hasShippedDocs ? `\`${skillDir}/.skilld/pkg/docs/\` or \`${skillDir}/.skilld/pkg/README.md\`` : docsType === "llms.txt" ? `\`${skillDir}/.skilld/docs/llms.txt\`` : docsType === "readme" ? `\`${skillDir}/.skilld/pkg/README.md\`` : `\`${skillDir}/.skilld/docs/\``], ["Package", `\`${skillDir}/.skilld/pkg/\``]];
708
812
  if (hasIssues) rows.push(["Issues", `\`${skillDir}/.skilld/issues/\``]);
709
813
  if (hasDiscussions) rows.push(["Discussions", `\`${skillDir}/.skilld/discussions/\``]);
@@ -714,9 +818,7 @@ function generateImportantBlock({ packageName, hasIssues, hasDiscussions, hasRel
714
818
  "|----------|------|",
715
819
  ...rows.map(([desc, cmd]) => `| ${desc} | ${cmd} |`)
716
820
  ].join("\n");
717
- return `**IMPORTANT:** Use these references
718
-
719
- ## Search
821
+ return `**IMPORTANT:** Use these references${features?.search !== false ? `\n\n## Search
720
822
 
721
823
  Use \`npx -y skilld search\` as your primary research tool — search before manually reading files. Hybrid semantic + keyword search across all indexed docs, issues, and releases.
722
824
 
@@ -724,7 +826,7 @@ Use \`npx -y skilld search\` as your primary research tool — search before man
724
826
  npx -y skilld search "<query>" -p ${packageName}
725
827
  ${hasIssues ? `npx -y skilld search "issues:<query>" -p ${packageName}\n` : ""}${hasReleases ? `npx -y skilld search "releases:<query>" -p ${packageName}\n` : ""}\`\`\`
726
828
 
727
- Filters: \`docs:\`, \`issues:\`, \`releases:\` prefix narrows by source type.
829
+ Filters: \`docs:\`, \`issues:\`, \`releases:\` prefix narrows by source type.` : ""}
728
830
 
729
831
  ${table}`;
730
832
  }
@@ -748,7 +850,8 @@ ${generateImportantBlock({
748
850
  hasChangelog,
749
851
  docsType,
750
852
  hasShippedDocs,
751
- skillDir
853
+ skillDir,
854
+ features: opts.features
752
855
  })}
753
856
  ${docsSection ? `${docsSection}\n` : ""}
754
857
 
@@ -763,7 +866,7 @@ The context window is a shared resource. Skills share it with system prompt, con
763
866
  }
764
867
  function getSectionDef(section, ctx, customPrompt) {
765
868
  switch (section) {
766
- case "llm-gaps": return llmGapsSection(ctx);
869
+ case "api-changes": return apiChangesSection(ctx);
767
870
  case "best-practices": return bestPracticesSection(ctx);
768
871
  case "api": return apiSection(ctx);
769
872
  case "custom": return customPrompt ? customSection(customPrompt) : null;
@@ -778,10 +881,12 @@ function buildSectionPrompt(opts) {
778
881
  });
779
882
  const sectionDef = getSectionDef(section, {
780
883
  packageName,
884
+ version,
781
885
  hasIssues,
782
886
  hasDiscussions,
783
887
  hasReleases,
784
- hasChangelog
888
+ hasChangelog,
889
+ features: opts.features
785
890
  }, customPrompt);
786
891
  if (!sectionDef) return "";
787
892
  const outputFile = SECTION_OUTPUT_FILES[section];
@@ -790,12 +895,12 @@ function buildSectionPrompt(opts) {
790
895
  "- Link to exact source file where you found info",
791
896
  "- TypeScript only, Vue uses `<script setup lang=\"ts\">`",
792
897
  "- Imperative voice (\"Use X\" not \"You should use X\")",
793
- "- **NEVER fetch external URLs.** All information is in the local `./.skilld/` directory. Use Read, Glob, and `skilld search` only.",
898
+ `- **NEVER fetch external URLs.** All information is in the local \`./.skilld/\` directory. Use Read, Glob${opts.features?.search !== false ? ", and `skilld search`" : ""} only.`,
794
899
  "- **Do NOT use Task tool or spawn subagents.** Work directly.",
795
900
  "- **Do NOT re-read files** you have already read in this session.",
796
901
  "- **Read `_INDEX.md` first** in issues/releases/discussions — only drill into files that look relevant. Skip stub/placeholder files."
797
902
  ];
798
- return `${preamble}
903
+ return `${preamble}${sectionDef.referenceWeights?.length ? `\n\n## Reference Priority\n\n| Reference | Path | Score | Use For |\n|-----------|------|:-----:|--------|\n${sectionDef.referenceWeights.map((w) => `| ${w.name} | [\`${w.path.split("/").pop()}\`](${w.path}) | ${w.score}/10 | ${w.useFor} |`).join("\n")}` : ""}
799
904
 
800
905
  ## Task
801
906
 
@@ -884,54 +989,10 @@ function unlinkSkillFromAgents(skillName, cwd) {
884
989
  } catch {}
885
990
  }
886
991
  }
887
- const FILE_PATTERN_MAP = {
888
- "vue": ["*.vue"],
889
- "svelte": ["*.svelte"],
890
- "astro": ["*.astro"],
891
- "solid-js": ["*.jsx", "*.tsx"],
892
- "qwik": ["*.tsx"],
893
- "marko": ["*.marko"],
894
- "riot": ["*.riot"],
895
- "typescript": [
896
- "*.ts",
897
- "*.tsx",
898
- "*.mts",
899
- "*.cts"
900
- ],
901
- "coffeescript": ["*.coffee"],
902
- "livescript": ["*.ls"],
903
- "elm": ["*.elm"],
904
- "sass": ["*.scss", "*.sass"],
905
- "less": ["*.less"],
906
- "stylus": ["*.styl"],
907
- "postcss": ["*.css", "*.pcss"],
908
- "pug": ["*.pug"],
909
- "ejs": ["*.ejs"],
910
- "handlebars": ["*.hbs", "*.handlebars"],
911
- "mustache": ["*.mustache"],
912
- "nunjucks": ["*.njk"],
913
- "liquid": ["*.liquid"],
914
- "yaml": ["*.yaml", "*.yml"],
915
- "js-yaml": ["*.yaml", "*.yml"],
916
- "toml": ["*.toml"],
917
- "@iarna/toml": ["*.toml"],
918
- "json5": ["*.json5"],
919
- "jsonc-parser": ["*.jsonc"],
920
- "markdown-it": ["*.md"],
921
- "marked": ["*.md"],
922
- "remark": ["*.md", "*.mdx"],
923
- "@mdx-js/mdx": ["*.mdx"],
924
- "graphql": ["*.graphql", "*.gql"],
925
- "graphql-tag": ["*.graphql", "*.gql"],
926
- "@graphql-codegen/cli": ["*.graphql", "*.gql"],
927
- "prisma": ["*.prisma"],
928
- "@prisma/client": ["*.prisma"],
929
- "wasm-pack": ["*.wasm"]
930
- };
931
992
  function generateSkillMd(opts) {
932
993
  const header = generatePackageHeader(opts);
933
- const search = generateSearchBlock(opts.name, opts.hasIssues, opts.hasReleases);
934
- const content = opts.body ? `${header}\n\n${search}\n\n${opts.body}` : `${header}\n\n${search}`;
994
+ const search = opts.features?.search !== false ? generateSearchBlock(opts.name, opts.hasIssues, opts.hasReleases) : "";
995
+ const content = opts.body ? search ? `${header}\n\n${search}\n\n${opts.body}` : `${header}\n\n${opts.body}` : search ? `${header}\n\n${search}` : header;
935
996
  const footer = generateFooter(opts.relatedSkills);
936
997
  return sanitizeMarkdown(repairMarkdown(`${generateFrontmatter(opts)}${content}\n${footer}`));
937
998
  }
@@ -1010,7 +1071,7 @@ function expandRepoName(repoUrl) {
1010
1071
  return [...variants];
1011
1072
  }
1012
1073
  function generateFrontmatter({ name, version, description: pkgDescription, globs, body, generatedBy, dirName, packages, repoUrl }) {
1013
- const patterns = globs ?? FILE_PATTERN_MAP[name];
1074
+ const patterns = globs ?? getFilePatterns(name);
1014
1075
  const globHint = patterns?.length ? ` or working with ${patterns.join(", ")} files` : "";
1015
1076
  const descSuffix = pkgDescription ? ` (${pkgDescription.replace(/\.?\s*$/, "")})` : "";
1016
1077
  const editHint = globHint ? `editing${globHint} or code importing` : "writing code importing";
@@ -1515,7 +1576,7 @@ function optimizeSection(opts) {
1515
1576
  });
1516
1577
  }
1517
1578
  async function optimizeDocs(opts) {
1518
- const { packageName, skillDir, model = "sonnet", version, hasGithub, hasReleases, hasChangelog, docFiles, docsType, hasShippedDocs, onProgress, timeout = 18e4, debug, noCache, sections, customPrompt } = opts;
1579
+ const { packageName, skillDir, model = "sonnet", version, hasGithub, hasReleases, hasChangelog, docFiles, docsType, hasShippedDocs, onProgress, timeout = 18e4, debug, noCache, sections, customPrompt, features } = opts;
1519
1580
  const sectionPrompts = buildAllSectionPrompts({
1520
1581
  packageName,
1521
1582
  skillDir,
@@ -1528,8 +1589,9 @@ async function optimizeDocs(opts) {
1528
1589
  docsType,
1529
1590
  hasShippedDocs,
1530
1591
  customPrompt,
1592
+ features,
1531
1593
  sections: sections ?? [
1532
- "llm-gaps",
1594
+ "api-changes",
1533
1595
  "best-practices",
1534
1596
  "api"
1535
1597
  ]
@@ -1673,7 +1735,7 @@ function shortenPath(p) {
1673
1735
  return parts.length > 2 ? `.../${parts.slice(-2).join("/")}` : p;
1674
1736
  }
1675
1737
  const SECTION_MAX_LINES = {
1676
- "llm-gaps": 160,
1738
+ "api-changes": 160,
1677
1739
  "best-practices": 300,
1678
1740
  "api": 160,
1679
1741
  "custom": 160
@@ -1858,6 +1920,6 @@ function isNodeBuiltin(pkg) {
1858
1920
  const base = pkg.startsWith("node:") ? pkg.slice(5) : pkg;
1859
1921
  return NODE_BUILTINS.has(base.split("/")[0]);
1860
1922
  }
1861
- export { detectInstalledAgents as _, optimizeDocs as a, targets as b, computeSkillDirName as c, sanitizeName as d, unlinkSkillFromAgents as f, buildSectionPrompt as g, buildAllSectionPrompts as h, getModelName as i, installSkillForAgents as l, SECTION_OUTPUT_FILES as m, getAvailableModels as n, generateSkillMd as o, SECTION_MERGE_ORDER as p, getModelLabel as r, FILE_PATTERN_MAP as s, detectImportedPackages as t, linkSkillToAgents as u, detectTargetAgent as v, __exportAll as x, getAgentVersion as y };
1923
+ export { detectTargetAgent as _, optimizeDocs as a, __exportAll as b, installSkillForAgents as c, unlinkSkillFromAgents as d, SECTION_MERGE_ORDER as f, detectInstalledAgents as g, buildSectionPrompt as h, getModelName as i, linkSkillToAgents as l, buildAllSectionPrompts as m, getAvailableModels as n, generateSkillMd as o, SECTION_OUTPUT_FILES as p, getModelLabel as r, computeSkillDirName as s, detectImportedPackages as t, sanitizeName as u, getAgentVersion as v, targets as y };
1862
1924
 
1863
1925
  //# sourceMappingURL=detect-imports.mjs.map