Skip to content
Open
Show file tree
Hide file tree
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
49 changes: 49 additions & 0 deletions .claude/skills/skill-recommender/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
name: skill-recommender
description: Analyze current project's tech stack and recommend relevant skills, plugins, agents, and MCP servers from the plum ecosystem data
triggers:
- recommend skills
- what plugins should I use
- suggest tools
- find relevant skills
- what should I install
- discover plugins
- recommend plugins
- what tools should I use
---

# Skill Recommender

Analyze the current project's tech stack and recommend relevant ecosystem tools.

## Instructions

1. Determine the target directory. Default to the current working directory unless the user specifies a different path.

2. Run the recommender script:
```bash
python3 scripts/ecosystem/recommend.py [TARGET_DIR] --markdown
```

**Flags:**
- `--markdown` — Pre-formatted markdown tables (default for this skill)
- `--top N` — Show more results per category (default: 5). Use `--top 10` if the user asks for more.
- `--exclude-no-install` — Only show entries with install commands. Use when the user asks "what should I install" or wants actionable results.
- `--min-score N` — Adjust score threshold (default: 35). Lower to 20 for broader results.
- `--pretty` — Pretty-print JSON (use instead of `--markdown` if you need to parse the output programmatically)

3. Present the markdown output directly to the user. The script handles formatting, grouping, and deduplication.

4. Tags prefixed with `~` in the output are inferred from descriptions (not explicit in the ecosystem data). Mention this if the user asks about tag accuracy.

5. After the tables, add a brief "You might also like" section with 1-2 contextual suggestions based on the stack (e.g., "Since you're using BubbleTea, check out the Charm ecosystem tools" or "Consider adding a CI/CD plugin for your GitHub Actions workflow").

6. If the script fails, fall back to reading the ecosystem JSON files directly from `ecosystem/` and match entries that share at least one tag with the project's detected stack. Do not recommend entries with zero tag overlap.

## Notes

- Zero external dependencies (Python stdlib only)
- Scoring: 70% relevance (bidirectional tag match, geometric mean) + 30% popularity (log-scaled with recency boost)
- Hard gate: entries with zero matching tags (explicit or inferred) are excluded
- Deduplication: same repo across sources is shown once (highest score wins)
- Default: top 5 per category, minimum score 35
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,6 @@ docs/tmp

# Local MCP server config (may contain secrets)
.mcp.json

# Python cache
__pycache__/
193 changes: 193 additions & 0 deletions docs/handoff/2026-02-15-unified-facets-handoff.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
# Unified Facets & Quick Actions Handoff

**Date:** 2026-02-15
**Branch:** `feature/unified-facets-and-quick-actions`
**Status:** Feature complete, needs merge to `main` + cleanup

---

## Context

