generated from nhcarrigan/template
feat: list available skills when running /skill with no args
- Add list_skills Tauri command to scan ~/.claude/skills/ - Only lists directories containing a SKILL.md file - Show helpful message when no skills are found - Display bullet-point list of available skills with usage hint
This commit is contained in:
@@ -180,3 +180,45 @@ pub async fn answer_question(
|
||||
let mut manager = bridge_manager.lock();
|
||||
manager.send_tool_result(&conversation_id, &tool_use_id, answers)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn list_skills() -> Result<Vec<String>, String> {
|
||||
use std::path::Path;
|
||||
use std::fs;
|
||||
|
||||
// Get the home directory
|
||||
let home = std::env::var_os("HOME")
|
||||
.ok_or_else(|| "Could not determine home directory".to_string())?;
|
||||
|
||||
let skills_dir = Path::new(&home).join(".claude").join("skills");
|
||||
|
||||
// If the skills directory doesn't exist, return empty list
|
||||
if !skills_dir.exists() {
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
|
||||
// Read the directory and collect skill names
|
||||
let mut skills = Vec::new();
|
||||
let entries = fs::read_dir(&skills_dir)
|
||||
.map_err(|e| format!("Failed to read skills directory: {}", e))?;
|
||||
|
||||
for entry in entries {
|
||||
let entry = entry.map_err(|e| format!("Failed to read directory entry: {}", e))?;
|
||||
let path = entry.path();
|
||||
|
||||
// Only include directories that contain a SKILL.md file
|
||||
if path.is_dir() {
|
||||
let skill_file = path.join("SKILL.md");
|
||||
if skill_file.exists() {
|
||||
if let Some(name) = path.file_name() {
|
||||
skills.push(name.to_string_lossy().to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort alphabetically
|
||||
skills.sort();
|
||||
|
||||
Ok(skills)
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ pub fn run() {
|
||||
send_wsl_notification,
|
||||
send_vbs_notification,
|
||||
validate_directory,
|
||||
list_skills,
|
||||
])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
|
||||
@@ -186,7 +186,7 @@ export const slashCommands: SlashCommand[] = [
|
||||
{
|
||||
name: "skill",
|
||||
description: "Invoke a Claude Code skill from ~/.claude/skills/",
|
||||
usage: "/skill <name> <data>",
|
||||
usage: "/skill [name] [data]",
|
||||
execute: async (args: string) => {
|
||||
const conversationId = get(claudeStore.activeConversationId);
|
||||
if (!conversationId) {
|
||||
@@ -198,11 +198,25 @@ export const slashCommands: SlashCommand[] = [
|
||||
const skillName = parts[0];
|
||||
const skillData = parts.slice(1).join(" ");
|
||||
|
||||
// If no skill name provided, list available skills
|
||||
if (!skillName) {
|
||||
claudeStore.addLine(
|
||||
"error",
|
||||
"Usage: /skill <skill-name> [data]\nSkills are loaded from ~/.claude/skills/<skill-name>/SKILL.md\nExample: /skill onboard-mentee Discord ID: 123, GitHub: username"
|
||||
);
|
||||
try {
|
||||
const skills = await invoke<string[]>("list_skills");
|
||||
if (skills.length === 0) {
|
||||
claudeStore.addLine(
|
||||
"system",
|
||||
"No skills found in ~/.claude/skills/\nCreate a skill by adding a folder with a SKILL.md file."
|
||||
);
|
||||
} else {
|
||||
const skillList = skills.map((s) => ` • ${s}`).join("\n");
|
||||
claudeStore.addLine(
|
||||
"system",
|
||||
`Available skills:\n${skillList}\n\nUsage: /skill <skill-name> [data]`
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
claudeStore.addLine("error", `Failed to list skills: ${error}`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user