AI Skills Are Not Prompts: A Markdown File That Gives Your Coding Agent Permanent Memory
Write Your First AI Skill Step by Step: From Principles to Engineering
Frontend AI Skill System · Introductory Chapter
Vercel's writing-guidelines Skill has been installed 32,500 times. GitHub's official create-agentsmd has been installed 11,800 times. This is not a toy—it is the infrastructure of AI programming in 2026.
Table of Contents
- Conclusion First
- I. Principles: 6 Things You Must Know Before Writing
- II. Hands-on: Write a Daily Report Generator in 15 Minutes
- III. Complex Skills: When 30 Lines Are Not Enough
- IV. Universal Standards: Rules Every Skill Should Follow
- V. Q&A
- VI. Mainstream Platform Adaptation: One Skill Runs on All IDEs
- Conclusion
Conclusion First
Skill = A Markdown file that tells the AI "when to use you, how to work, and what not to do."
It is not a Prompt. A Prompt is a one-off conversation. A Skill is a persistent professional SOP—write it once, and it automatically takes effect in every conversation.
Cursor calls it .cursor/rules/*.mdc, Claude Code calls it CLAUDE.md, GitHub calls it AGENTS.md, and skills.sh calls it SKILL.md. Different names, same essence.
This article teaches you to write one from scratch, then engineer it.
I. Principles: 6 Things You Must Know Before Writing
1.1 Trigger Conditions Determine Life or Death
The AI will not "actively discover" your Skill. It relies on keywords in the description to decide whether to load.
# ✅ Precise triggering
description: |
Load when user says "日报" / "standup" / "今天做了什么".
Generate structured daily report from git commits.
# ❌ So vague it's useless
description: |
A helpful skill for various tasks.
Empirical observation: When trigger words cover more than 3 expressions, the hit rate jumps from 40% to 90%+. A user saying "CR", "review", or "帮我看看代码" is the same intent—you must include them all.
1.2 Workflows Must Be Executable
Every step must have: Input → Action → Output.
# ✅ Executable
1. Read `git log --since="today" --oneline`
2. Categorize by feat/fix/refactor/docs
3. Output to `reports/daily/YYYY-MM-DD.md`
# ❌ Not executable
1. Analyze today's code changes
2. Generate a good daily report
"A good daily report" is not an output specification. Format, location, length—all must be nailed down.
1.3 Three Levels of Constraints
| Level | Meaning | Example |
|---|---|---|
| MUST | Iron law, violation means failure | MUST: All components use TypeScript strict |
| SHOULD | Strongly recommended, exceptions allowed | SHOULD: Prioritize existing knowledge base patterns |
| MUST NOT | Absolutely forbidden | MUST NOT: Do not generate any type |
Don't mark every rule as MUST. When 10 MUST rules conflict with each other, the AI will randomly pick one to follow.
1.4 One Skill Does One Thing
Want it to write code, write blogs, and do design reviews? Split it into three.
Judgment criterion: If the word "and" appears in the description, it should be split.
1.5 Examples > Descriptions
The information density of 1 precise example > 10 lines of text description. Examples should cover:
- 1 happy path
- 1 edge case
1.6 Writing Is Not the End
A Skill is alive. Review it after every use for the first two weeks, and fix any rules the AI didn't follow. After stabilization, review monthly.
A direct quote from GitHub's official AGENTS.md specification: "This is living documentation - update it as your project evolves."
Six Major Misconceptions (Pitfall Checklist)
| Misconception | Truth |
|---|---|
| "Write a longer description, the AI will understand" | The description is for trigger matching, not a manual. The more precise, the better |
| "Mark all rules as MUST" | Too many mandatory constraints will cause AI conflicts. Distinguish MUST from SHOULD |
| "One Skill file handles everything" | Split modules when exceeding 200 lines. Context window is a finite resource |
| "More examples are better" | 1-2 precise examples > 10 redundant examples |
| "Write it and forget it" | Skills need iteration. Use for 2 weeks, revise based on actual results |
| "The AI will automatically know when to use it" | It won't. If trigger conditions aren't clearly written, the Skill is a dead file |
II. Hands-on: Write a Daily Report Generator in 15 Minutes
2.1 Complete Code
---
name: daily-standup
description: |
Load when user says "日报" / "standup" / "今天做了什么" / "写日报".
Generate a structured daily standup report from git commits.
metadata:
author: your-name
version: "1.0.0"
layer: tool
createdAt: "2026-07-23"
---
# daily-standup — Daily Report Generator
> Automatically generate structured daily reports from git log. No more manually writing "fixed a bug today."
## Trigger Conditions
User input contains: 日报 / standup / 今天做了什么 / 写日报 / daily
## Workflow
1. Execute `git log --since="today 00:00" --oneline --author="$(git config user.name)"`
2. If no commits → Output "No commits today" and ask if manual supplement is needed
3. Categorize by prefix:
- feat: → ✨ New Feature
- fix: → 🐛 Bug Fix
- refactor: → ♻️ Refactor
- docs: → 📝 Documentation
- Other → 🔧 Miscellaneous
4. Merge similar items (when exceeding 10 items)
5. Ask for "Tomorrow's Plan" and "Blockers"
6. Output the final daily report
## Output Format
## Daily Report YYYY-MM-DD (DayOfWeek)
### Today's Accomplishments
- ✨ [feat] User registration API integration
- 🐛 [fix] Fixed login page white screen (#1234)
### Tomorrow's Plan
- (User answers)
### Blockers
- (User answers, write "None" if none)
## Constraints
- MUST: Only count today's commits, do not cross days
- MUST: Translate English commit messages to Chinese summaries
- SHOULD: Associate issue numbers (if commit message contains #number)
- MUST NOT: Do not fabricate non-existent commits
2.2 Line-by-Line Breakdown
| Section | Purpose | What Happens If Missing |
|---|---|---|
name |
Unique identifier | Cannot be referenced or managed |
description first line |
Trigger matching | AI doesn't know when to load |
metadata.version |
Version tracking | Don't know where to rollback if broken |
| Trigger Conditions section | Human-readable trigger explanation | Maintainer (future you) won't understand |
| Workflow step 2 | Empty result fallback | AI fabricates when there are no commits |
| Output format | Lock structure | Different output format each time |
| MUST NOT | Anti-hallucination | AI might fabricate commits |
30 lines. A usable Skill. Save as daily-standup/SKILL.md, done.
III. Complex Skills: When 30 Lines Are Not Enough
3.1 When to Split
- SKILL.md exceeds 200 lines
- Contains 3 or more independent sub-processes
- Requires variable configuration (registries, rule tables)
- Requires persistent memory (knowledge base)
3.2 Real Directory Structure
Taking fe-hub (Frontend Orchestration Hub, 58KB SKILL.md, v1.5) as an example:
fe-hub/
├── SKILL.md # Entry (architecture positioning + routing table + module index)
├── README.md # Human instructions (quick start)
├── CHANGELOG.md # Change log (what + why)
├── INSTALL.md # Installation guide
├── manifest.json # Machine-readable metadata
│
├── modules/ # 🔑 Modular sub-processes (11 total, loaded on demand)
│ ├── workflow-recipes.md # Standard workflows for common tasks
│ ├── input-security.md # Input security validation
│ ├── error-recovery-log.md # Error recovery + logging
│ ├── session-tracking.md # Multi-turn session tracking
│ ├── token-metrics.md # Token usage metrics
│ ├── usage-stats.md # Usage statistics
│ ├── knowledge-base.md # Knowledge base retrieval
│ ├── community-skills-matrix.md # Community Skill evaluation
│ ├── design-inspiration.md # Design inspiration library
│ ├── extension-guide.md # Extension development guide
│ └── plugin-packaging-guide.md # Plugin packaging guide
│
├── config/ # Variable configuration (separated from logic)
│ └── skill-registry.json # Sub-Skill registry
│
├── templates/ # Output templates
├── tech-stacks/ # Framework-specific rules
├── bin/ # Helper scripts
├── stats/ # Runtime statistics
├── logs/ # Runtime logs
├── sessions/ # Session persistence
├── reviews/ # Code review archives
└── docs/ # Output documents
3.3 5 Rules for Complex Skills
| # | Rule | Why |
|---|---|---|
| 1 | SKILL.md ≤ 300 lines, only index and routing | AI context window is limited, stuffing everything dilutes focus |
| 2 | modules/ one file per sub-process | Load on demand, unused ones don't consume tokens |
| 3 | config/ separated from logic | Changing registry doesn't require touching SKILL.md |
| 4 | manifest.json is mandatory | Supports automated version detection and dependency management |
| 5 | CHANGELOG.md must be maintained | In three months you'll forget why you changed that line |
3.4 How to Write the Entry File (Complex Version)
---
name: fe-hub
description: |
Load when user starts any frontend development task.
Orchestration hub: routes to the right fe-* Skill.
metadata:
author: mjd
version: "1.5.0"
layer: orchestration
---
# fe-hub — Frontend Orchestration Hub
> Unified entry point for all frontend tasks. Doesn't do the work, only dispatches.
## Routing Table
| User Intent | Trigger Words | Dispatch Target |
|----------|--------|----------|
| Write component/page | "组件/component/页面" | → fe-engineer-pack S3 |
| Write tests | "测试/test/单测/e2e" | → fe-test-pack |
| Fix bugs | "bug/报错/修复/fix" | → fe-engineer-pack S2 |
| Code review | "review/CR/审查" | → fe-engineer-pack S5 |
| Performance optimization | "性能/优化/lighthouse" | → fe-engineer-pack S7 |
| Initialize project | "初始化/init/新项目" | → fe-agent-init |
| Health check | "检查/健康/状态" | → fe-skill-inspector |
## Module Index
| Module | Description | File |
|------|------|------|
| Workflow Recipes | Standard workflows for common tasks | modules/workflow-recipes.md |
| Input Security | Anti-injection/authorization validation | modules/input-security.md |
| Error Recovery | Failure retry + degradation strategy | modules/error-recovery-log.md |
| Session Tracking | Multi-turn context management | modules/session-tracking.md |
## Global Constraints
- MUST: Write to stats/usage-log before route dispatch
- MUST NOT: Do not skip the 5-step detection of fe-base-skill
- SHOULD: Prioritize existing patterns in tech-stacks/
3.5 Module File Example (Route Dispatch)
Excerpt from modules/workflow-recipes.md:
# Route Dispatch Module
## Matching Rules
By priority from high to low:
1. **Exact Match**: User input contains a Skill's triggerKeywords from the registry
2. **Semantic Match**: User intent description has high semantic similarity with Skill's description
3. **Fallback**: Cannot match → Ask the user
## Route Record
Each route SHALL be written to stats/usage-log.md:
| Field | Description |
|------|------|
| timestamp | ISO 8601 |
| skill | Target Skill name |
| trigger | Trigger keyword |
| routedDomain | Hit domain |
| routeCorrected | Whether corrected by user (default false) |
## Conflict Resolution
When multiple Skills match simultaneously:
- Priority: Deeper layer takes precedence (base > capability > orchestration)
- Same layer: triggerKeywords exact match > semantic match
IV. Universal Standards: Rules Every Skill Should Follow
4.1 Minimum Directory Structure
my-skill/
├── SKILL.md # [Required] The only file automatically loaded by AI
├── README.md # [Recommended] Instructions for humans
├── CHANGELOG.md # [Recommended] Change log
├── manifest.json # [Recommended] Machine-readable metadata
├── modules/ # [Optional] Split when SKILL.md > 200 lines
├── knowledge/ # [Optional] Persistent memory (experience/patterns/cases)
├── config/ # [Optional] Variable configuration
├── templates/ # [Optional] Output templates
└── bin/ # [Optional] Helper scripts
4.2 Frontmatter Specification
---
name: skill-name # Unique identifier, kebab-case
description: | # First line must be trigger condition
Load when user [specific scenario].
[One-line core value].
metadata:
author: your-name
version: "1.0.0" # Semantic versioning
layer: tool # meta/orchestration/capability/base/tool/agent
createdAt: "2026-07-23"
updatedAt: "2026-07-23"
---
4.3 Body Structure (Recommended Order)
# skill-name — One-line positioning
> Supplementary note
## Trigger Conditions ← When to load (keyword list)
## Workflow ← Core process (numbered steps, each with Input→Action→Output)
## Output Specification ← Format, location, template
## Constraints ← MUST / SHOULD / MUST NOT
## Examples ← 1 normal + 1 edge case
## Known Limitations ← Honest disclosure (optional)
4.4 Rule Checklist
| # | Rule | Level |
|---|---|---|
| 1 | Frontmatter includes name + description + version | MUST |
| 2 | Description first line is "Load when..." | MUST |
| 3 | Body has explicit "Trigger Conditions" section | MUST |
| 4 | Each workflow step has Input→Action→Output | MUST |
| 5 | Constraints use MUST / SHOULD / MUST NOT three levels | SHOULD |
| 6 | Split to modules/ when exceeding 200 lines | SHOULD |
| 7 | Knowledge base has _index.md index | SHOULD |
| 8 | Update CHANGELOG on every modification | SHOULD |
| 9 | Examples cover normal + edge case | SHOULD |
| 10 | Do not hardcode variable configuration | MUST NOT |
4.5 Complete Example: code-reviewer
---
name: code-reviewer
description: |
Load when user says "review" / "代码审查" / "帮我看看这段代码" / "CR".
Structured code review with severity levels and actionable suggestions.
metadata:
author: mjd
version: "1.0.0"
layer: tool
createdAt: "2026-07-23"
---
# code-reviewer — Structured Code Review
> Not "looks good", but "Line 42 has a null pointer risk, suggest using optional chaining".
## Trigger Conditions
User input contains: review / CR / 代码审查 / 帮我看看 / 这段代码有问题吗
## Workflow
1. **Locate Code**: Code snippet provided by user / specified file / recently modified file
2. **Multi-dimensional Review**:
- 🔴 Correctness (logic errors, missing edge cases, null pointers)
- 🟡 Robustness (error handling, exception paths, resource leaks)
- 🟢 Maintainability (naming, duplication, complexity)
- 🔵 Performance (unnecessary loops, memory allocation, N+1)
3. **Output Review Report**
## Output Format
| Severity | Location | Issue | Suggestion |
|--------|------|------|------|
| 🔴 Critical | L42 | Unhandled null | Use optional chaining |
| 🟡 Warning | L78 | Empty catch block | At least console.error |
## Constraints
- MUST: Every issue must provide **specific modification suggestions**, not just "this is bad"
- MUST: Sort by severity, Critical first
- SHOULD: If overall code quality is good, acknowledge first then raise issues
- MUST NOT: Do not argue about style preferences (tab vs space, etc.)
## Examples
Input: User pastes a 20-line fetch function
Output:
| 🔴 | L5 | fetch has no error handling, network exception will cause unhandled rejection | Wrap with try-catch + timeout control |
| 🟡 | L12 | response.json() doesn't check status | Check res.ok first |
| 🟢 | L3 | Variable name `d` is unclear | Change to `responseData` |
V. Q&A
Q1: What's the difference between Skill and System Prompt?
System Prompt is the employee handbook, Skill is the job SOP.
- System Prompt: Globally effective, defines personality and general rules
- Skill: Loaded only in specific scenarios, defines specific workflows
An AI can simultaneously have 1 System Prompt + 30 Skills.
Q2: What's the relationship between Skill and RAG knowledge base?
- Skill = Process (how to do it)
- Knowledge Base = Experience (based on what to do it)
A Skill's knowledge/ directory is its "working memory". Reference existing patterns when writing code, rather than reasoning from scratch each time.
Q3: What's the appropriate file size?
| Type | Limit | What to Do If Exceeded |
|---|---|---|
| Single-file Skill | 200 lines | Split into modules/ |
| SKILL.md entry | 300 lines | Keep only index, point details to modules/ |
| Single module | 150 lines | Continue splitting into sub-modules |
| Total | No limit | Load on demand, don't stuff everything at once |
Q4: How to test if a Skill works well?
Three metrics:
- Trigger Accuracy: Does it load when trigger words are spoken? Does it not falsely trigger on unrelated content?
- Output Consistency: Run the same input 3 times, is the structure stable?
- Constraint Compliance Rate: Are MUST rules followed every time?
Q5: I wrote it but the AI doesn't use it?
99% of the time it's a description problem:
- Trigger words don't cover the user's actual expressions (user says "CR" but you only wrote "代码审查")
- Description is too long, match weight is diluted
- Conflicts with another Skill's trigger conditions
Q6: What if multiple Skills conflict?
Priority:
- Deeper layer takes precedence (base > capability > orchestration)
- Exact keywords > fuzzy semantic match
- If truly undecidable → Ask the user, don't guess
Q7: Are there ready-made ones from the community?
Yes. skills.sh is the npm for Agent Skills:
# Search
npx skills find "react typescript"
# Install
npx skills add vercel-labs/agent-skills@writing-guidelines
# Popular leaderboard (as of 2026-07-23)
# convex-create-component: 89K installs
# writing-guidelines: 32.5K installs
# create-agentsmd: 11.8K installs
Vercel, GitHub, Sentry, and LaunchDarkly have all published official Skills. Install others' first, understand the structure, then write your own.
VI. Mainstream Platform Adaptation: One Skill Runs on All IDEs
6.1 Platform Comparison Table
| Platform | Carrier | Location | Trigger Method | Multi-file |
|---|---|---|---|---|
| Cursor | .cursor/rules/*.mdc |
Project .cursor/rules/ |
Activates on glob file match | ✅ |
| Claude Code | CLAUDE.md + .claude/rules/ |
Project root/subdirectory/~/.claude/ | Load on startup + subdirectory on-demand | ✅ |
| GitHub Copilot | copilot-instructions.md + instructions/ |
.github/ |
Auto-load + path-specific | ✅ |
| Windsurf | .windsurfrules |
Project root | Auto-load | ❌ |
| Cline | .clinerules |
Project root/global | Auto-load | ❌ |
| Aone Copilot | .aone_copilot/rules/*.md |
Project root | Auto-load | ✅ |
| Universal | AGENTS.md |
Project root/subdirectory | Natively compatible with 22+ tools | ✅ |
6.2 Cursor Adaptation (.mdc Format)
Cursor uses .mdc files, supporting glob triggering—activates only when editing matching files:
.cursor/rules/
├── general.mdc # alwaysApply: true, globally effective
├── react.mdc # globs: "src/**/*.tsx"
├── testing.mdc # globs: "**/*.test.*"
└── security.mdc # globs: "src/api/**"
.mdc File Structure:
---
description: "Next.js + React + TypeScript Development Standards"
globs: "src/**/*.tsx"
alwaysApply: false
---
You are an expert in TypeScript, Next.js 14 App Router, React, Tailwind CSS.
Key Principles
- Use functional, declarative programming. Avoid classes.
- Use descriptive variable names with auxiliary verbs (isLoading, hasError).
- Favor named exports for components.
Error Handling
- Handle errors at the beginning of functions.
- Use early returns for error conditions.
- Use guard clauses for preconditions.
React/Next.js
- Use function, not const, for components.
- Minimize 'use client', 'useEffect', 'setState'. Favor RSC.
- Use Zod for form validation.
- Wrap client components in Suspense with fallback.
Key Difference: The globs field enables "trigger by file type"—load React rules when editing .tsx, load testing rules when editing .test.ts. This is Cursor's unique fine-grained control.
6.3 Claude Code Adaptation (Hierarchical + On-demand)
Claude Code uses CLAUDE.md, with two loading mechanisms:
Load on Startup (globally effective):
~/.claude/CLAUDE.md # User-level: personal preferences
project/CLAUDE.md # Project-level: team-shared standards
project/CLAUDE.local.md # Local-level: personal project preferences (gitignore)
Load on Demand (effective only when reading files in that directory):
project/src/CLAUDE.md # Subdirectory-level: module-specific rules
project/src/components/CLAUDE.md # Deeper level: component standards
⚠️ Note: Official documentation explicitly states "if two rules contradict, Claude may pick one arbitrarily". There is no guarantee that "deeper level always overrides shallower level"—avoiding contradictory rules is more important than relying on priority.
Also supports .claude/rules/ directory for path-specific rules, and @path/to/file syntax to import external files.
AGENTS.md Compatibility: Claude Code doesn't natively read AGENTS.md, but you can write @AGENTS.md in CLAUDE.md to import it.
6.4 GitHub Copilot Adaptation (Repository-level + Path-specific)
GitHub Copilot supports two layers of instructions:
.github/
├── copilot-instructions.md # Repository-level (globally effective)
└── instructions/
├── react.instructions.md # Path-specific (matches specific paths)
└── testing.instructions.md
copilot-instructions.md: Loaded for all Copilot interactionsinstructions/NAME.instructions.md: Effective only in file contexts matching the path
6.5 AGENTS.md Universal Solution
60,000+ open-source projects are using it, natively compatible with 22 AI programming tools:
Codex (OpenAI) · Jules (Google) · Cursor · Windsurf · Devin · Gemini CLI · Aider · goose · opencode · Zed · Warp · VS Code · Junie (JetBrains) · Amp · RooCode · Kilo Code · Phoenix · Semgrep · GitHub Copilot · Ona · Augment Code · Factory ...
# AGENTS.md
## Project Overview
React 18 + TypeScript + Vite single-page application...
## Setup Commands
pnpm install
pnpm dev
## Testing Instructions
pnpm test # Full suite
pnpm vitest run -t "login" # Single test case
## Code Style
- Functional components, no classes
- Naming: camelCase variables, PascalCase components
- Import order: react → third-party → local modules → styles
## Build and Deployment
pnpm build → dist/
CI: GitHub Actions, PR must pass lint + test
Monorepo Rule: One in root directory + one per sub-project, the closest one takes precedence.
6.6 Single-file Platform Adaptation (Windsurf / Cline)
Core strategy: Compress to within 100 lines, keep only workflow + constraints.
# .windsurfrules
## Role
Frontend development assistant. TypeScript strict, functional components.
## Workflow
Write code: Detect tech stack → Match standards → Generate → Self-check → Output
Fix bugs: Reproduce → Locate → Fix → Verify
## Constraints
- MUST: TypeScript strict, no `any`
- MUST: Components declared with function, not const arrow
- MUST: Error handling with early return + guard clause
- MUST NOT: Do not skip type checking
- SHOULD: Prioritize existing project components
Cut modular references, knowledge bases, examples—single-file platforms can't fit them, keep the most core 20%.
6.7 Cross-platform Migration Checklist
- Does the target platform support multiple files? (Determines if compression is needed)
- Trigger method? (Auto-load / glob match / path-specific / manual reference)
- How large is the context window? (Determines how much content can be stuffed in)
- Keep frontmatter (even if the platform doesn't parse it, keep for human reference)
- Test trigger accuracy with 3-5 real scenarios
- Record platform differences in CHANGELOG
6.8 One Sentence
The essence of Skill is platform-agnostic. What changes is the carrier (.mdc / CLAUDE.md / AGENTS.md / .windsurfrules), what remains constant are four things: trigger conditions + workflow + constraints + examples. Write one good SKILL.md, adaptation is just format conversion.
Conclusion
In 2026, the competitiveness of AI programming lies not in "which IDE you can use", but in how much professional memory you've loaded into the AI.
- A 30-line daily report generator saves you 10 minutes every day
- A 300-line orchestration hub makes 31 Skills work together
- One AGENTS.md lets 22 AI tools take over your project without explaining from scratch
Vercel did it, GitHub did it, Sentry did it. 32,500 people installed writing-guidelines.
Now it's your turn. Open your editor, start with that scenario you have to explain 3 times every day.
Your AI shouldn't have amnesia every day.
Next: "Write Your First AI Agent Step by Step" — When a Skill has memory, has a role, has initiative, it's no longer a tool, but a colleague.