skills 1.4.6 → 1.4.7
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 +5 -1
- package/dist/cli.mjs +116 -37
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
The CLI for the open agent skills ecosystem.
|
|
4
4
|
|
|
5
5
|
<!-- agent-list:start -->
|
|
6
|
-
Supports **OpenCode**, **Claude Code**, **Codex**, **Cursor**, and [
|
|
6
|
+
Supports **OpenCode**, **Claude Code**, **Codex**, **Cursor**, and [41 more](#available-agents).
|
|
7
7
|
<!-- agent-list:end -->
|
|
8
8
|
|
|
9
9
|
## Install a Skill
|
|
@@ -212,6 +212,7 @@ Skills can be installed to any of these agents:
|
|
|
212
212
|
| Amp, Kimi Code CLI, Replit, Universal | `amp`, `kimi-cli`, `replit`, `universal` | `.agents/skills/` | `~/.config/agents/skills/` |
|
|
213
213
|
| Antigravity | `antigravity` | `.agents/skills/` | `~/.gemini/antigravity/skills/` |
|
|
214
214
|
| Augment | `augment` | `.augment/skills/` | `~/.augment/skills/` |
|
|
215
|
+
| IBM Bob | `bob` | `.bob/skills/` | `~/.bob/skills/` |
|
|
215
216
|
| Claude Code | `claude-code` | `.claude/skills/` | `~/.claude/skills/` |
|
|
216
217
|
| OpenClaw | `openclaw` | `skills/` | `~/.openclaw/skills/` |
|
|
217
218
|
| Cline, Warp | `cline`, `warp` | `.agents/skills/` | `~/.agents/skills/` |
|
|
@@ -224,6 +225,7 @@ Skills can be installed to any of these agents:
|
|
|
224
225
|
| Cursor | `cursor` | `.agents/skills/` | `~/.cursor/skills/` |
|
|
225
226
|
| Deep Agents | `deepagents` | `.agents/skills/` | `~/.deepagents/agent/skills/` |
|
|
226
227
|
| Droid | `droid` | `.factory/skills/` | `~/.factory/skills/` |
|
|
228
|
+
| Firebender | `firebender` | `.agents/skills/` | `~/.firebender/skills/` |
|
|
227
229
|
| Gemini CLI | `gemini-cli` | `.agents/skills/` | `~/.gemini/skills/` |
|
|
228
230
|
| GitHub Copilot | `github-copilot` | `.agents/skills/` | `~/.copilot/skills/` |
|
|
229
231
|
| Goose | `goose` | `.goose/skills/` | `~/.config/goose/skills/` |
|
|
@@ -319,6 +321,7 @@ The CLI searches for skills in these locations within a repository:
|
|
|
319
321
|
- `skills/.system/`
|
|
320
322
|
- `.agents/skills/`
|
|
321
323
|
- `.augment/skills/`
|
|
324
|
+
- `.bob/skills/`
|
|
322
325
|
- `.claude/skills/`
|
|
323
326
|
- `./skills/`
|
|
324
327
|
- `.codebuddy/skills/`
|
|
@@ -433,6 +436,7 @@ Telemetry is automatically disabled in CI environments.
|
|
|
433
436
|
- [Command Code Skills Documentation](https://commandcode.ai/docs/skills)
|
|
434
437
|
- [Crush Skills Documentation](https://github.com/charmbracelet/crush?tab=readme-ov-file#agent-skills)
|
|
435
438
|
- [Cursor Skills Documentation](https://cursor.com/docs/context/skills)
|
|
439
|
+
- [Firebender Skills Documentation](https://docs.firebender.com/multi-agent/skills)
|
|
436
440
|
- [Gemini CLI Skills Documentation](https://geminicli.com/docs/cli/skills/)
|
|
437
441
|
- [GitHub Copilot Agent Skills](https://docs.github.com/en/copilot/concepts/agents/about-agent-skills)
|
|
438
442
|
- [iFlow CLI Skills Documentation](https://platform.iflow.cn/en/cli/examples/skill)
|
package/dist/cli.mjs
CHANGED
|
@@ -62,13 +62,48 @@ function isLocalPath(input) {
|
|
|
62
62
|
return isAbsolute(input) || input.startsWith("./") || input.startsWith("../") || input === "." || input === ".." || /^[a-zA-Z]:[/\\]/.test(input);
|
|
63
63
|
}
|
|
64
64
|
const SOURCE_ALIASES = { "coinbase/agentWallet": "coinbase/agentic-wallet-skills" };
|
|
65
|
+
function decodeFragmentValue(value) {
|
|
66
|
+
try {
|
|
67
|
+
return decodeURIComponent(value);
|
|
68
|
+
} catch {
|
|
69
|
+
return value;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function looksLikeGitSource(input) {
|
|
73
|
+
if (input.startsWith("github:") || input.startsWith("gitlab:") || input.startsWith("git@")) return true;
|
|
74
|
+
if (input.startsWith("http://") || input.startsWith("https://")) try {
|
|
75
|
+
const parsed = new URL(input);
|
|
76
|
+
const pathname = parsed.pathname;
|
|
77
|
+
if (parsed.hostname === "github.com") return /^\/[^/]+\/[^/]+(?:\.git)?(?:\/tree\/[^/]+(?:\/.*)?)?\/?$/.test(pathname);
|
|
78
|
+
if (parsed.hostname === "gitlab.com") return /^\/.+?\/[^/]+(?:\.git)?(?:\/-\/tree\/[^/]+(?:\/.*)?)?\/?$/.test(pathname);
|
|
79
|
+
} catch {}
|
|
80
|
+
if (/^https?:\/\/.+\.git(?:$|[/?])/i.test(input)) return true;
|
|
81
|
+
return !input.includes(":") && !input.startsWith(".") && !input.startsWith("/") && /^([^/]+)\/([^/]+)(?:\/(.+)|@(.+))?$/.test(input);
|
|
82
|
+
}
|
|
83
|
+
function parseFragmentRef(input) {
|
|
84
|
+
const hashIndex = input.indexOf("#");
|
|
85
|
+
if (hashIndex < 0) return { inputWithoutFragment: input };
|
|
86
|
+
const inputWithoutFragment = input.slice(0, hashIndex);
|
|
87
|
+
const fragment = input.slice(hashIndex + 1);
|
|
88
|
+
if (!fragment || !looksLikeGitSource(inputWithoutFragment)) return { inputWithoutFragment: input };
|
|
89
|
+
const atIndex = fragment.indexOf("@");
|
|
90
|
+
if (atIndex === -1) return {
|
|
91
|
+
inputWithoutFragment,
|
|
92
|
+
ref: decodeFragmentValue(fragment)
|
|
93
|
+
};
|
|
94
|
+
const ref = fragment.slice(0, atIndex);
|
|
95
|
+
const skillFilter = fragment.slice(atIndex + 1);
|
|
96
|
+
return {
|
|
97
|
+
inputWithoutFragment,
|
|
98
|
+
ref: ref ? decodeFragmentValue(ref) : void 0,
|
|
99
|
+
skillFilter: skillFilter ? decodeFragmentValue(skillFilter) : void 0
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function appendFragmentRef(input, ref, skillFilter) {
|
|
103
|
+
if (!ref) return input;
|
|
104
|
+
return `${input}#${ref}${skillFilter ? `@${skillFilter}` : ""}`;
|
|
105
|
+
}
|
|
65
106
|
function parseSource(input) {
|
|
66
|
-
const alias = SOURCE_ALIASES[input];
|
|
67
|
-
if (alias) input = alias;
|
|
68
|
-
const githubPrefixMatch = input.match(/^github:(.+)$/);
|
|
69
|
-
if (githubPrefixMatch) return parseSource(githubPrefixMatch[1]);
|
|
70
|
-
const gitlabPrefixMatch = input.match(/^gitlab:(.+)$/);
|
|
71
|
-
if (gitlabPrefixMatch) return parseSource(`https://gitlab.com/${gitlabPrefixMatch[1]}`);
|
|
72
107
|
if (isLocalPath(input)) {
|
|
73
108
|
const resolvedPath = resolve(input);
|
|
74
109
|
return {
|
|
@@ -77,13 +112,21 @@ function parseSource(input) {
|
|
|
77
112
|
localPath: resolvedPath
|
|
78
113
|
};
|
|
79
114
|
}
|
|
115
|
+
const { inputWithoutFragment, ref: fragmentRef, skillFilter: fragmentSkillFilter } = parseFragmentRef(input);
|
|
116
|
+
input = inputWithoutFragment;
|
|
117
|
+
const alias = SOURCE_ALIASES[input];
|
|
118
|
+
if (alias) input = alias;
|
|
119
|
+
const githubPrefixMatch = input.match(/^github:(.+)$/);
|
|
120
|
+
if (githubPrefixMatch) return parseSource(appendFragmentRef(githubPrefixMatch[1], fragmentRef, fragmentSkillFilter));
|
|
121
|
+
const gitlabPrefixMatch = input.match(/^gitlab:(.+)$/);
|
|
122
|
+
if (gitlabPrefixMatch) return parseSource(appendFragmentRef(`https://gitlab.com/${gitlabPrefixMatch[1]}`, fragmentRef, fragmentSkillFilter));
|
|
80
123
|
const githubTreeWithPathMatch = input.match(/github\.com\/([^/]+)\/([^/]+)\/tree\/([^/]+)\/(.+)/);
|
|
81
124
|
if (githubTreeWithPathMatch) {
|
|
82
125
|
const [, owner, repo, ref, subpath] = githubTreeWithPathMatch;
|
|
83
126
|
return {
|
|
84
127
|
type: "github",
|
|
85
128
|
url: `https://github.com/${owner}/${repo}.git`,
|
|
86
|
-
ref,
|
|
129
|
+
ref: ref || fragmentRef,
|
|
87
130
|
subpath: subpath ? sanitizeSubpath(subpath) : subpath
|
|
88
131
|
};
|
|
89
132
|
}
|
|
@@ -93,7 +136,7 @@ function parseSource(input) {
|
|
|
93
136
|
return {
|
|
94
137
|
type: "github",
|
|
95
138
|
url: `https://github.com/${owner}/${repo}.git`,
|
|
96
|
-
ref
|
|
139
|
+
ref: ref || fragmentRef
|
|
97
140
|
};
|
|
98
141
|
}
|
|
99
142
|
const githubRepoMatch = input.match(/github\.com\/([^/]+)\/([^/]+)/);
|
|
@@ -101,7 +144,8 @@ function parseSource(input) {
|
|
|
101
144
|
const [, owner, repo] = githubRepoMatch;
|
|
102
145
|
return {
|
|
103
146
|
type: "github",
|
|
104
|
-
url: `https://github.com/${owner}/${repo.replace(/\.git$/, "")}.git
|
|
147
|
+
url: `https://github.com/${owner}/${repo.replace(/\.git$/, "")}.git`,
|
|
148
|
+
...fragmentRef ? { ref: fragmentRef } : {}
|
|
105
149
|
};
|
|
106
150
|
}
|
|
107
151
|
const gitlabTreeWithPathMatch = input.match(/^(https?):\/\/([^/]+)\/(.+?)\/-\/tree\/([^/]+)\/(.+)/);
|
|
@@ -110,7 +154,7 @@ function parseSource(input) {
|
|
|
110
154
|
if (hostname !== "github.com" && repoPath) return {
|
|
111
155
|
type: "gitlab",
|
|
112
156
|
url: `${protocol}://${hostname}/${repoPath.replace(/\.git$/, "")}.git`,
|
|
113
|
-
ref,
|
|
157
|
+
ref: ref || fragmentRef,
|
|
114
158
|
subpath: subpath ? sanitizeSubpath(subpath) : subpath
|
|
115
159
|
};
|
|
116
160
|
}
|
|
@@ -120,7 +164,7 @@ function parseSource(input) {
|
|
|
120
164
|
if (hostname !== "github.com" && repoPath) return {
|
|
121
165
|
type: "gitlab",
|
|
122
166
|
url: `${protocol}://${hostname}/${repoPath.replace(/\.git$/, "")}.git`,
|
|
123
|
-
ref
|
|
167
|
+
ref: ref || fragmentRef
|
|
124
168
|
};
|
|
125
169
|
}
|
|
126
170
|
const gitlabRepoMatch = input.match(/gitlab\.com\/(.+?)(?:\.git)?\/?$/);
|
|
@@ -128,7 +172,8 @@ function parseSource(input) {
|
|
|
128
172
|
const repoPath = gitlabRepoMatch[1];
|
|
129
173
|
if (repoPath.includes("/")) return {
|
|
130
174
|
type: "gitlab",
|
|
131
|
-
url: `https://gitlab.com/${repoPath}.git
|
|
175
|
+
url: `https://gitlab.com/${repoPath}.git`,
|
|
176
|
+
...fragmentRef ? { ref: fragmentRef } : {}
|
|
132
177
|
};
|
|
133
178
|
}
|
|
134
179
|
const atSkillMatch = input.match(/^([^/]+)\/([^/@]+)@(.+)$/);
|
|
@@ -137,16 +182,19 @@ function parseSource(input) {
|
|
|
137
182
|
return {
|
|
138
183
|
type: "github",
|
|
139
184
|
url: `https://github.com/${owner}/${repo}.git`,
|
|
140
|
-
|
|
185
|
+
...fragmentRef ? { ref: fragmentRef } : {},
|
|
186
|
+
skillFilter: fragmentSkillFilter || skillFilter
|
|
141
187
|
};
|
|
142
188
|
}
|
|
143
|
-
const shorthandMatch = input.match(/^([^/]+)\/([^/]+)(?:\/(
|
|
189
|
+
const shorthandMatch = input.match(/^([^/]+)\/([^/]+)(?:\/(.+?))?\/?$/);
|
|
144
190
|
if (shorthandMatch && !input.includes(":") && !input.startsWith(".") && !input.startsWith("/")) {
|
|
145
191
|
const [, owner, repo, subpath] = shorthandMatch;
|
|
146
192
|
return {
|
|
147
193
|
type: "github",
|
|
148
194
|
url: `https://github.com/${owner}/${repo}.git`,
|
|
149
|
-
|
|
195
|
+
...fragmentRef ? { ref: fragmentRef } : {},
|
|
196
|
+
subpath: subpath ? sanitizeSubpath(subpath) : subpath,
|
|
197
|
+
...fragmentSkillFilter ? { skillFilter: fragmentSkillFilter } : {}
|
|
150
198
|
};
|
|
151
199
|
}
|
|
152
200
|
if (isWellKnownUrl(input)) return {
|
|
@@ -155,7 +203,8 @@ function parseSource(input) {
|
|
|
155
203
|
};
|
|
156
204
|
return {
|
|
157
205
|
type: "git",
|
|
158
|
-
url: input
|
|
206
|
+
url: input,
|
|
207
|
+
...fragmentRef ? { ref: fragmentRef } : {}
|
|
159
208
|
};
|
|
160
209
|
}
|
|
161
210
|
function isWellKnownUrl(input) {
|
|
@@ -634,6 +683,15 @@ const agents = {
|
|
|
634
683
|
return existsSync(join(home, ".augment"));
|
|
635
684
|
}
|
|
636
685
|
},
|
|
686
|
+
bob: {
|
|
687
|
+
name: "bob",
|
|
688
|
+
displayName: "IBM Bob",
|
|
689
|
+
skillsDir: ".bob/skills",
|
|
690
|
+
globalSkillsDir: join(home, ".bob/skills"),
|
|
691
|
+
detectInstalled: async () => {
|
|
692
|
+
return existsSync(join(home, ".bob"));
|
|
693
|
+
}
|
|
694
|
+
},
|
|
637
695
|
"claude-code": {
|
|
638
696
|
name: "claude-code",
|
|
639
697
|
displayName: "Claude Code",
|
|
@@ -742,6 +800,15 @@ const agents = {
|
|
|
742
800
|
return existsSync(join(home, ".factory"));
|
|
743
801
|
}
|
|
744
802
|
},
|
|
803
|
+
firebender: {
|
|
804
|
+
name: "firebender",
|
|
805
|
+
displayName: "Firebender",
|
|
806
|
+
skillsDir: ".agents/skills",
|
|
807
|
+
globalSkillsDir: join(home, ".firebender/skills"),
|
|
808
|
+
detectInstalled: async () => {
|
|
809
|
+
return existsSync(join(home, ".firebender"));
|
|
810
|
+
}
|
|
811
|
+
},
|
|
745
812
|
"gemini-cli": {
|
|
746
813
|
name: "gemini-cli",
|
|
747
814
|
displayName: "Gemini CLI",
|
|
@@ -1685,13 +1752,14 @@ function getGitHubToken() {
|
|
|
1685
1752
|
} catch {}
|
|
1686
1753
|
return null;
|
|
1687
1754
|
}
|
|
1688
|
-
async function fetchSkillFolderHash(ownerRepo, skillPath, token) {
|
|
1755
|
+
async function fetchSkillFolderHash(ownerRepo, skillPath, token, ref) {
|
|
1689
1756
|
let folderPath = skillPath.replace(/\\/g, "/");
|
|
1690
1757
|
if (folderPath.endsWith("/SKILL.md")) folderPath = folderPath.slice(0, -9);
|
|
1691
1758
|
else if (folderPath.endsWith("SKILL.md")) folderPath = folderPath.slice(0, -8);
|
|
1692
1759
|
if (folderPath.endsWith("/")) folderPath = folderPath.slice(0, -1);
|
|
1693
|
-
|
|
1694
|
-
|
|
1760
|
+
const branches = ref ? [ref] : ["main", "master"];
|
|
1761
|
+
for (const branch of branches) try {
|
|
1762
|
+
const url = `https://api.github.com/repos/${ownerRepo}/git/trees/${encodeURIComponent(branch)}?recursive=1`;
|
|
1695
1763
|
const headers = {
|
|
1696
1764
|
Accept: "application/vnd.github.v3+json",
|
|
1697
1765
|
"User-Agent": "skills-cli"
|
|
@@ -1822,7 +1890,7 @@ function createEmptyLocalLock() {
|
|
|
1822
1890
|
skills: {}
|
|
1823
1891
|
};
|
|
1824
1892
|
}
|
|
1825
|
-
var version$1 = "1.4.
|
|
1893
|
+
var version$1 = "1.4.7";
|
|
1826
1894
|
const isCancelled$1 = (value) => typeof value === "symbol";
|
|
1827
1895
|
async function isSourcePrivate(source) {
|
|
1828
1896
|
const ownerRepo = parseOwnerRepo(source);
|
|
@@ -2654,13 +2722,14 @@ async function runAdd(args, options = {}) {
|
|
|
2654
2722
|
let skillFolderHash = "";
|
|
2655
2723
|
const skillPathValue = skillFiles[skill.name];
|
|
2656
2724
|
if (parsed.type === "github" && skillPathValue) {
|
|
2657
|
-
const hash = await fetchSkillFolderHash(normalizedSource, skillPathValue, getGitHubToken());
|
|
2725
|
+
const hash = await fetchSkillFolderHash(normalizedSource, skillPathValue, getGitHubToken(), parsed.ref);
|
|
2658
2726
|
if (hash) skillFolderHash = hash;
|
|
2659
2727
|
}
|
|
2660
2728
|
await addSkillToLock(skill.name, {
|
|
2661
2729
|
source: lockSource || normalizedSource,
|
|
2662
2730
|
sourceType: parsed.type,
|
|
2663
2731
|
sourceUrl: parsed.url,
|
|
2732
|
+
ref: parsed.ref,
|
|
2664
2733
|
skillPath: skillPathValue,
|
|
2665
2734
|
skillFolderHash,
|
|
2666
2735
|
pluginName: skill.pluginName
|
|
@@ -2676,6 +2745,7 @@ async function runAdd(args, options = {}) {
|
|
|
2676
2745
|
const computedHash = await computeSkillFolderHash(skill.path);
|
|
2677
2746
|
await addSkillToLocalLock(skill.name, {
|
|
2678
2747
|
source: lockSource || parsed.url,
|
|
2748
|
+
ref: parsed.ref,
|
|
2679
2749
|
sourceType: parsed.type,
|
|
2680
2750
|
computedHash
|
|
2681
2751
|
}, cwd);
|
|
@@ -3366,9 +3436,10 @@ async function runInstallFromLock(args) {
|
|
|
3366
3436
|
nodeModuleSkills.push(skillName);
|
|
3367
3437
|
continue;
|
|
3368
3438
|
}
|
|
3369
|
-
const
|
|
3439
|
+
const installSource = entry.ref ? `${entry.source}#${entry.ref}` : entry.source;
|
|
3440
|
+
const existing = bySource.get(installSource);
|
|
3370
3441
|
if (existing) existing.skills.push(skillName);
|
|
3371
|
-
else bySource.set(
|
|
3442
|
+
else bySource.set(installSource, {
|
|
3372
3443
|
sourceType: entry.sourceType,
|
|
3373
3444
|
skills: [skillName]
|
|
3374
3445
|
});
|
|
@@ -3698,6 +3769,20 @@ function parseRemoveOptions(args) {
|
|
|
3698
3769
|
options
|
|
3699
3770
|
};
|
|
3700
3771
|
}
|
|
3772
|
+
function formatSourceInput(sourceUrl, ref) {
|
|
3773
|
+
if (!ref) return sourceUrl;
|
|
3774
|
+
return `${sourceUrl}#${ref}`;
|
|
3775
|
+
}
|
|
3776
|
+
function buildUpdateInstallSource(entry) {
|
|
3777
|
+
if (!entry.skillPath) return formatSourceInput(entry.sourceUrl, entry.ref);
|
|
3778
|
+
let skillFolder = entry.skillPath;
|
|
3779
|
+
if (skillFolder.endsWith("/SKILL.md")) skillFolder = skillFolder.slice(0, -9);
|
|
3780
|
+
else if (skillFolder.endsWith("SKILL.md")) skillFolder = skillFolder.slice(0, -8);
|
|
3781
|
+
if (skillFolder.endsWith("/")) skillFolder = skillFolder.slice(0, -1);
|
|
3782
|
+
let installSource = skillFolder ? `${entry.source}/${skillFolder}` : entry.source;
|
|
3783
|
+
if (entry.ref) installSource = `${installSource}#${entry.ref}`;
|
|
3784
|
+
return installSource;
|
|
3785
|
+
}
|
|
3701
3786
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
3702
3787
|
function getVersion() {
|
|
3703
3788
|
try {
|
|
@@ -3951,7 +4036,7 @@ function printSkippedSkills(skipped) {
|
|
|
3951
4036
|
console.log(`${DIM}${skipped.length} skill(s) cannot be checked automatically:${RESET}`);
|
|
3952
4037
|
for (const skill of skipped) {
|
|
3953
4038
|
console.log(` ${TEXT}•${RESET} ${skill.name} ${DIM}(${skill.reason})${RESET}`);
|
|
3954
|
-
console.log(` ${DIM}To update: ${TEXT}npx skills add ${skill.sourceUrl} -g -y${RESET}`);
|
|
4039
|
+
console.log(` ${DIM}To update: ${TEXT}npx skills add ${formatSourceInput(skill.sourceUrl, skill.ref)} -g -y${RESET}`);
|
|
3955
4040
|
}
|
|
3956
4041
|
}
|
|
3957
4042
|
async function runCheck(args = []) {
|
|
@@ -3974,7 +4059,8 @@ async function runCheck(args = []) {
|
|
|
3974
4059
|
skipped.push({
|
|
3975
4060
|
name: skillName,
|
|
3976
4061
|
reason: getSkipReason(entry),
|
|
3977
|
-
sourceUrl: entry.sourceUrl
|
|
4062
|
+
sourceUrl: entry.sourceUrl,
|
|
4063
|
+
ref: entry.ref
|
|
3978
4064
|
});
|
|
3979
4065
|
continue;
|
|
3980
4066
|
}
|
|
@@ -3995,7 +4081,7 @@ async function runCheck(args = []) {
|
|
|
3995
4081
|
const updates = [];
|
|
3996
4082
|
const errors = [];
|
|
3997
4083
|
for (const [source, skills] of skillsBySource) for (const { name, entry } of skills) try {
|
|
3998
|
-
const latestHash = await fetchSkillFolderHash(source, entry.skillPath, token);
|
|
4084
|
+
const latestHash = await fetchSkillFolderHash(source, entry.skillPath, token, entry.ref);
|
|
3999
4085
|
if (!latestHash) {
|
|
4000
4086
|
errors.push({
|
|
4001
4087
|
name,
|
|
@@ -4064,12 +4150,13 @@ async function runUpdate() {
|
|
|
4064
4150
|
skipped.push({
|
|
4065
4151
|
name: skillName,
|
|
4066
4152
|
reason: getSkipReason(entry),
|
|
4067
|
-
sourceUrl: entry.sourceUrl
|
|
4153
|
+
sourceUrl: entry.sourceUrl,
|
|
4154
|
+
ref: entry.ref
|
|
4068
4155
|
});
|
|
4069
4156
|
continue;
|
|
4070
4157
|
}
|
|
4071
4158
|
try {
|
|
4072
|
-
const latestHash = await fetchSkillFolderHash(entry.source, entry.skillPath, token);
|
|
4159
|
+
const latestHash = await fetchSkillFolderHash(entry.source, entry.skillPath, token, entry.ref);
|
|
4073
4160
|
if (latestHash && latestHash !== entry.skillFolderHash) updates.push({
|
|
4074
4161
|
name: skillName,
|
|
4075
4162
|
source: entry.source,
|
|
@@ -4093,15 +4180,7 @@ async function runUpdate() {
|
|
|
4093
4180
|
let failCount = 0;
|
|
4094
4181
|
for (const update of updates) {
|
|
4095
4182
|
console.log(`${TEXT}Updating ${update.name}...${RESET}`);
|
|
4096
|
-
|
|
4097
|
-
if (update.entry.skillPath) {
|
|
4098
|
-
let skillFolder = update.entry.skillPath;
|
|
4099
|
-
if (skillFolder.endsWith("/SKILL.md")) skillFolder = skillFolder.slice(0, -9);
|
|
4100
|
-
else if (skillFolder.endsWith("SKILL.md")) skillFolder = skillFolder.slice(0, -8);
|
|
4101
|
-
if (skillFolder.endsWith("/")) skillFolder = skillFolder.slice(0, -1);
|
|
4102
|
-
installUrl = update.entry.sourceUrl.replace(/\.git$/, "").replace(/\/$/, "");
|
|
4103
|
-
installUrl = `${installUrl}/tree/main/${skillFolder}`;
|
|
4104
|
-
}
|
|
4183
|
+
const installUrl = buildUpdateInstallSource(update.entry);
|
|
4105
4184
|
const cliEntry = join(__dirname, "..", "bin", "cli.mjs");
|
|
4106
4185
|
if (!existsSync(cliEntry)) {
|
|
4107
4186
|
failCount++;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skills",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.7",
|
|
4
4
|
"description": "The open agent skills ecosystem",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"amp",
|
|
40
40
|
"antigravity",
|
|
41
41
|
"augment",
|
|
42
|
+
"bob",
|
|
42
43
|
"claude-code",
|
|
43
44
|
"openclaw",
|
|
44
45
|
"cline",
|
|
@@ -51,6 +52,7 @@
|
|
|
51
52
|
"cursor",
|
|
52
53
|
"deepagents",
|
|
53
54
|
"droid",
|
|
55
|
+
"firebender",
|
|
54
56
|
"gemini-cli",
|
|
55
57
|
"github-copilot",
|
|
56
58
|
"goose",
|