Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.devoxx.genie.ui.settings.DevoxxGenieStateService;
import com.intellij.ide.BrowserUtil;
import com.intellij.openapi.project.Project;
import com.intellij.ui.HyperlinkLabel;
import com.intellij.ui.JBColor;
import com.intellij.ui.components.JBLabel;
import com.intellij.ui.components.JBScrollPane;
Expand Down Expand Up @@ -35,6 +36,29 @@ public class SkillsSettingsComponent extends AbstractSettingsComponent {

private static final String DOCS_URL = "https://genie.devoxx.com/docs/features/skills";

/** A curated external source where users can discover and download skills. */
private record SkillLink(String title, String url, String description) {}

/**
* Curated links shown in the "Browse skills online" section. Skills follow the open
* {@code SKILL.md} standard, so a skill folder downloaded from any of these sources can be
* dropped into one of the scanned skill directories and picked up by the {@link SkillRegistry}.
*/
private static final SkillLink[] SKILL_LINKS = {
new SkillLink("Anthropic Skills",
"https://github.com/anthropics/skills",
"Official Agent Skills published by Anthropic"),
new SkillLink("Agent Skills standard",
"https://agentskills.io",
"The open SKILL.md specification, portable across AI coding tools"),
new SkillLink("Claude Code Marketplace",
"https://github.com/netresearch/claude-code-marketplace",
"40+ community skills for AI-assisted development"),
new SkillLink("SkillsMP",
"https://skillsmp.com",
"Searchable directory of community SKILL.md files"),
};

private final Project project;
private final SkillRegistry registry;
private final SkillsTableModel tableModel = new SkillsTableModel();
Expand Down Expand Up @@ -100,6 +124,17 @@ public JPanel createPanel() {
gbc.gridy++;
panel.add(description, gbc);

// Curated links to places where users can find skills to download into the folders above.
addSection(panel, gbc, "Browse skills online");

JBLabel linksHint = new JBLabel(
"Download a skill's folder from one of these sources into a directory above, then click Reload.");
gbc.gridy++;
panel.add(linksHint, gbc);

gbc.gridy++;
panel.add(buildLinksPanel(), gbc);

// Toolbar: a single "Open Skills Folder" button + dropdown that selects which of the
// six skill directories to open, followed by the Reload button on the same row. The
// previous layout (six side-by-side buttons in a FlowLayout) overflowed and clipped
Expand Down Expand Up @@ -172,6 +207,36 @@ public JPanel createPanel() {
return panel;
}

/**
* Builds a panel listing the curated {@link #SKILL_LINKS}, one per row: a clickable
* {@link HyperlinkLabel} opening the source in the browser, followed by a short description.
*/
private JPanel buildLinksPanel() {
JPanel linksPanel = new JPanel(new GridBagLayout());
GridBagConstraints lgbc = new GridBagConstraints();
lgbc.gridy = 0;
lgbc.anchor = GridBagConstraints.WEST;
lgbc.insets = JBUI.insets(2, 0, 2, 12);

for (SkillLink link : SKILL_LINKS) {
HyperlinkLabel label = new HyperlinkLabel(link.title());
label.setHyperlinkTarget(link.url());
label.setToolTipText(link.url());
lgbc.gridx = 0;
lgbc.weightx = 0;
linksPanel.add(label, lgbc);

JBLabel desc = new JBLabel(link.description());
desc.setForeground(JBColor.GRAY);
lgbc.gridx = 1;
lgbc.weightx = 1.0;
linksPanel.add(desc, lgbc);

lgbc.gridy++;
}
return linksPanel;
}

public boolean isModified() {
Set<String> persisted = DevoxxGenieStateService.getInstance().getDisabledSkillNames();
if (persisted == null) {
Expand Down
Loading