← Back to Blog

Claude Code Skills vs Agents: 10 of 47 Prompts

Part of Claude Code Field Guide

A teammate asked me, “when do you reach for a Skill versus just letting a subagent handle it?” and my honest answer was a shrug. I had 47 copy-pasted prompts across my repos, a few .claude/commands/ files I half-remembered writing, and a vague sense that Claude Code’s subagents and Skills were “similar but different.” I’d been using neither on purpose.

Then I spent a week forcing myself to decide which was which, every time I noticed myself about to paste a prompt. The answer is simpler than I expected. Two frontmatter fields do most of the work: context: fork decides whether the Skill runs in a sub-agent at all, and agent: decides which sub-agent handles it. Here’s how I think about Claude Code agents vs skills now.

The two fields that decide agent vs skill

A Skill is just a prompt + optional helpers inside .claude/skills/<name>/SKILL.md. A subagent is a separate process with its own context window. Those are the pieces. The confusion is that a Skill can invoke a subagent via two frontmatter fields:

  • context: fork: run the Skill in a sub-agent so the diff Claude just read doesn’t clutter the main conversation. This is the single best feature for Skills that grep through large codebases. Set it on anything that reads more than a handful of files.
  • agent: field: pin the Skill to a specific sub-agent (Explore, Plan, etc.) instead of letting Claude autoroute. The sub-agents docs describe autorouting as the default path, with explicit pinning reserved for cases where you specifically need, say, the Plan agent’s planning behavior or the Explore agent’s read-only sandbox.

The decision reduces to: you type /<name> → it’s a Skill. Claude decides what to run based on a prompt → it’s autoroute, and your description field is doing the choosing. The agent runs underneath either way. Pick the field that matches which choice you’re making.

With that out of the way, the rest of this post is the frontmatter fields I actually use, five of the ten Skills I’d cry if I lost, and the one syntax trick I didn’t know about until month three.

The thirty-second version

A Skill is a SKILL.md file inside a directory, plus optional helper files. You drop it in .claude/skills/<name>/, and from then on /<name> runs that workflow. Same one-letter slash invocation as the old /commands style, but Skills carry more weight: they can ship templates, scripts, and examples in the same package, and Claude itself can decide when to invoke them based on the description.

If you’ve been using .claude/commands/<name>.md, your old files still work. Anthropic unified the two formats. A file at .claude/commands/review.md and a skill at .claude/skills/review/SKILL.md both produce /review. But new development has moved to skills, and a user-filed tracking issue asking for a hard deprecation timeline was closed as “not planned” — the directory keeps working for now, but nothing new is being built around it. The wind is blowing in one direction.

What changed and why I care

The conceptual jump is small. The practical jump is large.

Custom commands were a single Markdown file. SKILL.md is a Markdown file plus a directory. That directory can hold a template Claude is supposed to fill in, a scripts/ folder of executables Claude is allowed to run, and an examples/ folder of “this is what good output looks like.” Suddenly the workflow stops being a long instructions blob and starts being a tiny package. I can hand a teammate a directory and they get the whole workflow, not just my prompt.

Custom Commands vs Skills: Single File vs Package

A Skill’s directory is the contract. Drop in helpers and they ship with the prompt.

Anatomy of a Skill directory

The other change is invocation. With custom commands, you typed /review and the file ran. With Skills, you can still do that, but Claude can also notice that your message looks like it needs the review skill and pull it in on its own. The description field in the frontmatter is what powers that decision. Claude reads every Skill’s description at session start and matches against your prompt.

That last bit took me a beat to appreciate. The first time Claude invoked a skill I hadn’t asked for, I assumed it had hallucinated a tool. It hadn’t. I had written a description that started with “review the current PR” and asked Claude to “review the diff,” so it pulled in review-pr automatically. That is the entire point.

The frontmatter, the only part you need to memorize

Everything important about a Skill happens in the YAML frontmatter at the top of SKILL.md. The body is just the prompt.

---
name: review-pr
description: Review the current pull request. Use when the user asks to review a PR, check a diff, or comment on changes.
allowed-tools: Bash(gh *) Read Grep Glob
---

## Steps

1. Run `gh pr diff` to read the diff.
2. Identify each changed file.
3. For each file, check:
   - Logic correctness
   - Edge cases
   - Test coverage
   - Security issues
4. Post the review as a PR comment.

A few things are worth knowing.

description is the decision interface. Claude uses this string to figure out whether to invoke your skill. Lead with the trigger keywords. Don’t write “This skill helps with…”; that wastes tokens that should be doing routing work. The description plus when_to_use together get capped at about 1,536 characters before truncation, so be brutal.

allowed-tools adds permissions, doesn’t restrict them. This is a footgun I walked into. I assumed allowed-tools: Read Grep meant “this skill can ONLY use Read and Grep.” It does not. It means “this skill is additionally allowed to use Read and Grep without prompting.” The user’s normal permission settings still apply. There’s also a reported bug (closed as duplicate, but worth reading) where allowed-tools isn’t always enforced. Useful context if you were planning to rely on it as a security boundary. (Don’t.)

disable-model-invocation: true for anything dangerous. If the Skill sends a Slack message, deploys a service, or files a refund, you do not want Claude deciding to run it. This flag means “user must invoke explicitly with /skill-name.” I set this on every Skill that touches a side effect.

