refactor(plugins): consolidate Cursor packaging into one plugin bundle

Cursor supports bundling multiple skills in a single plugin, so the
Cursor marketplace now publishes one redis-development plugin - the
same directory the Claude Code plugin uses - instead of eight
per-skill plugins. Requested by the Cursor marketplace team for
user discoverability.
This commit is contained in:
Vasko Atanasov
2026-08-26 15:51:46 +03:00
parent fa7948e8ac
commit e7bf13aca3
13 changed files with 29 additions and 195 deletions
+6 -63
View File
@@ -6,73 +6,16 @@
},
"metadata": {
"description": "Official Redis plugins for Cursor",
"version": "1.4.0",
"pluginRoot": "skills"
"version": "1.4.0"
},
"plugins": [
{
"name": "redis-core",
"source": "redis-core",
"description": "Core Redis modeling — data structures, key naming, memory and TTL, atomic primitives, JSON vs Hash, Streams vs Pub/Sub.",
"version": "1.0.0",
"name": "redis-development",
"source": "./plugins/redis-development",
"description": "Redis development best practices — data structures, Redis Search (lexical + vector + hybrid retrieval), caching, and performance optimization, plus Iris Redis Agent Memory.",
"version": "1.4.0",
"category": "database",
"tags": ["redis", "database", "data-modeling"]
},
{
"name": "redis-connections",
"source": "redis-connections",
"description": "Redis client and connection guidance — pooling, multiplexing, pipelining, client-side caching, timeouts, slow commands.",
"version": "1.0.0",
"category": "database",
"tags": ["redis", "performance", "connections"]
},
{
"name": "redis-search",
"source": "redis-search",
"description": "Redis Search — FT.CREATE schema, FT.SEARCH / FT.AGGREGATE / FT.HYBRID, DIALECT 2, vector similarity (HNSW / FLAT), hybrid retrieval, RAG pipelines, zero-downtime index updates.",
"version": "1.0.0",
"category": "database",
"tags": ["redis", "search", "query-engine", "vector-search", "hybrid", "rag", "ai"]
},
{
"name": "redis-semantic-cache",
"source": "redis-semantic-cache",
"description": "Redis LangCache — cache-aside flow for LLM responses, similarity threshold tuning, per-task cache separation.",
"version": "1.0.0",
"category": "database",
"tags": ["redis", "semantic-cache", "langcache", "ai"]
},
{
"name": "redis-clustering",
"source": "redis-clustering",
"description": "Redis Cluster and replication — hash tags for multi-key operations, avoiding CROSSSLOT, reading from replicas.",
"version": "1.0.0",
"category": "database",
"tags": ["redis", "cluster", "replication"]
},
{
"name": "redis-security",
"source": "redis-security",
"description": "Redis security hardening — authentication and TLS, ACL-based least privilege, network bind, firewall, command renaming.",
"version": "1.0.0",
"category": "database",
"tags": ["redis", "security", "acl", "tls"]
},
{
"name": "redis-observability",
"source": "redis-observability",
"description": "Redis observability — key metrics to monitor (INFO), debugging commands (SLOWLOG, MEMORY DOCTOR, FT.PROFILE), Redis Insight.",
"version": "1.0.0",
"category": "database",
"tags": ["redis", "observability", "monitoring"]
},
{
"name": "iris-development",
"source": "iris-development",
"description": "Iris: Redis Agent Memory — provisioning a memory service, authenticating the SDK, appending session events, creating and searching long-term memories, and the async promotion contract.",
"version": "1.0.0",
"category": "ai",
"tags": ["iris", "redis", "agent-memory", "ai", "llm"]
"tags": ["redis", "database", "caching", "vector-search", "performance"]
}
]
}
+6 -8
View File
@@ -17,13 +17,13 @@ A collection of agentskills.io-compliant skills for AI coding agents working wit
## Where Skills Live
`skills/` is the source of truth. `plugins/redis-development/skills/` holds **generated real copies** of it for the ChatGPT, Codex, and Claude Code plugin package, committed to the repo, and `npm run sync:plugins` regenerates them.
`skills/` is the source of truth. `plugins/redis-development/skills/` holds **generated real copies** of it for the ChatGPT, Codex, Claude Code, and Cursor plugin package, committed to the repo, and `npm run sync:plugins` regenerates them. Every marketplace publishes that one plugin directory, each through its own per-plugin manifest inside `plugins/redis-development/` (`.claude-plugin/`, `.codex-plugin/`, `.cursor-plugin/`); the Claude and Cursor listings point at it from the repo-root `.claude-plugin/marketplace.json` and `.cursor-plugin/marketplace.json`.
Copies rather than symlinks, because Claude Code and Cursor both drop a symlink that escapes the plugin root when a plugin is installed from git, so the plugin loads no skills at all. Real files also survive a Windows checkout, where git writes symlinks as plain text files unless `core.symlinks` is on.
The copies also decide *when* an update publishes. The Claude Code plugin directory fetches only the `plugins/redis-development` subdirectory, and its nightly bot advances our pinned commit only when that subdirectory's own contents change. A skill edit that never lands there is never noticed, no matter how many versions we bump.
Only what an agent loads at runtime is vendored. `.cursor-plugin/` stays out (see `EXCLUDED_TOP_LEVEL` in [scripts/sync-plugin-skills.mjs](scripts/sync-plugin-skills.mjs)), because Cursor reads that manifest from `skills/`, where its marketplace `pluginRoot` points. Eval suites are not a special case here: they live in top-level [evals/](evals/), outside any skill.
Only what an agent loads at runtime is vendored. Eval suites are not a special case here: they live in top-level [evals/](evals/), outside any skill.
You should never have to run the sync by hand. The pre-commit hook runs it and stages the result, and `npm run validate:plugin-skills` (inside `validate:plugins`, so in both the hook and CI) fails when the copies drift, when a file lingers for a skill that no longer exists, or when a symlink reappears on either side.
@@ -36,8 +36,7 @@ skills/<skill-name>/
├── SKILL.md # Required: YAML frontmatter (name, description, license, metadata) + agent-facing instructions
├── references/ # Optional: long-form content loaded on demand (one file per topic)
├── scripts/ # Optional: executable code agents may invoke
── assets/ # Optional: static resources (templates, schemas, images)
└── .cursor-plugin/ # Per-skill Cursor plugin manifest (so the skill can be published as a Cursor plugin; not vendored)
── assets/ # Optional: static resources (templates, schemas, images)
```
Use [skills/redis-core/](skills/redis-core/) as the reference layout. Editorial convention across this repo: keep `SKILL.md` under ~150 lines with summary tables and key principles inline; move full Python/Java code samples into `references/<topic>.md` (one file per source rule). The agent loads `SKILL.md` once on activation; reference files are loaded only when the task requires them.
@@ -57,12 +56,11 @@ Use [skills/redis-core/](skills/redis-core/) as the reference layout. Editorial
```
2. Add long-form examples under `references/`.
3. If the skill needs internal eval coverage, add `evals/<skill-name>/<suite-name>/{evals.json, model-matrix.json}` at the repo root, run the suite, and promote a baseline (`npm run eval:baseline`) — validation requires every suite to carry a current baseline.
4. Create `.cursor-plugin/plugin.json` (`name`, `version`, `description`, `license`, `keywords` — see any existing skill).
5. To publish via the marketplaces:
4. To publish via the marketplaces:
- ChatGPT and Codex: the sync vendors every skill into `plugins/redis-development/`; keep its `.codex-plugin/plugin.json` version aligned with the Claude manifest before submitting the package to OpenAI.
- Claude Code: nothing to wire up. The sync vendors every skill under `skills/`, so committing runs it and the directory's nightly bot picks the change up.
- Cursor: add an entry to `.cursor-plugin/marketplace.json` pointing at `<skill-name>`, then re-submit the repo at [cursor.com/marketplace/publish](https://cursor.com/marketplace/publish). Cursor does not pull from git.
6. Validate: `npm run validate` (covers plugin manifests, the vendored copies, eval baselines, and the agentskills.io spec).
- Cursor: nothing to wire up either — the single `redis-development` plugin bundles every vendored skill. Cursor does not pull from git, so ask the Cursor marketplace team for a re-index (or re-submit at [cursor.com/marketplace/publish](https://cursor.com/marketplace/publish)) once the change lands.
5. Validate: `npm run validate` (covers plugin manifests, the vendored copies, eval baselines, and the agentskills.io spec).
## Running Validators
+1 -1
View File
@@ -34,7 +34,7 @@ npm run sync:plugins # regenerate the copies (the hook runs this and
npm run validate:plugin-skills # what CI runs; fails on drift or on any symlink
```
Never hand-edit anything under `plugins/redis-development/skills/` — the next sync overwrites it. `.cursor-plugin/` is deliberately not vendored, since Cursor reads it from `skills/`. Full rationale in [AGENTS.md](AGENTS.md#where-skills-live).
Never hand-edit anything under `plugins/redis-development/skills/` — the next sync overwrites it. Full rationale in [AGENTS.md](AGENTS.md#where-skills-live).
## Skill Structure
@@ -0,0 +1,14 @@
{
"name": "redis-development",
"version": "1.4.0",
"description": "Redis development best practices — data structures, query engine, vector search, caching, and performance optimization",
"author": {
"name": "Redis",
"url": "https://redis.io"
},
"homepage": "https://redis.io",
"repository": "https://github.com/redis/agent-skills",
"license": "MIT",
"keywords": ["redis", "database", "caching", "vector-search", "performance", "best-practices"],
"skills": "./skills/"
}
+2 -7
View File
@@ -17,10 +17,6 @@ import process from "node:process";
const PLUGIN_SKILLS_RELATIVE = path.join("plugins", "redis-development", "skills");
// Cursor reads each `.cursor-plugin/` manifest from `skills/`, where its
// marketplace `pluginRoot` points, so the published copy leaves it out.
const EXCLUDED_TOP_LEVEL = new Set([".cursor-plugin"]);
const repoRoot = process.cwd();
const skillsRoot = path.join(repoRoot, "skills");
const pluginSkillsRoot = path.join(repoRoot, PLUGIN_SKILLS_RELATIVE);
@@ -48,7 +44,7 @@ async function main() {
const expected = new Map();
for (const skill of skills) {
const skillRoot = path.join(skillsRoot, skill);
for (const relative of await listFiles(skillRoot, { applyExcludes: true })) {
for (const relative of await listFiles(skillRoot)) {
expected.set(path.join(skill, relative), path.join(skillRoot, relative));
}
}
@@ -90,7 +86,7 @@ async function listSkills() {
// Lists files relative to `root`. A symlink is reported rather than followed:
// one escaping a plugin root is exactly what stops the plugin from publishing.
async function listFiles(root, { applyExcludes = false } = {}) {
async function listFiles(root) {
const files = [];
const pending = [""];
@@ -100,7 +96,6 @@ async function listFiles(root, { applyExcludes = false } = {}) {
for (const entry of entries) {
const relativePath = relativeDir ? path.join(relativeDir, entry.name) : entry.name;
if (applyExcludes && EXCLUDED_TOP_LEVEL.has(relativePath.split(path.sep)[0])) continue;
if (entry.isSymbolicLink()) {
problems.push(
@@ -1,13 +0,0 @@
{
"name": "iris-development",
"version": "1.0.0",
"description": "Iris: Redis Agent Memory — provisioning a memory service, authenticating the SDK, appending session events, creating and searching long-term memories, and the async promotion contract. Examples in the official redis-agent-memory (Python) and @redis-iris/agent-memory (TypeScript) SDKs.",
"author": {
"name": "Redis",
"email": "support@redis.com"
},
"homepage": "https://redis.io",
"repository": "https://github.com/redis/agent-skills",
"license": "MIT",
"keywords": ["iris", "redis", "agent-memory", "ai", "llm", "session-memory", "long-term-memory"]
}
@@ -1,13 +0,0 @@
{
"name": "redis-clustering",
"version": "1.0.0",
"description": "Redis Cluster and replication — hash tags for multi-key operations, avoiding CROSSSLOT, reading from replicas.",
"author": {
"name": "Redis",
"email": "support@redis.com"
},
"homepage": "https://redis.io",
"repository": "https://github.com/redis/agent-skills",
"license": "MIT",
"keywords": ["redis", "cluster", "replication", "hash-tags", "sharding"]
}
@@ -1,13 +0,0 @@
{
"name": "redis-connections",
"version": "1.0.0",
"description": "Redis client and connection guidance — pooling, multiplexing, pipelining, client-side caching, timeouts, slow commands.",
"author": {
"name": "Redis",
"email": "support@redis.com"
},
"homepage": "https://redis.io",
"repository": "https://github.com/redis/agent-skills",
"license": "MIT",
"keywords": ["redis", "performance", "connections", "pooling", "pipelining", "client-side-cache"]
}
@@ -1,13 +0,0 @@
{
"name": "redis-core",
"version": "1.0.0",
"description": "Core Redis modeling — data structures, key naming, memory and TTL, atomic primitives, JSON vs Hash, Streams vs Pub/Sub.",
"author": {
"name": "Redis",
"email": "support@redis.com"
},
"homepage": "https://redis.io",
"repository": "https://github.com/redis/agent-skills",
"license": "MIT",
"keywords": ["redis", "database", "data-modeling", "data-structures", "key-naming"]
}
@@ -1,13 +0,0 @@
{
"name": "redis-observability",
"version": "1.0.0",
"description": "Redis observability — key metrics to monitor (INFO), debugging commands (SLOWLOG, MEMORY DOCTOR, FT.PROFILE), Redis Insight.",
"author": {
"name": "Redis",
"email": "support@redis.com"
},
"homepage": "https://redis.io",
"repository": "https://github.com/redis/agent-skills",
"license": "MIT",
"keywords": ["redis", "observability", "monitoring", "metrics", "slowlog"]
}
@@ -1,25 +0,0 @@
{
"name": "redis-search",
"version": "1.0.0",
"description": "Redis Search — FT.CREATE schema design, FT.SEARCH / FT.AGGREGATE / FT.HYBRID queries, DIALECT 2, vector similarity (HNSW / FLAT), hybrid retrieval, RAG pipelines, and zero-downtime index updates.",
"author": {
"name": "Redis",
"email": "support@redis.com"
},
"homepage": "https://redis.io",
"repository": "https://github.com/redis/agent-skills",
"license": "MIT",
"keywords": [
"redis",
"search",
"query-engine",
"ft-create",
"ft-search",
"ft-aggregate",
"ft-hybrid",
"vector",
"hnsw",
"rag",
"indexing"
]
}
@@ -1,13 +0,0 @@
{
"name": "redis-security",
"version": "1.0.0",
"description": "Redis security hardening — authentication and TLS, ACL-based least privilege, network bind, firewall, command renaming.",
"author": {
"name": "Redis",
"email": "support@redis.com"
},
"homepage": "https://redis.io",
"repository": "https://github.com/redis/agent-skills",
"license": "MIT",
"keywords": ["redis", "security", "acl", "auth", "tls", "hardening"]
}
@@ -1,13 +0,0 @@
{
"name": "redis-semantic-cache",
"version": "1.0.0",
"description": "Redis LangCache — cache-aside flow for LLM responses, similarity threshold tuning, per-task cache separation.",
"author": {
"name": "Redis",
"email": "support@redis.com"
},
"homepage": "https://redis.io",
"repository": "https://github.com/redis/agent-skills",
"license": "MIT",
"keywords": ["redis", "semantic-cache", "langcache", "llm", "ai"]
}