Anthropic handed the Agent Skills format to the Agentic AI Foundation on October 22, 2026, and reporting on the transfer describes the move as placing the standard under neutral Linux Foundation governance. Anthropic says more than 70 agent platforms, Cursor among them, had integrated the format by then. For anyone who writes Cursor skills, that changes the pitch: a SKILL.md folder you author today is no longer a Cursor trick. It is a portable unit of know-how that other agents can read too.
Cursor sits in a lot of developer workflows. The Stack Overflow 2025 Developer Survey found that 18% of respondents used Cursor, which made it one of the newer AI-enabled IDEs the survey measured. Most of those users still paste the same instructions into chat every morning. A skill replaces that habit with a file the agent finds and loads on its own.
This walkthrough builds a working skills library in 12 steps and about 45 minutes. You will write three skills, bundle a script with one of them, add a validator that fails CI when a skill breaks the spec, and test activation in the editor. If you have already wired up Cursor MCP servers, you will recognize the pattern: a small config artifact that expands what the agent can do, committed to Git so the whole team inherits it.
Don't miss new tech stories on Google
Add Shattered once in the Google app and our stories show up in your news suggestions.
What Cursor Skills Are and Why They Matter in October 2026 #
A skill is a directory that contains a required SKILL.md file and, optionally, scripts or reference material. The file opens with YAML frontmatter (a name and a description) followed by Markdown instructions. Cursor presents the available skills to the agent, and the agent decides whether one fits the task based largely on its description. You can also force the issue by typing /skill-name in the chat box.
Cursor’s changelog reportedly credits release 2.4 with introducing Agent Skills alongside subagents and image generation. Since then the feature has become stable enough that Cursor’s own best-practices material describes skills as dynamic capabilities defined in SKILL.md files. The October 2026 changelog entries are about polish rather than new concepts, including fixes that make links from built-in skills open the correct SKILL.md.
Three things make skills worth your time right now.
First, the standard has a neutral home. Because the Agent Skills specification and its GitHub organization now sit with the Agentic AI Foundation, the format will outlive any one vendor’s roadmap. The reference site at agentskills.io documents how an agent discovers, parses and loads skills, which is useful reading if you ever build tooling around them.
Second, skills are cheap on context. The specification describes progressive disclosure: only the name and description (roughly 100 tokens per skill) load at startup, and the full body loads when the skill activates. The recommended ceiling for a body is under 5,000 tokens. Even a library of dozens of skills adds only a compact catalog to every conversation, which is a sharp contrast with a 3,000-word rules file that loads on every request.
Third, the agentic wave is arriving in companies faster than the tooling discipline around it. McKinsey’s State of AI survey for 2025 found that 23% of respondents said their organizations were scaling an agentic AI system somewhere in the enterprise, and another 39% had begun experimenting with agents. Teams in that second group need a place to keep repeatable procedures, and a repo-level skills folder is the lightest option available.
Skills vs. rules vs. MCP vs. slash commands
New users confuse these four constantly. The table separates them by what each one is for and when it loads.
| Mechanism | Best for | When it loads | Lives in |
|---|---|---|---|
| Rules | Always-on conventions (style, naming, stack facts) | Every request, or by glob match | .cursor/rules/ |
| Skills | Repeatable procedures with steps, scripts, references | On demand, when the description matches or you type /name |
.cursor/skills/ or.agents/skills/ |
| MCP servers | Live access to external tools and data | When the agent calls a tool | .cursor/mcp.json |
| Plain prompts | One-off requests | When you type them | Chat box |
The rule of thumb: if the instruction applies to every task, it belongs in a rules file (the Cursor Rules migration guide covers that side). If it applies to one kind of task and takes more than a few lines to explain, make it a skill. If the agent needs to reach a system outside the repo, wire up MCP and let a skill describe how to use the tools well.
Prerequisites and Versions #
Gather these before you start. Nothing here costs money beyond whatever Cursor plan you already hold.
- Cursor, current stable build. One forum report points to a 3.x line, and release notes for Cursor 3.19 mention Skills fixes, but treat exact numbers as a lookup in your own About dialog. Skills need at least the 2.4 line.
- Git 2.40 or newer, so the project can live in a repository your team clones.
- Python 3.11 or newer for the validator and the changelog helper script. The code below uses only the standard library.
- A scratch repository with at least 20 commits, so the release-notes skill has history to summarize.
- Optional: the Cursor CLI, if you want to run skills headlessly later. The CLI and GitHub Actions walkthrough covers installation.
One billing note. Cursor changed its plan structure on October 12, 2026, introducing The X Subscription, and reports indicate third-party models such as Claude and GPT are now billed separately at API list prices on the new plans. Skills themselves cost nothing, but a skill that triggers long agent runs on a third-party model can raise your usage bill. Check your own plan page before you run the heavy examples.
How Cursor Finds and Loads a Skill #
Understanding the model saves hours of debugging later. Cursor scans the skill locations when a session starts and reads the frontmatter of each SKILL.md. The agent receives a compact list of names and descriptions. When your request matches a description, the agent reads the full body and follows it. If the body points to a script or reference file, the agent opens that file only when the instructions tell it to.
That flow has two consequences. The description is the trigger, so a vague description means the skill never fires. And the body is a prompt, so it should read like instructions to a capable colleague: goal, ordered steps, what done looks like.
The frontmatter contract
The specification requires two fields and allows two more:
| Field | Required | Limit | Notes |
|---|---|---|---|
name |
Yes | 64 characters | Lowercase letters, numbers and hyphens only. Must match the folder name. |
description |
Yes | 1,024 characters | What the skill does and when to use it. |
license |
No | n/a | License identifier or file reference. |
compatibility |
No | n/a | Environment needs, for example a Python version. |
Cursor’s /skills interface reportedly checks these limits and warns about invalid names, folder names that do not match, descriptions over 1,024 characters, and bodies that run past roughly 5,000 tokens. You will build your own validator in Step 10 so the same checks run in CI, not just in the editor.
Set Up the Environment (Steps 1-3) #
Step 1: Confirm Your Cursor Build Supports Skills
Open a terminal in any project and check the version. If you installed the shell command from the Command Palette, cursor --version prints it. Otherwise open Cursor, choose About, and read the number there.
cursor --version
Example output (your numbers will differ):
3.19.2
a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0
arm64
Anything on the 2.4 line or later supports Agent Skills in the editor and the CLI. Then type /skills in the agent chat. If the command opens a panel listing built-in and custom skills, you are ready. If the slash menu shows nothing for skills, update Cursor first and restart the window.
Step 2: Choose Where the Skills Will Live
Cursor reads skills from several places. Community documentation and Cursor forum reports agree on the main three, though you should confirm the list against Cursor’s docs because Cursor ships changes weekly.
| Location | Scope | Shared with team | Works in Cloud Agents |
|---|---|---|---|
.cursor/skills/<name>/SKILL.md |
One repository | Yes, via Git | Yes (most reliable path) |
.agents/skills/<name>/SKILL.md |
One repository, cross-tool | Yes, via Git | Depends on the tool |
~/.cursor/skills/<name>/SKILL.md |
Your machine, every project | No | Reports say synced personal skills may not register |
For this project, use .cursor/skills/. Forum reports from October 1 to 24 describe personal skills sitting on a Cloud Agent VM yet failing to register, while repository skills and plugin skills worked. Automations that run under a service account have the same limitation: they need the skill inside the selected repository’s .cursor/skills/ folder or in a team plugin. Repository placement is the choice that keeps working when you scale from your laptop to Cursor Cloud Agents.
Step 3: Create the Project Skeleton
Create a scratch repo, or use a real one. The layout below is the finished project you will have by Step 12.
mkdir cursor-skills-lab && cd cursor-skills-lab
git init -b main
mkdir -p .cursor/skills/release-notes/scripts
mkdir -p .cursor/skills/pr-review-checklist/references
mkdir -p .cursor/skills/db-migration-safety
mkdir -p tools .github/workflows
touch .cursor/skills/release-notes/SKILL.md \
.cursor/skills/pr-review-checklist/SKILL.md \
.cursor/skills/db-migration-safety/SKILL.md
Check the tree:
find .cursor -type f | sort
.cursor/skills/db-migration-safety/SKILL.md
.cursor/skills/pr-review-checklist/SKILL.md
.cursor/skills/release-notes/SKILL.md
The folder name is the skill name. Keep it lowercase with hyphens, because the name field in the frontmatter must match it exactly.
Write the Skills (Steps 4-7) #
Step 4: Write Your First Skill, release-notes
Start with a skill that does one job. Release notes are a good first target: everyone writes them, the steps are the same every time, and a script can do the boring part.
Open .cursor/skills/release-notes/SKILL.md and paste:
---
name: release-notes
description: Draft release notes from git history. Use when the user asks for a changelog, release notes, "what shipped", or a summary of commits between two tags or dates.
license: MIT
compatibility: Requires git and Python 3.11+
---
## Goal
Produce a Markdown release note that a customer can read in under a minute.
## Steps
1. Ask for the range if it was not given. Default to the last tag through HEAD.
2. Run `python scripts/changelog.py --since <tag-or-date>` from this skill's folder.
3. Read the grouped output. Merge duplicates and drop commits that only touch tests or CI.
4. Rewrite each line in plain language. Lead with the user benefit, not the file changed.
5. Put breaking changes in their own section at the top, marked **Breaking**.
6. Finish with a one-line summary and the list of contributors.
## Output format
- Title line: `## <version or date range>`
- Sections in this order: Breaking, Added, Fixed, Changed
- No commit hashes in the prose. Link PRs when the commit message includes a number.
## Done when
Every commit in the range is either represented in a line or consciously dropped.
Look closely at the description. It states what the skill does (“Draft release notes from git history”) and lists the phrases that should trigger it. The agent matches your request against that text, so the more natural-language triggers you include, the more reliably it fires. Descriptions that say only “Helps with releases” lose to the agent’s default behavior almost every time.
Step 5: Bundle a Script the Agent Can Run
Skills can ship executable helpers. Deterministic work (counting, grouping, parsing) belongs in code, not in the model’s head. Create .cursor/skills/release-notes/scripts/changelog.py:
#!/usr/bin/env python3
"""Group git commits by conventional-commit type for release notes."""
import argparse
import re
import subprocess
import sys
from collections import defaultdict
TYPES = {"feat": "Added", "fix": "Fixed", "perf": "Changed",
"refactor": "Changed", "docs": "Changed", "chore": "Skip",
"test": "Skip", "ci": "Skip"}
PATTERN = re.compile(r"^(?P<type>\w+)(\((?P<scope>[^)]+)\))?(?P<bang>!)?: (?P<msg>.+)$")
def git_log(since: str) -> list[str]:
cmd = ["git", "log", "--pretty=%s", "--no-merges"]
if re.fullmatch(r"\d{4}-\d{2}-\d{2}", since):
cmd.append(f"--since={since}")
else:
cmd.append(f"{since}..HEAD")
out = subprocess.run(cmd, capture_output=True, text=True, check=True).stdout
return [line for line in out.splitlines() if line.strip()]
def main() -> int:
ap = argparse.ArgumentParser()
ap.add_argument("--since", required=True, help="tag, ref, or YYYY-MM-DD")
args = ap.parse_args()
groups: dict[str, list[str]] = defaultdict(list)
for subject in git_log(args.since):
m = PATTERN.match(subject)
if not m:
groups["Changed"].append(subject)
continue
bucket = "Breaking" if m["bang"] else TYPES.get(m["type"], "Changed")
if bucket != "Skip":
scope = f"**{m['scope']}**: " if m["scope"] else ""
groups[bucket].append(scope + m["msg"])
for section in ("Breaking", "Added", "Fixed", "Changed"):
if groups[section]:
print(f"### {section}")
print("\n".join(f"- {item}" for item in groups[section]))
print()
return 0
if __name__ == "__main__":
sys.exit(main())
Test it by hand before you trust the agent with it. Make a few commits first if the repo is empty:
git add -A && git commit -m "chore: add skills skeleton"
git commit --allow-empty -m "feat(api): add pagination to /orders"
git commit --allow-empty -m "fix(auth): refresh token expiry off by one"
git commit --allow-empty -m "feat!: drop v1 endpoints"
python .cursor/skills/release-notes/scripts/changelog.py --since 2000-01-01
### Breaking
- drop v1 endpoints
### Added
- **api**: add pagination to /orders
### Fixed
- **auth**: refresh token expiry off by one
The script is a plain tool. The skill tells the agent when to call it and what to do with the output. That split is the pattern to copy: judgment in Markdown, determinism in scripts.
Step 6: Write pr-review-checklist With a Reference File
Long reference material should not live in the main body. The specification recommends keeping SKILL.md under about 5,000 tokens and moving detail into separate files that load only when needed. Create the checklist at .cursor/skills/pr-review-checklist/references/checklist.md:
## Correctness
- Does every new branch have a test, or a stated reason it does not?
- Are error paths handled, not just logged?
- Do new queries use parameters rather than string building?
## Safety
- Any new secret, token, or URL committed? Fail the review.
- Any new dependency? Check license and maintenance status.
- Any change to auth, billing, or permissions? Request a second reviewer.
## Operability
- Are new log lines free of personal data?
- Is there a rollback path, and is it written down?
- Do new env vars appear in the deployment docs?
Now the skill itself, .cursor/skills/pr-review-checklist/SKILL.md:
---
name: pr-review-checklist
description: Review a diff or pull request against the team checklist. Use when the user asks to review changes, check a PR, or "look over this diff" before merging.
---
## Steps
1. Get the diff: `git diff origin/main...HEAD` unless the user names another base.
2. Read `references/checklist.md` in this skill's folder.
3. Walk the diff file by file. For each checklist item, record pass, fail, or not applicable.
4. Report failures first, each with the file, the line range, and a suggested fix.
5. Close with a verdict: approve, approve with nits, or request changes.
## Rules
- Never approve a diff that adds a secret.
- Do not rewrite code during a review. Suggest, do not edit, unless asked.
- If the diff is over 800 changed lines, say so and review by directory.
The reference link works because the instructions name the file and the agent opens it at step 2. Nothing from the checklist enters context until the skill activates and the agent reaches that step.
Step 7: Add a Guardrail Skill, db-migration-safety
Skills are not limited to producing text. A guardrail skill tells the agent what to refuse and what to check before it touches a risky area. Write .cursor/skills/db-migration-safety/SKILL.md:
---
name: db-migration-safety
description: Check and write database migrations safely. Use when the user adds, edits, or reviews a SQL migration, alters a table, adds an index or column, or asks whether a schema change is safe to deploy.
compatibility: Assumes PostgreSQL 15+ and a migrations/ folder
---
## Before writing any migration
1. Open the newest file in `migrations/` to match naming and numbering.
2. State whether the change is additive (new nullable column, new table) or destructive (drop, rename, type change).
## Rules
- Destructive changes ship in two releases: stop reading the column first, drop it later.
- New NOT NULL columns need a default or a backfill step, never a bare constraint on a populated table.
- Create indexes with `CREATE INDEX CONCURRENTLY` and keep that statement outside a transaction.
- Never rename a column in one step. Add the new one, copy, switch reads, drop the old one.
- Every migration gets a down script, or a written note that it cannot be reversed.
## Output
Return the migration, the rollback, and a three-line risk note: lock behavior, estimated duration on a large table, and what to monitor after deploy.
Notice the rules are phrased as constraints the agent can verify. “Be careful with indexes” gives the model nothing to act on, while “use CREATE INDEX CONCURRENTLY” gives it a testable instruction.
Test Activation (Steps 8-9) #
Step 8: Test That Each Skill Activates on Its Own
Open the agent chat in the project and run three prompts without naming any skill. Watch whether the agent reads the matching SKILL.md. Cursor surfaces skill usage in the agent’s step list, so you can see the file being opened.
| Prompt (no skill name) | Expected skill | What you should see |
|---|---|---|
| Write up what shipped in the latest release | release-notes |
Agent runs scripts/changelog.py |
| “Look over my diff before I merge” | pr-review-checklist |
Agent runs git diff , then opensreferences/checklist.md |
| “Add an index on orders.customer_id” | db-migration-safety |
Agent chooses CREATE INDEX CONCURRENTLY and writes a rollback |
| “What is a closure in JavaScript?” | None | No skill loads |
The fourth row matters as much as the first three. A skill that fires on unrelated questions wastes context and annoys people. If the closure question pulls in the migration skill, your description is too broad.
A passing run for the first prompt looks roughly like this in the step list:
Reading .cursor/skills/release-notes/SKILL.md
Running: python .cursor/skills/release-notes/scripts/changelog.py --since v1.4.0
Drafting release notes...
Models are not deterministic. Run each prompt three times. If a skill fires two out of three, tighten the description with more of the phrases people actually type.
Step 9: Invoke a Skill Explicitly With a Slash Command
Automatic matching is convenient, and explicit invocation is dependable. Type / in the agent chat and the menu lists available skills. Pick release-notes or type it directly:
/release-notes since v1.4.0, group by team
The explicit form skips the matching step. Use it when you want a guaranteed run, such as the last step of a release checklist. Then run /skills and read the panel. Cursor reportedly flags a name that does not match its folder, a description past 1,024 characters, and a body over roughly 5,000 tokens. Fix every warning now, because those are the same rules the validator enforces in the next step.
Validate, Ship and Share (Steps 10-12) #
Step 10: Build a Validator That Fails on Bad Skills
Editor warnings help the author. A CI check helps the team, because a skill broken by a bad merge fails quietly: the agent just stops using it. Write tools/validate_skills.py:
#!/usr/bin/env python3
"""Validate SKILL.md files against Agent Skills limits."""
import re
import sys
from pathlib import Path
ROOTS = [".cursor/skills", ".agents/skills"]
NAME_RE = re.compile(r"^[a-z0-9]+(-[a-z0-9]+)*$")
MAX_NAME, MAX_DESC, MAX_BODY_TOKENS = 64, 1024, 5000
def parse(text: str):
m = re.match(r"^---\n(.*?)\n---\n(.*)$", text, re.S)
if not m:
return None, text
meta = {}
for line in m.group(1).splitlines():
if ":" in line and not line.startswith((" ", "\t")):
key, _, val = line.partition(":")
meta[key.strip()] = val.strip()
return meta, m.group(2)
def approx_tokens(body: str) -> int:
return int(len(body.split()) * 1.35)
def check(path: Path) -> list[str]:
errors = []
meta, body = parse(path.read_text(encoding="utf-8"))
folder = path.parent.name
if meta is None:
return [f"{path}: missing YAML frontmatter"]
name, desc = meta.get("name", ""), meta.get("description", "")
if not name:
errors.append(f"{path}: missing name")
elif len(name) > MAX_NAME or not NAME_RE.match(name):
errors.append(f"{path}: invalid name '{name}'")
elif name != folder:
errors.append(f"{path}: name '{name}' != folder '{folder}'")
if not desc:
errors.append(f"{path}: missing description")
elif len(desc) > MAX_DESC:
errors.append(f"{path}: description is {len(desc)} chars (max {MAX_DESC})")
elif len(desc) < 40:
errors.append(f"{path}: description too short to trigger reliably")
if approx_tokens(body) > MAX_BODY_TOKENS:
errors.append(f"{path}: body about {approx_tokens(body)} tokens (max {MAX_BODY_TOKENS})")
for ref in re.findall(r"`((?:references|scripts)/[^`\s]+)`", body):
if not (path.parent / ref).exists():
errors.append(f"{path}: referenced file missing: {ref}")
return errors
def main() -> int:
files = [p for r in ROOTS for p in Path(r).glob("*/SKILL.md")]
if not files:
print("no skills found")
return 1
problems = [e for f in sorted(files) for e in check(f)]
for e in problems:
print("FAIL", e)
print(f"checked {len(files)} skills, {len(problems)} problems")
return 1 if problems else 0
if __name__ == "__main__":
sys.exit(main())
Run it:
python tools/validate_skills.py
FAIL .cursor/skills/pr-review-checklist/SKILL.md: referenced file missing: references/checklist.md
checked 3 skills, 1 problems
If you saved the checklist file in Step 6 the failure will not appear, and the last line reads checked 3 skills, 0 problems. The reference check is the most useful rule in the script. It catches the commonest silent failure, where a skill points to a file that was renamed or never committed.
The token estimate multiplies the word count by 1.35. That is a rough guide, not a tokenizer, so treat the limit as a smoke alarm.
Step 11: Run the Validator in CI
Add .github/workflows/skills.yml:
name: validate-skills
on:
pull_request:
paths:
- ".cursor/skills/**"
- ".agents/skills/**"
- "tools/validate_skills.py"
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: python tools/validate_skills.py
A pull request that touches a skill now fails when the frontmatter breaks. Pair this with a code owner on the .cursor/skills/ folder, because a skill is effectively a prompt with the authority of repo policy. A reviewer should read it the way they read a deploy script.
Step 12: Share Across Tools and Run Skills in the Cloud
Commit everything:
git add -A
git commit -m "feat: add release-notes, pr-review-checklist, db-migration-safety skills"
git push -u origin main
Teammates who pull the branch get the skills in their next Cursor session. Nothing to install.
Because the format is now an open standard, you can expose the same folders to other agents. The Agent Skills convention uses .agents/skills/<skill-name>/SKILL.md, and Cursor’s community documentation lists it as a supported location. The simplest way to serve both is a symlink:
mkdir -p .agents
ln -s ../.cursor/skills .agents/skills
git add .agents && git commit -m "chore: expose skills to other agents"
Windows teammates may need Git’s symlink support enabled, or a copy step in CI instead. If your team also runs Claude Code or other terminal agents, the roundup of Claude Code, Codex CLI and OpenCode updates shows how fast those tools are changing, which is another reason to keep your procedures in a portable format.
For Cloud Agents and Automations, keep the skills in the repository and confirm the agent registers them on its first run. Reports from October 13 to 22 say personal skills can run when an automation uses the “Run as you” setting, while service-account automations need the skill in the selected repository’s .cursor/skills/ directory or in a team plugin.
Writing Descriptions That Trigger Reliably #
Most of the work in a good skill happens in two lines of frontmatter. The agent never sees your carefully ordered steps until the description wins the match, so spend your editing time there.
A strong description has three parts: a verb phrase that says what the skill produces, a “Use when” clause with the words people really type, and an optional boundary that names what the skill is not for. Compare these rewrites.
| Weak description | Stronger description | Why it wins |
|---|---|---|
| Helps with releases | Draft release notes from git history. Use when the user asks for a changelog, release notes, or what shipped between two tags. | Names the output and the trigger phrases |
| Database stuff | Check and write SQL migrations safely. Use when adding a column, index or table, or asking if a schema change is safe. Not for query tuning. | Separates migration work from query work |
| Code review | Review a diff against the team checklist. Use before merging a pull request. Not for style-only formatting. | States the moment of use and the exclusion |
| Testing helper | Generate pytest cases for a function the user selects. Use when asked to add tests, raise coverage or reproduce a bug in a test. | Lists three concrete request shapes |
Two habits make descriptions better over time. First, write them in the third person and in the present tense, since the agent reads them as catalog entries. Second, mine your own chat history for the real wording. If colleagues keep typing “cut a release” and your description says “publish a version”, add the phrase they use.
A worked end-to-end run
Put the three skills to work on a single change. Suppose you add a nullable shipped_at column and a pagination feature, then ask the agent, in one message, to prepare the pull request.
Add shipped_at to orders, then review my diff and draft release notes since v1.4.0
A healthy run shows three skills firing in a sensible order:
Reading .cursor/skills/db-migration-safety/SKILL.md
-> additive change (new nullable column), no backfill needed
-> writing migrations/0042_add_shipped_at.sql and rollback
Reading .cursor/skills/pr-review-checklist/SKILL.md
Reading .cursor/skills/pr-review-checklist/references/checklist.md
-> 11 items checked, 0 failures, 1 note (log line contains order id)
Reading .cursor/skills/release-notes/SKILL.md
Running: python .cursor/skills/release-notes/scripts/changelog.py --since v1.4.0
-> 3 sections drafted: Added (2), Fixed (1), Changed (1)
If only two of the three fire, do not edit the skills yet. Re-run with each task in its own message first. Multi-task prompts are the hardest case for any matching system, and a skill that works singly but not in a bundle is better fixed by splitting your request than by bloating descriptions.
The Complete Working Project #
By now the repository looks like this:
cursor-skills-lab/
├── .cursor/
│ └── skills/
│ ├── db-migration-safety/
│ │ └── SKILL.md
│ ├── pr-review-checklist/
│ │ ├── SKILL.md
│ │ └── references/checklist.md
│ └── release-notes/
│ ├── SKILL.md
│ └── scripts/changelog.py
├── .agents/skills -> ../.cursor/skills
├── .github/workflows/skills.yml
└── tools/validate_skills.py
| Component | Role | Failure it prevents |
|---|---|---|
Three SKILL.md files |
Procedures the agent loads on demand | Re-typing the same instructions every session |
changelog.py |
Deterministic grouping of commits | Model miscounting or inventing commits |
checklist.md |
Reference loaded only during reviews | Bloated context on unrelated chats |
validate_skills.py |
Frontmatter, size and reference checks | Silent skill breakage after a merge |
skills.yml |
Runs the validator on pull requests | Unreviewed edits to repo policy |
.agents/skills link |
Same skills for other agents | Maintaining two copies |
Total effort for the library: about 45 minutes the first time, and roughly 5 minutes for each skill you add afterward.
Rolling Skills Out to a Team #
A library that one person understands is a hobby. A library that ten people trust needs ownership, a review path and a retirement policy. The setup is light, and it pays off the first time someone edits a skill without telling anyone.
Start with ownership. Add a CODEOWNERS entry so every change to a skill requests review from the people who care about that procedure:
/.cursor/skills/db-migration-safety/ @your-org/platform-team
/.cursor/skills/pr-review-checklist/ @your-org/eng-leads
/.cursor/skills/release-notes/ @your-org/release-managers
/tools/validate_skills.py @your-org/eng-leads
Then stage the rollout so problems surface while the blast radius is small.
| Phase | Duration | Who | Goal | Exit check |
|---|---|---|---|---|
| Pilot | 1 week | 2 or 3 volunteers | Find descriptions that misfire | Prompt list passes 9 of 10 triggers and 10 of 10 non-triggers |
| Team default | 2 weeks | Whole team | Collect missing steps and wording | No open complaints about wrong activations |
| Cloud and CI | 1 week | Platform owner | Confirm repo skills register in Cloud Agents and automations | First automation run reads the skill |
| Steady state | Ongoing | Code owners | Quarterly pruning | Unused skills retired |
Measure with simple evidence rather than dashboards. Ask the pilot group to note each time a skill fired when it should not have, and each time it stayed silent when it should have fired. Those two lists tell you exactly which descriptions to edit. Save the prompts that exposed the problem in your test file so the fix stays fixed.
Retire skills on purpose. When a procedure changes, such as a move to a new migration tool, update the skill in the same pull request as the tooling change. When a procedure disappears, delete the folder. A stale skill is worse than none because the agent follows it with full confidence.
Finally, write a short contributor note in the repo README: where skills live, how to name them, how to run the validator locally, and who approves changes. Keep it under 15 lines. Contributors will read a short note, and they will ignore a long one.
Common Pitfalls When Writing Cursor Skills #
These seven mistakes account for most of the broken skills people report on the forums.
1. A vague description. The description is the only text the agent sees before deciding to load a skill. “Helps with releases” matches nothing in particular. Write what the skill does, then add “Use when” followed by the phrases a person would type. Aim for 150 to 400 characters, well under the 1,024 limit.
2. Saving a bare Markdown file. A skill is a SKILL.md inside its own subdirectory. A file named .cursor/skills/release-notes.md is invisible. This is the single most common reason a new skill never shows up.
3. A name that does not match the folder. The folder is release_notes, the frontmatter says release-notes, and the editor warns while the agent quietly ignores the skill. Names allow lowercase letters, numbers and hyphens only, up to 64 characters. Underscores and capitals fail.
4. Stuffing the body. The recommended ceiling is under 5,000 tokens for the body, and the full body is loaded every time the skill is activated. Move long tables and examples into references/ and tell the agent when to open them.
5. Putting personal skills where Cloud Agents cannot see them. A skill in ~/.cursor/skills/ works on your laptop. On a Cloud Agent VM it may be present on disk yet never register. If a skill must run in the cloud or in an automation, commit it to the repository.
6. Writing preferences instead of procedures. “Prefer small functions” is a rule, and it belongs in .cursor/rules/. A skill earns its place when it contains ordered steps, a definition of done, and ideally a script. If you cannot number the steps, you probably have a rule.
7. Trusting a script you never read. Skills can bundle code that the agent will run with your permissions. Read every script in a downloaded skill the way you would read an install script from the internet.
Troubleshooting: 10 Fixes for Skills That Do Not Work #
| # | Symptom | Likely cause | Fix |
|---|---|---|---|
| 1 | Skill missing from /skills |
Bare .md file or wrong folder |
Move to .cursor/skills/<name>/SKILL.md and restart the window |
| 2 | Warning about invalid name | Capitals, underscores or spaces | Rename folder and name to lowercase-with-hyphens |
| 3 | Warning: name does not match folder | Rename done in only one place | Make both identical |
| 4 | Skill exists but never auto-fires | Description too generic | Add “Use when” triggers with real user phrasing, or invoke with /name |
| 5 | Skill fires on unrelated questions | Description too broad | Narrow the nouns, add what the skill is not for |
| 6 | Agent says it cannot find the script | Relative path resolved from the wrong folder | State “from this skill’s folder” in the body and use clear relative paths |
| 7 | Works locally, absent in Cloud Agent | Personal skill in ~/.cursor/skills/ |
Commit it to .cursor/skills/ in the repo |
| 8 | Automation ignores the skill | Service-account run with personal skill | Place skill in the repo or a team plugin |
| 9 | Edits to SKILL.md have no effect |
Session cached the old frontmatter | Start a new chat, or reload the window |
| 10 | Validator reports a missing reference | File renamed or not committed | Fix the path in the body or commit the file |
When two skills compete
If two descriptions overlap, the agent may pick the wrong one. Give each skill a distinct domain noun, such as “SQL migration” versus “pull request diff”, and mention the neighbor in the description when the boundary is subtle: “Not for application code review.” Then re-run the activation prompts from Step 8.
When the agent ignores a step
Long procedures drift. If the agent skips step four, shorten the body, make the step an explicit checkpoint (“Do not continue until the test output is pasted”), and move optional detail to a reference file. Short, numbered, verifiable steps outperform paragraphs of prose.
When the model is the problem
Skills do not fix a weak model. As of late October 2026 Cursor lists a range of models, including recently released ones from Anthropic such as Claude Opus 5.5 and Sonnet 5.5, plus Cursor’s own Composer line. Before you rewrite a skill for the fifth time, run the same prompt on a stronger model. If the failure disappears, your skill was fine and the model lacked the capacity to follow it. Because third-party models are reportedly billed separately at API list prices on the new plans, run that comparison once, not in a loop.
Advanced Tips for Cursor Skills #
Put a “done when” line in every skill. A single sentence that defines completion gives the agent a stopping condition and gives you something to grade. The release-notes example ends with “every commit in the range is either represented in a line or consciously dropped,” which an auditor can check.
Let scripts do the counting. Models are unreliable at arithmetic over long lists. Any skill that tallies, diffs or parses should call a script and read its output. The changelog helper in Step 5 is the template.
Chain skills deliberately. A release workflow can name other skills in its steps: draft notes with release-notes, then run pr-review-checklist on the changelog PR. Keep each skill single-purpose and let a short orchestrating skill call them in order.
Version your skills like code. Put a line in the body such as “Updated for Postgres 15+” and tag the repo when procedures change. When an incident review asks why the agent behaved a certain way, the Git history of .cursor/skills/ is your answer.
Pair skills with MCP. A skill can describe how to use a server’s tools well: which tool to call first, which arguments to avoid, how to read the result. Bloomberg reported on October 21, 2026 that Skills over MCP (SEP-2640) became an official MCP extension during September, a single-source claim worth confirming on the MCP project blog. Either way, a local skill that documents your own MCP server is a cheap win. If you are building the server side, the secure MCP server walkthrough shows how to harden it.
Test descriptions like search queries. Keep a plain text file of 10 prompts that should trigger a skill and 10 that should not. Run it after every description edit. It takes three minutes and catches regressions that no linter will.
Keep the catalog small. Each skill adds roughly 50 to 100 tokens of catalog text to every conversation. Fifty skills is manageable, but 500 is a different problem. Prune skills nobody invoked in the last quarter.
Security: Treat Skills as Executable Code #
A skill is instructions plus, sometimes, scripts, and both run with the agent’s authority. Researchers have already measured the risk. An academic paper on arXiv (2601.10338), summarized by the Agentic AI Wiki, studied skills collected from public marketplaces and reported that skills bundling executable scripts were 2.12 times more likely to contain a vulnerability than instruction-only skills. The same summary notes the largest real campaign it examined hid its payload in prose inside SKILL.md, not in code, so reading only the scripts is not enough.
Apply four habits:
- Review third-party skills in full, including the Markdown body, before copying them into
.cursor/skills/. - Never give a skill instructions to fetch and execute remote content.
- Keep secrets out of skill folders. A reference file is committed to Git like any other.
- Require code-owner review on the skills directory, as set up in Step 11.
The Agent Skills GitHub organization hosts the open specification and discussion, which is the right place to follow security guidance now that the standard has moved to the Agentic AI Foundation.
For broader tooling choices in this area, the software and developer tools hub tracks Cursor and its rivals.
Frequently Asked Questions #
What are Cursor Skills?
Cursor Skills are folders containing a SKILL.md file with YAML frontmatter and Markdown instructions, plus optional scripts and reference files. The agent reads each skill’s name and description, loads the full instructions when a task matches, and you can also invoke one directly with a slash command.
Where do I put a skill file in Cursor?
Use .cursor/skills/<skill-name>/SKILL.md for a project, ~/.cursor/skills/<skill-name>/SKILL.md for all your projects, or .agents/skills/<skill-name>/SKILL.md for the cross-tool convention. For Cloud Agents and automations, the repository location is the dependable choice.
How is a skill different from a Cursor rule?
A rule is a standing convention that applies to every request or to files matching a glob. A skill is a procedure the agent loads on demand for a specific kind of task. Use rules for style and stack facts, and skills for multi-step workflows.
How long can a SKILL.md be?
The name is limited to 64 characters and the description to 1,024 characters. The specification recommends keeping the body under 5,000 tokens and moving detail into separate reference files that load only when needed.
Do Cursor Skills work in other tools?
Yes. Agent Skills is an open format, and Anthropic reported that more than 70 agent platforms, including Cursor, had integrated it by October 22 and 23, 2026. A skill written to the specification can be shared across compatible tools, though behavior can still vary by agent and model.
Do skills cost extra in Cursor?
Skills are a feature of the format and carry no separate price. They do consume context tokens, and long agent runs count against your plan. Cursor changed its plans on October 12, 2026, and reports say third-party models are billed at API prices on the new tiers, so check your plan page for current rules.
Why does my skill not trigger automatically?
Usually the description is too generic or the file is not in a skill subfolder. Rewrite the description with explicit “Use when” phrases, confirm the folder structure with /skills, and use /skill-name as a fallback while you tune the wording.
Can I use skills with Cursor Cloud Agents?
Yes, when the skill lives in the repository. Reports from October 2026 say synced personal skills may not register on Cloud Agent VMs, while repository skills and plugin skills work.