> ## Documentation Index
> Fetch the complete documentation index at: https://felimet-hub.jmcores.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 02-5 Skills / Hooks / Subagents / Plugins: Mechanism Overview

> These four mechanisms transform Claude Code from a conversational agent into an automated system that fits your workflow. This unit establishes selection criteria and breaks down format, placement, priority, and security boundaries for each.

export const MechanismPicker = ({lang = "zh"}) => {
  const t = {
    zh: {
      q1: {
        text: "你想要的效果，比較像哪一種？",
        context: "例如「每次存檔後自動跑 lint」vs「需要時請 Claude 幫我 review 程式碼」",
        yes: "像前者：必須每次都發生，不依賴 Claude 有沒有想到",
        no: "像後者：需要時才觸發，Claude 判斷或我主動叫它"
      },
      q2: {
        text: "這個任務需要大量讀取或探索嗎？",
        context: "例如「掃整個 codebase 找出哪些函式違反命名規範」這種，會產生很多中間內容，如果都丟進主對話你的指令會被稀釋",
        yes: "是：任務會產生大量中間內容，只需要最終結論回來就好",
        no: "否：主對話處理就夠了，不會太吵"
      },
      q3: {
        text: "這個流程需要分給其他人或跨專案共用嗎？",
        context: "例如「整個團隊都要裝這套設定」或「這是我個人工作流，只在我自己的環境用」",
        yes: "是：要打包讓團隊一次安裝，或放到市集分享",
        no: "否：就我自己用，或只在這個專案用"
      },
      hook: "Hook",
      subagent: "Subagent",
      plugin: "Plugin",
      skill: "Skill",
      hookDesc: "Hook 是事件驅動、由 Claude Code 強制執行的機制，不靠模型自覺。「每次存檔後自動格式化」「擋掉包含明文密鑰的 git push」「每次 session 結束前跑驗證」這類必須保證發生的動作，掛在 PreToolUse / PostToolUse / Stop 等事件上，不管 Claude 這一輪有沒有記得，都一定會執行。",
      subagentDesc: "Subagent 給子任務一個乾淨的 context window。「掃整個 repo 找安全問題、只給我結論」「讀一百個檔案整理成摘要」這類探索性任務，放進主上下文會讓雜訊稀釋你的指令；丟給 subagent，它在隔離環境跑完只傳結論回來，省 token 又提升品質。",
      pluginDesc: "Plugin 把 skills / agents / hooks / MCP 打包成一個可安裝單位。「讓整個團隊一次裝好這套工作流設定」「我做好的一套工具想放到市集分享」這類要打包分發的情境，用 plugin 是正確選項——一個 /plugin install 讓所有人拿到一致的設定。",
      skillDesc: "Skill 是可重用的流程，用 SKILL.md 定義步驟。「幫我依實驗室格式整理文獻」「按這套 checklist 審查 PR」這類我想要 Claude 照步驟執行的任務，用 Skill——session 啟動時只佔一行描述，被觸發後全文才載入，可以裝幾十個不撐爆 context。",
      reset: "重新選擇",
      learnMore: "了解更多",
      paths: {
        hook: "/code-agent/customization/hooks",
        subagent: "/code-agent/customization/subagents",
        plugin: "/code-agent/customization/plugins",
        skill: "/code-agent/customization/skills"
      }
    },
    en: {
      q1: {
        text: "Which outcome are you looking for?",
        context: "For example: 'run lint automatically every time I save' vs 'have Claude review my code when I need it'",
        yes: "Like the first: must happen every time, regardless of whether Claude remembers to do it",
        no: "Like the second: triggered when needed, Claude decides or I invoke it explicitly"
      },
      q2: {
        text: "Does this task involve heavy reading or open-ended exploration?",
        context: "For example: 'scan the entire codebase to find functions that violate naming conventions' -- a task that generates a lot of intermediate content. If all of that lands in the main conversation, it dilutes your instructions.",
        yes: "Yes: the task produces a lot of intermediate content; I only need the final conclusion",
        no: "No: the main conversation can handle it fine without too much noise"
      },
      q3: {
        text: "Does this workflow need to be shared with others or used across projects?",
        context: "For example: 'the whole team needs this setup installed' vs 'this is my personal workflow, just for my own environment'",
        yes: "Yes: package it so the team can install it in one step, or share it on a marketplace",
        no: "No: just for me, or just for this project"
      },
      hook: "Hook",
      subagent: "Subagent",
      plugin: "Plugin",
      skill: "Skill",
      hookDesc: "Hooks are event-driven and enforced by Claude Code itself -- not dependent on the model remembering. 'Auto-format after every save,' 'block a git push that contains a plaintext secret,' 'run a validation check at the end of every session' -- these must-always-happen actions attach to PreToolUse, PostToolUse, Stop, and similar events. They fire whether or not Claude thought of it this turn.",
      subagentDesc: "A subagent gives a subtask its own clean context window. 'Scan the whole repo for security issues and give me only the summary,' 'read a hundred files and condense them into a digest' -- exploration-heavy tasks that would flood the main conversation with noise. Offload them to a subagent: it runs in isolation and returns only the conclusion, saving tokens and improving quality.",
      pluginDesc: "A plugin bundles skills, agents, hooks, and MCP into one installable unit. 'Get the whole team set up with this workflow in a single step,' 'I built a useful toolset and want to publish it on the marketplace' -- these distribution use cases are exactly what plugins are for. One /plugin install and everyone gets a consistent configuration.",
      skillDesc: "A skill is a reusable process defined in a SKILL.md. 'Format my references in the lab style,' 'review a PR against this checklist' -- tasks where you want Claude to follow a defined sequence of steps. At session start it occupies only one line of description (progressive disclosure); the full body loads only when triggered, so you can have dozens installed without blowing up context.",
      reset: "Start over",
      learnMore: "Learn more",
      paths: {
        hook: "/en/code-agent/customization/hooks",
        subagent: "/en/code-agent/customization/subagents",
        plugin: "/en/code-agent/customization/plugins",
        skill: "/en/code-agent/customization/skills"
      }
    }
  };
  const labels = t[lang] || t.zh;
  const resultMeta = {
    hook: {
      color: "#d64c1a",
      icon: "M13 10V3L4 14h7v7l9-11h-7z"
    },
    subagent: {
      color: "#5a7fbf",
      icon: "M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 1 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 1 21 16z"
    },
    plugin: {
      color: "#bf7551",
      icon: "M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82zM7 7h.01"
    },
    skill: {
      color: "#4e9b6a",
      icon: "M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
    }
  };
  const [step, setStep] = useState(0);
  const [result, setResult] = useState(null);
  const handleQ1 = yes => {
    if (yes) {
      setResult("hook");
      setStep(99);
    } else {
      setStep(2);
    }
  };
  const handleQ2 = yes => {
    if (yes) {
      setResult("subagent");
      setStep(99);
    } else {
      setStep(3);
    }
  };
  const handleQ3 = yes => {
    setResult(yes ? "plugin" : "skill");
    setStep(99);
  };
  const reset = () => {
    setStep(0);
    setResult(null);
  };
  const cs = {
    root: "mp-root",
    card: "mp-card",
    question: "mp-question",
    context: "mp-context",
    btns: "mp-btns",
    btn: "mp-btn",
    resultCard: "mp-result-card",
    resultHeader: "mp-result-header",
    resultIcon: "mp-result-icon",
    resultTitle: "mp-result-title",
    resultDesc: "mp-result-desc",
    resultFooter: "mp-result-footer",
    resetBtn: "mp-reset-btn",
    learnBtn: "mp-learn-btn",
    stepDots: "mp-step-dots",
    dot: "mp-dot",
    dotActive: "mp-dot-active"
  };
  const css = `
    .mp-root { font-family: inherit; margin: 1.5rem 0; }
    .mp-card {
      background: var(--mp-bg, #faf8f4);
      border: 1.5px solid var(--mp-border, #e8e0d6);
      border-radius: 10px;
      padding: 1.4rem 1.75rem;
    }
    .dark .mp-card {
      --mp-bg: #232120;
      --mp-border: #3a342e;
    }
    .mp-question {
      font-size: 1rem;
      font-weight: 700;
      color: var(--mp-text, #2a1f18);
      margin-bottom: 0.35rem;
    }
    .dark .mp-question { --mp-text: #ede8e0; }
    .mp-context {
      font-size: 0.84rem;
      color: var(--mp-muted, #7a6a58);
      margin-bottom: 1rem;
      line-height: 1.55;
    }
    .dark .mp-context { --mp-muted: #9a8878; }
    .mp-btns { display: flex; gap: 0.75rem; flex-wrap: wrap; }
    .mp-btn {
      padding: 0.6rem 1.15rem;
      border-radius: 7px;
      border: 1.5px solid #bf7551;
      background: transparent;
      color: #bf7551;
      font-size: 0.88rem;
      cursor: pointer;
      transition: background 0.15s, color 0.15s;
      text-align: left;
      line-height: 1.4;
    }
    .mp-btn:hover { background: #bf7551; color: #fff; }
    .dark .mp-btn { border-color: #d4896a; color: #d4896a; }
    .dark .mp-btn:hover { background: #d4896a; color: #1a1410; }
    .mp-result-card {
      border-radius: 10px;
      padding: 1.4rem 1.75rem;
      background: var(--mp-res-bg, #fdf9f5);
      border: 2px solid var(--mp-res-border, #bf7551);
    }
    .dark .mp-result-card {
      --mp-res-bg: #201c19;
      --mp-res-border: #d4896a;
    }
    .mp-result-header { display: flex; align-items: center; gap: 0.75rem; margin-bottom: 0.75rem; }
    .mp-result-icon {
      width: 36px; height: 36px;
      border-radius: 50%;
      display: flex; align-items: center; justify-content: center;
      flex-shrink: 0;
    }
    .mp-result-title { font-size: 1.15rem; font-weight: 700; }
    .mp-result-desc { font-size: 0.91rem; line-height: 1.65; color: var(--mp-desc, #5a4a3a); margin-bottom: 1rem; }
    .dark .mp-result-desc { --mp-desc: #c0b09a; }
    .mp-result-footer { display: flex; gap: 0.75rem; flex-wrap: wrap; }
    .mp-reset-btn {
      padding: 0.45rem 1rem;
      border-radius: 6px;
      border: 1.5px solid var(--mp-border2, #c8bdb0);
      background: transparent;
      color: var(--mp-reset-text, #7a6a5a);
      font-size: 0.88rem;
      cursor: pointer;
    }
    .dark .mp-reset-btn { --mp-border2: #4a4038; --mp-reset-text: #9a8a7a; }
    .mp-reset-btn:hover { border-color: #bf7551; color: #bf7551; }
    .mp-learn-btn {
      padding: 0.45rem 1rem;
      border-radius: 6px;
      background: #bf7551;
      color: #fff;
      font-size: 0.88rem;
      text-decoration: none;
      border: none;
      cursor: pointer;
    }
    .mp-learn-btn:hover { background: #a85f3f; color: #fff; }
    .mp-step-dots { display: flex; gap: 6px; margin-bottom: 1rem; }
    .mp-dot {
      width: 7px; height: 7px; border-radius: 50%;
      background: var(--mp-dot, #d6cec4);
      transition: background 0.2s;
    }
    .dark .mp-dot { --mp-dot: #4a3e34; }
    .mp-dot-active { background: #bf7551 !important; }
    @media (max-width: 500px) {
      .mp-btns { flex-direction: column; }
      .mp-btn { width: 100%; }
    }
  `;
  const questionMap = {
    0: {
      q: labels.q1,
      handler: handleQ1
    },
    2: {
      q: labels.q2,
      handler: handleQ2
    },
    3: {
      q: labels.q3,
      handler: handleQ3
    }
  };
  const currentQ = questionMap[step];
  const meta = result ? resultMeta[result] : null;
  const stepNum = step === 0 ? 1 : step === 2 ? 2 : step === 3 ? 3 : 3;
  return <div className={cs.root}>
      <style>{css}</style>
      {step !== 99 && currentQ && <div className={cs.card}>
          <div className={cs.stepDots}>
            {[1, 2, 3].map(n => <div key={n} className={`${cs.dot}${n <= stepNum ? " " + cs.dotActive : ""}`} />)}
          </div>
          <div className={cs.question}>{currentQ.q.text}</div>
          <div className={cs.context}>{currentQ.q.context}</div>
          <div className={cs.btns}>
            <button className={cs.btn} onClick={() => currentQ.handler(true)}>
              {currentQ.q.yes}
            </button>
            <button className={cs.btn} onClick={() => currentQ.handler(false)}>
              {currentQ.q.no}
            </button>
          </div>
        </div>}
      {step === 99 && result && meta && <div className={cs.resultCard} style={{
    borderColor: meta.color
  }}>
          <div className={cs.resultHeader}>
            <div className={cs.resultIcon} style={{
    background: meta.color + "22"
  }}>
              <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={meta.color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                <path d={meta.icon} />
              </svg>
            </div>
            <div className={cs.resultTitle} style={{
    color: meta.color
  }}>{labels[result]}</div>
          </div>
          <div className={cs.resultDesc}>{labels[result + "Desc"]}</div>
          <div className={cs.resultFooter}>
            <button className={cs.resetBtn} onClick={reset}>{labels.reset}</button>
            <a className={cs.learnBtn} href={labels.paths[result]}>{labels.learnMore}</a>
          </div>
        </div>}
    </div>;
};

export const LearnerPrimer = ({items = [], lang = "zh"}) => {
  const t = lang === "en" ? {
    title: "Before this unit, be honest with yourself",
    sub: "If you can't answer these, that gap is exactly what this unit closes."
  } : {
    title: "讀這個單元前，先誠實面對",
    sub: "這幾題答不出來，正是這個單元要替你補的洞。"
  };
  const css = `
  .lp-root{--lp-bg:#FAF7F1;--lp-surface:rgba(191,117,81,0.05);--lp-border:rgba(0,0,0,0.09);--lp-edge:rgba(191,117,81,0.42);--lp-text:#2b2722;--lp-dim:#6f6a62;--lp-accent:#bf7551;border:1px solid var(--lp-border);border-left:3px solid var(--lp-edge);border-radius:13px;background:var(--lp-bg);color:var(--lp-text);overflow:hidden;margin:1.25rem 0;}
  .dark .lp-root{--lp-bg:#1b1a18;--lp-surface:rgba(207,138,104,0.07);--lp-border:rgba(255,255,255,0.08);--lp-edge:rgba(207,138,104,0.5);--lp-text:#e7e3da;--lp-dim:#a8a299;--lp-accent:#cf8a68;}
  .lp-head{display:flex;align-items:center;gap:9px;padding:13px 18px 11px;border-bottom:1px solid var(--lp-border);background:var(--lp-surface);}
  .lp-ic{color:var(--lp-accent);flex-shrink:0;}
  .lp-htx{display:flex;flex-direction:column;gap:1px;min-width:0;}
  .lp-title{font-size:14px;font-weight:650;line-height:1.3;letter-spacing:.01em;}
  .lp-sub{font-size:12px;color:var(--lp-dim);line-height:1.4;}
  .lp-list{list-style:none;margin:0;padding:10px 18px 14px;display:flex;flex-direction:column;gap:0;}
  .lp-item{display:flex;align-items:baseline;gap:11px;padding:7px 0;font-size:14px;line-height:1.6;border-top:1px solid var(--lp-border);}
  .lp-item:first-child{border-top:none;}
  .lp-mark{flex-shrink:0;color:var(--lp-accent);font-size:13px;font-weight:700;line-height:1.55;font-variant-numeric:tabular-nums;opacity:.85;}
  .lp-q{flex:1 1 0;min-width:0;color:var(--lp-text);}
  @media (max-width:620px){.lp-head{padding:12px 14px 10px;}.lp-list{padding:8px 14px 12px;}}
  `;
  return <div className="lp-root">
      <style>{css}</style>
      <div className="lp-head">
        <svg className="lp-ic" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10" /><circle cx="12" cy="12" r="6" /><circle cx="12" cy="12" r="2" /></svg>
        <span className="lp-htx">
          <span className="lp-title">{t.title}</span>
          <span className="lp-sub">{t.sub}</span>
        </span>
      </div>
      <ul className="lp-list">
        {items.map((q, i) => <li className="lp-item" key={i}>
            <span className="lp-mark">{String(i + 1).padStart(2, "0")}</span>
            <span className="lp-q">{q}</span>
          </li>)}
      </ul>
    </div>;
};

<LearnerPrimer
  lang="en"
  items={[
"Use a Hook when you need something guaranteed to happen; use a Skill when it might happen",
"Putting formatting rules in CLAUDE.md and hoping the model follows them? The model will miss it",
"Giving a review-only subagent write tools violates the principle of least privilege",
"Dumping an exploration task into the main context lets noise dilute your instructions first",
"High stars on a plugin does not mean it is safe -- stars reflect marketing reach",
"Your hook reads file_path from an environment variable? That variable does not exist",
"Putting skills/ inside .claude-plugin/ means the plugin never loads them",
]}
/>

<Info>
  **What this unit solves**

  These four mechanisms transform Claude Code from "a conversational agent" into "an automated system that fits your workflow." They are commonly misused: tasks that require guaranteed behavior are written as Skills and left for the model to remember; subtasks that should be isolated are jammed into the main context; configurations that should be packaged are copied by hand. This unit first gives you the selection criteria for "when to use which one," then unpacks the format, placement, priority order, and security boundaries for each mechanism individually. Deep production details are left for Part IV -- this unit establishes the selection overview.
</Info>

## Learning objectives

* [ ] Explain what problem each of Skill / Hook / Subagent / Plugin solves, and given a task, determine which one to reach for.
* [ ] Read and understand the main frontmatter fields of a `SKILL.md` and a subagent definition.
* [ ] List the main Hook events and handler types, and describe one practical example of a deterministic gate.
* [ ] Safely install a plugin from the official and community marketplaces, and know what to scan before installing.

<Warning>
  **Currency notice**

  Mechanisms and fields were verified as of 2026-05. Claude Code evolves quickly; for exact fields and event lists refer to the official documentation. Production details are in the dedicated Part IV units.
</Warning>

***

## 1. Decide first: selecting among the four mechanisms

The four mechanisms are not parallel substitutes -- they answer different questions. Read the selection table first, then continue to the per-mechanism details:

| What you want                                                                                             | Use          | Why                                                                               |
| --------------------------------------------------------------------------------------------------------- | ------------ | --------------------------------------------------------------------------------- |
| A reusable **process** -- have Claude handle a class of task step by step                                 | **Skill**    | Body loads on demand; at rest it is only one line of description, saving tokens   |
| A **deterministically guaranteed** action (formatting, blocking dangerous commands)                       | **Hook**     | Event-driven, enforced by Claude Code itself -- not dependent on model compliance |
| **Isolating a subtask** into a clean context (exploration, review) -- main agent gets only the conclusion | **Subagent** | Independent context window, saves main-thread tokens and improves quality         |
| **Packaging and distributing** the above to a team or others                                              | **Plugin**   | One install brings along skills / agents / hooks / MCP together                   |

Selection principle: **Use Hook for "must happen," Skill for "reusable process," Subagent for "isolated context," Plugin for "package and distribute."** They are orthogonal but composable -- a single plugin can carry a skill, a hook, and a subagent at the same time.

<Tip>
  **The most common selection mistake: writing Hook-worthy behavior into a Skill or CLAUDE.md**

  Things like "format after every save" or "block writes to certain paths" need to be guaranteed. Writing them into `CLAUDE.md` or a Skill is asking the model to comply -- and the model may miss it. For something that must happen without fail, use a Hook (see Section 3 and the strategy-vs-rule distinction in [01-6](/en/code-agent/foundations/harness-engineering)).
</Tip>

### Interactive selection tool

Answer a few questions below and get a mechanism recommendation:

<MechanismPicker lang="en" />

***

## 2. Skills: reusable processes

A Skill is a reusable process defined in a `SKILL.md` file (YAML frontmatter + Markdown body). Unlike `CLAUDE.md`, which is fully loaded at session start, Skills use **progressive disclosure**: only the `description` enters context when the session begins; the full `SKILL.md` body is loaded as a message only when the Skill is triggered \[1]. This lets you install dozens of Skills without bloating the context window.

**Main frontmatter fields** (all optional; only `description` is strongly recommended) \[1]:

| Field                                | Purpose                                                                                                                                       |
| ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `description`                        | Purpose and trigger conditions; Claude uses this to decide whether to auto-load the Skill (combined with `when_to_use`, 1536-character limit) |
| `allowed-tools` / `disallowed-tools` | Tools added to / removed from the allowed set while this Skill is active, without prompting                                                   |
| `model` / `effort`                   | Override the model or effort level while this Skill is active; restored when the turn ends                                                    |
| `disable-model-invocation`           | If `true`, Claude will not auto-load the Skill and the description does not enter context; only manual `/name` invocation works               |
| `user-invocable`                     | If `false`, the Skill does not appear in the `/` menu, but Claude can still auto-load it                                                      |
| `context: fork` + `agent`            | Run inside a forked subagent; `agent` specifies the subagent type                                                                             |
| `paths`                              | Glob pattern; only auto-triggers when the operation touches a matching file path                                                              |

<Note>
  **A minimal SKILL.md**

  ```markdown theme={null}
  ---
  name: tidy-refs
  description: Clean up a reference list in the lab's citation format. Trigger when the user asks to organize references or BibTeX entries.
  allowed-tools: Read, Edit
  ---

  # Tidy references
  1. Read the reference file the user specifies.
  2. Reorder entries in IEEE numbering; use et al. for three or more authors.
  3. Mark entries missing a year with n.d. (no date) -- do not invent dates.
  ```

  Place it at `~/.claude/skills/tidy-refs/SKILL.md` (personal) or `.claude/skills/tidy-refs/SKILL.md` (project). Claude only reads these instructions after the Skill is triggered.
</Note>

**Placement and priority** (highest to lowest): enterprise managed policy > personal `~/.claude/skills/` > project `.claude/skills/` > plugin (plugin skills use the `plugin-name:skill-name` namespace and do not conflict with other layers) \[1].

**Dynamic context injection**: `SKILL.md` can contain commands that execute before the Skill loads and whose output replaces the command inline -- letting you inject live information (git status, date) into the process \[1]. The syntax is a leading backtick-escaped command on its own line; multi-line blocks are also supported:

```text theme={null}
!`git status --short`
```

You can disable this behavior with `disableSkillShellExecution: true` in `settings.json`.

**Relationship with legacy commands**: `.claude/commands/<name>.md` is still supported and generates the same `/name` slash command. When a Skill and a command share the same name, **the Skill wins** \[1]. For the trade-offs between Commands and Skills see [04-3](/en/code-agent/customization/commands) and [04-4](/en/code-agent/customization/skills).

***

## 3. Hooks: deterministic event-driven gates

A Hook is a custom command attached to a lifecycle event. The fundamental difference between Hooks and Skills / CLAUDE.md is **enforceability**: CLAUDE.md says "please follow this," and a Hook says "I will make sure this happens." Use Hooks for anything that must be guaranteed; do not write it into instructions and hope for model compliance.

**Events**: Claude Code had approximately 30 hook events as of 2026-06 \[2]. The ones you will reach for first:

| Event              | When it fires             | Typical use                                               |
| ------------------ | ------------------------- | --------------------------------------------------------- |
| `SessionStart`     | Session begins            | Inject project context, environment check                 |
| `UserPromptSubmit` | After you submit a prompt | Inject dynamic context, intercept                         |
| `PreToolUse`       | Before a tool executes    | Block dangerous commands, rewrite parameters              |
| `PostToolUse`      | After a tool executes     | Auto-format / lint / type-check                           |
| `Stop`             | Turn ends                 | Deterministic wrap-up verification (convergence sentinel) |
| `SessionEnd`       | Session ends              | Cleanup, final validation                                 |

The full event list (including `PermissionRequest`, `SubagentStart` / `SubagentStop`, `PreCompact`, and others) is in the official docs and [04-6](/en/code-agent/customization/hooks).

**Handler types**: `command` (run a shell command or script), `http` (POST event JSON to a URL), `mcp_tool` (call an MCP tool), `prompt` (evaluate with an LLM), `agent` (agentic verifier with tools) \[2].

**Protocol**: a Hook receives a JSON payload via stdin (containing `session_id`, `tool_name`, `tool_input`, and more). Exit code 2 is a blocking error (stderr is shown to Claude and the action is blocked); exit 0 triggers parsing of the stdout JSON for a decision \[2]. To block a specific tool call in `PreToolUse`, return:

```json theme={null}
{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny",
    "permissionDecisionReason": "Database writes not allowed"
  }
}
```

<Note>
  **A PostToolUse hook that auto-formats on save**

  Attach a PostToolUse hook in `settings.json` pointing to a script, with matcher `Edit|Write`:

  ```json theme={null}
  {
    "hooks": {
      "PostToolUse": [
        {
          "matcher": "Edit|Write",
          "hooks": [{ "type": "command", "command": ".claude/hooks/format.sh" }]
        }
      ]
    }
  }
  ```

  The hook script reads the modified file path from the stdin JSON (`tool_input.file_path`) and runs the formatter against it. Note that Claude Code does not provide a `$CLAUDE_FILE_PATHS` environment variable for this (as of 2026-05) \[2] -- the path must come from stdin JSON, not from the environment.
</Note>

***

## 4. Subagents: child agents with isolated context

A Subagent is a child agent defined in `.claude/agents/*.md` (YAML frontmatter + system prompt) and managed via `/agents`. Its core value is **context isolation**: dispatch an exploration-heavy or read-heavy subtask to a subagent with a clean context window, and the main agent receives only the final conclusion -- saving main-thread tokens and preventing irrelevant content from diluting the main context (connects to [01-4](/en/code-agent/foundations/context-engineering)) \[3].

**Main frontmatter fields** (only `name` and `description` are required) \[3]:

| Field                       | Purpose                                                                                      |
| --------------------------- | -------------------------------------------------------------------------------------------- |
| `name` / `description`      | Identifier and the basis for "when to delegate"                                              |
| `tools` / `disallowedTools` | Tool allowlist / blocklist; omitting `tools` inherits all tools from the parent conversation |
| `model`                     | `sonnet` / `opus` / `haiku` / full model ID / `inherit` (default: inherit)                   |
| `skills`                    | List of Skills whose full content is injected directly at startup                            |
| `memory`                    | `user` / `project` / `local`, each corresponding to a different agent-memory directory       |
| `isolation`                 | The only valid value is `worktree`, which runs the subagent in a temporary git worktree      |

**Placement and priority** (highest to lowest): managed policy > `--agents` CLI flag > project `.claude/agents/` > user `~/.claude/agents/` > plugin \[3].

**Built-in subagents**: `Explore` (Haiku, read-only, skips CLAUDE.md, for search and analysis), `Plan` (read-only planning), `general-purpose` (full tools, complex multi-step tasks) \[3]. One important constraint: **subagents cannot generate subagents** (no nested delegation).

<Note>
  **A read-only review subagent**

  ```markdown theme={null}
  ---
  name: kb-reviewer
  description: Review knowledge-base units for compliance with the writing spec. Use before marking a unit complete.
  tools: Read, Grep, Glob, Bash
  model: inherit
  ---
  You are a read-only quality reviewer. Check tone, full-width punctuation, dead links, and
  currency annotations against writing-spec.md. Return a tiered issue list. Do not modify any files.
  ```

  Giving it only read-only tools is least-privilege in practice. The main agent delegates and receives only the issue list -- it never has the review process's extensive file reads diluting its own context. For full subagent production details see [04-5](/en/code-agent/customization/subagents).
</Note>

***

## 5. Plugins and marketplaces: packaging and distribution

A Plugin packages skills, agents, hooks, and MCP servers into a single installable unit, letting a team install a consistent configuration in one step.

**Marketplaces and installation** (as of 2026-05) \[4]:

* **Official marketplace** `claude-plugins-official` is available automatically on startup: `/plugin install <name>@claude-plugins-official`, browsable at `claude.com/plugins`.
* **Community marketplace** `anthropics/claude-plugins-community`: first run `/plugin marketplace add anthropics/claude-plugins-community`, then `/plugin install <name>@claude-community`.
* **Arbitrary marketplace**: `/plugin marketplace add owner/repo` (GitHub), a Git URL, or a local path (the repo must contain `.claude-plugin/marketplace.json`).

**Plugin structure**: `.claude-plugin/plugin.json` at the repo root is the manifest (the only file in that directory). Components go in the outer `skills/`, `agents/`, `commands/`, `hooks/hooks.json`, `.mcp.json`, `.lsp.json`, `monitors/monitors.json`, and `bin/`, plus a plugin-level `settings.json` (only `agent` and `subagentStatusLine` keys take effect) \[4].

The official documentation explicitly warns: **do not** put `commands/`, `agents/`, `skills/`, or `hooks/` inside the `.claude-plugin/` directory -- only `plugin.json` goes there.

Full directory layout:

<Tree>
  <Tree.Folder name="my-plugin/" defaultOpen>
    <Tree.Folder name=".claude-plugin/" defaultOpen>
      <Tree.File name="plugin.json · the only file that belongs here" />
    </Tree.Folder>

    <Tree.Folder name="skills/">
      <Tree.File name="skill-name/SKILL.md" />
    </Tree.Folder>

    <Tree.Folder name="agents/">
      <Tree.File name="agent-name.md" />
    </Tree.Folder>

    <Tree.Folder name="hooks/">
      <Tree.File name="hooks.json" />
    </Tree.Folder>

    <Tree.Folder name="commands/">
      <Tree.File name="command-name.md" />
    </Tree.Folder>

    <Tree.File name=".mcp.json" />

    <Tree.File name="settings.json · only agent / subagentStatusLine keys take effect" />
  </Tree.Folder>
</Tree>

<Warning>
  **Scan before installing: plugins and Skills are supply-chain assets**

  A community Skill or plugin is someone else's code and instructions running inside your agent. Before installing, scan for: hidden Unicode (prompt injection), outbound-execute patterns like `curl | bash`, overly broad tool permissions, `ANTHROPIC_BASE_URL` overrides, and `enableAllProjectMcpServers` auto-approval. High star counts do not mean safe or maintained. For the full threat model, scan commands, and relevant CVEs see [03-3](/en/code-agent/judgment/security-privacy-supply-chain); for correct usage see [04-7](/en/code-agent/customization/plugins).
</Warning>

***

## Tool comparison

Mapping the four mechanisms across tools reveals uneven coverage (as of 2026-05; exact mechanisms are subject to each vendor's current documentation; see [02-6](/en/code-agent/configuration/other-tools-comparison) for deeper comparison):

| Concept                            | Anthropic Claude (primary)                           | OpenAI (Codex)                                    | Google (Gemini CLI)                     | GitHub Copilot                   | Cursor                       |
| ---------------------------------- | ---------------------------------------------------- | ------------------------------------------------- | --------------------------------------- | -------------------------------- | ---------------------------- |
| Reusable process (Skill / command) | `SKILL.md` + `.claude/commands/` \[1]                | prompts / custom instructions (per official docs) | custom instructions (per official docs) | `.prompt.md` (per official docs) | `.cursor/rules/*.mdc`        |
| Event-driven Hook                  | `hooks` events (\~30 events) \[2]                    | per official docs                                 | per official docs                       | per official docs                | no equivalent Hook mechanism |
| Subagent / context isolation       | `.claude/agents/*.md` + built-in Explore / Plan \[3] | per official docs                                 | per official docs                       | per official docs                | per official docs            |
| Plugin / extension marketplace     | plugin + marketplace \[4]                            | per official docs                                 | extensions (per official docs)          | per official docs                | per official docs            |

<Note>
  **The comparison table gives coordinates only**

  Naming and maturity of mechanisms varies significantly across vendors; precise details are subject to each vendor's current official documentation. Claude Code provides approximately 30 hook events and built-in subagent context isolation \[2, 3]; most other tools lean toward "instructions / rules" layers without an equivalent deterministic event mechanism. For deeper comparison see [02-6](/en/code-agent/configuration/other-tools-comparison).
</Note>

***

## Hands-on exercises

<Steps>
  <Step title="Write a minimal Skill">
    Following the example in Section 2, create a `SKILL.md` under `~/.claude/skills/` (for example, "clean up references in the lab's citation format") with only a `description` and the procedure steps. Trigger it and confirm that Claude actually follows the steps.
  </Step>

  <Step title="Add a PostToolUse Hook to run lint / formatting after every save">
    Following the example in Section 3, attach a PostToolUse hook in `settings.json` with an `Edit|Write` matcher, pointing to a script that reads `tool_input.file_path` from the stdin JSON. Edit a file and confirm the hook actually fires.
  </Step>

  <Step title="Build a read-only review subagent">
    Following the example in Section 4, create a subagent in `.claude/agents/` that is given only `Read` / `Grep` tools. Use `/agents` to confirm it loads, then dispatch it to review some content and receive only the conclusion.
  </Step>
</Steps>

***

## Common pitfalls

<Warning>
  **Anti-pattern list**

  * **Writing Hook-worthy behavior into CLAUDE.md and hoping for compliance**: formatting and blocking dangerous commands must be guaranteed. CLAUDE.md and Skills both rely on model compliance, which can be missed. Use a Hook.
  * **Installing high-star but unmaintained or overly permissive plugins**: stars reflect marketing reach, not safety or maintenance. Scan before installing (see [03-3](/en/code-agent/judgment/security-privacy-supply-chain)).
  * **Giving a subagent too many tool permissions**: a review-only subagent with write tools violates least privilege. Read-only tasks get read-only tools.
  * **Using a Skill for an exploration task that should be isolated**: dumping large amounts of reads into the main context dilutes it. Use a subagent, send only the conclusion.
  * **Placing components inside `.claude-plugin/`**: only `plugin.json` belongs there. `skills/`, `agents/`, and `hooks/` go in the outer directory \[4].
</Warning>

***

## Self-check

<Check>
  **The bar for passing this unit**

  1. Given a recurring task (for example, "run tests before every commit and block failing commits"), can you determine whether to use a Skill, a Hook, or a Subagent? What is your reasoning?
  2. What is the difference in effect between `disable-model-invocation: true` and `user-invocable: false` on a Skill?
  3. If you want Claude Code to always run formatting after every save, which hook event do you use? Why not put this in CLAUDE.md?
  4. What tool permissions should a review-only subagent have? What principle does giving it write tools violate?
  5. Before installing a plugin from the community marketplace, what categories of risk signals do you scan for?
</Check>

***

## Sources and further reading

Factual claims are grounded in official documentation; fast-changing items are annotated as of 2026-05.

<div className="references">
  * \[1] Anthropic, "Skills," Claude Code Docs. (`SKILL.md` frontmatter fields; progressive disclosure -- loads on demand; placement priority: enterprise > personal > project > plugin; `` !`command` `` dynamic injection and `disableSkillShellExecution`; Skill wins over a same-named `.claude/commands/` entry) [https://code.claude.com/docs/en/skills](https://code.claude.com/docs/en/skills) (as of 2026-05)

  * \[2] Anthropic, "Hooks," Claude Code Docs. (\~30 hook events; handler types: command / http / mcp\_tool / prompt / agent; stdin JSON protocol, exit code 2 blocks, exit 0 + JSON decision; `PreToolUse` `permissionDecision: deny`; matcher syntax; no `$CLAUDE_FILE_PATHS` environment variable -- path comes from stdin JSON `tool_input.file_path`) [https://code.claude.com/docs/en/hooks](https://code.claude.com/docs/en/hooks) (as of 2026-05)

  * \[3] Anthropic, "Subagents," Claude Code Docs. (`.claude/agents/*.md` frontmatter; placement priority: managed > `--agents` > project > user > plugin; built-in Explore / Plan / general-purpose; context isolation returns only the conclusion; subagents cannot be nested; `isolation: worktree`) [https://code.claude.com/docs/en/sub-agents](https://code.claude.com/docs/en/sub-agents) (as of 2026-05)

  * \[4] Anthropic, "Plugins," Claude Code Docs. (official marketplace `claude-plugins-official` available automatically; community `anthropics/claude-plugins-community`; `/plugin install`, `/plugin marketplace add`; plugin structure: `.claude-plugin/plugin.json` + outer `skills/` `agents/` `hooks/hooks.json` `.mcp.json`; only `plugin.json` goes in `.claude-plugin/`) [https://code.claude.com/docs/en/plugins](https://code.claude.com/docs/en/plugins) (as of 2026-05)
</div>

* Related: [01-6](/en/code-agent/foundations/harness-engineering) on the strategy-vs-rule distinction (the design starting point for Hooks); [04-3](/en/code-agent/customization/commands) Command; [04-4](/en/code-agent/customization/skills) Skill; [04-5](/en/code-agent/customization/subagents) Subagent; [04-6](/en/code-agent/customization/hooks) Hooks; [04-7](/en/code-agent/customization/plugins) Plugin production details; [03-3](/en/code-agent/judgment/security-privacy-supply-chain) security and supply-chain threat model.
