Skip to content

Commit b69e56a

Browse files
davila7claude
andcommitted
feat: Add plugin skills support to Skills Manager Dashboard
🎯 Skills Manager now detects skills from 3 sources: - Personal: ~/.claude/skills/ - Project: .claude/skills/ - Plugin: ~/.claude/plugins/marketplaces/*/plugins/*/skills/*/ ✨ Features: - Added loadPluginSkills() to scan marketplace-installed skills - Skills from /plugin install now appear in dashboard - Detailed logging for debugging skill detection - Fixed filter counts to show consistent totals 🔧 Improvements: - Filter counts remain static regardless of active filter - Shows total count for each category (All, Personal, Project, Plugin) - Enhanced logging for better troubleshooting - Supports skills installed via Claude Code plugin system 📦 Version: 1.28.3 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent e3d3c0e commit b69e56a

File tree

4 files changed

+101
-15
lines changed

4 files changed

+101
-15
lines changed

cli-tool/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cli-tool/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "claude-code-templates",
3-
"version": "1.28.2",
3+
"version": "1.28.3",
44
"description": "CLI tool to setup Claude Code configurations with framework-specific commands, automation hooks and MCP Servers for your projects",
55
"main": "src/index.js",
66
"bin": {

cli-tool/src/skill-dashboard-web/script.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -362,11 +362,11 @@ function updateStats() {
362362
document.getElementById('sidebarTotalSkills').textContent = total;
363363
document.getElementById('sidebarPersonalSkills').textContent = personal;
364364

365-
// Filter counts
366-
document.getElementById('countAll').textContent = state.filteredSkills.length;
367-
document.getElementById('countPersonal').textContent = state.filteredSkills.filter(s => s.source === 'Personal').length;
368-
document.getElementById('countProject').textContent = state.filteredSkills.filter(s => s.source === 'Project').length;
369-
document.getElementById('countPlugin').textContent = state.filteredSkills.filter(s => s.source === 'Plugin').length;
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;
370370
}
371371

372372
// Update Empty State

cli-tool/src/skill-dashboard.js

Lines changed: 93 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,24 @@ class SkillDashboard {
2626
async loadSkillsData() {
2727
try {
2828
// Load personal skills
29+
console.log(chalk.gray(`📂 Scanning personal skills: ${this.personalSkillsDir}`));
2930
this.personalSkills = await this.loadSkillsFromDirectory(this.personalSkillsDir, 'Personal');
31+
console.log(chalk.gray(`✓ Found ${this.personalSkills.length} personal skill(s)`));
3032

3133
// Load project skills (if in a project directory)
3234
const projectSkillsDir = path.join(process.cwd(), '.claude', 'skills');
35+
console.log(chalk.gray(`📂 Scanning project skills: ${projectSkillsDir}`));
3336
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)`));
3443

3544
// 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}`));
3747

3848
} catch (error) {
3949
console.error(chalk.red('Error loading skills data:'), error.message);
@@ -46,38 +56,114 @@ class SkillDashboard {
4656

4757
try {
4858
if (!(await fs.pathExists(skillsDir))) {
49-
if (this.options.verbose) {
50-
console.log(chalk.yellow(`Skills directory not found: ${skillsDir}`));
51-
}
59+
console.log(chalk.gray(` ℹ Directory does not exist: ${skillsDir}`));
5260
return skills;
5361
}
5462

5563
const skillDirs = await fs.readdir(skillsDir);
64+
console.log(chalk.gray(` 📁 Found ${skillDirs.length} item(s) in ${skillsDir}`));
5665

5766
for (const skillDir of skillDirs) {
67+
// Skip hidden files and directories
68+
if (skillDir.startsWith('.')) continue;
69+
5870
const skillPath = path.join(skillsDir, skillDir);
5971

6072
try {
6173
const stat = await fs.stat(skillPath);
62-
if (!stat.isDirectory()) continue;
74+
if (!stat.isDirectory()) {
75+
console.log(chalk.gray(` ⊘ Skipping non-directory: ${skillDir}`));
76+
continue;
77+
}
6378

6479
// Look for SKILL.md
6580
const skillMdPath = path.join(skillPath, 'SKILL.md');
6681

6782
if (await fs.pathExists(skillMdPath)) {
83+
console.log(chalk.gray(` ✓ Found SKILL.md in ${skillDir}`));
6884
const skillData = await this.parseSkill(skillMdPath, skillPath, skillDir, source);
6985
if (skillData) {
7086
skills.push(skillData);
87+
console.log(chalk.green(` ✅ Loaded skill: ${skillData.name}`));
7188
}
89+
} else {
90+
console.log(chalk.gray(` ⊘ No SKILL.md in ${skillDir}`));
7291
}
7392
} catch (error) {
74-
console.warn(chalk.yellow(`Warning: Error loading skill ${skillDir}`), error.message);
93+
console.warn(chalk.yellow(` ⚠ Error loading skill ${skillDir}:`), error.message);
94+
}
95+
}
96+
97+
return skills;
98+
} catch (error) {
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+
}
75161
}
76162
}
77163

78164
return skills;
79165
} catch (error) {
80-
console.warn(chalk.yellow(`Warning: Error loading skills from ${skillsDir}`), error.message);
166+
console.warn(chalk.yellow(`Warning: Error loading plugin skills:`), error.message);
81167
return skills;
82168
}
83169
}

0 commit comments

Comments
 (0)