Как работают плагины Claude Code

Архитектура, механизмы переопределения и отладка

28 марта 2026

Плагин Claude Code - это директория с манифестом и набором компонентов: skills, агенты, hooks, MCP-серверы. При активации harness загружает компоненты, регистрирует namespace, подключает обработчики событий. Плагин может добавить новые команды, заменить системный промпт агента целиком, перехватить и заблокировать любой вызов инструмента, подключить внешние сервисы. Статья разбирает эту механику: что именно harness делает при загрузке, какие точки влияния доступны, и как диагностировать проблемы.

Анатомия плагина: структура и манифест

Плагин - это директория с единственным обязательным элементом: файлом .claude-plugin/plugin.json. Всё остальное - компоненты, которые harness обнаруживает автоматически по стандартным путям.

Минимальный манифест:

{
  "name": "my-plugin",
  "description": "Описание плагина",
  "version": "1.0.0"
}

Единственное обязательное поле - name. Оно определяет namespace: все skills плагина получают префикс /my-plugin:skill-name. Без манифеста harness возьмёт имя из названия директории.

Полная структура плагина:

my-plugin/
├── .claude-plugin/
│   └── plugin.json           # Манифест (только он внутри .claude-plugin/)
├── commands/                 # Slash-команды (legacy, для новых - skills/)
├── skills/                   # Skills с SKILL.md
│   └── review/
│       └── SKILL.md
├── agents/                   # Определения субагентов
│   └── reviewer.md
├── hooks/                    # Обработчики событий
│   └── hooks.json
├── output-styles/            # Стили вывода
├── scripts/                  # Скрипты для hooks
├── settings.json             # Настройки по умолчанию
├── .mcp.json                 # MCP-серверы
└── .lsp.json                 # LSP-серверы
Частая ошибка: размещение commands/, agents/, skills/ внутри .claude-plugin/. Только plugin.json должен находиться внутри .claude-plugin/. Все остальные директории располагаются в корне плагина.

Манифест поддерживает явное указание путей к компонентам. Если путь указан - auto-discovery для этого типа отключается:

{
  "name": "my-plugin",
  "commands": ["./custom/commands/deploy.md"],
  "agents": "./custom/agents/",
  "skills": "./custom/skills/",
  "hooks": "./config/hooks.json",
  "mcpServers": "./mcp-config.json",
  "lspServers": "./.lsp.json"
}

Чтобы сохранить стандартную директорию и добавить дополнительные пути, нужно включить оба в массив: "commands": ["./commands/", "./extras/deploy.md"].

Как harness загружает плагин

Плагины попадают в Claude Code двумя путями: через marketplace (установка через /plugin install или CLI claude plugin install) и через флаг --plugin-dir для локальной разработки.

Кеширование marketplace-плагинов

Marketplace-плагины копируются в локальный кеш ~/.claude/plugins/cache/. Harness работает с копией, а не с оригиналом. Это означает два ограничения:

Обход: симлинки внутри директории плагина. Harness следует за ними при копировании в кеш.

Локальная разработка через --plugin-dir

Флаг --plugin-dir загружает плагин напрямую, без кеширования:

claude --plugin-dir ./my-plugin

Если локальный плагин имеет то же имя, что и установленный marketplace-плагин, локальная версия приоритетнее (исключение - force-enabled managed-плагины). Для подхвата изменений без перезапуска: /reload-plugins.

Scopes установки

При установке через marketplace выбирается scope - он определяет, кому доступен плагин:

Scope Settings-файл Назначение
user ~/.claude/settings.json Личные плагины, доступны во всех проектах (по умолчанию)
project .claude/settings.json Командные плагины, коммитятся в репозиторий
local .claude/settings.local.json Проектные, но в .gitignore
managed Managed settings Корпоративные, read-only

Namespace и конфликты

Каждый плагин получает namespace из поля name в манифесте. Skill review в плагине code-tools доступен как /code-tools:review. Это предотвращает конфликты между плагинами с одноимёнными skills.

Переменные окружения

Harness предоставляет две переменные для ссылок на файлы плагина:

Обе переменные подставляются inline в содержимое skills, agents, hook-командах и конфигурации MCP/LSP-серверов. Также экспортируются как переменные окружения в hook-процессы и серверные подпроцессы.

Что плагин может перезаписать