context: fork runs the Skill in a sub-agent. The Skill executes in a separate context window and reports back. Your main conversation doesn’t get cluttered with the diff Claude just read. This is the single best feature for skills that grep through large codebases.

model: opus (or sonnet, or haiku) overrides the session model for this Skill. Cheap models for cheap work. I run a /lint-commit skill on Haiku because it’s a one-shot string check, and /architect-feature on Opus because it actually has to think. The cost difference adds up — my Skills bill is probably a third of what it would be with one model for everything.

Five Skills worth copying

Of the ten I kept, here are five Skill patterns I keep recommending, ordered by how much mileage I’d expect from each.

/review-pr — Reads the current diff via gh pr diff, comments inline. The Skill that started this whole thing for me.

/triage-issue $ARGUMENTS — Takes an issue number, reads the issue, classifies it (bug/feature/duplicate), labels it. Uses positional args: /triage-issue 123 becomes $ARGUMENTS = 123.

/architect-feature — Forks the context, reads the codebase, returns three implementation approaches with tradeoffs. model: opus, context: fork. This is the Skill I wrote a paragraph ago about offloading thinking-heavy work.

/release-notes — Looks at git log since last tag, drafts release notes. Has disable-model-invocation: true because I don’t want Claude generating release notes mid-conversation when I asked an unrelated question.

/lint-commit — Runs git diff --staged, checks for console.logs, debugger statements, .env values. Cheap, on Haiku.

The fifth one is the one I’d recommend you write first. Linters that catch the small embarrassing stuff before they ship are the kind of thing you’ll never miss until you turn them off.

The !command trick that changed how I think about prompts

Buried halfway through the Anthropic docs is a piece of syntax that quietly reshapes how a SKILL.md works: the backtick-bang expression. You can run shell commands inside a SKILL.md and have their output substituted into the prompt before Claude reads it.

---
name: pr-summary
description: Summarize the current PR
context: fork
---

## PR information

- Diff: !`gh pr diff`
- Comments: !`gh pr view --comments`
- Files changed: !`gh pr diff --name-only`

## Task
Summarize the PR using the data above.

When the Skill runs, the backtick-bang expressions get replaced with their command output. Claude never sees !gh pr diff. It sees the actual diff. This is huge: it means your Skill always operates on fresh, real data instead of whatever Claude scraped from the conversation. I started using this for everything that takes “the current state of X” as input, which turns out to be most of my Skills.

For multi-line commands, there’s a ! block syntax. You can grab node --version, npm --version, and git status in one go and dump them at the top of an “environment context” Skill.

Should you migrate from .claude/commands/?

Yes, but not in a panic. The custom commands directory still works, and there’s no announced sunset date. But:

  • New Anthropic features (context: fork, the model: override, model-invoked descriptions) only land in Skills.
  • Users are filing issues on Anthropic’s official plugins repo pointing out that many of its plugins still ship custom commands instead of skills — the migration pressure is visible even inside Anthropic’s own distribution.
  • The internal Claude Code source has a string loadedFrom === "commands_DEPRECATED" floating around. That isn’t a public timeline, but it’s a signal.

Migration per file is quick. The only gotcha is that custom commands lived in a flat directory (commands/review.md), and Skills live in a nested one (skills/review/SKILL.md). A one-liner shell script handles the move. If your custom commands didn’t have helper files, the migration is genuinely just: rename, wrap in a directory, add a richer description.

What I’d skip on a first pass

A few features in the Skills system look cool but I haven’t found a real use for yet, and they’re worth flagging so you don’t sink an afternoon into them.

The agent: field for picking which sub-agent runs the Skill. Claude Code ships several sub-agents (Explore, Plan, etc.). You can pin a Skill to one, but the sub-agents docs frame autorouting as the default — explicit pinning is reserved for the few cases where you need a specific agent’s capabilities.

Plugin Skills via the marketplace. If you’re publishing Skills publicly, the namespacing (plugin-name:skill-name) is great. If you’re writing them for yourself or your team, just stick them in .claude/skills/ and commit. Don’t over-engineer the distribution.

Building “smart” skills that detect what to do. Tempting, but the LLM is already the smart part. Your Skill should be a procedure, not a flowchart. If you find yourself writing “if the diff is large, do X, else do Y” inside SKILL.md, you’re doing Claude’s job for it.

The closing self-own

There’s a point where you catch yourself wanting a Skill just to index your Skills. There’s a real, measurable productivity gain here, and there’s also the recursive joy of automating the act of automating things until you’ve built a small bureaucracy of helpful clerks. Both can be true. I’m choosing to enjoy it.

If you’ve been using .claude/commands/ and never opened the Skills page, do this today: pick the one prompt you’ve copy-pasted most often this month, give it a name, and write twenty lines of YAML around it. Tomorrow’s you will type /<name> instead, and the day after you’ll wonder how you ever lived without it.

References

Related read: I broke down Claude Code vs ChatGPT Codex recently. Codex’s “custom instructions” sit in roughly the same conceptual slot as Skills, but the developer ergonomics are very different.


Want to go deeper?

This article touches a slice. The full Claude Code playbook — CLAUDE.md patterns from 2 lines to 100, Plan Mode workflow, team operations, non-coding applications — is in Practical Claude Code.

Practical Claude Code Related book Practical Claude Code The field guide for engineers who use Claude Code every day — CLAUDE.md, Plan Mode, and team workflows from a year of real production use View the book page →