explainx.ainewsletter3.4k
trending๐Ÿ”ฅloopsskills
pricing
workshops โ†—
explainx.ai

Learn to lead teams that combine humans and agents. Platform access, live workshops, bootcamps, and 50+ courses โ€” plus skills, tools, and MCP to practice what you learn.

follow us

custom AI agents

[email protected]

get started

Join ยท $29/mo

learn

start for freepathwaysworkshopsbootcampscoursescertificationscertification testsexplainx universitycorporate trainingfacilitatorshackathonslearn skills & mcp

discover

skillstoolsagentsmcp serversdesignsllmsagiranks

content

releasesvisionmissionaboutcommunityteamcareersresourcespromptsgenerators hubgenerator SEO hubprompt templatesprompt guidesblogfor LLMsdemo

Sister Products

Infloq

Infloq

Influencer marketing

BgBlur

BgBlur

Privacy-first blur

Olly Social

Olly Social

Social AI copilot

Ceptory

Ceptory

Video intelligence

BgRemover

BgRemover

Background removal

newsletter ยท weekly

Get AI news, tools, and insights in your inbox.

contactsupportprivacytermsdata rightssubmission guidelines

ยฉ 2026 AISOLO Technologies Pvt Ltd

โ† Back to blog

explainx / blog

Skills vs Hooks vs Prompts: When to Use Each (2026 Decision Guide)

A practical decision guide comparing the three Claude Code customization primitives โ€” CLAUDE.md system prompts, SKILL.md agent skills, and hooks. Learn exactly when each applies and how to combine them.

Jun 27, 2026ยท10 min readยทYash Thakker
Agent SkillsClaude CodeHooksCLAUDE.mdDeveloper Tools
Skills vs Hooks vs Prompts: When to Use Each (2026 Decision Guide)

Claude Code gives you three distinct ways to shape how the agent behaves. Most developers discover them in order โ€” first the system prompt, then skills, then hooks โ€” and end up using each for jobs the others do better. This guide fixes that by explaining the conceptual territory each primitive owns, when each is the right tool, and what happens when you combine all three.

Quick reference: the three primitives

