DEV Community

dubleCC
dubleCC

Posted on • Originally published at heycc.cn

Claude Code Skills in Practice: Dissecting addyosmani/agent-skills

Originally published at heycc.cn. This is a mirrored copy — the canonical version is kept up to date at the source.

Claude Code Skills in Practice: Dissecting addyosmani/agent-skills

Most Claude Code users' first "skill" is a paragraph bolted onto CLAUDE.md: a checklist for how to write tests, a reminder to run the linter, a note about branch naming. It works until the file grows past a few hundred lines and every one of those lines gets loaded into every conversation, whether the task needs it or not. addyosmani/agent-skills is a useful specimen because it is not a toy — as of this writing it sits at 68,517 GitHub stars and 7,426 forks, MIT-licensed, created by Addy Osmani (Chrome/DevTools alum, now at Google) — and it is built specifically to demonstrate what a disciplined skill pack looks like versus a prompt dump. It packages 24 skills across skills/, a meta-skill that routes between them, four subagent personas in agents/, seven reference checklists, and eight slash commands, all organized around a six-stage SDLC: Define → Plan → Build → Verify → Review → Ship.

This piece does three things: reads the actual SKILL.md files (not the README summary) to show the real anatomy, explains the discovery/loading mechanism in Claude Code that makes this structure pay off, and gives a concrete framework for judging whether your own skill pack is doing real work or just relocating CLAUDE.md bloat into more files.

Claude Code's two-tier skill discovery and loading mechanism: name-and-description listing at session start, then full SKILL.md body loading on invocation

What the repo actually contains

The top-level layout, confirmed against the live repo's GitHub file listing:

agent-skills/
├── .claude/commands/        # 8 slash commands: spec, plan, build, test, review, webperf, code-simplify, ship
├── .claude-plugin/
├── .gemini/commands/         # same 8 commands, mirrored for Gemini CLI
├── .github/workflows/        # CI workflows
├── .opencode/                 # OpenCode-specific config
├── agents/                    # 4 specialist subagent personas
├── commands/                  # same 8 commands, mirrored for Antigravity CLI
├── docs/                       # setup guides per platform
├── hooks/                       # session lifecycle hooks
├── references/                  # 7 supplementary checklists
├── skills/                       # 24 skill directories, each with SKILL.md
├── scripts/
├── AGENTS.md
├── CLAUDE.md
├── CONTRIBUTING.md
├── LICENSE
├── plugin.json
└── README.md
Enter fullscreen mode Exit fullscreen mode

plugin.json is minimal — just name, version, and description:

{
  "name": "agent-skills",
  "version": "1.0.0",
  "description": "Production-grade engineering skills for AI coding agents."
}
Enter fullscreen mode Exit fullscreen mode

