TL;DR
SKILL.mdis Claude Code's plugin-style format — YAML frontmatter, body of instructions, can be triggered by name. .cursorrules is a single plain-text file at the repo root that Cursor injects before every prompt. .windsurfrules follows the same idea for Windsurf (Codeium), with a slightly richer XML-ish syntax for global vs. workspace rules. copilot-instructions.mdis GitHub Copilot's equivalent, also plain markdown but scoped per repo via .github/.
They all do the same conceptual thing — pin context to a project so the AI behaves consistently. They diverge on three axes that bite in practice: scope, activation, and versioning.
| Dimension | SKILL.md | .cursorrules | .windsurfrules | copilot-inst. |
|---|---|---|---|---|
| IDE | Claude Code | Cursor | Windsurf / Codeium | GitHub Copilot |
| File location | .claude/skills/<name>/SKILL.md | .cursorrules at repo root | .windsurfrules at repo root | .github/copilot-instructions.md |
| Frontmatter | YAML | None | None | None |
| Trigger model | Named, on-demand | Always-on | Always-on | Always-on |
| Multiple skills | Yes — folder per skill | One file (concat) | One file (sections) | One file (concat) |
| Versioning | Semver in frontmatter | Git history only | Git history only | Git history only |
1. SKILL.md (Claude Code)
Anthropic's Claude Code uses a folder-per-skill model. Each skill lives at .claude/skills/<name>/SKILL.md with YAML frontmatter that declares metadata and triggers:
---
name: code-review
description: Strict review checklist enforcing security, performance,
and maintainability standards before merge.
version: 1.2.0
triggers: [code-review, review, pr-review]
tags: [quality, security, review]
---
# Code Review
You are a senior engineer reviewing a pull request...The big idea is on-demand activation. The skill isn't injected on every prompt — it loads when the user types a triggering phrase or invokes it explicitly. That keeps your context window clean and lets you have many skills coexist without blowing up token budgets.
What it's good at: a library of specialized behaviours (review, refactor, write tests, generate migration). The named-trigger model scales further than a single always-on file.
What it's bad at:always-on context. If you want a rule like “every TypeScript file must use strict mode” to apply automatically, SKILL.md isn't the right tool — Claude Code has separate CLAUDE.md files for that.
2. .cursorrules (Cursor)
Cursor takes the opposite approach. One file at the repo root, plain text or markdown, injected before every prompt the assistant sees:
# Project: Skillwright
## Coding standards
- Strict TypeScript. No `any`, no unguarded type assertions.
- React components are functions with typed props (no React.FC).
- Files stay under 800 lines. Functions under 50.
## Testing
- Vitest for unit, Playwright for E2E.
- 80% line coverage minimum.
## Don't
- Don't run `pnpm install` without me asking.
- Don't introduce a new dependency without flagging it.It's elegant: one file, no metadata, no schemas. Cursor reads it on every chat. The cost is that everything is always on — no way to scope a rule to one task or one trigger. The file gets long, and long files start contradicting themselves.
What it's good at: codifying repo-wide conventions every contributor (human or AI) needs to follow.
What it's bad at: task-specific behaviour. Trying to use .cursorrulesas both “general standards” and “activate code-review mode” muddles both jobs.
3. .windsurfrules (Windsurf / Codeium)
Windsurf uses a similar root-file convention but with a richer structure: rules can be tagged with scope (global vs. workspace) and grouped semantically:
# Project rules
<rule>
trigger: always
content: |
Use strict TypeScript. Forbid `any` and unguarded `as` casts.
All public functions have explicit return types.
</rule>
<rule>
trigger: glob
glob: "**/*.test.ts"
content: |
Use Vitest. Each test has a single assertion or a tightly
related group asserting one fact.
</rule>The glob trigger is genuinely useful — you can scope rules to test files, migration files, etc. without polluting the global context window. But the syntax is non-portable; you can't paste a .windsurfrules file into Cursor and have it work.
What it's good at: medium-complexity setups where some rules are global and others apply only to certain file patterns.
What it's bad at: portability. The tag-syntax-everywhere model is unique to Windsurf.
4. copilot-instructions.md (GitHub Copilot)
Copilot's answer is the simplest of the four: a markdown file at .github/copilot-instructions.md that Copilot reads into context when it operates inside that repo:
# Copilot instructions for Skillwright
This is a Tauri 2.0 desktop app with a React + TypeScript frontend
and a Rust backend.
## When generating code
- Frontend uses Zustand for state, never React Context.
- Backend commands are `async fn` returning `Result<T, String>`.
- Path APIs use `app_handle.path().app_data_dir()` (Tauri v2).
- Don't use `tauri::api::*` — removed in v2.This is the lowest-overhead option of the four. It's also the least expressive — no triggers, no scoping, just one file the AI reads when you're in this repo. For most projects it's enough. For projects with many distinct AI workflows, it isn't.
What it's good at: stable cross-team conventions. Easy to review in a PR.
What it's bad at: anything that needs to be conditional on task or file pattern.
Where they overlap
All four formats encode the same handful of things in practice:
- Project-wide coding conventions (style, types, structure).
- Forbidden patterns (don't use X, don't modify Y).
- Tooling preferences (use this test runner, this formatter).
- Domain context (what this project is, who uses it).
For a typical mid-size repo, ~80% of the content is identical across all four files. The remaining 20% is where the formats actually differ — and where things go wrong.
The hidden cost of running all four
Most teams I talk to who use multiple AI coding tools end up with three or four of these files in their repo. The cost shows up six ways:
- Drift. Someone updates
.cursorrulesafter a tricky bug. The same lesson never makes it into.windsurfrulesorcopilot-instructions.md. Six months later, the AI in Windsurf reintroduces the same bug. - Copy-paste rot. Engineers paste the same content into four files with slight reformatting. Now you have four versions of the same rule, none authoritative.
- No version history.“When did we add the no-any rule?” can be answered with
git log .cursorrules, but only crudely. There's no semantic versioning, no changelog, no “rule v2.1 tightens this”. - No reuse across projects. The TypeScript-strict rules you wrote for one repo get re-typed for the next. Every repo is its own snowflake.
- No deactivation path.If a rule is wrong, you find out when the AI generates wrong code, not from a lint warning. There's no
npm auditfor prompts. - Onboarding cost. A new engineer joining the team has to read four config files in four formats and figure out which one is authoritative — usually nobody knows.
Strategies people try (and why they break)
Strategy A — “Just use one tool”
Tempting, doesn't work in practice. Different team members prefer different IDEs. Different tasks favour different tools (Cursor for tight inline edits; Claude Code for multi-file refactors; Copilot for autocomplete). Forcing one tool wastes more time than it saves.
Strategy B — Symlinks
.cursorrules → copilot-instructions.md. Cute, but the files diverge in syntax (Windsurf's tag-based, Claude's YAML-frontmatter) and you can't symlink across those. Also .github/copilot-instructions.md is in a subdirectory which complicates everything.
Strategy C — Generate from a single source
Write your conventions once in some canonical format and generate the four IDE files at build time with a script. This works — but the script is its own maintenance burden, and most teams never get past the “I'll do it later” stage.
The unified-format approach
We built Skillwright because Strategy C is the right answer and the script is the wrong artifact. Skillwright is a desktop app that holds your skills in a canonical format (YAML-frontmatter SKILL.md), then compiles to all four IDE-native formats — .cursorrules, .windsurfrules, copilot-instructions.md, and Claude Code's SKILL.md folders — and deploys the right files to the right paths in every project you choose.
You author once. You version once. When you fix a rule, the fix propagates to every IDE in every project. Drift becomes a thing Skillwright shows you, not a thing you discover by accident.
We're also publishing a small library of MIT-licensed starter skills — code review, commit conventions, TypeScript strict, security review, TDD, accessibility — that you can drop in without writing anything from scratch.
Comparison summary
If you're picking just one format because you only use one tool:
- Many distinct AI workflows in one repo: SKILL.md (named, on-demand activation).
- One set of repo-wide conventions, no scoping:
.cursorrulesorcopilot-instructions.md. - Mixed always-on + glob-scoped rules:
.windsurfrules.
If you use more than one tool — which most teams do — Skillwright turns the four-files problem into a one-library decision.
Further reading
- Free SKILL.md, .cursorrules, and .windsurfrules templates — six MIT-licensed skills you can install in one click.
- Founding Member pricing — $24.99 lifetime, first 100 customers.