@iceinvein/agent-skills 0.1.4 → 0.1.5
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 +10 -2
- package/dist/cli/index.js +138 -21
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -9,14 +9,22 @@
|
|
|
9
9
|
|
|
10
10
|
Install agent skills into AI coding tools — Claude Code, Cursor, Codex, Gemini CLI.
|
|
11
11
|
|
|
12
|
+
## Prerequisites
|
|
13
|
+
|
|
14
|
+
[Bun](https://bun.sh) is required. Install it with:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
curl -fsSL https://bun.sh/install | bash
|
|
18
|
+
```
|
|
19
|
+
|
|
12
20
|
## Quick Start
|
|
13
21
|
|
|
14
22
|
```bash
|
|
15
23
|
# Install a skill (auto-detects your tools)
|
|
16
|
-
|
|
24
|
+
bunx @iceinvein/agent-skills install design-review
|
|
17
25
|
|
|
18
26
|
# Install for a specific tool
|
|
19
|
-
|
|
27
|
+
bunx @iceinvein/agent-skills install design-review --tool claude
|
|
20
28
|
```
|
|
21
29
|
|
|
22
30
|
## Commands
|
package/dist/cli/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
#!/usr/bin/env
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
// @bun
|
|
2
3
|
import { createRequire } from "node:module";
|
|
3
4
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
4
5
|
|
|
@@ -449,6 +450,53 @@ async function installSkill(cwd, manifest, files, targetTools) {
|
|
|
449
450
|
return { ok: true, installed, skipped };
|
|
450
451
|
}
|
|
451
452
|
|
|
453
|
+
// src/cli/github.ts
|
|
454
|
+
var REPO2 = "iceinvein/agent-skills";
|
|
455
|
+
var BRANCH2 = "master";
|
|
456
|
+
var BASE2 = `https://raw.githubusercontent.com/${REPO2}/${BRANCH2}`;
|
|
457
|
+
function buildRawUrl2(skillName, filePath) {
|
|
458
|
+
return `${BASE2}/skills/${skillName}/${filePath}`;
|
|
459
|
+
}
|
|
460
|
+
async function fetchSkillManifest2(skillName) {
|
|
461
|
+
const url = buildRawUrl2(skillName, "skill.json");
|
|
462
|
+
const res = await fetch(url);
|
|
463
|
+
if (res.status === 404) {
|
|
464
|
+
return { ok: false, error: `Skill '${skillName}' not found` };
|
|
465
|
+
}
|
|
466
|
+
if (!res.ok) {
|
|
467
|
+
return { ok: false, error: `Failed to fetch manifest: HTTP ${res.status}` };
|
|
468
|
+
}
|
|
469
|
+
const data = await res.json();
|
|
470
|
+
return validateManifest(data);
|
|
471
|
+
}
|
|
472
|
+
async function fetchSkillFile2(skillName, filePath) {
|
|
473
|
+
const url = buildRawUrl2(skillName, filePath);
|
|
474
|
+
const res = await fetch(url);
|
|
475
|
+
if (!res.ok) {
|
|
476
|
+
return { ok: false, error: `Failed to fetch '${filePath}': HTTP ${res.status}` };
|
|
477
|
+
}
|
|
478
|
+
const content = await res.text();
|
|
479
|
+
return { ok: true, content };
|
|
480
|
+
}
|
|
481
|
+
async function fetchAllSkillFiles2(skillName, manifest) {
|
|
482
|
+
const files = new Map;
|
|
483
|
+
if (manifest.files?.prompt) {
|
|
484
|
+
const result = await fetchSkillFile2(skillName, manifest.files.prompt);
|
|
485
|
+
if (!result.ok)
|
|
486
|
+
return { error: result.error };
|
|
487
|
+
files.set(manifest.files.prompt, result.content);
|
|
488
|
+
}
|
|
489
|
+
if (manifest.files?.supporting) {
|
|
490
|
+
for (const supportFile of manifest.files.supporting) {
|
|
491
|
+
const result = await fetchSkillFile2(skillName, supportFile);
|
|
492
|
+
if (!result.ok)
|
|
493
|
+
return { error: result.error };
|
|
494
|
+
files.set(supportFile, result.content);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
return files;
|
|
498
|
+
}
|
|
499
|
+
|
|
452
500
|
// src/cli/commands/remove.ts
|
|
453
501
|
async function removeSkill(cwd, skillName) {
|
|
454
502
|
const lockfile = await readLockfile(cwd);
|
|
@@ -456,7 +504,7 @@ async function removeSkill(cwd, skillName) {
|
|
|
456
504
|
if (!entry) {
|
|
457
505
|
return { ok: false, error: `Skill '${skillName}' is not installed` };
|
|
458
506
|
}
|
|
459
|
-
const manifestResult = await
|
|
507
|
+
const manifestResult = await fetchSkillManifest2(skillName);
|
|
460
508
|
if (manifestResult.ok) {
|
|
461
509
|
for (const tool of entry.tools) {
|
|
462
510
|
const adapter = getAdapter(tool);
|
|
@@ -489,9 +537,9 @@ async function removeSkill(cwd, skillName) {
|
|
|
489
537
|
}
|
|
490
538
|
|
|
491
539
|
// src/cli/commands/list.ts
|
|
492
|
-
var
|
|
493
|
-
var
|
|
494
|
-
var INDEX_URL = `https://raw.githubusercontent.com/${
|
|
540
|
+
var REPO3 = "iceinvein/agent-skills";
|
|
541
|
+
var BRANCH3 = "master";
|
|
542
|
+
var INDEX_URL = `https://raw.githubusercontent.com/${REPO3}/${BRANCH3}/skills/index.json`;
|
|
495
543
|
async function listSkills() {
|
|
496
544
|
const res = await fetch(INDEX_URL);
|
|
497
545
|
if (!res.ok) {
|
|
@@ -503,7 +551,73 @@ async function listSkills() {
|
|
|
503
551
|
|
|
504
552
|
// src/cli/commands/info.ts
|
|
505
553
|
async function infoSkill(skillName) {
|
|
506
|
-
return
|
|
554
|
+
return fetchSkillManifest2(skillName);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// src/cli/commands/remove.ts
|
|
558
|
+
async function removeSkill2(cwd, skillName) {
|
|
559
|
+
const lockfile = await readLockfile(cwd);
|
|
560
|
+
const entry = lockfile.skills[skillName];
|
|
561
|
+
if (!entry) {
|
|
562
|
+
return { ok: false, error: `Skill '${skillName}' is not installed` };
|
|
563
|
+
}
|
|
564
|
+
const manifestResult = await fetchSkillManifest2(skillName);
|
|
565
|
+
if (manifestResult.ok) {
|
|
566
|
+
for (const tool of entry.tools) {
|
|
567
|
+
const adapter = getAdapter(tool);
|
|
568
|
+
const toolFiles = entry.files.filter((f) => {
|
|
569
|
+
const config = manifestResult.manifest.install[tool];
|
|
570
|
+
if (!config)
|
|
571
|
+
return false;
|
|
572
|
+
if (config.prompt && f === config.prompt)
|
|
573
|
+
return true;
|
|
574
|
+
if (config.supporting && Object.values(config.supporting).includes(f))
|
|
575
|
+
return true;
|
|
576
|
+
if (config.mcpServers && (f.includes(".claude/settings") || f.includes(".cursor/mcp") || f.includes(".gemini/settings")))
|
|
577
|
+
return true;
|
|
578
|
+
return false;
|
|
579
|
+
});
|
|
580
|
+
await adapter.remove(cwd, manifestResult.manifest, toolFiles);
|
|
581
|
+
}
|
|
582
|
+
} else {
|
|
583
|
+
const { unlinkSync: unlinkSync4, existsSync: existsSync6 } = await import("node:fs");
|
|
584
|
+
const { join: join7 } = await import("node:path");
|
|
585
|
+
for (const file of entry.files) {
|
|
586
|
+
const fullPath = join7(cwd, file);
|
|
587
|
+
if (existsSync6(fullPath)) {
|
|
588
|
+
unlinkSync4(fullPath);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
await removeSkillFromLockfile(cwd, skillName);
|
|
593
|
+
return { ok: true, removed: entry.files };
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
// src/cli/commands/install.ts
|
|
597
|
+
async function installSkill2(cwd, manifest, files, targetTools) {
|
|
598
|
+
const compatibleTools = targetTools.filter((t) => manifest.tools.includes(t));
|
|
599
|
+
const skipped = targetTools.filter((t) => !manifest.tools.includes(t));
|
|
600
|
+
if (compatibleTools.length === 0) {
|
|
601
|
+
return {
|
|
602
|
+
ok: false,
|
|
603
|
+
error: `Skill '${manifest.name}' does not support any of: ${targetTools.join(", ")}. Supported: ${manifest.tools.join(", ")}`
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
const installed = {};
|
|
607
|
+
const allFiles = [];
|
|
608
|
+
for (const tool of compatibleTools) {
|
|
609
|
+
const adapter = getAdapter(tool);
|
|
610
|
+
const toolFiles = await adapter.install(cwd, manifest, files);
|
|
611
|
+
installed[tool] = toolFiles;
|
|
612
|
+
allFiles.push(...toolFiles);
|
|
613
|
+
}
|
|
614
|
+
await addSkillToLockfile(cwd, manifest.name, {
|
|
615
|
+
version: manifest.version,
|
|
616
|
+
tools: compatibleTools,
|
|
617
|
+
installedAt: new Date().toISOString(),
|
|
618
|
+
files: allFiles
|
|
619
|
+
});
|
|
620
|
+
return { ok: true, installed, skipped };
|
|
507
621
|
}
|
|
508
622
|
|
|
509
623
|
// src/cli/commands/update.ts
|
|
@@ -515,22 +629,25 @@ async function updateSkill(cwd, skillName) {
|
|
|
515
629
|
}
|
|
516
630
|
const oldVersion = entry.version;
|
|
517
631
|
const tools = entry.tools;
|
|
518
|
-
const manifestResult = await
|
|
632
|
+
const manifestResult = await fetchSkillManifest2(skillName);
|
|
519
633
|
if (!manifestResult.ok) {
|
|
520
634
|
return { ok: false, error: manifestResult.error };
|
|
521
635
|
}
|
|
522
|
-
const filesResult = await
|
|
636
|
+
const filesResult = await fetchAllSkillFiles2(skillName, manifestResult.manifest);
|
|
523
637
|
if ("error" in filesResult) {
|
|
524
638
|
return { ok: false, error: filesResult.error };
|
|
525
639
|
}
|
|
526
|
-
await
|
|
527
|
-
const installResult = await
|
|
640
|
+
await removeSkill2(cwd, skillName);
|
|
641
|
+
const installResult = await installSkill2(cwd, manifestResult.manifest, filesResult, tools);
|
|
528
642
|
if (!installResult.ok) {
|
|
529
643
|
return { ok: false, error: installResult.error };
|
|
530
644
|
}
|
|
531
645
|
return { ok: true, from: oldVersion, to: manifestResult.manifest.version };
|
|
532
646
|
}
|
|
533
647
|
|
|
648
|
+
// src/cli/types.ts
|
|
649
|
+
var TOOL_NAMES2 = ["claude", "cursor", "codex", "gemini"];
|
|
650
|
+
|
|
534
651
|
// src/cli/index.ts
|
|
535
652
|
function parseArgs(argv) {
|
|
536
653
|
if (argv.length === 0)
|
|
@@ -550,7 +667,7 @@ function parseArgs(argv) {
|
|
|
550
667
|
}
|
|
551
668
|
function printHelp() {
|
|
552
669
|
console.log(`
|
|
553
|
-
@iceinvein/agent-skills
|
|
670
|
+
@iceinvein/agent-skills \u2014 Install agent skills into AI coding tools
|
|
554
671
|
|
|
555
672
|
Usage:
|
|
556
673
|
agent-skills install <skill> [--tool <tool>] Install a skill
|
|
@@ -559,20 +676,20 @@ Usage:
|
|
|
559
676
|
agent-skills list List available skills
|
|
560
677
|
agent-skills info <skill> Show skill details
|
|
561
678
|
|
|
562
|
-
Tools: ${
|
|
679
|
+
Tools: ${TOOL_NAMES2.join(", ")}
|
|
563
680
|
|
|
564
681
|
If --tool is omitted, auto-detects tools in the current directory.
|
|
565
682
|
`);
|
|
566
683
|
}
|
|
567
684
|
function printInstalled(result, skipped) {
|
|
568
685
|
for (const [tool, files] of Object.entries(result)) {
|
|
569
|
-
console.log(`
|
|
686
|
+
console.log(` \u2713 ${tool}`);
|
|
570
687
|
for (const file of files) {
|
|
571
|
-
console.log(`
|
|
688
|
+
console.log(` \u2192 ${file}`);
|
|
572
689
|
}
|
|
573
690
|
}
|
|
574
691
|
for (const tool of skipped) {
|
|
575
|
-
console.log(`
|
|
692
|
+
console.log(` \u2298 ${tool} (skill does not support this tool)`);
|
|
576
693
|
}
|
|
577
694
|
}
|
|
578
695
|
async function main() {
|
|
@@ -597,8 +714,8 @@ async function main() {
|
|
|
597
714
|
}
|
|
598
715
|
let tools;
|
|
599
716
|
if (flags.tool) {
|
|
600
|
-
if (!
|
|
601
|
-
console.error(`Error: unknown tool '${flags.tool}'. Must be one of: ${
|
|
717
|
+
if (!TOOL_NAMES2.includes(flags.tool)) {
|
|
718
|
+
console.error(`Error: unknown tool '${flags.tool}'. Must be one of: ${TOOL_NAMES2.join(", ")}`);
|
|
602
719
|
process.exit(1);
|
|
603
720
|
}
|
|
604
721
|
tools = [flags.tool];
|
|
@@ -616,7 +733,7 @@ async function main() {
|
|
|
616
733
|
process.exit(1);
|
|
617
734
|
}
|
|
618
735
|
console.log(`
|
|
619
|
-
|
|
736
|
+
\u2713 Installed '${skillName}' v${manifestResult.manifest.version}:`);
|
|
620
737
|
printInstalled(result.installed, result.skipped);
|
|
621
738
|
break;
|
|
622
739
|
}
|
|
@@ -631,7 +748,7 @@ async function main() {
|
|
|
631
748
|
console.error(`Error: ${result.error}`);
|
|
632
749
|
process.exit(1);
|
|
633
750
|
}
|
|
634
|
-
console.log(
|
|
751
|
+
console.log(`\u2713 Removed '${skillName}'`);
|
|
635
752
|
break;
|
|
636
753
|
}
|
|
637
754
|
case "update": {
|
|
@@ -646,7 +763,7 @@ async function main() {
|
|
|
646
763
|
console.error(`Error: ${result.error}`);
|
|
647
764
|
process.exit(1);
|
|
648
765
|
}
|
|
649
|
-
console.log(
|
|
766
|
+
console.log(`\u2713 Updated '${skillName}' from v${result.from} to v${result.to}`);
|
|
650
767
|
break;
|
|
651
768
|
}
|
|
652
769
|
case "list": {
|
|
@@ -658,7 +775,7 @@ async function main() {
|
|
|
658
775
|
process.exit(1);
|
|
659
776
|
}
|
|
660
777
|
for (const skill of result.skills) {
|
|
661
|
-
const typeTag = skill.type === "prompt" ? "\uD83D\uDCDD" : skill.type === "code" ? "
|
|
778
|
+
const typeTag = skill.type === "prompt" ? "\uD83D\uDCDD" : skill.type === "code" ? "\u2699\uFE0F" : "\uD83D\uDD00";
|
|
662
779
|
console.log(` ${typeTag} ${skill.name} (v${skill.version})`);
|
|
663
780
|
console.log(` ${skill.description}
|
|
664
781
|
`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iceinvein/agent-skills",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Install agent skills into AI coding tools",
|
|
5
5
|
"author": "iceinvein",
|
|
6
6
|
"license": "MIT",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"skills"
|
|
14
14
|
],
|
|
15
15
|
"scripts": {
|
|
16
|
-
"build": "bun build src/cli/index.ts --outdir dist/cli --target
|
|
16
|
+
"build": "bun build src/cli/index.ts --outdir dist/cli --target bun",
|
|
17
17
|
"test": "bun test",
|
|
18
18
|
"dev": "bun run src/cli/index.ts"
|
|
19
19
|
},
|