The references/ directory contains exactly seven files, not five: accessibility-checklist.md, definition-of-done.md, observability-checklist.md, orchestration-patterns.md, performance-checklist.md, security-checklist.md, testing-patterns.md. (The README's own prose undercounts this too — it says "5 supplementary checklists" while its accompanying description names seven distinct topics: definition-of-done, testing patterns, security, performance, accessibility, observability, and orchestration patterns. The file listing is the ground truth; go with seven.)

The skills/ directory has exactly 24 entries, one per stage-mapped concern, plus the meta-skill:

Stage Skills (directory names under skills/)
Define interview-me, idea-refine, spec-driven-development
Plan planning-and-task-breakdown
Build incremental-implementation, test-driven-development, context-engineering, source-driven-development, doubt-driven-development, frontend-ui-engineering, api-and-interface-design
Verify browser-testing-with-devtools, debugging-and-error-recovery
Review code-review-and-quality, code-simplification, security-and-hardening, performance-optimization
Ship git-workflow-and-versioning, ci-cd-and-automation, deprecation-and-migration, documentation-and-adrs, observability-and-instrumentation, shipping-and-launch
Meta using-agent-skills

That's 3 + 1 + 7 + 2 + 4 + 6 + 1 = 24. Every skill is plain Markdown, so the repo is also usable outside Claude Code — the docs describe compatibility with Cursor, Gemini CLI, Windsurf, OpenCode, GitHub Copilot, Antigravity CLI, and Kiro, since none of those tools require anything beyond a text file with instructions in it. What's Claude-Code-specific is not the content, it's the discovery and loading contract — covered below.

The actual SKILL.md anatomy

Here's the real frontmatter and opening of skills/spec-driven-development/SKILL.md, fetched directly from the repo:

---
name: spec-driven-development
description: Creates specs before coding. Use when starting a new project, feature, or significant change and no specification exists yet. Use when requirements are unclear, ambiguous, or only exist as a vague idea.
---
Enter fullscreen mode Exit fullscreen mode

That's the entire frontmatter — no allowed-tools, no disable-model-invocation, no context: fork. The pack deliberately keeps every skill invokable by both the user and the model, and leaves tool access ungated, because these are advisory/process skills, not automation skills with side effects. Only two YAML keys appear across the file: name and description. Compare that to how Claude Code's own docs describe the field: "Only description is recommended so Claude knows when to use the skill" — the pack follows that minimalism instead of over-specifying.

The body that follows runs to several hundred lines — well inside the "keep it under 500 lines" guidance Anthropic gives skill authors, though independent re-fetches of the raw file returned inconsistent line/character counts (one pass read roughly 200 lines, another roughly 250), likely due to how the fetch tool renders code blocks and tables. Rather than repeat an unreproducible exact figure, the honest statement is: it's a substantial, multi-hundred-line file, not a stub — verify the precise count yourself against skills/spec-driven-development/SKILL.md at a pinned commit if you need it for a citation.

The body has a consistent seven-part shape, repeated with small variations across all 24 files. Using spec-driven-development as the concrete example:

1. Overview — one paragraph stating the rule bluntly: "The spec is the shared source of truth between you and the human engineer... Code without a spec is guessing."

2. When to Use / When NOT to Use — an explicit negative case, not just triggers:

"Single-line fixes, typo corrections, or changes where requirements are unambiguous and self-contained."

This negative list matters more than it looks — it's what keeps the skill from over-triggering on trivial requests, which the docs flag as a common failure mode ("Skill triggers too often").

3. A gated, numbered process — for this skill, four phases (Specify → Plan → Tasks → Implement) each ending in a human review gate, rendered as ASCII flow:

SPECIFY ──→ PLAN ──→ TASKS ──→ IMPLEMENT
   │          │        │          │
   ▼          ▼        ▼          ▼
 Human      Human    Human      Human
 reviews    reviews  reviews    reviews
Enter fullscreen mode Exit fullscreen mode

Each phase includes a literal template block the agent is meant to fill in (a six-section spec template: Objective, Commands, Project Structure, Code Style, Testing Strategy, Boundaries) — reusable structure, not just prose telling the agent to "write a good spec."

4. Cross-references with explicit precedence rules. This is the detail most homegrown skill files skip. When spec-driven-development's Plan phase overlaps with the dedicated planning-and-task-breakdown skill, the file doesn't duplicate that skill's logic — it says:

"Follow planning-and-task-breakdown for the dependency-graph mapping and vertical-slicing mechanics behind these steps; it is the canonical source. The bullets above are a lightweight summary; if they ever diverge, planning-and-task-breakdown takes precedence."

That sentence is doing real engineering work: it resolves the ambiguity of "which file wins" at authoring time, rather than leaving the agent to guess at run time when two loaded skills disagree.

5. Common Rationalizations table — the pack's signature device. A two-column table of excuse → rebuttal:

Rationalization Reality
"This is simple, I don't need a spec" Simple tasks don't need long specs, but they still need acceptance criteria. A two-line spec is fine.
"I'll write the spec after I code it" That's documentation, not specification. The spec's value is in forcing clarity before code.
"The spec will slow us down" A 15-minute spec prevents hours of rework. Waterfall in 15 minutes beats debugging in 15 hours.
"Requirements will change anyway" That's why the spec is a living document. An outdated spec is still better than no spec.
"The user knows what they want" Even clear requests have implicit assumptions. The spec surfaces those assumptions.

Every one of the 24 skills has this table, tuned to that skill's typical shortcut. test-driven-development's table rebuts "I'll add tests after," code-review-and-quality's rebuts "it's a small change, review isn't worth the time." The mechanism is the same everywhere: name the exact sentence an agent (or a human under deadline pressure) is likely to think, then pre-empt it in text the model will have already read by the time it starts rationalizing.

6. Red Flags — a bullet list of observable behaviors that indicate the skill's rule is being violated, e.g. "Starting to write code without any written requirements," "Asking 'should I just start building?' before clarifying what 'done' means." These are phrased as things to catch in the agent's own transcript, functioning as a self-monitoring checklist rather than external QA.

7. Verification — a closing checklist gate, not a suggestion:

- [ ] The spec covers all six core areas
- [ ] The human has reviewed and approved the spec
- [ ] Success criteria are specific and testable
- [ ] Boundaries (Always/Ask First/Never) are defined
- [ ] The spec is saved to a file in the repository
Enter fullscreen mode Exit fullscreen mode

code-review-and-quality — the largest file in the pack — follows the identical seven-part shape but names its core mechanic explicitly in the Overview: "Review covers five axes: correctness, readability, architecture, security, and performance," paired with an approval standard lifted near-verbatim from Google's engineering culture: "Approve a change when it definitely improves overall code health, even if it isn't perfect." That's a direct echo of the "continuous improvement over perfection" review philosophy documented in Software Engineering at Google.

The README states this Google-engineering lineage openly, in a single dense sentence: "Hyrum's Law in API design, the Beyonce Rule and test pyramid in testing, change sizing and review speed norms in code review, Chesterton's Fence in simplification, trunk-based development in git workflow, Shift Left and feature flags in CI/CD." That sentence matters because it's easy to misread as "these four concepts all live in Ship-stage skills" — they don't. Per the README's own attribution: Hyrum's Law sits in api-and-interface-design (Build stage), the Beyoncé Rule sits in test-driven-development (Build stage), Chesterton's Fence sits in code-simplification (Review stage), and trunk-based development sits in git-workflow-and-versioning (Ship stage). Only trunk-based development is actually a Ship-stage concept; the other three are scattered across Build and Review. The pattern worth naming isn't "Ship-stage skills carry the Google lineage" — it's that each stage of the six-stage SDLC gets at least one named, attributed engineering principle rather than a generic "follow best practices" gesture, which is a more precise (and more interesting) design choice than concentrating them in one stage.

The meta-skill: how 24 files avoid becoming 24 competing opinions

using-agent-skills/SKILL.md is the router. Its frontmatter:

---
name: using-agent-skills
description: Discovers and invokes agent skills. Use when starting a session or when you need to discover which skill applies to the current task. This is the meta-skill that governs how all other skills are discovered and invoked.
---
Enter fullscreen mode Exit fullscreen mode

Its body opens with a decision tree mapping task shape to skill name — this is the actual content, verbatim structure preserved:

Task arrives
    │
    ├── Don't know what you want yet? ──────→ interview-me
    ├── Have a rough concept, need variants? → idea-refine
    ├── New project/feature/change? ──→ spec-driven-development
    ├── Have a spec, need tasks? ──────→ planning-and-task-breakdown
    ├── Implementing code? ────────────→ incremental-implementation
    │   ├── UI work? ─────────────────→ frontend-ui-engineering
    │   ├── API work? ────────────────→ api-and-interface-design
    │   ├── Need better context? ─────→ context-engineering
    │   ├── Need doc-verified code? ───→ source-driven-development
    │   └── Stakes high / unfamiliar code? ──→ doubt-driven-development
    ├── Writing/running tests? ────────→ test-driven-development
    │   └── Browser-based? ───────────→ browser-testing-with-devtools
    ├── Something broke? ──────────────→ debugging-and-error-recovery
    ├── Reviewing code? ───────────────→ code-review-and-quality
    │   ├── Too complex? ─────────────→ code-simplification
    │   ├── Security concerns? ───────→ security-and-hardening
    │   └── Performance concerns? ────→ performance-optimization
    ├── Committing/branching? ─────────→ git-workflow-and-versioning
    ├── CI/CD pipeline work? ──────────→ ci-cd-and-automation
    ├── Deprecating/migrating? ────────→ deprecation-and-migration
    ├── Writing docs/ADRs? ───────────→ documentation-and-adrs
    ├── Adding logs/metrics/alerts? ───→ observability-and-instrumentation
    └── Deploying/launching? ─────────→ shipping-and-launch
Enter fullscreen mode Exit fullscreen mode

Then a section of "Core Operating Behaviors" that apply regardless of which leaf skill fires — "Surface Assumptions," "Manage Confusion Actively" (STOP, name the confusion, ask, wait — don't guess), "Push Back When Warranted." This is the layer that keeps the pack from being 24 independent voices: cross-cutting behavior lives once, in the meta-skill, and stage skills reference it rather than restating it.

Note what the meta-skill is not doing mechanically: it is not Claude Code's actual discovery engine. It's a skill like any other — its own description has to win a matching contest against the other 23 for Claude to decide to read it. The real technical discovery mechanism lives in Claude Code itself, and it's worth being precise about how that works, because it's the part a pure prompt-stuffing approach cannot replicate at all.

How Claude Code actually discovers and loads a skill

This is confirmed against Claude Code's official skills documentation (code.claude.com/docs/en/skills), not inferred from the repo:

Discovery is two-tier — listing, then loading. At session start, Claude Code loads every skill's name and description into context (this is the "listing"). It does not load the skill body. Only when a skill is actually invoked — either the user types /skill-name or the model decides the description matches the current request — does the full SKILL.md content get injected as a message into the conversation. This is the progressive-disclosure design the docs state directly: "Unlike CLAUDE.md content, a skill's body loads only when it's used, so long reference material costs almost nothing until you need it." A long SKILL.md that never triggers costs only its description in tokens for the whole session; the equivalent CLAUDE.md section costs those tokens on every single turn.

The description field has a hard budget. The docs specify: description + when_to_use combined is truncated at 1,536 characters per skill in the listing. Beyond that, the total listing budget scales at 1% of the model's context window, and when skills accumulate past that budget, the least-recently-invoked skills get their descriptions dropped first — so skills you actually use keep full text, and unused ones degrade to name-only or disappear from the model's consideration entirely. /doctor reports how many descriptions are currently truncated.

Discovery locations, in override order: enterprise (managed settings) > personal (~/.claude/skills/<name>/SKILL.md) > project (.claude/skills/<name>/SKILL.md), and plugin skills load namespaced as plugin-name:skill-name so they never collide with the other three tiers. Nested .claude/skills/ directories inside a monorepo also load automatically once Claude touches a file in that subdirectory — a deploy skill at the repo root and another at apps/web/.claude/skills/deploy/ coexist, with the nested one addressable as /apps/web:deploy.

Content, once loaded, is sticky for the session. The rendered SKILL.md enters the conversation as a message and Claude Code does not re-read the file on later turns — so a skill's instructions need to read as standing rules, not one-time steps. Under auto-compaction, invoked skills get re-attached after a summary, but only within a combined 25,000-token budget across all re-attached skills, capped at the first 5,000 tokens of each — meaning a skill invoked early in a long session can be silently dropped or truncated after compaction if enough other skills fired afterward.

Invocation control is a frontmatter switch, not folklore. disable-model-invocation: true removes a skill's description from context entirely and makes it callable only by explicit /name — the documented use case is exactly the deploy/commit/send-message pattern: "You don't want Claude deciding to deploy because your code looks ready." The inverse, user-invocable: false, hides a skill from the / menu but keeps it available for the model to load automatically — for background knowledge (the docs' example: a legacy-system-context skill) that isn't a meaningful thing for a human to invoke as a command. addyosmani/agent-skills uses neither switch on any of its 24 skills — every one stays dual-invocable, consistent with the pack functioning as advisory process guidance rather than automation with side effects.

allowed-tools pre-approves, it does not sandbox. The docs are explicit that this field grants permission for listed tools while the skill is active so Claude doesn't prompt for each one — it does not restrict the tool pool to that list; every other tool remains callable and governed by normal permission settings. This is a frequently misread detail: allowed-tools: Read Grep on a skill does not mean the skill can only use Read and Grep.

What a /spec invocation involves — and what's unverified here

spec-driven-development also ships as the /spec slash command (.claude/commands/spec.md in the repo, mirrored for Gemini CLI under .gemini/commands/). The documented installation path is:

# Install as a Claude Code plugin (marketplace method described in the repo's docs/)
/plugin marketplace add addyosmani/agent-skills
/plugin install agent-skills

# Or clone into project-level skills directly
git clone https://github.com/addyosmani/agent-skills.git /tmp/agent-skills
cp -r /tmp/agent-skills/skills/* .claude/skills/
Enter fullscreen mode Exit fullscreen mode

Per the documented lifecycle described above, typing /spec Add rate limiting to the public API should cause: (1) Claude Code resolves /spec to the spec-driven-development skill or its command wrapper, (2) the full SKILL.md content — the four-phase gate, the six-section template, the rationalization table — is rendered into the conversation as one message with $ARGUMENTS expanded to the request text, (3) the model executes the first phase, "Specify," which per the file's own instructions must open by listing its assumptions and stopping for human correction before writing any spec content.

This sequence has not been executed and captured for this article — no /plugin install output or resulting /skills listing was run and pasted in. That is a deliberate omission rather than a fabricated transcript: the mechanics above are derived from reading the skill file and the platform docs, not from an observed run, and presenting an invented terminal transcript as if it were real output would be worse than not having one. A reader who wants the artifact should run the two install commands above in a scratch Claude Code project and diff the resulting /skills listing against the table in this article — that is the actual reproducible check, even though it isn't performed here.

Skill pack vs. prompt-stuffed CLAUDE.md

Dimension Prompt-stuffed CLAUDE.md Well-designed skill pack (this repo's pattern)
Token cost when unused Full text loaded every turn, always Only name + description (≤1,536 chars) loaded until invoked
Structure per concern Usually a flat bullet list, mixed with unrelated facts One file per concern: Overview → When/When-not → gated process → rationalization table → red flags → verification checklist
Handling "agent takes the shortcut" Relies on the model remembering a rule stated once, possibly pages earlier in context Explicit rationalization table pre-empts the specific excuse, read fresh at invocation time
Cross-references between concerns Duplicated prose, or silent gaps, across sections Explicit "canonical source / takes precedence" pointers between skills
Who can trigger it Always "in scope," no way to restrict disable-model-invocation / user-invocable frontmatter controls human-only vs model-only vs both
Side-effect safety (deploy, commit, send) No built-in distinction from advisory content disable-model-invocation: true is the documented pattern specifically for this
Reusability outside one repo Copy-paste, no distribution mechanism Installable as a Claude Code plugin, or portable as plain Markdown to Cursor/Gemini CLI/Windsurf/etc.
Auditability of "did it actually help" No way to isolate one rule's effect from the rest of CLAUDE.md Still hard — the pack has no built-in telemetry or before/after eval, same limitation as any prompt-based intervention

That last row is worth being honest about: nothing in this repo, and nothing in Claude Code's skill mechanism, measures whether a skill actually changed model behavior for the better on a given task. The rationalization tables and red-flag lists are plausible-looking mitigations for known failure modes, not evaluated interventions. If you adopt this pack (or build your own on its pattern), the open question it doesn't answer is how you'd know it's working — that requires your own before/after comparison on real tasks, which is outside what either the repo or Claude Code's docs provide.

Where the pattern is strong, and where to be skeptical

The genuinely new idea here is not "write down your process" — every engineering team has a wiki page for that. It's the combination of (1) per-concern files small enough to stay under the truncation budget, (2) an explicit rationalization table that pre-empts the specific excuse a model is likely to generate for skipping the process, and (3) precedence pointers between files so 24 documents don't silently contradict each other. That's a genuine structural improvement over a single CLAUDE.md, and it costs nothing extra at runtime because of Claude Code's progressive-disclosure loading.

Two things to watch before treating this repo as a template to copy wholesale. First, the pack is advisory prose, not enforcement — nothing stops a model from reading the gate text in spec-driven-development and proceeding to write code anyway; the "gate" is a strongly worded instruction, not a tool-level block. Second, star count is not a quality signal here worth leaning on: the repository was created 2026-02-15, meaning roughly 68,500 stars and 7,400 forks accrued in under five months — an unusually fast trajectory for a prompt/skill-pack repo rather than a runtime or library with typical viral-adoption dynamics. That's not evidence of a problem, but it's also not evidence the pack is battle-tested at scale; treat the popularity as a discovery signal, not a correctness signal, and judge the actual file contents (as this article tries to do) rather than the star count.

What was checked before publish (2026-07-02)

Checked directly against primary sources before publication:

  • references/ file count: confirmed as 7 files via the GitHub repository file listing (accessibility-checklist.md, definition-of-done.md, observability-checklist.md, orchestration-patterns.md, performance-checklist.md, security-checklist.md, testing-patterns.md) — corrects an earlier draft that said "five," which had copied the README's own internal miscount rather than counting the actual files.
  • Hyrum's Law / Beyoncé Rule / Chesterton's Fence / trunk-based development attribution: confirmed against the README's own attribution sentence — these map to api-and-interface-design (Build), test-driven-development (Build), code-simplification (Review), and git-workflow-and-versioning (Ship) respectively, not concentrated in Ship-stage skills as an earlier draft implied.
  • Star/fork counts: 68,517 stars / 7,426 forks, checked against the GitHub API repos/addyosmani/agent-skills endpoint on 2026-07-02. These numbers move continuously and will be stale within hours of publication — treat them as an order-of-magnitude indicator, not a precise figure to cite elsewhere.
  • Repository creation date: 2026-02-15, from the same GitHub API endpoint.
  • License: MIT, confirmed via the API's license.spdx_id field and the repo's LICENSE file.
  • Top-level directory listing: re-verified against the GitHub repo root listing; corrected to include .github/workflows/ and .opencode/, which an earlier draft omitted.
  • spec-driven-development/SKILL.md exact line/character count: could NOT be reliably reproduced. An earlier draft stated "204 lines, 8,298 characters," which did not reproduce on independent re-fetch (one re-check returned ~247 lines / ~9,847 characters, itself only an approximate reading via a summarizing fetch tool rather than a direct byte count). Because this number could not be pinned down with confidence, this revision drops the precise figure and describes the file qualitatively instead. Readers who need an exact count should run wc -l / wc -c directly against the raw file at a pinned commit.
  • Claude Code discovery/loading mechanics (1,536-character description cap, 1% context-window listing budget, least-recently-invoked drop order, /doctor reporting, 25,000-token combined re-attachment budget with 5,000-token per-skill cap, enterprise > personal > project override order, disable-model-invocation / user-invocable semantics, allowed-tools pre-approval-not-restriction behavior): checked against Claude Code's official skills documentation at code.claude.com/docs/en/skills.
  • Not independently executed: the /plugin install and resulting /skills listing described in the "worked example" section were not actually run for this article. The command sequence is accurate as documented, but no live output was captured — this is stated explicitly rather than simulated as if observed.
  • Editorial note: this piece was revised on 2026-07-02 specifically to correct a file-count error, a mischaracterization of principle-to-skill-stage mapping, an unverifiable precise-count claim, and to remove an internal drafting artifact that had been left in the body text of an earlier version. All corrections above were checked against primary sources (GitHub API, GitHub file listings, raw README and SKILL.md content, and Claude Code's official documentation) rather than re-asserted from memory.

Sources

Top comments (0)