惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
V2EX
J
Java Code Geeks
月光博客
月光博客
博客园_首页
The GitHub Blog
The GitHub Blog
Vercel News
Vercel News
B
Blog RSS Feed
博客园 - 聂微东
宝玉的分享
宝玉的分享
T
Tailwind CSS Blog
Jina AI
Jina AI
S
SegmentFault 最新的问题
B
Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
有赞技术团队
有赞技术团队
Hugging Face - Blog
Hugging Face - Blog
Google DeepMind News
Google DeepMind News
阮一峰的网络日志
阮一峰的网络日志
The Cloudflare Blog
量子位
Martin Fowler
Martin Fowler
博客园 - Franky
大猫的无限游戏
大猫的无限游戏
博客园 - 叶小钗

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
I Copy-Pasted the Same Prompt 47 Times Before Noticing Cl...
Ken Imoto · 2026-05-14 · via DEV Community

I copy-pasted the same review prompt 47 times last month. PRs, internal scripts, the README of a side project I was supposed to ship in 2024. The prompt was fine. I was the problem. Claude Code has had a feature for this since late 2025, and I'd been ignoring it because the docs page had a name I didn't understand: Skills.

I finally caved when a teammate asked, "what's the difference between your custom commands and Skills?" and I realized I had no idea. So I read the docs, ported my entire .claude/commands/ directory over, and now my workflow is shorter, sharper, and 100% less copy-paste. Here's what I learned.

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 the GitHub tracking issue for full deprecation of .claude/commands/ is open. 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.

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.

Enter fullscreen mode Exit fullscreen mode

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. Anthropic's authoring best practices emphasize this — every character past the truncation point is dead weight.

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 an open bug 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.

There's also a newer effort field added in the 2026 changelog that overrides the model effort level when the Skill runs, and paths: now accepts a YAML list of globs for scoping. Worth poking at after your first migration if you want finer control.

My five workhorse Skills

Here's what's in my personal ~/.claude/skills/ directory, ordered by how much I'd cry if I lost them.

/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 does more for prompt quality than any prompt-engineering technique I've tried. You can run shell commands inside a SKILL.md and have their output substituted into the prompt before Claude reads it.

`yaml

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, the new effort field) only land in Skills.
  • Anthropic's official plugins themselves have started flagging custom-command usage as "should migrate."
  • The internal Claude Code source has a string loadedFrom === "commands_DEPRECATED" floating around. That isn't a public timeline, but it's a signal.

My migration was fifteen minutes per file. 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). I wrote a one-liner shell script to move them and committed the result. 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. I tried it; the autorouting Claude does on its own is good enough that explicit pinning rarely helped.

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

My SKILL.md files are now collectively three lines longer than the actual code they orchestrate. I had to write a Skill called /list-my-skills to remember what they all do. 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


If you've been writing Claude Code config for more than a few weeks and you can feel the shape of what a coherent harness looks like — Skills, CLAUDE.md, hooks, sub-agents, all in one place — that's the book I wrote. CLAUDE.md patterns from 2 lines to 100, the Skill design taxonomy, Plan Mode, team operations, non-coding applications.

👉 Practical Claude Code — Patterns for Building Reliable Agent Harnesses