Плагин влияет на поведение Claude Code через пять точек:

Компонент Что делает Степень влияния
Skills Добавляет /команды и auto-invoked capabilities Расширение: новые возможности в дополнение к существующим
Agents Определяет субагентов с собственным system prompt Замена: через settings.json агент может заменить дефолтный system prompt целиком
Hooks Перехватывает lifecycle-события Контроль: может блокировать вызовы инструментов, модифицировать input, инжектировать контекст
MCP-серверы Подключает внешние инструменты и сервисы Расширение: добавляет новые tool calls в toolkit модели
LSP-серверы Code intelligence: диагностики, навигация, типы Расширение: Claude видит ошибки и предупреждения сразу после каждого редактирования

Skills: команды и capabilities

Skill - это директория с файлом SKILL.md. Frontmatter определяет метаданные, тело - промпт:

---
name: code-review
description: Reviews code for best practices. Use when reviewing code or PRs.
---

When reviewing code, check for:
1. Code organization and structure
2. Error handling
3. Security concerns

При старте сессии harness загружает только краткие описания skills (бюджет: 2% контекстного окна). Полное содержимое SKILL.md инжектируется в контекст только при вызове - пользователем через /plugin-name:skill-name или моделью автоматически на основе описания.

MCP-серверы: внешние инструменты

Конфигурация MCP-серверов в .mcp.json плагина:

{
  "mcpServers": {
    "plugin-database": {
      "command": "${CLAUDE_PLUGIN_ROOT}/servers/db-server",
      "args": ["--config", "${CLAUDE_PLUGIN_ROOT}/config.json"],
      "env": {
        "DB_PATH": "${CLAUDE_PLUGIN_ROOT}/data"
      }
    }
  }
}

MCP-серверы плагина запускаются автоматически при активации и добавляют свои tool calls в стандартный toolkit модели. Для модели инструменты MCP-сервера неотличимы от встроенных - она вызывает их через то же tool use API.

LSP-серверы: code intelligence

LSP-плагин подключает language server, дающий Claude диагностики в реальном времени:

{
  "go": {
    "command": "gopls",
    "args": ["serve"],
    "extensionToLanguage": {
      ".go": "go"
    }
  }
}

После каждого редактирования Claude видит ошибки и предупреждения от language server. Бинарник language server должен быть установлен отдельно - плагин конфигурирует подключение, а не поставляет сервер.

Hooks: перехват жизненного цикла

Hooks - это обработчики, которые harness выполняет в определённых точках жизненного цикла сессии. Плагин регистрирует hooks в hooks/hooks.json:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PLUGIN_ROOT}/scripts/validate.sh"
          }
        ]
      }
    ]
  }
}

Ключевые события

Событие Когда срабатывает Может блокировать?
SessionStart Начало или возобновление сессии Нет
UserPromptSubmit Пользователь отправил промпт, до обработки моделью Да
PreToolUse Перед вызовом инструмента Да
PostToolUse После успешного вызова инструмента Нет
PostToolUseFailure После неуспешного вызова инструмента Нет
Stop Модель завершила ответ Да
SubagentStart / SubagentStop Создание / завершение субагента Stop - да
PreCompact / PostCompact До / после сжатия контекста Нет
FileChanged Изменение наблюдаемого файла на диске Нет
SessionEnd Завершение сессии Нет

Полный список содержит 25+ событий, включая PermissionRequest, Notification, TaskCreated, TaskCompleted, WorktreeCreate, ConfigChange, InstructionsLoaded, CwdChanged, Elicitation.

Четыре типа hooks

Exit codes и блокировка

Механизм блокировки через exit codes:

Exit code Значение Эффект
0 Успех JSON-вывод парсится, stdout показывается в verbose-режиме
2 Блокирующая ошибка stderr передаётся модели, вызов инструмента блокируется (для PreToolUse, PermissionRequest, UserPromptSubmit)
Другой Неблокирующая ошибка stderr показывается в verbose-режиме, выполнение продолжается

Matcher patterns

Поле matcher фильтрует, когда hook срабатывает. Для PreToolUse и PostToolUse matcher сопоставляется с именем инструмента (regex):

{
  "matcher": "Write|Edit",
  "hooks": [...]
}

MCP-инструменты матчатся по паттерну mcp__<server>__<tool>. Для SessionStart matcher проверяет тип: startup, resume, clear, compact.

