Claude Code is a terminal-based coding agent that can automate the repetitive parts of your development workflow, not just generate code.
This article isn't about installation or basic usage. It's written for developers already using Claude Code who want to learn how to design Skills that deliver meaningful automation and consistency in real-world projects.
Among Claude Code's features, Skills are the main way to define how Claude should handle repeatable tasks and follow your project's engineering conventions. In this article, we'll look at how they keep code quality consistent across a team.
Updated July 2026 — The January version of this guide described Skills as single
.mdfiles in.claude/commands/. Skills have since become directory-based (.claude/skills/<name>/SKILL.md), adopted a formal frontmatter specification, and become an open standard at agentskills.io. This revision reflects the current format. The examples come from skills I actually use in real projects.
1. What Are Skills?
In Claude Code, a Skill is a directory containing a SKILL.md file with the instructions, resources, and execution steps Claude follows when the skill is invoked. For personal and project skills, the directory name becomes the command name: .claude/skills/code-review/SKILL.md gives you /code-review. (Plugin skills are namespaced by the plugin name: /my-plugin:review.)
- Rules are your 'Policy Documents'
- Skills are your 'Standard Operating Procedures'
The important distinction is this: a Skill is not an independent agent. It packages instructions, resources, and tool permissions—Claude, or you, decides when to invoke it, unless the frontmatter restricts invocation.
If you remember "custom slash commands" (
.claude/commands/*.md): they've been merged into Skills. A file at.claude/commands/deploy.mdand a skill at.claude/skills/deploy/SKILL.mdboth create/deploy, and old command files keep working. Skills are the recommended format—they add supporting files, invocation control, and a richer frontmatter. If both define the same name, the skill wins.
2. Skill File Structure and Location
Skills can be managed per-project or globally across your machine:
| Scope | Location | Applies to |
|---|---|---|
| Personal | ~/.claude/skills/<name>/SKILL.md |
All your projects |
| Project | .claude/skills/<name>/SKILL.md |
This project only (shared via Git) |
| Plugin | <plugin>/skills/<name>/SKILL.md |
Wherever the plugin is enabled |
The file must be named exactly SKILL.md, and a skill is a directory, not a single file. That directory can carry supporting material that loads only when needed:
code-review/
├── SKILL.md # required: frontmatter + instructions
├── references/ # detailed docs, loaded on demand
├── scripts/ # executable helpers (run, not loaded)
└── assets/ # templates, static resources
For me, this is the most useful improvement over the old single-file format. Keep SKILL.md under ~500 lines and push heavy reference material into references/—the body stays in context for the whole session once loaded, so every line has a recurring token cost.
The Key: YAML Frontmatter
---
name: code-review
description: Review code against .claude/rules/ for architecture and convention violations.
argument-hint: "[path] [--staged|--branch] [--fix]"
allowed-tools: Read Glob Grep Bash(git *)
---
☝️ The description field is still critical. Claude normally sees the names and descriptions of available Skills and uses that metadata to decide which one is relevant. If you say "review my code," that request gets matched against skill descriptions—so yours must contain clear, searchable keywords.
One distinction worth knowing before the table: the Agent Skills standard defines the portable core fields (name, description, license, compatibility, metadata, allowed-tools). The rest below—argument-hint, disable-model-invocation, user-invocable, context—are Claude Code extensions. The table covers the fields used in this guide, not every option Claude Code supports (there are also when_to_use, model, paths, hooks, and more):
| Field | What it does |
|---|---|
name |
Display name (defaults to the directory name) |
description |
Auto-invocation trigger. Keep it ≤1,024 chars for cross-tool compatibility |
argument-hint |
Autocomplete hint shown after /name
|
allowed-tools |
Tools Claude may use without permission prompts while the skill runs (space-separated per the standard; Claude Code also accepts commas) |
disable-model-invocation |
true = only you can trigger it; Claude never auto-invokes |
user-invocable |
false = hidden from the / menu; Claude-only background knowledge |
context: fork |
Run the skill in an isolated subagent context |
Two of these encode a design decision the old format couldn't express: who is allowed to pull the trigger. For side-effect workflows—deploying, committing, sending messages—set disable-model-invocation: true so Claude can't decide on its own that now is a good time to deploy. For pure background knowledge, set user-invocable: false so it stays out of your command menu.
3. Real Example: /code-review Skill
The architecture-review skill from the January version of this post is still the one I use every day—it has just grown up. Here's the frontmatter of my current production /code-review skill:
---
name: code-review
description: Review code against .claude/rules/ for architecture and convention
violations. Supports --staged, --head, --last, --today, --branch scope options.
Add --fix to auto-correct.
argument-hint: "[path] [--staged|--head|--last|--today|--branch] [--fix]"
allowed-tools: Read, Glob, Grep, Edit, Bash(git *), Bash(find *)
---
The current version relies on two features that didn't exist in January:
1. Arguments. $ARGUMENTS in the skill body is substituted with whatever you type after the command, so one skill covers many scopes:
| Invocation | Review scope |
|---|---|
/code-review |
Files changed in the last 5 commits |
/code-review src/user/ |
A specific directory |
/code-review --staged |
Final check right before committing |
/code-review --branch |
Current branch vs main, before opening a PR |
/code-review --staged --fix |
Auto-fix what it finds |
2. Dynamic context injection. A !`command` placeholder runs before Claude sees the skill and gets replaced with its output. My skill uses it to enumerate the rule files and changed files up front:
- Project rules: !`find .claude/rules -name "*.md" | sort`
- Staged files: !`git diff --name-only --cached`
The Claude Code client runs these commands during preprocessing; the model receives only the expanded results as part of the skill instructions. That removes an entire class of "the model forgot to check X first" failures.
📎 Full working example: code-review SKILL.md — save it as .claude/skills/code-review/SKILL.md in your project. The directory name is what creates the /code-review command.
Claude Code already ships a bundled
/code-reviewskill. Adding your owncode-reviewskill at the personal or project level overrides the bundled version—which is exactly what I want here: a review driven by my rule files, not a generic one.
Why This Skill Is Powerful
- Rule-driven checklists — The skill loads
.claude/rules/dynamically instead of hardcoding policies, so the same skill works in every project and stays aligned with the current rule files. - Severity Level definitions — CRITICAL/WARNING/SUGGESTION priorities prevent getting lost in minor issues.
- Explicit execution process — A five-step procedure makes the review process more consistent.
4. Example Output
Running /code-review in the terminal produces results like this:
> /code-review src/user/api/user_router.py
🔍 Reviewing: src/user/api/user_router.py
## Architecture Violations Found
### 🚨 CRITICAL (2)
**Line 45**: Direct Repository import detected
- Found: `from src.user.repositories.user_repository import UserRepository`
- Fix: Remove this import. Use Service layer instead.
**Line 78**: Business logic in API layer
- Found: `if user.age >= 18 and user.verified:`
- Fix: Move this validation to UserService.validate_user_eligibility()
### ⚠️ WARNING (1)
**Line 23**: Service manually instantiated
- Found: `service = UserService()`
- Fix: Use `service: UserService = Depends(get_user_service)`
### 💡 SUGGESTION (1)
**Line 12**: Consider adding return type hint
- Current: `async def get_user(user_id: int):`
- Suggested: `async def get_user(user_id: int) -> StandardResponse[UserResponse]:`
---
Summary: 2 critical, 1 warning, 1 suggestion
Run `/code-review --fix` to auto-fix applicable issues.
One command produces a repeatable first-pass architecture review based on your project's documented rules. It doesn't replace human review—but it catches routine violations before a pull request ever reaches another developer.
Security Note: Review Skills Before Trusting Them
The same two features that make skills powerful make them worth auditing. Skills are executable workflow definitions, not passive documentation:
-
allowed-toolspre-approves tool usage for the duration of the skill—no permission prompts. - Dynamic context expressions like
!`command`run during preprocessing, before the rendered skill content ever reaches the model. - A skill checked into an unfamiliar repository deserves a read before you accept workspace trust. (You can disable shell preprocessing entirely with the
disableSkillShellExecutionsetting.) - Keep permissions narrow:
Bash(git *)beatsBash(*), and list only the tools the procedure actually needs.
5. Where Skills Provide the Most Value
① Consistent Code Quality
Human reviewers vary by mood and energy. A well-defined Skill applies the same checklist every time, reducing variation and making common omissions less likely.
② Encapsulating Complex Workflows
Tasks that touch multiple files (adding a new API endpoint requires Router, Service, Schema, and Test files) can be bundled into a single Skill, reducing the chance of missing a step.
③ Knowledge as an Asset
Embed your design philosophy into Skill files and share via Git. Junior developers can generate code that is consistently aligned with documented senior guidelines. And because Skills follow an open standard, the SOPs you encode aren't locked into one tool.
6. Practical Patterns
These are skills currently in my ~/.claude/skills/ and project .claude/skills/ directories—not hypotheticals:
| Skill Command | What It Does |
|---|---|
| /code-review | Check architecture violations against .claude/rules/ with severity levels and --fix
|
| /commit-push | Stage, generate a conventional commit message, confirm, push |
| /create-post | Scaffold a new blog post following every content convention (slug rules, image folders, frontmatter schema) |
| /feature-image | Crop and convert cover images to 16:9 WebP under a size budget |
| /review-skill | The meta one: audit SKILL.md files against the open standard, with --fix
|
Notice the pattern in the last row—once your process knowledge lives in files, you can write skills that maintain other skills.
7. Key Tips for Designing Skills
- Craft your description carefully — It's the primary signal Claude uses to decide when to load a Skill automatically. Describe both what the skill does and when to use it: "Review code for Clean Architecture compliance" beats "Code review."
- Link to Rules — Instead of duplicating policies inside the skill, load them:
.claude/rules/is the single source and the skill is the procedure that applies it. - Make checklists explicit — "Review this code" produces inconsistent results. "Check these 5 things" delivers reliability.
- Define Severity Levels — Not all issues are equal. Include priority criteria in your Skill.
- Add verification steps — Always end with "verify the modified code builds" or "run lint" as a final check.
- Keep
SKILL.mdlean — Under ~500 lines. Move deep reference material toreferences/files that load on demand; the skill body occupies context for the whole session. - Control the trigger — Side-effect workflows (deploy, commit, publish) get
disable-model-invocation: true. Guardrails belong in frontmatter, not in hope. - Combine with MCP — If you have MCP servers connected to external tools (GitHub, databases), you can write instructions like "query the DB schema before writing code" for smarter automation.
Conclusion
Claude Code Skills turn repeated instructions into reusable, version-controlled workflows.
Their quality depends less on clever prompting than on how clearly you've defined the process Claude should follow.
If your team repeatedly explains the same conventions during code reviews, those conventions are good candidates for a Skill. Start with one narrow workflow, test it against real tasks, and refine it as your process changes.
In the next article, we'll explore Custom Agents—how to build AI that autonomously decides when to use which Skill.
Series:
- Enforcing Team Architecture with .claude/rules in Claude Code (FastAPI Practical Guide) — Teaching AI your policies
- Skills Guide — Teaching AI your procedures (this article)
- Claude Code Agents Guide: How Skills Power Your Subagents — Teaching AI when to act
Originally published at jamongx.com.
Top comments (0)