@crafter/skillkit 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 +7 -8
- package/package.json +1 -1
- package/src/bin.ts +1 -1
- package/src/commands/health.ts +4 -2
- package/src/commands/list.ts +10 -2
- package/src/commands/scan.ts +7 -2
- package/src/index.ts +1 -1
- package/src/scanner/skills.ts +52 -4
- package/src/types/index.ts +1 -0
package/README.md
CHANGED
|
@@ -99,14 +99,13 @@ All data stays on your machine. No telemetry. No signup.
|
|
|
99
99
|
|
|
100
100
|
## Supported Agents
|
|
101
101
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
- Claude Code
|
|
105
|
-
-
|
|
106
|
-
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
- Gemini CLI
|
|
102
|
+
Scans skill directories for 15+ agents automatically:
|
|
103
|
+
|
|
104
|
+
- Claude Code, Cursor, Codex, Windsurf, Gemini CLI
|
|
105
|
+
- Cline, Roo Code, Continue, OpenCode, GitHub Copilot
|
|
106
|
+
- OpenHands, Amp, Goose, Kilo Code, Trae
|
|
107
|
+
|
|
108
|
+
Skills installed via [skills.sh](https://skills.sh) symlinks are deduplicated across agents.
|
|
110
109
|
|
|
111
110
|
## License
|
|
112
111
|
|
package/package.json
CHANGED
package/src/bin.ts
CHANGED
package/src/commands/health.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { homedir } from "node:os";
|
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { getTopSkills } from "../db/queries";
|
|
5
5
|
import { getDb } from "../db/schema";
|
|
6
|
-
import { scanInstalledSkills } from "../scanner/skills";
|
|
6
|
+
import { getDetectedAgents, scanInstalledSkills } from "../scanner/skills";
|
|
7
7
|
import { bold, dim, green, red, yellow } from "../tui/colors";
|
|
8
8
|
|
|
9
9
|
const METADATA_BUDGET = 16000;
|
|
@@ -114,7 +114,9 @@ export async function runHealth(): Promise<void> {
|
|
|
114
114
|
|
|
115
115
|
console.log(`\n ${bold("SKILLKIT HEALTH REPORT")}\n`);
|
|
116
116
|
|
|
117
|
-
|
|
117
|
+
const agents = getDetectedAgents();
|
|
118
|
+
console.log(check(`${skills.length} skills across ${agents.length} agents`));
|
|
119
|
+
console.log(dim(` ${agents.join(", ")}`));
|
|
118
120
|
|
|
119
121
|
if (dbExists && hasDbData) {
|
|
120
122
|
console.log(
|
package/src/commands/list.ts
CHANGED
|
@@ -16,10 +16,15 @@ export function runList(): void {
|
|
|
16
16
|
const skills = scanInstalledSkills();
|
|
17
17
|
|
|
18
18
|
if (skills.length === 0) {
|
|
19
|
-
console.log("\n No skills
|
|
19
|
+
console.log("\n No skills found.\n");
|
|
20
20
|
return;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
const agentCounts = new Map<string, number>();
|
|
24
|
+
for (const s of skills) {
|
|
25
|
+
agentCounts.set(s.agent, (agentCounts.get(s.agent) ?? 0) + 1);
|
|
26
|
+
}
|
|
27
|
+
|
|
23
28
|
const totalSize = skills.reduce((acc, s) => acc + s.size, 0);
|
|
24
29
|
|
|
25
30
|
console.log(`\n ${bold(`INSTALLED SKILLS (${skills.length})`)}\n`);
|
|
@@ -40,7 +45,10 @@ export function runList(): void {
|
|
|
40
45
|
console.log(` ${name}${desc}${size}`);
|
|
41
46
|
}
|
|
42
47
|
|
|
48
|
+
const agentSummary = [...agentCounts.entries()]
|
|
49
|
+
.map(([a, c]) => `${a} (${c})`)
|
|
50
|
+
.join(", ");
|
|
43
51
|
console.log(
|
|
44
|
-
`\n ${dim(`Total: ${skills.length} skills | ${formatSize(totalSize)}
|
|
52
|
+
`\n ${dim(`Total: ${skills.length} skills | ${formatSize(totalSize)} | ${agentSummary}`)}\n`,
|
|
45
53
|
);
|
|
46
54
|
}
|
package/src/commands/scan.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { join } from "node:path";
|
|
|
4
4
|
import { upsertInstalledSkill } from "../db/queries";
|
|
5
5
|
import { getDb } from "../db/schema";
|
|
6
6
|
import { scanAllSessions } from "../scanner/index";
|
|
7
|
-
import { scanInstalledSkills } from "../scanner/skills";
|
|
7
|
+
import { getDetectedAgents, scanInstalledSkills } from "../scanner/skills";
|
|
8
8
|
import { bold, cyan, dim } from "../tui/colors";
|
|
9
9
|
|
|
10
10
|
function detectSource(skillPath: string): "skills.sh" | "manual" {
|
|
@@ -37,7 +37,12 @@ function countSessions(): number {
|
|
|
37
37
|
export async function runScan(): Promise<void> {
|
|
38
38
|
const db = getDb();
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
const agents = getDetectedAgents();
|
|
41
|
+
if (agents.length === 0) {
|
|
42
|
+
console.log(`\n ${dim("No agent skill directories found.")}\n`);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
console.log(`\n ${dim(`Scanning ${agents.length} agents: ${agents.join(", ")}`)}`);
|
|
41
46
|
|
|
42
47
|
const skills = scanInstalledSkills();
|
|
43
48
|
|
package/src/index.ts
CHANGED
|
@@ -13,7 +13,7 @@ export {
|
|
|
13
13
|
} from "./db/queries";
|
|
14
14
|
export { getDb } from "./db/schema";
|
|
15
15
|
export { parseSessionFile, scanAllSessions } from "./scanner/index";
|
|
16
|
-
export { scanInstalledSkills } from "./scanner/skills";
|
|
16
|
+
export { getDetectedAgents, scanInstalledSkills } from "./scanner/skills";
|
|
17
17
|
export type {
|
|
18
18
|
InstalledSkill,
|
|
19
19
|
SkillInvocation,
|
package/src/scanner/skills.ts
CHANGED
|
@@ -3,6 +3,24 @@ import { homedir } from "node:os";
|
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import type { InstalledSkill } from "../types";
|
|
5
5
|
|
|
6
|
+
const AGENT_SKILL_PATHS: Array<{ agent: string; dir: string }> = [
|
|
7
|
+
{ agent: "Claude Code", dir: join(homedir(), ".claude", "skills") },
|
|
8
|
+
{ agent: "Cursor", dir: join(homedir(), ".cursor", "skills") },
|
|
9
|
+
{ agent: "Codex", dir: join(homedir(), ".codex", "skills") },
|
|
10
|
+
{ agent: "Windsurf", dir: join(homedir(), ".codeium", "windsurf", "skills") },
|
|
11
|
+
{ agent: "Gemini CLI", dir: join(homedir(), ".gemini", "skills") },
|
|
12
|
+
{ agent: "Cline", dir: join(homedir(), ".cline", "skills") },
|
|
13
|
+
{ agent: "Roo Code", dir: join(homedir(), ".roo", "skills") },
|
|
14
|
+
{ agent: "Continue", dir: join(homedir(), ".continue", "skills") },
|
|
15
|
+
{ agent: "OpenCode", dir: join(homedir(), ".config", "opencode", "skills") },
|
|
16
|
+
{ agent: "GitHub Copilot", dir: join(homedir(), ".copilot", "skills") },
|
|
17
|
+
{ agent: "OpenHands", dir: join(homedir(), ".openhands", "skills") },
|
|
18
|
+
{ agent: "Amp", dir: join(homedir(), ".config", "agents", "skills") },
|
|
19
|
+
{ agent: "Goose", dir: join(homedir(), ".config", "goose", "skills") },
|
|
20
|
+
{ agent: "Kilo Code", dir: join(homedir(), ".kilocode", "skills") },
|
|
21
|
+
{ agent: "Trae", dir: join(homedir(), ".trae", "skills") },
|
|
22
|
+
];
|
|
23
|
+
|
|
6
24
|
function parseYamlFrontmatter(content: string): Record<string, string> {
|
|
7
25
|
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
8
26
|
if (!match || !match[1]) return {};
|
|
@@ -38,12 +56,13 @@ function getDirSize(dirPath: string): number {
|
|
|
38
56
|
return total;
|
|
39
57
|
}
|
|
40
58
|
|
|
41
|
-
|
|
42
|
-
|
|
59
|
+
function scanSkillsDir(
|
|
60
|
+
skillsDir: string,
|
|
61
|
+
agent: string,
|
|
62
|
+
): InstalledSkill[] {
|
|
43
63
|
if (!existsSync(skillsDir)) return [];
|
|
44
64
|
|
|
45
65
|
const skills: InstalledSkill[] = [];
|
|
46
|
-
|
|
47
66
|
let entries: string[];
|
|
48
67
|
try {
|
|
49
68
|
entries = readdirSync(skillsDir);
|
|
@@ -95,8 +114,37 @@ export function scanInstalledSkills(): InstalledSkill[] {
|
|
|
95
114
|
description,
|
|
96
115
|
size,
|
|
97
116
|
installedAt: new Date(stat.birthtime).toISOString(),
|
|
117
|
+
agent,
|
|
98
118
|
});
|
|
99
119
|
}
|
|
100
120
|
|
|
101
|
-
return skills
|
|
121
|
+
return skills;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export function scanInstalledSkills(): InstalledSkill[] {
|
|
125
|
+
const allSkills: InstalledSkill[] = [];
|
|
126
|
+
const seen = new Set<string>();
|
|
127
|
+
|
|
128
|
+
for (const { agent, dir } of AGENT_SKILL_PATHS) {
|
|
129
|
+
const skills = scanSkillsDir(dir, agent);
|
|
130
|
+
for (const skill of skills) {
|
|
131
|
+
try {
|
|
132
|
+
const ino = statSync(skill.path).ino;
|
|
133
|
+
const key = `${ino}`;
|
|
134
|
+
if (seen.has(key)) continue;
|
|
135
|
+
seen.add(key);
|
|
136
|
+
} catch {}
|
|
137
|
+
allSkills.push(skill);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return allSkills.sort((a, b) => a.name.localeCompare(b.name));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function getDetectedAgents(): string[] {
|
|
145
|
+
const agents: string[] = [];
|
|
146
|
+
for (const { agent, dir } of AGENT_SKILL_PATHS) {
|
|
147
|
+
if (existsSync(dir)) agents.push(agent);
|
|
148
|
+
}
|
|
149
|
+
return agents;
|
|
102
150
|
}
|