Add /skills command (#8600)

Signed-off-by: Lucas Alvares Gomes <lucasagomes@gmail.com>
Co-authored-by: Lifei Zhou <lifei@squareup.com>
This commit is contained in:
Lucas Alvares Gomes
2026-04-22 13:36:39 +01:00
committed by GitHub
parent 501dde5570
commit bdf5c43f3d
4 changed files with 146 additions and 1 deletions
+57
View File
@@ -666,6 +666,14 @@ impl CliSession {
}
}
}
InputResult::LoadSkills(names) => {
history.save(editor);
self.handle_load_skills(&names).await?;
}
InputResult::ListSkills => {
history.save(editor);
self.handle_list_skills().await?;
}
}
Ok(())
}
@@ -875,6 +883,55 @@ impl CliSession {
}
}
async fn handle_load_skills(&mut self, names: &[String]) -> Result<()> {
// NOTE: We don't validate the skill names here because the load_skill tool will
// handle that and provide feedback to the user if any skill names are invalid.
let message = format!(
"Use the load_skill tool to load the following skills: {}.",
names
.iter()
.map(|n| format!("\"{}\"", n))
.collect::<Vec<_>>()
.join(", ")
);
self.push_message(Message::user().with_text(&message));
output::show_thinking();
let result = self
.process_agent_response(true, CancellationToken::default())
.await;
output::hide_thinking();
result?;
Ok(())
}
async fn handle_list_skills(&mut self) -> Result<()> {
use comfy_table::{presets, Cell, ContentArrangement, Table};
use goose::agents::platform_extensions::skills::list_installed_skills;
let cwd = std::env::current_dir().unwrap_or_default();
let skills = list_installed_skills(Some(&cwd));
if skills.is_empty() {
println!("{}", console::style("No skills available.").yellow());
return Ok(());
}
let mut table = Table::new();
table.set_content_arrangement(ContentArrangement::Dynamic);
table.load_preset(presets::ASCII_FULL);
table.set_header(vec!["Skill", "Description"]);
let mut sorted_skills = skills;
sorted_skills.sort_by(|a, b| a.name.cmp(&b.name));
for skill in &sorted_skills {
table.add_row(vec![Cell::new(&skill.name), Cell::new(&skill.description)]);
}
println!("{table}");
Ok(())
}
async fn handle_compact(&mut self) -> Result<()> {
let prompt = "Are you sure you want to compact this conversation? This will condense the message history.";
let should_summarize = match cliclack::confirm(prompt).initial_value(true).interact() {