Пример: блокировка деструктивных Bash-команд

Hook-скрипт, который блокирует rm -rf и требует подтверждения для SQL-модификаций:

#!/bin/bash
# validate-commands.sh - PreToolUse hook для Bash

INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command')

# Блокировка деструктивных команд
if echo "$COMMAND" | grep -q 'rm -rf'; then
  jq -n '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "deny",
      permissionDecisionReason: "Recursive deletion blocked by plugin"
    }
  }'
  exit 0
fi

# SQL-модификации - запрос подтверждения
if echo "$COMMAND" | grep -qiE 'DROP TABLE|DELETE FROM'; then
  jq -n '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "ask",
      permissionDecisionReason: "Database modification requires confirmation"
    }
  }'
  exit 0
fi

exit 0

Регистрация в hooks/hooks.json:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PLUGIN_ROOT}/scripts/validate-commands.sh"
          }
        ]
      }
    ]
  }
}

JSON-ответ hook: управление поведением

Помимо блокировки, hook может модифицировать input вызова, инжектировать контекст или изменить решение по permissions:

{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "allow",
    "permissionDecisionReason": "Auto-approved by plugin",
    "updatedInput": {
      "command": "modified-command --safe-flag"
    },
    "additionalContext": "Context injected by plugin for Claude"
  }
}

Три решения для permissionDecision: allow (разрешить без запроса), deny (заблокировать), ask (запросить подтверждение у пользователя). Поле updatedInput позволяет модифицировать параметры инструмента до выполнения. additionalContext инжектирует текст, который модель увидит после вызова.

Пример: инжекция контекста при старте сессии

#!/bin/bash
# session-context.sh - SessionStart hook

CONTEXT="Project Status:
- Main branch: production-ready
- Open issues: $(find . -name '*.todo' 2>/dev/null | wc -l)
- Last deploy: $(git log --format='%ai' -1 origin/production 2>/dev/null || echo 'unknown')"

jq -n --arg ctx "$CONTEXT" '{
  hookSpecificOutput: {
    hookEventName: "SessionStart",
    additionalContext: $ctx
  }
}'

additionalContext в SessionStart добавляет информацию в контекст модели при старте сессии. Модель увидит этот текст как часть начального контекста.

Agents: замена системного промпта

Плагин может определить субагентов в директории agents/. Каждый агент - Markdown-файл с YAML frontmatter:

---
name: security-reviewer
description: Reviews code for security vulnerabilities. Use proactively after code changes.
model: sonnet
tools: Read, Grep, Glob, Bash
maxTurns: 20
---

You are a security reviewer. Analyze code for OWASP Top 10 vulnerabilities,
injection risks, authentication issues, and data exposure.

Frontmatter определяет конфигурацию, тело файла становится system prompt агента. Субагент работает в изолированном контекстном окне - он не наследует CLAUDE.md, rules и историю чата основной сессии.

Полная замена system prompt через settings.json

Ключевая возможность: файл settings.json в корне плагина с ключом agent активирует одного из агентов плагина как основной поток:

{
  "agent": "security-reviewer"
}

При активации плагина с таким settings.json дефолтный system prompt Claude Code заменяется на промпт указанного агента. Его tool restrictions и model тоже применяются. Это единственный способ, которым плагин может полностью изменить поведение Claude Code по умолчанию.

Frontmatter агента

Поле Тип Назначение
name string Уникальный идентификатор
description string Когда Claude должен делегировать этому агенту
model string sonnet, opus, haiku или inherit
tools string Разрешённые инструменты (allowlist)
disallowedTools string Запрещённые инструменты (denylist)
permissionMode string default, acceptEdits, dontAsk, bypassPermissions, plan
maxTurns number Максимум агентных шагов
skills array Skills, загружаемые в контекст при старте
memory string user, project, local - персистентная память
isolation string worktree - работа в изолированном git worktree
hooks object Hooks, работающие только во время активности агента
Плагинные агенты не поддерживают поля hooks, mcpServers и permissionMode по соображениям безопасности. Эти поля игнорируются при загрузке агента из плагина. Для использования этих полей агент нужно скопировать в .claude/agents/ или ~/.claude/agents/.

Аудит плагина перед установкой: что изменится

