plugin-deck
Live discovery dashboard for Claude Code plugins. Aggregates the official
Anthropic marketplace plus the largest community marketplaces, deduplicates
~700+ plugins, and ships a "what's new" feed updated every 6 hours.
Why
The Claude Code plugin ecosystem went GA in 2026 and grew fast — 4,200+
skills, 770+ MCP servers, 2,500+ marketplaces are scattered across GitHub.
Discovery is fragmented: every marketplace ships its own marketplace.json
and devs end up clone-and-grep'ing across half a dozen repos.
plugin-deck is a single dashboard that pulls each marketplace.json on a
6-hour cron, dedupes plugins by name, surfaces what's appeared this week,
and lets you filter by category, source marketplace, or GitHub stars.
Live data sources (all public, all unauthenticated)
| Marketplace | URL | Plugins |
|---|---|---|
| Anthropic Official | <https://raw.githubusercontent.com/anthropics/claude-plugins-official/main/.claude-plugin/marketplace.json> | ~168 |
| cc-marketplace (Anand D. Tyagi) | <https://raw.githubusercontent.com/ananddtyagi/cc-marketplace/main/.claude-plugin/marketplace.json> | ~119 |
| claude-code-plugins-plus (Jeremy Longshore) | <https://raw.githubusercontent.com/jeremylongshore/claude-code-plugins-plus-skills/main/.claude-plugin/marketplace.json> | ~427 |
When a fetch fails, the affected marketplace is marked last_fetch_status = and the dashboard shows the previous data. No fallback to
"error: …"
seed data ever happens — the dashboard refuses to fabricate plugins.
Optional GitHub repo metadata (stars, last push) is fetched from the public
GitHub API for plugins whose source URL points at github.com. With no token
the rate is capped at 50 repos per 6h cycle (60 req/hour public limit). SetGITHUB_TOKEN to raise the cap to 300 per cycle.
Cron schedule
| Cron | Job |
|---|---|
| 0 /6 | Re-pull every marketplace.json |
| 30 /6 | Enrich GitHub repo metadata for the oldest-stale ~50 repos |
| 5 3 * | Daily snapshot of plugin counts per marketplace |
A bootstrap fetch runs immediately at startup if the database is empty, so
the dashboard is never empty on first launch.
API
Everything is mounted under BASE_PATH = /plugin-deck. All endpoints are
public — no auth, no admin password.
GET /plugin-deck/health # health check
GET /plugin-deck/ # SPA
GET /plugin-deck/api/stats # totals + last refresh
GET /plugin-deck/api/marketplaces # source marketplaces
GET /plugin-deck/api/categories # categories overall + by marketplace
GET /plugin-deck/api/plugins?q=&category=&marketplace=&sort=&limit=&offset=
GET /plugin-deck/api/plugins/:name # detail incl. all listings + GitHub meta
GET /plugin-deck/api/whats-new?since=YYYY-MM-DD # plugins first seen since
GET /plugin-deck/api/timeline?days=30 # daily totals from snapshots
GET /plugin-deck/api/events # raw add/remove/category events
POST /plugin-deck/api/refresh # force a refresh (1 call/min/IP)
Run locally
cp .env.example .env
npm install
node server.js
# open http://localhost:4745/plugin-deck/
The first boot fetches all three marketplaces immediately. Wait ~10 seconds
and reload the page.
Stack
- Node.js 20+ / Express
- better-sqlite3 (WAL mode)
- node-cron
- helmet + compression
- Vanilla JS SPA, dark theme, English UI
- Chart.js via CDN
Tech notes
- The DB is created in
./data/plugin-deck.db(orPLUGIN_DECK_DATA_DIRif set). - Plugins are deduped by
namefor the browse view; a plugin appearing in - multiple marketplaces shows badges for each.
plugin_eventsrecords every add/remove/category change so the- "What's new" feed is honest — it's not a snapshot diff guess.
License
MIT.