@safeskill/cli 0.2.0 → 0.2.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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.1
4
+
5
+ - Added Flocks agent support with `.flocks/plugins/skills` install paths.
6
+ - Added hub resolve fallback for new or unsupported agent-specific resolve requests.
7
+ - Fixed zip artifact extraction when packages contain explicit directory entries.
8
+
3
9
  ## 0.0.1
4
10
 
5
11
  - Renamed the published package and CLI command from `skills` to `safeskill`.
package/README.md CHANGED
@@ -6,7 +6,7 @@ The SafeSkill CLI for the open agent skills ecosystem.
6
6
 
7
7
  <!-- agent-list:start -->
8
8
 
9
- Supports **OpenCode**, **Claude Code**, **Codex**, **Cursor**, and [40 more](#available-agents).
9
+ Supports **OpenCode**, **Claude Code**, **Codex**, **Cursor**, and [41 more](#available-agents).
10
10
 
11
11
  <!-- agent-list:end -->
12
12
 
@@ -238,48 +238,49 @@ Skills can be installed to any of these agents:
238
238
 
239
239
  <!-- supported-agents:start -->
240
240
 
241
- | Agent | `--agent` | Project Path | Global Path |
242
- | ------------------------------------- | ---------------------------------------- | ---------------------- | ------------------------------- |
243
- | Amp, Kimi Code CLI, Replit, Universal | `amp`, `kimi-cli`, `replit`, `universal` | `.agents/skills/` | `~/.config/agents/skills/` |
244
- | Antigravity | `antigravity` | `.agents/skills/` | `~/.gemini/antigravity/skills/` |
245
- | Augment | `augment` | `.augment/skills/` | `~/.augment/skills/` |
246
- | Claude Code | `claude-code` | `.claude/skills/` | `~/.claude/skills/` |
247
- | OpenClaw | `openclaw` | `skills/` | `~/.openclaw/skills/` |
248
- | Cline, Warp | `cline`, `warp` | `.agents/skills/` | `~/.agents/skills/` |
249
- | CodeBuddy | `codebuddy` | `.codebuddy/skills/` | `~/.codebuddy/skills/` |
250
- | Codex | `codex` | `.agents/skills/` | `~/.codex/skills/` |
251
- | Command Code | `command-code` | `.commandcode/skills/` | `~/.commandcode/skills/` |
252
- | Continue | `continue` | `.continue/skills/` | `~/.continue/skills/` |
253
- | Cortex Code | `cortex` | `.cortex/skills/` | `~/.snowflake/cortex/skills/` |
254
- | Crush | `crush` | `.crush/skills/` | `~/.config/crush/skills/` |
255
- | Cursor | `cursor` | `.agents/skills/` | `~/.cursor/skills/` |
256
- | Deep Agents | `deepagents` | `.agents/skills/` | `~/.deepagents/agent/skills/` |
257
- | Droid | `droid` | `.factory/skills/` | `~/.factory/skills/` |
258
- | Firebender | `firebender` | `.agents/skills/` | `~/.firebender/skills/` |
259
- | Gemini CLI | `gemini-cli` | `.agents/skills/` | `~/.gemini/skills/` |
260
- | GitHub Copilot | `github-copilot` | `.agents/skills/` | `~/.copilot/skills/` |
261
- | Goose | `goose` | `.goose/skills/` | `~/.config/goose/skills/` |
262
- | Junie | `junie` | `.junie/skills/` | `~/.junie/skills/` |
263
- | iFlow CLI | `iflow-cli` | `.iflow/skills/` | `~/.iflow/skills/` |
264
- | Kilo Code | `kilo` | `.kilocode/skills/` | `~/.kilocode/skills/` |
265
- | Kiro CLI | `kiro-cli` | `.kiro/skills/` | `~/.kiro/skills/` |
266
- | Kode | `kode` | `.kode/skills/` | `~/.kode/skills/` |
267
- | MCPJam | `mcpjam` | `.mcpjam/skills/` | `~/.mcpjam/skills/` |
268
- | Mistral Vibe | `mistral-vibe` | `.vibe/skills/` | `~/.vibe/skills/` |
269
- | Mux | `mux` | `.mux/skills/` | `~/.mux/skills/` |
270
- | OpenCode | `opencode` | `.agents/skills/` | `~/.config/opencode/skills/` |
271
- | OpenHands | `openhands` | `.openhands/skills/` | `~/.openhands/skills/` |
272
- | Pi | `pi` | `.pi/skills/` | `~/.pi/agent/skills/` |
273
- | Qoder | `qoder` | `.qoder/skills/` | `~/.qoder/skills/` |
274
- | Qwen Code | `qwen-code` | `.qwen/skills/` | `~/.qwen/skills/` |
275
- | Roo Code | `roo` | `.roo/skills/` | `~/.roo/skills/` |
276
- | Trae | `trae` | `.trae/skills/` | `~/.trae/skills/` |
277
- | Trae CN | `trae-cn` | `.trae/skills/` | `~/.trae-cn/skills/` |
278
- | Windsurf | `windsurf` | `.windsurf/skills/` | `~/.codeium/windsurf/skills/` |
279
- | Zencoder | `zencoder` | `.zencoder/skills/` | `~/.zencoder/skills/` |
280
- | Neovate | `neovate` | `.neovate/skills/` | `~/.neovate/skills/` |
281
- | Pochi | `pochi` | `.pochi/skills/` | `~/.pochi/skills/` |
282
- | AdaL | `adal` | `.adal/skills/` | `~/.adal/skills/` |
241
+ | Agent | `--agent` | Project Path | Global Path |
242
+ | ------------------------------------- | ---------------------------------------- | ------------------------- | ---------------------------------- |
243
+ | Amp, Kimi Code CLI, Replit, Universal | `amp`, `kimi-cli`, `replit`, `universal` | `.agents/skills/` | `~/.config/agents/skills/` |
244
+ | Antigravity | `antigravity` | `.agents/skills/` | `~/.gemini/antigravity/skills/` |
245
+ | Augment | `augment` | `.augment/skills/` | `~/.augment/skills/` |
246
+ | Claude Code | `claude-code` | `.claude/skills/` | `~/.claude/skills/` |
247
+ | OpenClaw | `openclaw` | `skills/` | `~/.openclaw/skills/` |
248
+ | Cline, Warp | `cline`, `warp` | `.agents/skills/` | `~/.agents/skills/` |
249
+ | CodeBuddy | `codebuddy` | `.codebuddy/skills/` | `~/.codebuddy/skills/` |
250
+ | Codex | `codex` | `.agents/skills/` | `~/.codex/skills/` |
251
+ | Command Code | `command-code` | `.commandcode/skills/` | `~/.commandcode/skills/` |
252
+ | Continue | `continue` | `.continue/skills/` | `~/.continue/skills/` |
253
+ | Cortex Code | `cortex` | `.cortex/skills/` | `~/.snowflake/cortex/skills/` |
254
+ | Crush | `crush` | `.crush/skills/` | `~/.config/crush/skills/` |
255
+ | Cursor | `cursor` | `.agents/skills/` | `~/.cursor/skills/` |
256
+ | Deep Agents | `deepagents` | `.agents/skills/` | `~/.deepagents/agent/skills/` |
257
+ | Droid | `droid` | `.factory/skills/` | `~/.factory/skills/` |
258
+ | Firebender | `firebender` | `.agents/skills/` | `~/.firebender/skills/` |
259
+ | Flocks | `flocks` | `.flocks/plugins/skills/` | `~/.flocks/plugins/skills/` |
260
+ | Gemini CLI | `gemini-cli` | `.agents/skills/` | `~/.gemini/skills/` |
261
+ | GitHub Copilot | `github-copilot` | `.agents/skills/` | `~/.copilot/skills/` |
262
+ | Goose | `goose` | `.goose/skills/` | `~/.config/goose/skills/` |
263
+ | Junie | `junie` | `.junie/skills/` | `~/.junie/skills/` |
264
+ | iFlow CLI | `iflow-cli` | `.iflow/skills/` | `~/.iflow/skills/` |
265
+ | Kilo Code | `kilo` | `.kilocode/skills/` | `~/.kilocode/skills/` |
266
+ | Kiro CLI | `kiro-cli` | `.kiro/skills/` | `~/.kiro/skills/` |
267
+ | Kode | `kode` | `.kode/skills/` | `~/.kode/skills/` |
268
+ | MCPJam | `mcpjam` | `.mcpjam/skills/` | `~/.mcpjam/skills/` |
269
+ | Mistral Vibe | `mistral-vibe` | `.vibe/skills/` | `~/.vibe/skills/` |
270
+ | Mux | `mux` | `.mux/skills/` | `~/.mux/skills/` |
271
+ | OpenCode | `opencode` | `.agents/skills/` | `~/.config/opencode/skills/` |
272
+ | OpenHands | `openhands` | `.openhands/skills/` | `~/.openhands/skills/` |
273
+ | Pi | `pi` | `.pi/skills/` | `~/.pi/agent/skills/` |
274
+ | Qoder | `qoder` | `.qoder/skills/` | `~/.qoder/skills/` |
275
+ | Qwen Code | `qwen-code` | `.qwen/skills/` | `~/.qwen/skills/` |
276
+ | Roo Code | `roo` | `.roo/skills/` | `~/.roo/skills/` |
277
+ | Trae | `trae` | `.trae/skills/` | `~/.trae/skills/` |
278
+ | Trae CN | `trae-cn` | `.trae/skills/` | `~/.trae-cn/skills/` |
279
+ | Windsurf | `windsurf` | `.windsurf/skills/` | `~/.codeium/windsurf/skills/` |
280
+ | Zencoder | `zencoder` | `.zencoder/skills/` | `~/.zencoder/skills/` |
281
+ | Neovate | `neovate` | `.neovate/skills/` | `~/.neovate/skills/` |
282
+ | Pochi | `pochi` | `.pochi/skills/` | `~/.pochi/skills/` |
283
+ | AdaL | `adal` | `.adal/skills/` | `~/.adal/skills/` |
283
284
 
284
285
  <!-- supported-agents:end -->
285
286
 
@@ -361,6 +362,7 @@ The CLI searches for skills in these locations within a repository:
361
362
  - `.cortex/skills/`
362
363
  - `.crush/skills/`
363
364
  - `.factory/skills/`
365
+ - `.flocks/plugins/skills/`
364
366
  - `.goose/skills/`
365
367
  - `.junie/skills/`
366
368
  - `.iflow/skills/`
@@ -381,6 +383,7 @@ The CLI searches for skills in these locations within a repository:
381
383
  - `.neovate/skills/`
382
384
  - `.pochi/skills/`
383
385
  - `.adal/skills/`
386
+
384
387
  <!-- skill-discovery:end -->
385
388
 
386
389
  ### Plugin Manifest Discovery
package/dist/cli.mjs CHANGED
@@ -607,9 +607,7 @@ async function extractDownloadedArtifact(destination, fileName, bytes) {
607
607
  import_yauzl.open(tempZipPath, {
608
608
  lazyEntries: true,
609
609
  strictFileNames: false,
610
- decodeStrings: true,
611
- encoding,
612
- validateEntryNames: false
610
+ decodeStrings: true
613
611
  }, (err, zipfile) => {
614
612
  if (err) {
615
613
  reject(err);
@@ -617,16 +615,22 @@ async function extractDownloadedArtifact(destination, fileName, bytes) {
617
615
  }
618
616
  const processedFiles = /* @__PURE__ */ new Set();
619
617
  zipfile.on("entry", (entry) => {
620
- if (entry.isDirectory) {
621
- zipfile.readEntry();
622
- return;
623
- }
624
- let fileName = entry.fileName;
625
- fileName = fileName.replace(/[^\w\-._/\\]/g, (char) => {
618
+ let fileName = entry.fileName.replace(/\\/g, "/");
619
+ const isDirectoryEntry = fileName.endsWith("/");
620
+ fileName = fileName.replace(/[^\w\-._/]/g, (char) => {
626
621
  const code = char.charCodeAt(0);
627
622
  if (code < 32 || code > 126) return "_";
628
623
  return char;
629
624
  });
625
+ if (isDirectoryEntry) {
626
+ const directoryName = fileName.replace(/\/+$/, "");
627
+ if (!directoryName) {
628
+ zipfile.readEntry();
629
+ return;
630
+ }
631
+ mkdir(join(destination, directoryName), { recursive: true }).then(() => zipfile.readEntry()).catch(reject);
632
+ return;
633
+ }
630
634
  if (processedFiles.has(fileName)) {
631
635
  zipfile.readEntry();
632
636
  return;
@@ -720,14 +724,19 @@ async function searchSkillsCatalog(query, limit = 10) {
720
724
  }
721
725
  }
722
726
  async function resolveHubSkill(source, agent) {
723
- const baseUrl = await getSafeSkillHubBaseUrl();
724
- const response = await fetch(buildApiUrl(baseUrl, "/resolve"), {
727
+ const resolveUrl = buildApiUrl(await getSafeSkillHubBaseUrl(), "/resolve");
728
+ const resolveWithAgent = agent ? await fetch(resolveUrl, {
725
729
  method: "POST",
726
730
  headers: getHeaders({ "content-type": "application/json" }),
727
731
  body: JSON.stringify({
728
732
  source,
729
- ...agent ? { agent } : {}
733
+ agent
730
734
  })
735
+ }) : null;
736
+ const response = resolveWithAgent && resolveWithAgent.ok ? resolveWithAgent : await fetch(resolveUrl, {
737
+ method: "POST",
738
+ headers: getHeaders({ "content-type": "application/json" }),
739
+ body: JSON.stringify({ source })
731
740
  });
732
741
  if (!response.ok) throw new Error(`hub resolve failed: ${response.status}`);
733
742
  return readEnvelope(response);
@@ -1167,6 +1176,15 @@ const agents = {
1167
1176
  return existsSync(join(home, ".firebender"));
1168
1177
  }
1169
1178
  },
1179
+ flocks: {
1180
+ name: "flocks",
1181
+ displayName: "Flocks",
1182
+ skillsDir: ".flocks/plugins/skills",
1183
+ globalSkillsDir: join(home, ".flocks/plugins/skills"),
1184
+ detectInstalled: async () => {
1185
+ return existsSync(join(home, ".flocks"));
1186
+ }
1187
+ },
1170
1188
  "gemini-cli": {
1171
1189
  name: "gemini-cli",
1172
1190
  displayName: "Gemini CLI",
@@ -1440,6 +1458,7 @@ const SKILLS_SUBDIR = "skills";
1440
1458
  function sanitizeName(name) {
1441
1459
  const asciiName = name.toLowerCase().replace(/[^a-z0-9._]+/g, "-").replace(/^[.\-]+|[.\-]+$/g, "");
1442
1460
  if (asciiName.length === 0) {
1461
+ if (!/[\p{L}\p{N}]/u.test(name)) return "unnamed-skill";
1443
1462
  let hash = 0;
1444
1463
  for (let i = 0; i < name.length; i++) {
1445
1464
  const char = name.charCodeAt(i);
@@ -2259,7 +2278,7 @@ function createEmptyLocalLock() {
2259
2278
  skills: {}
2260
2279
  };
2261
2280
  }
2262
- var version$1 = "0.2.0";
2281
+ var version$1 = "0.2.1";
2263
2282
  const isCancelled$1 = (value) => typeof value === "symbol";
2264
2283
  async function isSourcePrivate(source) {
2265
2284
  const ownerRepo = parseOwnerRepo(source);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@safeskill/cli",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "SafeSkill CLI, for safe your skills",
5
5
  "type": "module",
6
6
  "bin": {
@@ -51,6 +51,7 @@
51
51
  "deepagents",
52
52
  "droid",
53
53
  "firebender",
54
+ "flocks",
54
55
  "gemini-cli",
55
56
  "github-copilot",
56
57
  "goose",