skilld 0.3.2 → 0.4.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 +9 -8
- package/dist/_chunks/detect-imports.mjs +51 -36
- package/dist/_chunks/detect-imports.mjs.map +1 -1
- package/dist/_chunks/git-skills.mjs +319 -0
- package/dist/_chunks/git-skills.mjs.map +1 -0
- package/dist/_chunks/releases.mjs +2 -61
- package/dist/_chunks/releases.mjs.map +1 -1
- package/dist/_chunks/sanitize2.mjs +249 -0
- package/dist/_chunks/sanitize2.mjs.map +1 -0
- package/dist/_chunks/storage.mjs +2 -241
- package/dist/_chunks/storage.mjs.map +1 -1
- package/dist/_chunks/sync-git.mjs +69 -0
- package/dist/_chunks/sync-git.mjs.map +1 -0
- package/dist/_chunks/sync-parallel.mjs +10 -4
- package/dist/_chunks/sync-parallel.mjs.map +1 -1
- package/dist/_chunks/utils.d.mts +54 -1
- package/dist/_chunks/utils.d.mts.map +1 -1
- package/dist/_chunks/yaml.mjs +24 -0
- package/dist/_chunks/yaml.mjs.map +1 -0
- package/dist/agent/index.d.mts +11 -1
- package/dist/agent/index.d.mts.map +1 -1
- package/dist/agent/index.mjs +2 -2
- package/dist/cli.mjs +143 -22
- package/dist/cli.mjs.map +1 -1
- package/dist/index.mjs +1 -0
- package/dist/sources/index.d.mts +2 -2
- package/dist/sources/index.mjs +3 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -34,22 +34,23 @@ Skilld leverages maintainers existing effort. Maintainers write great docs for u
|
|
|
34
34
|
|
|
35
35
|
## Features
|
|
36
36
|
|
|
37
|
-
- 🌍 **
|
|
38
|
-
-
|
|
39
|
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
37
|
+
- 🌍 **Any Source: Opt-in** - Any NPM dependency or GitHub source, docs auto-resolved
|
|
38
|
+
- 📦 **Bleeding Edge Context** - Latest issues, discussions, and releases synced on
|
|
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
|
|
41
|
+
- 🔍 **Semantic Search** - Query indexed docs across all skills via [retriv](https://github.com/harlan-zw/retriv) embeddings
|
|
42
|
+
- 🎯 **Safe & Versioned** - Prompt injection sanitization, version-aware caching, auto-updates on new releases
|
|
43
|
+
- 🤝 **Ecosystem** - Compatible with [`npx skills`](https://skills.sh/) and [skills-npm](https://github.com/antfu/skills-npm)
|
|
43
44
|
|
|
44
45
|
## Quick Start
|
|
45
46
|
|
|
46
47
|
Run skilld in a project to generate skills for your dependencies through a simple interactive wizard:
|
|
47
48
|
|
|
48
49
|
```bash
|
|
49
|
-
npx skilld
|
|
50
|
+
npx -y skilld
|
|
50
51
|
```
|
|
51
52
|
|
|
52
|
-
If you need to re-configure skilld, just run `npx skilld config` to update your agent, model, or preferences.
|
|
53
|
+
If you need to re-configure skilld, just run `npx -y skilld config` to update your agent, model, or preferences.
|
|
53
54
|
|
|
54
55
|
### Tips
|
|
55
56
|
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as sanitizeMarkdown, t as repairMarkdown } from "./sanitize2.mjs";
|
|
2
|
+
import { _ as writeSections, h as readCachedSection } from "./storage.mjs";
|
|
3
|
+
import { t as yamlEscape } from "./yaml.mjs";
|
|
2
4
|
import { createRequire } from "node:module";
|
|
3
5
|
import { homedir } from "node:os";
|
|
4
|
-
import { dirname, join } from "pathe";
|
|
5
|
-
import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, unlinkSync, writeFileSync } from "node:fs";
|
|
6
|
+
import { dirname, join, relative } from "pathe";
|
|
7
|
+
import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
|
|
6
8
|
import { exec, spawn, spawnSync } from "node:child_process";
|
|
7
9
|
import { globby } from "globby";
|
|
8
10
|
import { findDynamicImports, findStaticImports } from "mlly";
|
|
@@ -695,16 +697,24 @@ function generateImportantBlock({ packageName, hasIssues, hasDiscussions, hasRel
|
|
|
695
697
|
if (hasDiscussions) rows.push(["Discussions", `\`${skillDir}/.skilld/discussions/\``]);
|
|
696
698
|
if (hasChangelog) rows.push(["Changelog", `\`${skillDir}/.skilld/pkg/${hasChangelog}\``]);
|
|
697
699
|
if (hasReleases) rows.push(["Releases", `\`${skillDir}/.skilld/releases/\``]);
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
| Resource | Command |
|
|
701
|
-
|----------|---------|
|
|
702
|
-
| Search all | \`Bash 'npx skilld search "<query>" -p ${packageName}'\` |
|
|
703
|
-
${[
|
|
700
|
+
const table = [
|
|
704
701
|
"| Resource | Path |",
|
|
705
702
|
"|----------|------|",
|
|
706
703
|
...rows.map(([desc, cmd]) => `| ${desc} | ${cmd} |`)
|
|
707
|
-
].join("\n")
|
|
704
|
+
].join("\n");
|
|
705
|
+
return `**IMPORTANT:** Use these references
|
|
706
|
+
|
|
707
|
+
## Search
|
|
708
|
+
|
|
709
|
+
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.
|
|
710
|
+
|
|
711
|
+
\`\`\`bash
|
|
712
|
+
npx -y skilld search "<query>" -p ${packageName}
|
|
713
|
+
${hasIssues ? `npx -y skilld search "issues:<query>" -p ${packageName}\n` : ""}${hasReleases ? `npx -y skilld search "releases:<query>" -p ${packageName}\n` : ""}\`\`\`
|
|
714
|
+
|
|
715
|
+
Filters: \`docs:\`, \`issues:\`, \`releases:\` prefix narrows by source type.
|
|
716
|
+
|
|
717
|
+
${table}`;
|
|
708
718
|
}
|
|
709
719
|
function buildPreamble(opts) {
|
|
710
720
|
const { packageName, skillDir, hasIssues, hasDiscussions, hasReleases, hasChangelog, docFiles, docsType = "docs", hasShippedDocs = false, versionContext } = opts;
|
|
@@ -803,27 +813,6 @@ function buildAllSectionPrompts(opts) {
|
|
|
803
813
|
}
|
|
804
814
|
return result;
|
|
805
815
|
}
|
|
806
|
-
const NEEDS_QUOTING = /[:"'\\\n\r\t#{}[\],&*!|>%@`]/;
|
|
807
|
-
function yamlEscape(value) {
|
|
808
|
-
if (!NEEDS_QUOTING.test(value)) return value;
|
|
809
|
-
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t")}"`;
|
|
810
|
-
}
|
|
811
|
-
function yamlUnescape(raw) {
|
|
812
|
-
const trimmed = raw.trim();
|
|
813
|
-
if (!trimmed) return "";
|
|
814
|
-
if (trimmed.startsWith("\"") && trimmed.endsWith("\"")) return trimmed.slice(1, -1).replace(/\\n/g, "\n").replace(/\\r/g, "\r").replace(/\\t/g, " ").replace(/\\"/g, "\"").replace(/\\\\/g, "\\");
|
|
815
|
-
if (trimmed.startsWith("'") && trimmed.endsWith("'")) return trimmed.slice(1, -1);
|
|
816
|
-
return trimmed;
|
|
817
|
-
}
|
|
818
|
-
function yamlParseKV(line) {
|
|
819
|
-
const trimmed = line.trim();
|
|
820
|
-
const colonIdx = trimmed.indexOf(":");
|
|
821
|
-
if (colonIdx === -1) return null;
|
|
822
|
-
const key = trimmed.slice(0, colonIdx).trim();
|
|
823
|
-
const rawValue = trimmed.slice(colonIdx + 1);
|
|
824
|
-
if (!key) return null;
|
|
825
|
-
return [key, yamlUnescape(rawValue)];
|
|
826
|
-
}
|
|
827
816
|
function sanitizeName(name) {
|
|
828
817
|
return name.toLowerCase().replace(/[^a-z0-9._]+/g, "-").replace(/^[.\-]+|[.\-]+$/g, "").slice(0, 255) || "unnamed-skill";
|
|
829
818
|
}
|
|
@@ -857,6 +846,32 @@ function installSkillForAgents(skillName, skillContent, options = {}) {
|
|
|
857
846
|
paths
|
|
858
847
|
};
|
|
859
848
|
}
|
|
849
|
+
function linkSkillToAgents(skillName, sharedDir, cwd) {
|
|
850
|
+
for (const [, agent] of Object.entries(targets)) {
|
|
851
|
+
const agentSkillsDir = join(cwd, agent.skillsDir);
|
|
852
|
+
if (!existsSync(join(cwd, agent.skillsDir.split("/")[0]))) continue;
|
|
853
|
+
const target = join(agentSkillsDir, skillName);
|
|
854
|
+
let isSymlink = false;
|
|
855
|
+
let targetExists = false;
|
|
856
|
+
try {
|
|
857
|
+
const stat = lstatSync(target);
|
|
858
|
+
targetExists = true;
|
|
859
|
+
isSymlink = stat.isSymbolicLink();
|
|
860
|
+
} catch {}
|
|
861
|
+
if (targetExists && !isSymlink) continue;
|
|
862
|
+
if (isSymlink) unlinkSync(target);
|
|
863
|
+
mkdirSync(agentSkillsDir, { recursive: true });
|
|
864
|
+
symlinkSync(relative(agentSkillsDir, join(sharedDir, skillName)), target);
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
function unlinkSkillFromAgents(skillName, cwd) {
|
|
868
|
+
for (const [, agent] of Object.entries(targets)) {
|
|
869
|
+
const target = join(cwd, agent.skillsDir, skillName);
|
|
870
|
+
try {
|
|
871
|
+
if (lstatSync(target).isSymbolicLink()) unlinkSync(target);
|
|
872
|
+
} catch {}
|
|
873
|
+
}
|
|
874
|
+
}
|
|
860
875
|
const FILE_PATTERN_MAP = {
|
|
861
876
|
"vue": ["*.vue"],
|
|
862
877
|
"svelte": ["*.svelte"],
|
|
@@ -1018,12 +1033,12 @@ function generateFrontmatter({ name, version, description: pkgDescription, globs
|
|
|
1018
1033
|
return lines.join("\n");
|
|
1019
1034
|
}
|
|
1020
1035
|
function generateSearchBlock(name, hasIssues, hasReleases) {
|
|
1021
|
-
const examples = [`npx skilld search "query" -p ${name}`];
|
|
1022
|
-
if (hasIssues) examples.push(`npx skilld search "issues:error handling" -p ${name}`);
|
|
1023
|
-
if (hasReleases) examples.push(`npx skilld search "releases:deprecated" -p ${name}`);
|
|
1036
|
+
const examples = [`npx -y skilld search "query" -p ${name}`];
|
|
1037
|
+
if (hasIssues) examples.push(`npx -y skilld search "issues:error handling" -p ${name}`);
|
|
1038
|
+
if (hasReleases) examples.push(`npx -y skilld search "releases:deprecated" -p ${name}`);
|
|
1024
1039
|
return `## Search
|
|
1025
1040
|
|
|
1026
|
-
Use \`npx skilld search\` instead of grepping \`.skilld/\` directories — hybrid semantic + keyword search across all indexed docs, issues, and releases.
|
|
1041
|
+
Use \`npx -y skilld search\` instead of grepping \`.skilld/\` directories — hybrid semantic + keyword search across all indexed docs, issues, and releases.
|
|
1027
1042
|
|
|
1028
1043
|
\`\`\`bash
|
|
1029
1044
|
${examples.join("\n")}
|
|
@@ -1832,6 +1847,6 @@ function isNodeBuiltin(pkg) {
|
|
|
1832
1847
|
const base = pkg.startsWith("node:") ? pkg.slice(5) : pkg;
|
|
1833
1848
|
return NODE_BUILTINS.has(base.split("/")[0]);
|
|
1834
1849
|
}
|
|
1835
|
-
export {
|
|
1850
|
+
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 };
|
|
1836
1851
|
|
|
1837
1852
|
//# sourceMappingURL=detect-imports.mjs.map
|