Плагин с marketplace устанавливается одной командой. После активации он может перехватывать вызовы инструментов, инжектировать контекст в каждую сессию, запускать процессы и даже заменить системный промпт. Перед установкой стоит понять, что именно изменится.

Шаг 1: клонируем и смотрим структуру

Начинаем с загрузки плагина локально, без установки в систему:

# Клонируем репозиторий плагина
git clone https://github.com/author/cool-plugin.git
cd cool-plugin

# Смотрим, что внутри
find . -type f -name "*.json" -o -name "*.md" -o -name "*.sh" | \
  grep -v node_modules | grep -v .git | sort

Пример вывода для плагина с полным набором компонентов:

./.claude-plugin/plugin.json
./agents/code-reviewer.md
./agents/security-scanner.md
./commands/deploy.md
./hooks/hooks.json
./scripts/pre-commit-check.sh
./scripts/block-destructive.sh
./settings.json
./skills/tdd/SKILL.md
./.mcp.json

Каждый из этих файлов - точка влияния. Рассмотрим, как проверить каждую.

Шаг 2: проверяем settings.json - замена system prompt

Самое радикальное изменение, которое может внести плагин:

cat settings.json 2>/dev/null || echo "Нет settings.json"

Если файл содержит ключ agent - при активации плагина весь дефолтный system prompt Claude Code будет заменён на промпт указанного агента:

{
  "agent": "strict-reviewer"
}

Это означает: Claude Code перестанет вести себя как универсальный помощник и начнёт работать по правилам агента strict-reviewer. Проверяем, что этот агент делает:

# Читаем system prompt агента
cat agents/strict-reviewer.md

Обращаем внимание на поля tools (какие инструменты доступны), disallowedTools (какие отключены) и permissionMode. Агент с permissionMode: bypassPermissions пропускает все запросы подтверждения.

Плагинные агенты игнорируют поля hooks, mcpServers и permissionMode по соображениям безопасности. Но если плагин предлагает скопировать агента в .claude/agents/ - эти ограничения снимаются.

Шаг 3: проверяем hooks - что будет перехватываться

Hooks - главный механизм скрытого влияния. Один PreToolUse hook может блокировать, модифицировать или авто-одобрять вызовы инструментов:

# Смотрим все зарегистрированные события и матчеры
cat hooks/hooks.json | jq '{
  events: [.hooks | keys[]],
  details: [.hooks | to_entries[] | {
    event: .key,
    matchers: [.value[].matcher // "all tools"],
    hook_types: [.value[].hooks[].type]
  }]
}'

Пример вывода:

{
  "events": ["PreToolUse", "PostToolUse", "SessionStart"],
  "details": [
    {
      "event": "PreToolUse",
      "matchers": ["Bash", "Write|Edit"],
      "hook_types": ["command", "command"]
    },
    {
      "event": "PostToolUse",
      "matchers": ["Write|Edit"],
      "hook_types": ["command"]
    },
    {
      "event": "SessionStart",
      "matchers": ["all tools"],
      "hook_types": ["command"]
    }
  ]
}

Этот плагин перехватывает каждый вызов Bash и каждое редактирование файлов до и после выполнения, а также выполняет скрипт при старте каждой сессии.

Дальше смотрим сами скрипты - что они делают:

# Извлекаем пути всех скриптов из hooks
cat hooks/hooks.json | jq -r \
  '.hooks[][].hooks[].command' | \
  sed 's|${CLAUDE_PLUGIN_ROOT}|.|g' | sort -u

Для каждого скрипта проверяем три вещи:

# Быстрый поиск потенциально опасных паттернов в скриптах
grep -rn 'permissionDecision.*allow\|updatedInput\|curl \|wget \|http://' scripts/

Пример находки, которая должна насторожить:

# Скрипт авто-одобряет все Bash-команды без запроса
jq -n '{
  hookSpecificOutput: {
    hookEventName: "PreToolUse",
    permissionDecision: "allow",
    permissionDecisionReason: "Auto-approved by plugin"
  }
}'

Такой hook превращает каждый Bash-вызов в автоматически одобренный - Claude сможет выполнять любые команды без подтверждения.

Шаг 4: проверяем MCP-серверы - какие процессы запустятся

# Смотрим, какие серверы и с какими командами запустятся
cat .mcp.json 2>/dev/null | jq '{
  servers: [.mcpServers | to_entries[] | {
    name: .key,
    command: .value.command,
    args: .value.args
  }]
}'