PrimitiveFile/LocationWhen it's activePrimary job
System prompt / CLAUDE.md.claude/CLAUDE.mdEvery single requestProject context, standing rules, conventions
Skills (SKILL.md).claude/skills/*/SKILL.mdWhen task matches triggerStep-by-step procedures for specific task types
Hooks.claude/settings.jsonOn tool call eventsAutomated shell commands, validation, notifications

The three primitives do not overlap โ€” they cover different dimensions of agent customization. Getting this right means your agent setup is efficient, predictable, and maintainable.

System prompts and CLAUDE.md

What they control

CLAUDE.md is Claude Code's project-level context file. When Claude Code starts a session, it reads the CLAUDE.md from the project root and includes it in the system prompt. This content is always present, always paying its token cost, and applies to everything Claude does in that session.

Think of it as the briefing document you would give a contractor on their first day: the tech stack, the team conventions, the things that are always true about this project.

# MyProject โ€” Agent Context

## Tech stack
- Next.js 15 (App Router), TypeScript 5, Tailwind CSS
- Database: PostgreSQL via Prisma ORM
- Auth: Clerk
- Deployment: Vercel

## Coding conventions
- Use named exports, never default exports
- All async functions must handle errors explicitly โ€” no swallowed catches
- Prefer `const` over `let`; never use `var`
- CSS: utility classes only, no inline styles

## Team rules
- Never modify migration files once they are committed to main
- All external API calls must go through lib/api-client.ts
- Feature flags use LaunchDarkly โ€” see docs/feature-flags.md

## What is in this repo
- /apps/web โ€” Next.js frontend
- /apps/api โ€” Express backend
- /packages/shared โ€” shared types and utilities

When CLAUDE.md is the right choice

Use CLAUDE.md for anything that is true for every task in this project:

  • Tech stack and library versions
  • Coding style conventions (naming, formatting, error handling)
  • Repository structure overview
  • Team rules ("never do X")
  • Links to important internal documentation

What CLAUDE.md cannot do

CLAUDE.md cannot trigger contextually. It cannot respond to events. It cannot run shell commands. It cannot load different instructions based on what task you are doing. Everything in CLAUDE.md applies all the time, which is why it should contain only context and rules that are relevant all the time.

The most common mistake: putting procedure in CLAUDE.md. "When writing a migration: 1. Run prisma migrate dev, 2. Add rollback logic, 3. Update the docs." That belongs in a skill, not in CLAUDE.md โ€” it bloats every request with instructions that are only relevant when you are actually writing a migration.

Agent skills (SKILL.md)

What they control

Skills encode how to do specific kinds of tasks. They are loaded on demand through a mechanism called progressive disclosure: Claude Code scans the skill descriptions to find a match for the current task, then loads the full SKILL.md body only for skills that match.

This matters because a project might have 20 installed skills. Without progressive disclosure, all 20 would consume context tokens on every request. With progressive disclosure, you pay only for the description metadata of idle skills, and the full body only when the skill is actually relevant.

---
name: add-database-migration
description: >-
  Use this skill when the user asks to add, create, or write a database
  migration, or to change the database schema, or to add/remove/modify
  a table or column.
version: 1.1.0
---

## Purpose
Add a Prisma migration following the team's safety conventions.

## Steps
1. Identify the schema change needed from the user's description.
2. Edit prisma/schema.prisma to reflect the change.
3. Run: npx prisma migrate dev --name <descriptive-name>
4. Verify the generated migration file looks correct.
5. Add a rollback comment at the top of the migration file.
6. Update docs/database-schema.md to reflect the change.
7. Show the full diff for the user to review before committing.

When skills are the right choice

Use a skill for any multi-step procedure that:

  • Applies to a specific task type (not all tasks)
  • Would be annoying to re-explain every time
  • Benefits from consistent execution
  • A new team member should be able to follow

Good examples: writing database migrations, drafting PR descriptions, adding feature flags, running release checklists, creating API endpoints following your project's patterns, setting up new components with the right file structure.

What skills cannot do

Skills cannot run shell commands autonomously. They can instruct Claude to run commands via the Bash tool, but the execution depends on Claude deciding to do so, tool permissions being granted, and the user approving if approval mode is on.

Skills cannot react to file changes or tool call events. They are instructions Claude follows, not event handlers. If you need something to run automatically when Claude edits a file, that is a hook.

Skills cannot change agent behavior at the infrastructure level โ€” they cannot modify which tools are available, change timeout settings, or alter how the agent itself works.

Hooks

What they control

Hooks are shell commands that Claude Code executes automatically when specific events occur. They live in settings.json and run outside the Claude context โ€” they are not part of the conversation, they do not get paid in tokens, and they execute regardless of whether the user asks for them.

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit",
        "hooks": [
          {
            "type": "command",
            "command": "npx tsc --noEmit 2>&1 | head -20"
          }
        ]
      }
    ]
  }
}

This hook runs TypeScript compilation after every file edit, and the output is shown to Claude so it can react to type errors immediately.

Hook types

PreToolUse: Runs before Claude calls a tool. Useful for validation, logging, or preventing certain operations.

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "echo 'About to run bash command' >> ~/.claude/audit.log"
          }
        ]
      }
    ]
  }
}

PostToolUse: Runs after a tool call completes. Useful for validation, automated testing, or updating derived files.

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit",
        "hooks": [
          {
            "type": "command",
            "command": "cd $(git rev-parse --show-toplevel) && npx eslint --max-warnings 0 $(git diff --name-only HEAD) 2>&1 | tail -20"
          }
        ]
      }
    ]
  }
}

Notification: Runs when Claude sends a notification event (typically when a long-running task completes or when Claude needs to surface something).

When hooks are the right choice

Use hooks for things that should happen automatically on every occurrence of an event, regardless of what Claude is doing:

  • Running the linter after every file edit
  • Running type checking after TypeScript file edits
  • Validating migration files after they are created
  • Logging all bash commands to an audit file
  • Sending a notification when a long task completes
  • Blocking certain commands in production environments

The key distinction: hooks enforce policy at the infrastructure level; skills give Claude knowledge at the reasoning level. If you want Claude to know to run the linter, use a hook. If you want Claude to know how to reason about lint errors, use a skill or CLAUDE.md context.

What hooks cannot do

Hooks cannot give Claude reasoning context. A hook can run npx eslint and surface the output, but it cannot explain to Claude what your team's ESLint conventions mean or how to fix specific categories of errors. For that, you need a skill or CLAUDE.md.

Hooks run shell commands, not arbitrary code with access to Claude's context. They see JSON event data about the triggering tool call, but they do not have access to the conversation history or Claude's current reasoning.

Decision flowchart

Use this flowchart when you are deciding where to put a new piece of agent configuration:

Is this a standing rule or context that applies to EVERY task in this project?
  โ†’ YES: Put it in CLAUDE.md
  โ†’ NO: Continue

Is this a multi-step procedure for a specific kind of task?
  โ†’ YES: Make it a SKILL.md skill
  โ†’ NO: Continue

Should this happen automatically on every tool call event, without
Claude deciding whether to do it?
  โ†’ YES: Configure it as a hook
  โ†’ NO: You might not need any of these โ€” consider if this is a
         one-off prompt instead

The gray areas

"I want Claude to always check for security issues when editing files."

This sounds like a hook (runs on every edit automatically) but it also needs Claude to reason about what it finds. The right answer is both: a PostToolUse hook that runs a static analysis tool, plus a skill or CLAUDE.md note about how to interpret and fix the kinds of issues it flags.

"I want Claude to follow our API design conventions."

If the conventions are brief (a few rules: use camelCase, always return {data, error}, use HTTP status codes correctly), put them in CLAUDE.md. If following them requires a multi-step procedure (check existing patterns, scaffold the endpoint, update the OpenAPI spec, write tests), make it a skill.

"I want Claude to use TypeScript strict mode."

One line in CLAUDE.md: "All TypeScript files use strict mode." Also a tsconfig.json โ€” enforcement at the tool level is better than policy at the context level.

Combining all three

Here is a real example: a database migration workflow that uses all three primitives.

CLAUDE.md (always-on context):

## Database
- ORM: Prisma 5
- Database: PostgreSQL 16
- Never write raw SQL โ€” always use Prisma schema + migrations
- Never modify a migration file after it has been merged to main

SKILL.md (procedure loaded when the task matches):

---
name: add-database-migration
description: >-
  Use this skill when the user asks to add a database migration, change
  the schema, add or remove a column, or modify a table.
version: 1.0.0
---

## Steps
1. Read the current prisma/schema.prisma to understand existing structure.
2. Identify the minimal schema change required.
3. Edit prisma/schema.prisma.
4. Run: npx prisma migrate dev --name <descriptive-name-in-snake_case>
5. Read the generated migration file to verify it is correct.
6. Add a comment at the top: -- Rollback: [describe what to do to undo this]
7. Update docs/database-schema.md.
8. Show the complete diff for user review.

Hook (automatic validation):

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit",
        "hooks": [
          {
            "type": "command",
            "command": "if echo '$CLAUDE_TOOL_INPUT' | jq -r '.path' | grep -q 'prisma/schema.prisma'; then npx prisma validate 2>&1; fi"
          }
        ]
      }
    ]
  }
}

When the user says "add a column for user preferences," the flow is:

  1. CLAUDE.md gives Claude context: Prisma, PostgreSQL, no raw SQL.
  2. The skill triggers and gives Claude the step-by-step procedure.
  3. After Claude edits schema.prisma, the hook automatically runs prisma validate and surfaces any schema errors Claude can fix.

All three layers working together, each doing what it does best.

Weekly digest3.4k readers

Catch up on AI

Curated AI updates on agents, skills, and MCP โ€” delivered to your inbox. Unsubscribe anytime.

Anti-patterns to avoid

Putting procedure in CLAUDE.md

# Bad โ€” this belongs in a skill
## When writing migrations:
1. Edit the Prisma schema
2. Run npx prisma migrate dev
3. Add a rollback comment
4. Update the docs

This burns tokens on every request. Most requests are not about migrations. Move it to a skill.

Putting standing context in a skill

---
name: edit-any-file
description: Use this skill whenever editing any file.
---
## Context
- This project uses Next.js 15
- TypeScript strict mode
- Named exports only

A skill that triggers on "edit any file" is just a bad CLAUDE.md. Move the context to CLAUDE.md and delete this skill.

Using hooks when a skill instruction would suffice

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit",
        "hooks": [
          {
            "type": "command",
            "command": "echo 'Remember to write tests for this change'"
          }
        ]
      }
    ]
  }
}

An echo hook that reminds Claude to write tests is not really a hook โ€” it is a rule. Put it in CLAUDE.md: "Always write tests for behavior changes." Claude will reason about it appropriately rather than just seeing a hollow reminder after every edit.

Duplicating content across all three

If your CLAUDE.md says "use Prisma," your migration skill also has a "context" section saying "use Prisma," and your hook script has a Prisma check โ€” you have three sources of truth. When your ORM changes, you update two of the three and introduce a subtle inconsistency. Keep each fact in one place.

Team adoption patterns

Onboarding with CLAUDE.md and skills together

The most effective onboarding experience is to commit both CLAUDE.md and the .claude/skills/ directory to the repository. New team members clone the repo and immediately have the agent configured with team conventions and the full skill library. No setup step, no onboarding document to read before coding.

Version-locking skills for team consistency

When skills are installed from a registry, use a skills.lock.json to pin exact versions:

{
  "skills": {
    "explainx/add-database-migration": "1.2.3",
    "explainx/write-pr-description": "2.0.1"
  }
}

This prevents one team member from getting a different skill version than another after a registry update. Treat it like package-lock.json.

Hook configurations: personal vs shared

Some hooks should be shared (lint validation, type checking โ€” these enforce team standards). Others should be personal (audit logging, notification preferences).

Shared hooks go in .claude/settings.json (committed to the repo). Personal hooks go in ~/.claude/settings.json (your home directory, not committed). Both sets are applied in the same session.

Performance implications

Token usage

CLAUDE.md tokens are paid on every request. Keep it under 2,000 tokens. If your CLAUDE.md has grown to 5,000 tokens because you added procedure sections, refactor those sections into skills.

Skills use progressive disclosure. The description field is roughly 20โ€“50 tokens per skill for the discovery scan. The full body (200โ€“600 tokens for a typical skill) is loaded only on a match. With 20 installed skills, idle overhead is around 1,000 tokens โ€” far better than 20 ร— 400 tokens if everything were in CLAUDE.md.

Hooks run shell commands outside the Claude context and do not consume tokens. Their output is injected as tool result text, which does consume tokens, so keep hook output concise (pipe through head -20 or similar).

Latency

Hooks add latency to tool calls because they run synchronously before returning the tool result. A hook that runs a full test suite after every file edit will make editing feel slow. Reserve hooks for fast checks (linting, type checking) and run slow checks (full test suite) asynchronously or as a separate step.

How these primitives are evolving

The CLAUDE.md and SKILL.md specifications are converging toward a more formalized standard. Expect to see:

  • Skill composition: explicit syntax for one skill calling another
  • Conditional hooks: hooks that trigger only when specific conditions in the skill context are met
  • Cross-agent portability: shared format for skills across Claude Code, Cursor, and Gemini CLI
  • Registry-aware lock files: skills.lock.json becoming a first-class part of the CLI toolchain

For now, the mental model is stable: CLAUDE.md for context, skills for procedures, hooks for automation.

Read next

  • How to Build Your First Agent Skill (Step-by-Step)
  • What are agent skills? A complete guide
  • Top 10 AI Agent Skills Directories & Registries
  • What is CLAUDE.md? Persistent Memory for Claude Code
  • Agent Markdown Files โ€” Complete Guide

Related posts

Jun 27, 2026

How to Build Your First Agent Skill (Step-by-Step, 2026)

Agent skills are reusable instruction packages that teach your AI coding assistant how to handle a specific class of task. This guide walks you through building one from scratch โ€” from the blank SKILL.md to a published package others can install.

Jun 23, 2026

One CLAUDE.md Prompt Eliminates Generic Claude Code Answers โ€” Here's Exactly What to Write

Claude Code starts every session knowing nothing about your project. CLAUDE.md is the only signal that survives across sessions โ€” and most developers write ones that are nearly useless. This post shows the difference between a generic CLAUDE.md (that changes nothing) and a specific one (that eliminates boilerplate answers) with before/after examples.

May 17, 2026

Agent Skills: The Secure, Validated Registry for Professional AI Coding Agents

A deep dive into Agent Skills, the managed skill registry solving the security crisis in AI agent extensions. Learn how threat modeling, static analysis, and human curation make it safe to extend Antigravity, Claude Code, Cursor, and other professional coding agents with zero-trust workflows.