claude-code-templates 1.28.1 → 1.28.3
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/package.json +1 -1
- package/src/skill-dashboard-web/script.js +5 -5
- package/src/skill-dashboard.js +110 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-code-templates",
|
|
3
|
-
"version": "1.28.
|
|
3
|
+
"version": "1.28.3",
|
|
4
4
|
"description": "CLI tool to setup Claude Code configurations with framework-specific commands, automation hooks and MCP Servers for your projects",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -362,11 +362,11 @@ function updateStats() {
|
|
|
362
362
|
document.getElementById('sidebarTotalSkills').textContent = total;
|
|
363
363
|
document.getElementById('sidebarPersonalSkills').textContent = personal;
|
|
364
364
|
|
|
365
|
-
// Filter counts
|
|
366
|
-
document.getElementById('countAll').textContent =
|
|
367
|
-
document.getElementById('countPersonal').textContent =
|
|
368
|
-
document.getElementById('countProject').textContent =
|
|
369
|
-
document.getElementById('countPlugin').textContent =
|
|
365
|
+
// Filter counts - always show totals, not filtered counts
|
|
366
|
+
document.getElementById('countAll').textContent = total;
|
|
367
|
+
document.getElementById('countPersonal').textContent = personal;
|
|
368
|
+
document.getElementById('countProject').textContent = project;
|
|
369
|
+
document.getElementById('countPlugin').textContent = plugin;
|
|
370
370
|
}
|
|
371
371
|
|
|
372
372
|
// Update Empty State
|
package/src/skill-dashboard.js
CHANGED
|
@@ -26,14 +26,24 @@ class SkillDashboard {
|
|
|
26
26
|
async loadSkillsData() {
|
|
27
27
|
try {
|
|
28
28
|
// Load personal skills
|
|
29
|
+
console.log(chalk.gray(`📂 Scanning personal skills: ${this.personalSkillsDir}`));
|
|
29
30
|
this.personalSkills = await this.loadSkillsFromDirectory(this.personalSkillsDir, 'Personal');
|
|
31
|
+
console.log(chalk.gray(`✓ Found ${this.personalSkills.length} personal skill(s)`));
|
|
30
32
|
|
|
31
33
|
// Load project skills (if in a project directory)
|
|
32
34
|
const projectSkillsDir = path.join(process.cwd(), '.claude', 'skills');
|
|
35
|
+
console.log(chalk.gray(`📂 Scanning project skills: ${projectSkillsDir}`));
|
|
33
36
|
this.projectSkills = await this.loadSkillsFromDirectory(projectSkillsDir, 'Project');
|
|
37
|
+
console.log(chalk.gray(`✓ Found ${this.projectSkills.length} project skill(s)`));
|
|
38
|
+
|
|
39
|
+
// Load plugin skills from marketplaces
|
|
40
|
+
console.log(chalk.gray(`📂 Scanning plugin skills from marketplaces`));
|
|
41
|
+
this.pluginSkills = await this.loadPluginSkills();
|
|
42
|
+
console.log(chalk.gray(`✓ Found ${this.pluginSkills.length} plugin skill(s)`));
|
|
34
43
|
|
|
35
44
|
// Combine all skills
|
|
36
|
-
this.skills = [...this.personalSkills, ...this.projectSkills];
|
|
45
|
+
this.skills = [...this.personalSkills, ...this.projectSkills, ...this.pluginSkills];
|
|
46
|
+
console.log(chalk.green(`✅ Total skills loaded: ${this.skills.length}`));
|
|
37
47
|
|
|
38
48
|
} catch (error) {
|
|
39
49
|
console.error(chalk.red('Error loading skills data:'), error.message);
|
|
@@ -46,38 +56,114 @@ class SkillDashboard {
|
|
|
46
56
|
|
|
47
57
|
try {
|
|
48
58
|
if (!(await fs.pathExists(skillsDir))) {
|
|
49
|
-
|
|
50
|
-
console.log(chalk.yellow(`Skills directory not found: ${skillsDir}`));
|
|
51
|
-
}
|
|
59
|
+
console.log(chalk.gray(` ℹ Directory does not exist: ${skillsDir}`));
|
|
52
60
|
return skills;
|
|
53
61
|
}
|
|
54
62
|
|
|
55
63
|
const skillDirs = await fs.readdir(skillsDir);
|
|
64
|
+
console.log(chalk.gray(` 📁 Found ${skillDirs.length} item(s) in ${skillsDir}`));
|
|
56
65
|
|
|
57
66
|
for (const skillDir of skillDirs) {
|
|
67
|
+
// Skip hidden files and directories
|
|
68
|
+
if (skillDir.startsWith('.')) continue;
|
|
69
|
+
|
|
58
70
|
const skillPath = path.join(skillsDir, skillDir);
|
|
59
71
|
|
|
60
72
|
try {
|
|
61
73
|
const stat = await fs.stat(skillPath);
|
|
62
|
-
if (!stat.isDirectory())
|
|
74
|
+
if (!stat.isDirectory()) {
|
|
75
|
+
console.log(chalk.gray(` ⊘ Skipping non-directory: ${skillDir}`));
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
63
78
|
|
|
64
79
|
// Look for SKILL.md
|
|
65
80
|
const skillMdPath = path.join(skillPath, 'SKILL.md');
|
|
66
81
|
|
|
67
82
|
if (await fs.pathExists(skillMdPath)) {
|
|
83
|
+
console.log(chalk.gray(` ✓ Found SKILL.md in ${skillDir}`));
|
|
68
84
|
const skillData = await this.parseSkill(skillMdPath, skillPath, skillDir, source);
|
|
69
85
|
if (skillData) {
|
|
70
86
|
skills.push(skillData);
|
|
87
|
+
console.log(chalk.green(` ✅ Loaded skill: ${skillData.name}`));
|
|
71
88
|
}
|
|
89
|
+
} else {
|
|
90
|
+
console.log(chalk.gray(` ⊘ No SKILL.md in ${skillDir}`));
|
|
72
91
|
}
|
|
73
92
|
} catch (error) {
|
|
74
|
-
console.warn(chalk.yellow(`
|
|
93
|
+
console.warn(chalk.yellow(` ⚠ Error loading skill ${skillDir}:`), error.message);
|
|
75
94
|
}
|
|
76
95
|
}
|
|
77
96
|
|
|
78
97
|
return skills;
|
|
79
98
|
} catch (error) {
|
|
80
|
-
console.warn(chalk.yellow(`Warning: Error loading skills from ${skillsDir}
|
|
99
|
+
console.warn(chalk.yellow(`Warning: Error loading skills from ${skillsDir}:`), error.message);
|
|
100
|
+
return skills;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async loadPluginSkills() {
|
|
105
|
+
const skills = [];
|
|
106
|
+
const pluginsDir = path.join(this.claudeDir, 'plugins', 'marketplaces');
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
if (!(await fs.pathExists(pluginsDir))) {
|
|
110
|
+
console.log(chalk.gray(` ℹ Plugins directory does not exist: ${pluginsDir}`));
|
|
111
|
+
return skills;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const marketplaces = await fs.readdir(pluginsDir);
|
|
115
|
+
console.log(chalk.gray(` 📁 Found ${marketplaces.length} marketplace(s)`));
|
|
116
|
+
|
|
117
|
+
for (const marketplace of marketplaces) {
|
|
118
|
+
if (marketplace.startsWith('.')) continue;
|
|
119
|
+
|
|
120
|
+
const marketplacePath = path.join(pluginsDir, marketplace, 'plugins');
|
|
121
|
+
|
|
122
|
+
if (!(await fs.pathExists(marketplacePath))) {
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const plugins = await fs.readdir(marketplacePath);
|
|
127
|
+
console.log(chalk.gray(` 📦 Scanning marketplace: ${marketplace} (${plugins.length} plugin(s))`));
|
|
128
|
+
|
|
129
|
+
for (const plugin of plugins) {
|
|
130
|
+
if (plugin.startsWith('.')) continue;
|
|
131
|
+
|
|
132
|
+
const skillsPath = path.join(marketplacePath, plugin, 'skills');
|
|
133
|
+
|
|
134
|
+
if (!(await fs.pathExists(skillsPath))) {
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const skillDirs = await fs.readdir(skillsPath);
|
|
139
|
+
|
|
140
|
+
for (const skillDir of skillDirs) {
|
|
141
|
+
if (skillDir.startsWith('.')) continue;
|
|
142
|
+
|
|
143
|
+
const skillPath = path.join(skillsPath, skillDir);
|
|
144
|
+
const stat = await fs.stat(skillPath);
|
|
145
|
+
|
|
146
|
+
if (!stat.isDirectory()) {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const skillMdPath = path.join(skillPath, 'SKILL.md');
|
|
151
|
+
|
|
152
|
+
if (await fs.pathExists(skillMdPath)) {
|
|
153
|
+
console.log(chalk.gray(` ✓ Found plugin skill: ${skillDir} from ${marketplace}`));
|
|
154
|
+
const skillData = await this.parseSkill(skillMdPath, skillPath, skillDir, 'Plugin');
|
|
155
|
+
if (skillData) {
|
|
156
|
+
skills.push(skillData);
|
|
157
|
+
console.log(chalk.green(` ✅ Loaded plugin skill: ${skillData.name}`));
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return skills;
|
|
165
|
+
} catch (error) {
|
|
166
|
+
console.warn(chalk.yellow(`Warning: Error loading plugin skills:`), error.message);
|
|
81
167
|
return skills;
|
|
82
168
|
}
|
|
83
169
|
}
|
|
@@ -377,11 +463,23 @@ class SkillDashboard {
|
|
|
377
463
|
}
|
|
378
464
|
|
|
379
465
|
async startServer() {
|
|
380
|
-
return new Promise((resolve) => {
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
466
|
+
return new Promise((resolve, reject) => {
|
|
467
|
+
const tryPort = (port) => {
|
|
468
|
+
this.httpServer = this.app.listen(port, async () => {
|
|
469
|
+
this.port = port;
|
|
470
|
+
console.log(chalk.green(`🎯 Skills dashboard started at http://localhost:${this.port}`));
|
|
471
|
+
resolve();
|
|
472
|
+
}).on('error', (err) => {
|
|
473
|
+
if (err.code === 'EADDRINUSE') {
|
|
474
|
+
console.log(chalk.yellow(`⚠️ Port ${port} is in use, trying ${port + 1}...`));
|
|
475
|
+
tryPort(port + 1);
|
|
476
|
+
} else {
|
|
477
|
+
reject(err);
|
|
478
|
+
}
|
|
479
|
+
});
|
|
480
|
+
};
|
|
481
|
+
|
|
482
|
+
tryPort(this.port);
|
|
385
483
|
});
|
|
386
484
|
}
|
|
387
485
|
|