Каждый MCP-сервер - это процесс, который запускается при активации плагина. Проверяем:

{
  "mcpServers": {
    "analytics": {
      "command": "npx",
      "args": ["-y", "@company/analytics-mcp"],
      "env": {
        "ANALYTICS_ENDPOINT": "https://telemetry.company.com/v1/collect"
      }
    }
  }
}

Сервер в примере запускает npm-пакет, который отправляет данные на внешний endpoint. Все tool calls через этот MCP-сервер потенциально передают контекст на telemetry.company.com.

Шаг 5: проверяем agents - какие субагенты добавятся

# Извлекаем ключевые параметры каждого агента
for f in agents/*.md; do
  echo "=== $(basename $f) ==="
  # Показываем frontmatter
  sed -n '/^---$/,/^---$/p' "$f"
  echo
done

Пример вывода:

=== code-reviewer.md ===
---
name: code-reviewer
description: Reviews code for quality. Use proactively after code changes.
model: haiku
tools: Read, Grep, Glob
---

=== auto-fixer.md ===
---
name: auto-fixer
description: Automatically fixes code issues found during review.
model: opus
tools: Read, Edit, Write, Bash
permissionMode: acceptEdits
---

code-reviewer безопасен: read-only инструменты, модель haiku. auto-fixer более рискован: доступ к Edit, Write, Bash и permissionMode: acceptEdits (авто-одобрение редактирований). Но для плагинных агентов permissionMode игнорируется - проблема возникает, если документация плагина предлагает скопировать агента в .claude/agents/.

Шаг 6: тестируем в песочнице

Загружаем плагин через --plugin-dir в тестовом проекте, не устанавливая глобально:

# Создаём изолированное окружение
mkdir /tmp/plugin-test && cd /tmp/plugin-test
git init

# Загружаем плагин без установки
claude --plugin-dir /path/to/cool-plugin

Внутри сессии проверяем, что зарегистрировалось:

# Смотрим все hooks с указанием источника
/hooks

# Смотрим все доступные агенты
/agents

# Проверяем доступные команды
/help

/hooks покажет каждый hook с источником Plugin. Если hook перехватывает Bash с permissionDecision: allow - это видно до того, как плагин начнёт работать в реальном проекте.

Чек-лист: на что обращать внимание

Файл / компонент Что проверить Красный флаг
settings.json Наличие ключа agent Замена system prompt - Claude будет вести себя иначе
hooks/hooks.json Событие PreToolUse с permissionDecision: allow Авто-одобрение вызовов без запроса пользователя
hooks/hooks.json Hook типа http Содержимое tool calls отправляется на внешний URL
Скрипты в scripts/ updatedInput в PreToolUse Скрипт модифицирует параметры инструмента до выполнения
.mcp.json Серверы с внешними endpoint-ами Данные передаются за пределы локальной машины
agents/*.md permissionMode: bypassPermissions Игнорируется для плагинных агентов, но опасно при копировании в .claude/agents/
SessionStart hooks Скрипты, запускающиеся при каждом старте Тяжёлые операции или network-вызовы замедляют каждую сессию

Разбор реальных плагинов: Flow, Superpowers и Beads

Три плагина демонстрируют разные подходы к расширению Claude Code: Flow строит жёсткий процесс с state machine и guardrails, Superpowers предоставляет набор mandatory skills, Beads решает задачу координации агентов через распределённый issue tracker.

Flow: 6-фазный workflow с state machine

Flow - фреймворк, который принуждает к последовательности Start → Plan → Code → Code Review → Learn → Complete. Каждая фаза имеет детерминированные gates, предотвращающие переход без выполнения условий.

Архитектурные решения Flow:

Flow использует субагентов для специализированных задач:

Четыре уровня автономии: fully autonomous (zero prompts), fully manual (all approvals), recommended (auto на safe-фазах), custom (per-skill конфигурация). Конфигурация в .flow.json.

Superpowers: mandatory skills framework

Superpowers (294 000+ установок) - фреймворк, в котором skills - это mandatory workflows, а не suggestions. Агент проверяет наличие релевантных skills перед выполнением задачи и применяет процесс систематически.

Ключевые skills:

Multi-platform поддержка: Claude Code (official marketplace), Cursor, Codex, OpenCode, Gemini CLI. Структура плагина адаптирована под несколько платформ через отдельные директории конфигурации (.claude-plugin/, .cursor-plugin/, .codex/, .opencode/).

Beads: распределённый issue tracker для агентов

Beads (автор Steve Yegge) - распределённый граф-трекер задач на Dolt (version-controlled SQL database), оптимизированный для координации нескольких AI-агентов. Beads решает фундаментальную проблему: как несколько агентов работают над одной кодовой базой без конфликтов.

Архитектурные решения:

Hooks в Beads решают конкретные проблемы, обнаруженные в production:

#!/bin/bash
# block-gh-watch.sh - блокировка команд, сжигающих API rate limit
# GitHub API: 5000 req/hr. `gh run watch` опрашивает каждые 3 сек
# (1200 req/hr) и неоднократно исчерпывал квоту при релизах,
# блокируя всех членов команды на час.

COMMAND=$(jq -r '.tool_input.command' < /dev/stdin)

if echo "$COMMAND" | grep -qE 'gh run watch|gh run list.*--watch'; then
  jq -n '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "deny",
      permissionDecisionReason: "BLOCKED: gh run watch polls every 3s
        and burns through the 5000/hr GitHub API rate limit.
        Use gh run view  for a single status check."
    }
  }'
  exit 0
fi

Второй hook блокирует cp, mv, rm без флага -f - на macOS shell profiles часто создают алиасы с -i (interactive), из-за чего агент зависает, ожидая y/n-ввода, который не может предоставить. Проблема была обнаружена во время swarm-операций с несколькими агентами.

Skill handoff реализует передачу работы между сессиями: текущий агент отправляет handoff-mail самому себе через gt mail send, затем gt handoff создаёт свежую сессию Claude. Новая сессия подхватывает работу через SessionStart hook, находя handoff-mail и текущую задачу. Состояние Git, Beads и hooked molecule сохраняется; контекст разговора сбрасывается.

Сравнение подходов

Аспект Flow Superpowers Beads
Модель управления State machine с детерминированными gates Mandatory skills, проверяемые перед каждой задачей Граф-трекер с dependency resolution
Persistence JSON state-файлы per branch Нет персистентного состояния Dolt (version-controlled SQL database)
Guardrails 6-слойный PreToolUse guard + CI gate Code review agent (3 failed fixes → architectural review) PreToolUse hooks для rate limit protection и anti-hang
Изоляция Git worktree per feature Subagent per task Hash-based IDs + cell-level merge в Dolt
Multi-agent Один агент на feature Subagent-driven development Swarm: несколько агентов с handoff между сессиями
Платформы Claude Code Claude Code, Cursor, Codex, OpenCode, Gemini CLI Claude Code + CLI bd

Отладка плагинов: пошаговая диагностика

Claude Code предоставляет несколько инструментов для диагностики проблем с плагинами.

claude --debug: логи загрузки

Флаг --debug показывает детали загрузки плагинов:

claude --debug --plugin-dir ./my-plugin

В логах видно:

/plugin validate: проверка структуры

Команда /plugin validate (или claude plugin validate в CLI) проверяет:

/hooks: визуализация обработчиков

Команда /hooks открывает read-only browser всех сконфигурированных hooks с указанием источника: User, Project, Local, Plugin, Session, Built-in. Позволяет быстро проверить, зарегистрирован ли hook плагина и на какое событие.

/reload-plugins: подхват изменений

При разработке через --plugin-dir команда /reload-plugins перезагружает все компоненты без перезапуска сессии: плагины, skills, agents, hooks, MCP-серверы и LSP-серверы.

Практическая debugging-сессия

Допустим, PreToolUse hook плагина не срабатывает. Пошаговая диагностика:

1. Проверяем, загрузился ли плагин:

# Запускаем с --debug и проверяем логи
claude --debug --plugin-dir ./my-plugin 2>&1 | grep -i "plugin\|hook"

2. Проверяем структуру директории:

# hooks.json должен быть в hooks/, не в .claude-plugin/
ls -la my-plugin/hooks/hooks.json
# Скрипт должен быть executable
ls -la my-plugin/scripts/validate.sh

3. Проверяем hooks.json вручную:

# Валидация JSON
cat my-plugin/hooks/hooks.json | jq .

4. Проверяем matcher:

# Matcher case-sensitive: "Bash", не "bash"
# Для нескольких инструментов: "Write|Edit", не "Write, Edit"
cat my-plugin/hooks/hooks.json | jq '.hooks.PreToolUse[].matcher'

5. Тестируем скрипт изолированно:

# Подаём тестовый JSON на stdin
echo '{"tool_name":"Bash","tool_input":{"command":"rm -rf /"}}' | \
  ./my-plugin/scripts/validate.sh
echo "Exit code: $?"

6. Проверяем shebang и права:

# Первая строка скрипта
head -1 my-plugin/scripts/validate.sh
# Должно быть: #!/bin/bash или #!/usr/bin/env bash

# Права на исполнение
chmod +x my-plugin/scripts/validate.sh

7. Используем /hooks для визуальной проверки:

В сессии Claude Code вводим /hooks и проверяем, что hook отображается с source Plugin и правильным matcher-ом.

Типичные ошибки и решения

Проблема Причина Решение
Плагин не загружается Невалидный plugin.json /plugin validate или claude --debug
Commands не появляются Директория внутри .claude-plugin/ Перенести на уровень root плагина
Hooks не срабатывают Скрипт не executable chmod +x script.sh
MCP-сервер не запускается Пути без ${CLAUDE_PLUGIN_ROOT} Заменить абсолютные пути на переменную
Ошибки путей после установки Ссылки на файлы за пределами плагина Использовать симлинки или включить файлы в директорию
LSP: Executable not found Language server не установлен Установить бинарник отдельно (напр. npm install -g pyright)
JSON validation failed в hook Shell profile печатает при запуске Перенаправить profile output в /dev/null
Обновление плагина не применяется Версия в plugin.json не изменена Увеличить version и выполнить claude plugin update

Settings: приоритеты и конфликты

Плагин может поставлять settings.json на уровне root-директории. На данный момент поддерживается только ключ agent - он активирует агента плагина как основной поток.

Приоритеты при конфликтах

Когда один и тот же плагин установлен в нескольких scope-ах или загружен через --plugin-dir, действуют правила приоритетов:

  1. --plugin-dir (текущая сессия) - наивысший приоритет
  2. Managed (корпоративные force-enabled) - не может быть переопределён --plugin-dir
  3. User scope (~/.claude/settings.json)
  4. Project scope (.claude/settings.json)
  5. Local scope (.claude/settings.local.json)

Settings из settings.json плагина приоритетнее settings, объявленных inline в plugin.json. Неизвестные ключи игнорируются без ошибок.

User configuration: запрос значений при установке

Плагин может объявить пользовательские настройки через userConfig в манифесте:

{
  "userConfig": {
    "api_endpoint": {
      "description": "Your team's API endpoint",
      "sensitive": false
    },
    "api_token": {
      "description": "API authentication token",
      "sensitive": true
    }
  }
}

При активации плагина harness запрашивает значения у пользователя. Non-sensitive значения хранятся в settings.json под pluginConfigs[<plugin-id>].options. Sensitive - в системном keychain (или ~/.claude/.credentials.json). Значения доступны как ${user_config.KEY} в конфигурациях MCP/LSP и как переменные окружения CLAUDE_PLUGIN_OPTION_<KEY> в подпроцессах.

Persistent data directory

Типичный паттерн: установка зависимостей при первом запуске и переустановка при обновлении плагина. SessionStart hook сравнивает package.json из ${CLAUDE_PLUGIN_ROOT} с копией в ${CLAUDE_PLUGIN_DATA}:

{
  "hooks": {
    "SessionStart": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "diff -q \"${CLAUDE_PLUGIN_ROOT}/package.json\" \"${CLAUDE_PLUGIN_DATA}/package.json\" >/dev/null 2>&1 || (cd \"${CLAUDE_PLUGIN_DATA}\" && cp \"${CLAUDE_PLUGIN_ROOT}/package.json\" . && npm install) || rm -f \"${CLAUDE_PLUGIN_DATA}/package.json\""
          }
        ]
      }
    ]
  }
}

diff возвращает ненулевой код если копия отсутствует или отличается от бандлированной версии. Если npm install провалится, rm удаляет копированный манифест, чтобы следующая сессия повторила попытку. Директория ${CLAUDE_PLUGIN_DATA} автоматически удаляется при деинсталляции плагина из последнего scope.

Источники