Plum is a TUI plugin manager for Claude Code. This branch implements a comprehensive UX overhaul: unified facets (combined filter/sort tabs) and a context-aware quick action menu (Space key overlay). It builds on top of the TUI UX improvements already merged to main (marketplace autocomplete, dynamic filters — PR #9).

## Key Documents

| Document | Location | Purpose |
|----------|----------|---------|
| Implementation Log | `docs/buzzminson/2026-02-04-tui-ux-improvements-tasks-5-11.md` | Full implementation details, timeline, decisions |
| Previous Handoff | `docs/handoff/2026-01-15-cli-commands-handoff.md` | Prior CLI commands feature (for format reference) |

---

## What's Done (3 commits ahead of `main`)

### Commit 1: `4db6259` — feat: implement unified facets and quick action menu
The core feature. ~1000 lines added across 7 files.

### Commit 2: `51523a5` — refactor: maximus code review fixes
Post-review cleanup: division-by-zero guards on empty facets, URL validation before `exec.Command`, consolidated facet cycling with `cycleFacet()` helper, extracted marketplace filtering helpers, removed duplicate utilities.

### Commit 3: `b920b64` — fix: same-name plugins from different marketplaces
Changed dedup key from plugin name to `plugin@marketplace`, so plugins with the same name from different sources both appear.

### Features Implemented

**Unified Facets Model:**
- Plugin list facets: `All | Discover | Ready | Installed ║ ↑Name | ↑Updated | ↑Stars`
- Marketplace list facets: `↑Plugins | ↑Stars | ↑Name | ↑Updated`
- Tab/Shift+Tab cycles through all facets (filters AND sorts)
- Visual `║` separator between filter and sort sections

**Quick Action Menu (Space key):**
- Context-aware overlay with keyboard shortcut hints
- Plugin List: [m] Browse Marketplaces, [f] Filter by Marketplace, [s] Sort, [v] Toggle View, [u] Refresh
- Plugin Detail (Discoverable): [i] 2-Step Install, [m] Marketplace, [p] Plugin, [g] GitHub, [l] Link
- Plugin Detail (Installed): [o] Open Local, [p] Copy Path, [g] GitHub, [l] Link
- Marketplace List: [Enter] View, [f] Show Plugins, [i] Copy Install, [g] GitHub

**2-Step Install Copy (i key):**
- On discoverable plugins, copies formatted multi-step install commands to clipboard

**Marketplace Picker Enhancement (Shift+F):**
- Alternative trigger for `@` marketplace autocomplete from the plugin list

**Same-Name Plugin Fix:**
- `internal/config/config.go` — dedup key changed from `pluginName` to `pluginName@marketplaceName`

### Files Changed (vs `main`)

| File | Lines | What Changed |
|------|-------|-------------|
| `internal/ui/quick_menu.go` | +281 (new) | Complete quick menu system |
| `internal/ui/model.go` | +418/-341 | Facet types, navigation methods, sort logic |
| `internal/ui/view.go` | +228/-66 | Unified facet rendering, quick menu overlay |
| `internal/ui/update.go` | +182/-90 | Space/Shift+F/i key handlers, quick menu keys |
| `internal/ui/marketplace_view.go` | +61/-34 | Facet-based sort tab rendering |
| `internal/ui/help_view.go` | +17/-17 | Updated help text for new shortcuts |
| `internal/config/config.go` | +37/-37 | Plugin dedup fix (name@marketplace) |
| `docs/buzzminson/...` | +307 (new) | Implementation log |

---

## Current State (verified 2026-02-15)

| Check | Status |
|-------|--------|
| `go build ./cmd/plum` | Passes |
| `go test ./...` | All pass (8 packages) |
| `golangci-lint run` | 1 pre-existing warning only (gocyclo on `handleListKeys`, complexity 45 > 40) |
| Branch pushed to origin | Up to date |
| PR open | No PR created yet |

### Uncommitted Local Changes

1. **`.gitignore`** — Added `.mcp.json` entry (local MCP server config). This is a good change, should be committed.
2. **`cmd/debug-plugins/`** — A debug utility for listing loaded plugins and checking dedup. Used during the same-name bug fix. Can be committed if useful for debugging, or removed.

---

## What Needs to Be Done

### Required: Merge to Main

1. **Decide on uncommitted files:**
- Commit `.gitignore` change (recommended — keeps `.mcp.json` out of repo)
- Either commit `cmd/debug-plugins/` as a dev tool or delete it
2. **Create PR** from `feature/unified-facets-and-quick-actions` → `main`
3. **Merge PR**

### Recommended: Known Issues to Address

1. **`handleListKeys` complexity (gocyclo 45 > 40):**
- Pre-existing but getting worse as features are added
- Refactor into sub-handlers: `handleListNavigation()`, `handleListActions()`, `handleListInput()`
- This would bring each handler well under the 40 threshold

2. **Plugin sort modes `↑Updated` and `↑Stars` are stubs:**
- `applyPluginSort()` in `model.go:543-551` currently sorts ALL modes by name only
- Need `UpdatedAt` and `Stars` fields on `plugin.Plugin` struct
- Populate from marketplace manifest or GitHub API
- Then implement real sort comparisons

3. **Quick menu doesn't dim background:**
- `renderQuickMenuOverlay()` receives `baseView` but ignores it (`_ = baseView`)
- Menu renders centered but the underlying view is not dimmed/blurred
- Would need line-by-line overlay composition for proper overlay effect

### Optional: Future Enhancements (from backlog)

4. Marketplace filter facets (All | Installed | Cached | Available)
5. Integration tests for facet navigation and quick menu
6. README update with animated GIF demos of new features
7. Quick action icons/emojis for visual distinction

---

## Architecture Notes

### Facets System

```
Facet struct {
Type FacetType // FacetFilter or FacetSort
DisplayName string // e.g. "All", "↑Name"
FilterMode FilterMode // For filter facets
SortMode PluginSortMode // For plugin sort facets
MarketplaceSort MarketplaceSortMode // For marketplace sort facets
IsActive bool
}
```

- `GetPluginFacets()` returns 7 facets (4 filters + 3 sorts)
- `GetMarketplaceFacets()` returns 4 sort facets
- `cycleFacet(direction)` handles Tab/Shift+Tab navigation
- Filters and sorts are independent — you can filter AND sort simultaneously

### Quick Menu System

- `ViewQuickMenu` state overlays on top of `quickMenuPreviousView`
- `GetQuickActionsForView()` dispatches based on what view the menu was opened from
- `ExecuteQuickMenuAction()` synthesizes a `tea.KeyMsg` to reuse existing key handlers
- Direct letter key presses in the menu execute immediately (no need to navigate + Enter)

### Plugin Dedup (config.go)

```
// Before (bug): plugins deduped by name → same-name plugins from different marketplaces hidden
seenPluginNames[mp.Name]

// After (fix): deduped by full qualified name → both shown
seenPluginFullNames[mp.Name + "@" + marketplaceName]
```

---

## Pre-Push Checklist

Always run before pushing:
```bash
golangci-lint run --timeout=5m
go test ./...
go build -o ./plum ./cmd/plum
```

---

## Quick Start for Buzzminson

```bash
# You're already on the right branch
git status

# Verify everything still builds and passes
go test ./... && go build -o ./plum ./cmd/plum

# Run the TUI to manually test features
./plum

# Key things to test:
# - Tab through facets in plugin list (should see filters ║ sorts)
# - Space to open quick menu in any view
# - Shift+F to open marketplace picker
# - 'i' on a discoverable plugin detail to copy 2-step install
```
118 changes: 118 additions & 0 deletions docs/plans/2026-02-15-skill-recommender-v2-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# Skill Recommender v2 Design

**Date:** 2026-02-15
**Status:** Approved
**Branch:** feature/ecosystem-discovery

## Problem

The v1 skill recommender produces noisy results:
- Items match on single generic tags like "backend" (supabase in skills-leaderboard)
- High-popularity items score above threshold with zero tag overlap
- Duplicate entries appear across categories (e.g., everything-claude-code in plugins + skills)
- Ecosystem JSONs lack language/framework tags, limiting match quality for non-JS/React stacks
- No markdown output mode — Claude must parse JSON and reformat every time

## Decisions

- **Approach:** Comprehensive pass — extract scoring engine, enrich data, add features
- **Deduplication:** Keep highest-scoring entry only, annotate with `also_found_in`
- **Tag enrichment:** Curate JSONs manually + add lightweight keyword inference as fallback
- **Hard gate:** Items with zero matching tags (explicit or inferred) are excluded regardless of score

## Design

### 1. Scoring Engine (`scripts/ecosystem/scorer.py`)

New module with a multi-stage pipeline:

**Stage 1 — Tag matching (80% of relevance)**
- Bidirectional overlap: item tags ∩ stack tags
- Geometric mean of (overlap/item_tags) and (overlap/stack_tags)
- Prevents single-generic-tag matches from scoring high

**Stage 2 — Keyword inference (20% of relevance)**
- Curated `KEYWORD_TAG_MAP` maps description keywords → tags
- e.g., "terminal" → "terminal", "golang" → "go", "react native" → "react-native"
- Inferred tags count at 50% weight vs explicit tags
- Shown separately in output as `inferred_tags`

**Stage 3 — Popularity normalization**
- Log-scale within each source (unchanged)
- Recency boost: entries updated in past 3 months get 10% bump

**Stage 4 — Deduplication**
- Key on `owner/name` (lowercased)
- Keep entry with highest final score
- Annotate with `also_found_in: [source_keys]`

**Final formula:** `(relevance * 0.7) + (popularity * 0.3)`

**Hard gate:** Zero matching tags (explicit + inferred) → excluded.

### 2. Ecosystem Data Enrichment

Curate tags across all 5 JSON files:

| File | Focus |
|------|-------|
| `skills-leaderboard.json` | Add missing language tags, `development`/`general` for universal skills |
| `plugins.json` | Add `cli`, `github`, `development` where applicable |
| `agents.json` | Add `python`, `typescript`, `sdk`, `terminal` where applicable |
| `skills.json` | Add `go`, `python`, `php`, `tui` to domain-specific entries |
| `mcp-servers.json` | Add `slack`, `git`, `filesystem` to specialized servers |

Rules:
- Only factually accurate tags based on description/name
- Lowercase, hyphenated format
- Max 2-3 additions per entry
- Prefer tags matching `detect_stack.py` output

### 3. New Features for `recommend.py`

**`--markdown` flag**
- Pre-formatted markdown tables grouped by category
- Columns: Name, Score, Popularity, Matching Tags, Install Command

**`--exclude-no-install` flag**
- Filters entries where `install_cmd` is null

**`--json` flag (default)**
- Current behavior, explicit for clarity

**Updated defaults:**
- `--min-score` raised from 15 → 20
- Hard gate applied automatically

**Dedup in output:**
- Applied automatically
- `also_found_in` array on deduplicated entries

### 4. SKILL.md Updates

- Use `--markdown` by default
- Document `--exclude-no-install` for actionable-only queries
- Update fallback instructions (require tag match when reading JSONs directly)
- Add `--top 10` suggestion for expanded results

## Files Changed

| File | Action |
|------|--------|
| `scripts/ecosystem/scorer.py` | **New** — Multi-stage scoring engine |
| `scripts/ecosystem/recommend.py` | **Modified** — Import scorer, add flags, raise min-score |
| `scripts/ecosystem/detect_stack.py` | **No changes** |
| `ecosystem/skills-leaderboard.json` | **Modified** — Tag enrichment |
| `ecosystem/plugins.json` | **Modified** — Tag enrichment |
| `ecosystem/agents.json` | **Modified** — Tag enrichment |
| `ecosystem/skills.json` | **Modified** — Tag enrichment |
| `ecosystem/mcp-servers.json` | **Modified** — Tag enrichment |
| `.claude/skills/skill-recommender/SKILL.md` | **Modified** — Use new flags |

## Success Criteria

- Running against plum repo: skills_leaderboard returns 0 results (no relevant skills exist for Go/TUI in that dataset) rather than false positives
- No entries with empty `matching_tags` + empty `inferred_tags` appear in output
- No duplicate owner/name entries across categories
- `--markdown` produces clean, copy-pasteable tables
- `--exclude-no-install` filters curated lists correctly
Loading
Loading