Beyond Prompt Files: Cursor Skills and Subagents
You built a /review-diff command. Fifty lines of Markdown: check scope creep, flag missing tests, don’t edit files. You run it before every PR. Perfect.
Every time you run it, the same failure mode shows up: the agent “reviews” your auth middleware change by rewriting three unrelated components, deletes a test it decided was redundant, and gives you a cheerful summary that never mentions the security regression you introduced two files up.
The prompt was fine. The architecture was wrong.
A classic slash command does one thing: it injects text into the chat you are already in. Same agent that will implement your next feature. Same write access. Same wandering context. “Do not edit files” is a suggestion; the runtime does not enforce it.
That is not a prompt engineering problem. It is a separation of concerns problem.
I still use classic slash commands for one-shot work—scaffold a component, draft a PR body, fix lint errors. When a task needs a dedicated specialist with its own session, output shape, and permissions, I use Skills that delegate to subagents.
Same / menu. Different contract.
What Are Skills and Subagents?
Classic commands live in .cursor/commands/*.md (or ~/.cursor/commands/ globally). Each file is a prompt: Cursor reads it and appends the text to your current Agent chat. That model still works and still appears in the / dropdown.
Skills live in .cursor/skills/<name>/SKILL.md (or ~/.cursor/skills/ globally). They also appear in /, but they are designed as routers: short frontmatter (name, description, optional disable-model-invocation: true) plus instructions for when and how to delegate.
Subagents live in .cursor/agents/<name>.md. Each file defines a specialist: role, discovery steps, output format, and frontmatter flags like readonly: true or readonly: false.
Commands and Skills coexist. Use commands when you want a pasted prompt in the room you are already in. Use Skills when you want to route work to a specialist in a separate session.
Personal vs project scope: files under ~/.cursor/ follow you across repos; files under .cursor/ in a project are version-controlled and shared with your team. I keep workflow routers (/pre-plan, /pre-review) in ~/.cursor/skills/ and project-specific agents or rules in the repo.
The pattern is always the same: Skill triggers → subagent runs → structured result returns → you decide what happens in main chat.
+ optional edits"] end subgraph SkillFlow ["Skill + subagent"] Skill["/pre-plan"] --> Delegate["Task tool delegates"] Delegate --> Sub["Subagent session
readonly: true"] Sub --> Out2["Fixed report shape
no collateral edits"] Out2 --> You["You implement
in a fresh chat"] end
Two Approaches, Same Slash Menu
Classic command: the prompt is the worker
File: .cursor/commands/plan-feature.md
# Plan a change
List affected files, risks, and three options.
Do not write code until I approve.
You type /plan-feature remove legacy useModal hook — keep ModalProvider API.
What happens under the hood:
- Cursor reads the file and appends it to your current Agent prompt.
- The main agent greps the repo, reasons, responds.
- Nothing stops it from opening files and patching them in the same turn.
- Tomorrow you run the same command and get a different outline—no fixed sections, no severity tiers.
The command file is a script you paste. The executor is whoever is already in the room.
Skill + subagent: the prompt routes to a specialist
Two files instead of one.
Skill (.cursor/skills/pre-plan/SKILL.md) — thin entry point:
---
name: pre-plan
description: Pre-implementation planning before code changes
disable-model-invocation: true
---
The body is short: spawn implementation-planner, readonly, return a structured brief—do not plan in this chat.
Subagent (.cursor/agents/implementation-planner.md) — the playbook:
---
name: implementation-planner
readonly: true
---
Discovery steps, risk grading, minimum three options, fixed output headings—all live here.
Subagent permissions are configurable. In the agent frontmatter you set readonly: true or readonly: false. For planning and review workflows I use readonly: true so the runtime blocks file edits—the constraint is declared in config, not buried in a prompt line. A subagent that implements fixes after review would use readonly: false; the Skill still delegates, but the specialist is allowed to write.
You type /pre-plan remove legacy useModal hook — keep ModalProvider API.
What happens under the hood:
disable-model-invocation: trueblocks inline execution—the Skill must delegate.- A separate session runs discovery (with
readonly: true, no file edits): definition, callers, tests, hidden coupling. - You get the same report shape every time: Scope → Impact map → Risks → Options → Recommendation.
- You implement in a fresh chat when you are ready to edit.
The Skill is a button. The subagent is a specialist. Your implementation session never sat through the planning grep marathon.
Side by Side
.cursor/commands/*.md |
Skill + .cursor/agents/*.md |
|
|---|---|---|
| What you author | Full instructions | Router + specialist playbook |
| Who runs it | Main Agent | Delegated subagent |
| Can it edit files? | Yes — main Agent has write access by default | Configurable — readonly: true or readonly: false on the subagent |
| Output | Whatever the model feels like | Sections you define |
| Context | Eats your working chat | Report in, you decide next |
| Sweet spot | Generate, fix, template | Delegated workflows: plan, review, explore, audit |
A commit-message command does not need this machinery. Any workflow where you want a separate brain, fixed report sections, and configurable write access does.
Not every Skill needs disable-model-invocation: true. Use it when the Skill must not run inline — when delegation is the point. Not every subagent needs readonly: true. Use readonly for investigation and review; allow writes when the specialist should implement fixes in isolation.
Example Patterns You Can Build
The table below is illustrative — names you might invent for your own routers and specialists. Only /pre-plan and /pre-review are ones I run daily; the rest show how the same split applies elsewhere.
| Skill (entry) | Subagent (worker) | Typical use |
|---|---|---|
/pre-plan |
implementation-planner |
Impact map, risks, options before coding |
/pre-review |
strict-reviewer |
Severity-ranked diff review before PR |
/explore-module |
codebase-explorer |
How does X work — report only, no edits |
/audit-deps |
dependency-auditor |
License/CVE pass over manifest files |
/draft-migration |
migration-planner |
Schema or API migration options |
/test-gaps |
coverage-reviewer |
What behavior changed but has no test |
Five-Minute Setup
1. Create a subagent — .cursor/agents/strict-reviewer.md:
---
name: strict-reviewer
readonly: true
---
Review the current diff. Output: Critical / Warning / Suggestion / Checks run.
Do not edit files. Run git diff first.
2. Create a Skill — .cursor/skills/pre-review/SKILL.md:
---
name: pre-review
description: Strict diff review before PR
disable-model-invocation: true
---
Launch strict-reviewer (readonly). Return severity-ranked report only — do not review inline.
3. Invoke — type /pre-review focus on auth changes in Agent chat.
You should see delegation to a separate session (not an inline review in your current thread). The subagent returns a fixed report shape; your main chat stays clean for implementation.
For project-wide conventions and verify steps, add AGENTS.md at the repo root. Cursor reads it when agents work in that project.
See also Cursor documentation for the latest on commands, skills, and agent configuration.
Two Gates I Actually Use
/pre-plan and /pre-review are the pair I reach for most. Both follow the same Skill → subagent split described above.
/pre-plan — evidence before edits
Use when the cost of guessing is higher than waiting five minutes. Input can be informal:
/pre-plan remove useModal — keep ModalProvider.create API
/pre-plan how does session refresh interact with the API client
The implementation-planner subagent proves claims from the repo: locate definitions, map callers and tests, grade risks, list at least three options (including “do nothing”), recommend one path. You read the report, then open the editor.
/pre-review — review without collateral damage
Classic /review-diff fails predictably: the agent “fixes” while reviewing, or praises a diff it never fully read.
/pre-review delegates to strict-reviewer with readonly: true and git-first discovery (git diff → staged → branch vs default → latest commit). Output is always Critical / Warning / Suggestion / Checks run. No drive-by refactors — you apply fixes in the session you choose.
What to Keep in Git
| Path | Role |
|---|---|
.cursor/skills/*/SKILL.md |
Project-specific routers (optional — I use ~/.cursor/skills/ for personal ones) |
.cursor/agents/*.md |
Specialist playbooks shared with the team |
.cursor/rules/*.mdc |
Scoped guardrails (optional) |
AGENTS.md |
Commands, verify steps, project conventions |
Skills trigger. Agents investigate. Rules constrain. You merge.
When to Stay on Classic Commands
Keep .cursor/commands/ when:
- One shot, immediate output (“add a Vitest file for this module”).
- You want edits in the same turn.
- Structure does not matter.
Add Skills + subagents when:
- Readonly is a requirement, not a line in a prompt — set
readonly: trueon the subagent. - You need comparable reports across runs.
- Your implementation chat is precious and you refuse to fill it with discovery noise.
I use both. Commands for velocity. Skills + subagents whenever the job needs a specialist with a fixed report shape.
Conclusion
Classic slash commands made prompts shareable. Skills and subagents make workflows much harder to ignore — delegation and readonly are declared in config, not buried in paragraph twelve of a Markdown file.
- Command = paste instructions into the agent you already have.
- Skill = delegate, with
disable-model-invocationas the tripwire. - Subagent = specialist playbook;
readonlyin frontmatter controls whether it can edit files.
The same Skill → subagent split works anywhere you need a structured report from a separate session instead of a pasted prompt.