mirror of
https://github.com/redis/agent-skills.git
synced 2026-09-19 01:25:14 +08:00
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:
@@ -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"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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
@@ -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/"
|
||||
}
|
||||
@@ -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"]
|
||||
}
|
||||
Reference in New Issue
Block a user