SpyBara
Go Premium

plugins/components.md 2026-10-07 23:59 UTC to 2026-10-08 20:01 UTC

This page contains 118 additions and 118 deletions.

2026
Thu 1 23:59 Fri 2 22:59 Wed 7 23:59 Thu 8 21:58

플러그인에 컴포넌트 추가하기

Claude Code 플러그인에 skills, hooks, MCP 서버 및 다른 모든 컴포넌트 유형을 추가하고, 각각에 대해 검증하는 예제를 포함합니다.

export const Piece = ({id, children}) =>

{children}
;

export const PluginExplorer = ({children}) => { const PIECES = [{ id: 'manifest', name: 'Manifest', path: '.claude-plugin/plugin.json', lines: [{ depth: 0, kind: 'folder', text: '.claude-plugin/' }, { depth: 1, kind: 'file', text: 'plugin.json' }], href: '/en/plugins/manifest-reference#manifest-file', linkText: 'Go to the manifest reference' }, { id: 'skills', name: 'Skills', path: 'skills/review/SKILL.md', lines: [{ depth: 0, kind: 'folder', text: 'skills/' }, { depth: 1, kind: 'folder', text: 'review/' }, { depth: 2, kind: 'file', text: 'SKILL.md' }], href: '/en/plugins/components#skills', linkText: 'Go to the Skills section' }, { id: 'commands', name: 'Commands', path: 'commands/about.md', lines: [{ depth: 0, kind: 'folder', text: 'commands/' }, { depth: 1, kind: 'file', text: 'about.md' }], href: '/en/plugins/components#commands', linkText: 'Go to the Commands section' }, { id: 'agents', name: 'Agents', path: 'agents/security-reviewer.md', lines: [{ depth: 0, kind: 'folder', text: 'agents/' }, { depth: 1, kind: 'file', text: 'security-reviewer.md' }], href: '/en/plugins/components#agents', linkText: 'Go to the Agents section' }, { id: 'hooks', name: 'Hooks', path: 'hooks/hooks.json', lines: [{ depth: 0, kind: 'folder', text: 'hooks/' }, { depth: 1, kind: 'file', text: 'hooks.json' }], href: '/en/plugins/components#hooks', linkText: 'Go to the Hooks section' }, { id: 'monitors', name: 'Monitors', path: 'monitors/monitors.json', lines: [{ depth: 0, kind: 'folder', text: 'monitors/' }, { depth: 1, kind: 'file', text: 'monitors.json' }], href: '/en/plugins/components#monitors', linkText: 'Go to the Monitors section' }, { id: 'output-styles', name: 'Output styles', path: 'output-styles/terse.md', lines: [{ depth: 0, kind: 'folder', text: 'output-styles/' }, { depth: 1, kind: 'file', text: 'terse.md' }], href: '/en/plugins/components#themes-and-output-styles', linkText: 'Go to the Themes and output styles section' }, { id: 'themes', name: 'Themes', path: 'themes/dracula.json', lines: [{ depth: 0, kind: 'folder', text: 'themes/' }, { depth: 1, kind: 'file', text: 'dracula.json' }], href: '/en/plugins/components#themes-and-output-styles', linkText: 'Go to the Themes and output styles section' }, { id: 'workflows', name: 'Workflows', path: 'workflows/audit-routes.js', lines: [{ depth: 0, kind: 'folder', text: 'workflows/' }, { depth: 1, kind: 'file', text: 'audit-routes.js' }], href: '/en/workflows#distribute-a-workflow-in-a-plugin', linkText: 'Go to Distribute a workflow in a plugin' }, { id: 'bin', name: 'Executables', path: 'bin/hello-plugin', lines: [{ depth: 0, kind: 'folder', text: 'bin/' }, { depth: 1, kind: 'file', text: 'hello-plugin' }], href: '/en/plugins/components#executables', linkText: 'Go to the Executables section' }, { id: 'scripts', name: 'Scripts', path: 'scripts/format.sh', lines: [{ depth: 0, kind: 'folder', text: 'scripts/' }, { depth: 1, kind: 'file', text: 'format.sh' }], href: '/en/plugins/components#hooks', linkText: 'Go to the Hooks section' }, { id: 'settings', name: 'Default settings', path: 'settings.json', lines: [{ depth: 0, kind: 'file', text: 'settings.json' }], href: '/en/plugins/components#default-settings', linkText: 'Go to the Default settings section' }, { id: 'mcp', name: 'MCP servers', path: '.mcp.json', lines: [{ depth: 0, kind: 'file', text: '.mcp.json' }], href: '/en/plugins/components#mcp-servers', linkText: 'Go to the MCP servers section' }, { id: 'lsp', name: 'LSP servers', path: '.lsp.json', lines: [{ depth: 0, kind: 'file', text: '.lsp.json' }], href: '/en/plugins/components#lsp-servers', linkText: 'Go to the LSP servers section' }]; const [selectedId, setSelectedId] = useState('manifest'); const [isFullscreen, setIsFullscreen] = useState(false); const rootRef = useRef(null); useEffect(() => { const onFsChange = () => setIsFullscreen(!!document.fullscreenElement); document.addEventListener('fullscreenchange', onFsChange); return () => document.removeEventListener('fullscreenchange', onFsChange); }, []); const toggleFullscreen = () => { if (!rootRef.current) return; if (document.fullscreenElement) document.exitFullscreen(); else rootRef.current.requestFullscreen().catch(() => {}); }; const selected = PIECES.find(p => p.id === selectedId) || PIECES[0]; const onTreeKeyDown = e => { const keys = ['ArrowDown', 'ArrowUp', 'Home', 'End']; if (keys.indexOf(e.key) === -1) return; const i = PIECES.findIndex(p => p.id === selectedId); let next = i; if (e.key === 'ArrowDown') next = Math.min(PIECES.length - 1, i + 1); if (e.key === 'ArrowUp') next = Math.max(0, i - 1); if (e.key === 'Home') next = 0; if (e.key === 'End') next = PIECES.length - 1; e.preventDefault(); if (next === i) return; const id = PIECES[next].id; setSelectedId(id); const el = document.getElementById('pe-node-' + id); if (el) el.focus(); }; const FolderIcon = () => ; const FileIcon = () => ; return <div ref={rootRef} className={isFullscreen ? 'pe-root pe-fullscreen not-prose' : 'pe-root not-prose'} data-selected={selected.id}>

  <div className="pe-head">
    <div className="pe-head-text">
      <div className="pe-title">What goes in a plugin</div>
      <div className="pe-sub">This example plugin, <code>my-plugin</code>, has one of every kind of component, each in its default location. Select a file or folder to read what it’s for and see what goes in it.</div>
    </div>
    <button type="button" className="pe-fs-btn" onClick={toggleFullscreen} aria-label={isFullscreen ? 'Exit fullscreen' : 'Fullscreen'} title={isFullscreen ? 'Exit fullscreen' : 'Fullscreen'}>
      {isFullscreen ? '⤡' : '⛶'}
    </button>
  </div>

  <div className="pe-body">
    <div className="pe-tree-pane">
      <div className="pe-caption" id="pe-tree-caption">Plugin directory</div>
      <div role="group" aria-labelledby="pe-tree-caption" onKeyDown={onTreeKeyDown}>
        <div className="pe-rootline"><FolderIcon /><span>my-plugin/</span></div>
        {PIECES.map(p => <button key={p.id} id={'pe-node-' + p.id} type="button" className="pe-node" aria-pressed={p.id === selected.id} aria-label={p.name + ', ' + p.path} onClick={() => setSelectedId(p.id)}>
            {p.lines.map((line, i) => <span key={i} className="pe-line pe-line-tree" style={{
paddingLeft: line.depth * 18 + 'px'

}}> {line.kind === 'folder' ? : } {line.text} {p.required && i === p.lines.length - 1 ? {p.required} : null} )} {p.path} {p.required ? {p.required} : null} )}

    <div className="pe-panel" role="region" aria-labelledby="pe-panel-caption" aria-live="polite" aria-atomic="true">
      <div className="pe-caption" id="pe-panel-caption">Selected piece</div>
      <div className="pe-name">{selected.name}{selected.required ? <span className="pe-req">{selected.required}</span> : null}</div>
      <div className="pe-path">{selected.path}</div>

      <div className="pe-block">{children}</div>

      <a className="pe-link" href={selected.href}>{selected.linkText}</a>
    </div>
  </div>
</div>;

};

Claude Code 플러그인은 skills, agents, hooks, MCP 서버와 같은 컴포넌트로 구성됩니다. 각 컴포넌트는 플러그인의 기본 폴더, .claude-plugin/plugin.json의 선택적 manifest 키(해당 폴더를 대체하거나 추가함), 그리고 사용자가 보는 이름을 가집니다. 각 키의 전체 필드 테이블은 manifest 참조를 참조하십시오.

이 페이지를 사용하여 이미 로드되는 플러그인에 컴포넌트를 추가합니다.

컴포넌트를 추가한 후, 실행 중인 세션에서 /reload-plugins를 실행하거나 새 세션을 시작하여 Claude Code가 이를 로드하도록 합니다. 로드하기 전에 컴포넌트의 파일을 확인하려면 플러그인 디렉토리에서 셸에서 claude plugin validate .를 실행합니다.

플러그인 디렉토리 탐색

탐색기는 기본 위치에 모든 종류의 구성 요소 중 하나씩 포함하는 예제 플러그인 my-plugin을 보여줍니다:

각 파일은 해당 형식의 가장 작은 유효한 예제이며, 유용하기보다는 형태를 보여주기 위한 것입니다: 실제 스킬이나 에이전트는 전체 지침을 포함하고 종종 지원 파일을 포함하며, 실제 훅이나 모니터는 실제 작업을 수행합니다. 탐색기 이후의 섹션은 동일한 파일을 예제로 사용하고 더 완전한 파일로 연결됩니다. 파일이나 폴더를 선택하여 그 용도를 읽고, 그 안에 무엇이 들어가는지 확인하고, 그것을 다루는 섹션을 찾습니다.

[매니페스트](/docs/ko/plugins/manifest-reference)는 플러그인의 `.claude-plugin/` 디렉토리에 있는 `plugin.json` 파일입니다. 플러그인의 메타데이터와 Claude Code가 사용자에게 요청하는 `userConfig` 값을 포함합니다. Claude Code는 매니페스트 없이도 플러그인을 로드합니다. 파일 내에서 `name`만 필수입니다. 이 파일에서 `description`은 `/plugin`의 플러그인에 대해 사용자가 보는 텍스트이고, `version`은 변경할 때까지 사용자를 해당 버전에 유지합니다:
```json theme={null}
{
  "name": "my-plugin",
  "version": "1.0.0",
  "description": "Review, formatting, and database tools for this team"
}
```
[스킬](/docs/ko/skills)은 `SKILL.md` 파일입니다. 각 스킬을 `skills/` 아래의 자체 디렉토리에 저장합니다. Claude는 모든 스킬의 `description`을 읽고, 사용자가 요청한 내용이 설명과 일치할 때(예: 여기서 Claude에게 풀 요청을 검토하도록 요청할 때), Claude는 스킬의 지침을 로드하고 따릅니다. 사용자는 `/my-plugin:review`로 직접 실행할 수도 있습니다:
```markdown theme={null}
---
description: Reviews a pull request for style and test coverage. Use when asked to review code.
---

Review the changed files. Report style problems first, then missing tests.
```
명령은 사용자가 이름으로 실행하는 단일 Markdown 파일입니다. 명령은 이전 형식입니다: 스킬은 같은 방식으로 이름으로 실행되며 자체 디렉토리에 지원 파일을 포함할 수도 있으므로 새로운 것은 스킬로 작성하고 이미 있는 파일은 `commands/`에 유지합니다. 이 파일은 `/my-plugin:about`이 되고 스킬과 동일한 프론트매터를 사용합니다:
```markdown theme={null}
---
description: Summarize the repository
---

Summarize what this repository does in three sentences.
```
[서브에이전트](/docs/ko/sub-agents)는 자체 지침과 자체 컨텍스트 윈도우를 가진 별도의 어시스턴트이며, Claude가 작업을 위임하고 결과를 다시 받을 수 있습니다. `agents/` 아래의 각 Markdown 파일은 하나를 정의합니다: 프론트매터는 이름을 지정하고 사용 시기를 말하며, 본문은 시스템 프롬프트입니다. 이 파일은 `my-plugin:security-reviewer`로 명명되며, 사용자는 `@agent-my-plugin:security-reviewer`로 호출할 수 있습니다:
```markdown theme={null}
---
name: security-reviewer
description: Reviews code changes for security issues. Use after edits to authentication or input handling.
model: sonnet
---

You are a security reviewer. Read the changed files and report injection, authentication, and secrets-handling risks.
```
[훅](/docs/ko/hooks-guide)은 파일 편집 후와 같이 Claude Code의 라이프사이클의 특정 지점에서 자동으로 무언가를 실행합니다: 셸 명령, HTTP 요청, MCP 도구 호출, 모델에 대한 프롬프트, 또는 서브에이전트. 플러그인의 훅을 플러그인 루트의 `hooks/hooks.json`에 저장합니다. 이 파일은 Claude가 파일을 작성하거나 편집한 후 플러그인의 `scripts/format.sh`를 실행합니다:
```json theme={null}
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "\"${CLAUDE_PLUGIN_ROOT}/scripts/format.sh\""
          }
        ]
      }
    ]
  }
}
```
모니터는 세션이 시작될 때 Claude Code가 백그라운드에서 시작하고 세션이 끝날 때까지 계속 실행하는 셸 명령입니다. 출력하는 내용은 Claude에게 알림으로 전달됩니다. `when` 필드는 대신 명명된 스킬이 처음 실행될 때 시작할 수 있습니다. 이 파일은 오류 로그를 추적합니다:
```json theme={null}
[
  {
    "name": "error-log",
    "command": "tail -F ./logs/error.log",
    "description": "Application error log"
  }
]
```
플러그인은 [출력 스타일](/docs/ko/output-styles)을 포함할 수 있으며, 이는 Claude가 응답을 포맷하고 표현하는 방식을 변경합니다. 각 출력 스타일을 `output-styles/.md`로 저장합니다. 이 파일은 `/output-style`에 `my-plugin:terse`로 나타납니다:
```markdown theme={null}
---
name: terse
description: Answer in as few words as possible
keep-coding-instructions: true
---

Keep every reply short. Skip preambles and summaries.
```
플러그인은 Claude Code 인터페이스용 [색상 테마](/docs/ko/terminal-config#create-a-custom-theme)를 포함할 수 있습니다. 각 테마를 `themes/.json`으로 저장합니다. 이 파일은 `/theme`에 `Dracula`로 나타나며, `my-plugin`에서 온 것으로 표시됩니다:
```json theme={null}
{
  "name": "Dracula",
  "base": "dark",
  "overrides": {
    "claude": "#bd93f9",
    "error": "#ff5555"
  }
}
```
`workflows/` 폴더는 [워크플로우](/docs/ko/workflows) `.js` 파일을 보유합니다: `meta` 블록, 그 다음 여러 서브에이전트를 조율하는 스크립트 본문. 이 파일은 `/my-plugin:audit-routes`로 실행됩니다:
```javascript theme={null}
export const meta = {
  name: 'audit-routes',
  description: 'Audit every route handler for missing auth checks',
}

const found = await agent('List every .ts file under src/routes/.', {
  schema: { type: 'object', required: ['files'], properties: { files: { type: 'array', items: { type: 'string' } } } },
})

const audits = await pipeline(found.files, file =>
  agent(`Audit ${file} for missing authentication checks.`, { label: file }),
)

return audits.filter(Boolean)
```
`bin/`은 플러그인이 명령줄 도구를 제공하는 방법입니다. 플러그인이 활성화되어 있는 동안 Claude Code는 이 폴더를 실행하는 셸의 `PATH`에 넣으므로 Claude 또는 스킬의 지침이 사용자가 아무것도 설치하지 않고도 이름으로 도구를 실행할 수 있습니다. 이 [실행 파일](#executables)이 있으면 `hello-plugin`은 Claude가 실행할 수 있는 명령입니다:
```bash theme={null}
#!/bin/bash
echo "hello from my-plugin"
```
`hooks/hooks.json`의 훅은 스크립트를 실행하고, 이 폴더는 예제가 이를 유지하는 곳입니다. `scripts/` 이름은 관례이지 Claude Code가 찾는 것이 아닙니다: 훅은 파일을 경로 `${CLAUDE_PLUGIN_ROOT}/scripts/format.sh`로 가리킵니다. 포매터 스크립트는 다음과 같을 수 있습니다:
```bash theme={null}
#!/bin/bash
npx prettier --write .
```
플러그인 루트의 `settings.json`은 플러그인이 활성화되어 있는 동안 적용되는 [설정](/docs/ko/settings-reference)을 보유하므로 플러그인은 세션의 동작 방식을 변경할 수 있고 구성 요소만 추가하는 것이 아닙니다. 플러그인에서 적용되는 키는 [`agent`](/docs/ko/settings-reference#agent)와 [`subagentStatusLine`](/docs/ko/settings-reference#subagentstatusline) 두 개뿐입니다; 다른 모든 키는 삭제됩니다. [기본 설정](#default-settings)을 참조합니다.
이 파일은 `agent`를 설정하며, 이는 세션의 주 스레드를 플러그인 자체의 `security-reviewer` 에이전트로 실행하므로 해당 에이전트의 시스템 프롬프트, 도구 제한 및 모델이 전체 세션에 적용됩니다:

```json theme={null}
{
  "agent": "security-reviewer"
}
```
[MCP 서버](/docs/ko/mcp)는 Claude에게 외부 시스템의 도구를 제공합니다. 플러그인 루트의 `.mcp.json`에서 선언합니다. 이 파일은 플러그인 내부의 스크립트에서 로컬 서버를 시작하며, `/mcp`에 `plugin:my-plugin:db`로 나타납니다:
```json theme={null}
{
  "mcpServers": {
    "db": {
      "command": "node",
      "args": ["${CLAUDE_PLUGIN_ROOT}/server.js"]
    }
  }
}
```
LSP 서버는 Claude에게 언어에 대한 [진단 및 코드 네비게이션](/docs/ko/plugins/code-intelligence)을 제공합니다. 플러그인 루트의 `.lsp.json`에서 서버를 선언합니다. 이 파일은 `.go` 파일에 대해 Go 언어 서버를 연결합니다:
```json theme={null}
{
  "gopls": {
    "command": "gopls",
    "args": ["serve"],
    "extensionToLanguage": {
      ".go": "go"
    }
  }
}
```

각 유형의 구성 요소 추가하기

아래 각 섹션은 한 가지 유형의 구성 요소를 다룹니다. 플러그인에서 해당 파일을 두는 위치, 검증을 통과하는 예시, 플러그인이 로드된 후 사용자에게 보이는 내용, 기본 위치를 변경하는 매니페스트 키를 설명합니다. 플러그인에 필요한 것만 추가하면 되며, 필수 항목은 없습니다.

Skills

스킬은 설명이 작업과 일치할 때 Claude가 로드할 수 있는 SKILL.md 파일입니다. 사용자가 명령으로 직접 실행할 수도 있습니다. 각 스킬은 skills/ 아래의 개별 디렉터리에 저장합니다.

my-plugin/
├── .claude-plugin/
│   └── plugin.json
└── skills/
    └── review/
        └── SKILL.md

Claude가 언제 사용할지 알 수 있도록 SKILL.md에 description을 지정합니다.

---
description: Reviews a pull request for style and test coverage. Use when asked to review code.
---

Review the changed files. Report style problems first, then missing tests.

플러그인을 로드하면 /my-plugin:review가 스킬을 실행합니다. 명령 이름과 호출 주체는 다음 규칙을 따릅니다.

기본 skills/ 디렉터리 외부에 스킬을 둘 수도 있습니다.

플러그인에 지침을 포함하려면 스킬로 작성하십시오. Claude Code는 플러그인 루트의 CLAUDE.md를 로드하지 않으며, claude plugin validate는 CLAUDE.md at the plugin root is not loaded as project context 경고를 표시합니다.

보호된 파일 편집 차단처럼 항상 지켜져야 하는 규칙이라면 스킬이 아닌 훅으로 플러그인에 추가하십시오. 둘 중 무엇을 선택할지는 유사한 기능 비교의 Hook vs Skill 탭을 참조하십시오.

frontmatter 필드와 보조 파일에 대해서는 Skills를 참조하십시오.

Commands

명령은 사용자가 /my-plugin:about처럼 이름으로 실행하는 단일 Markdown 파일입니다.

명령을 commands/<file>.md에 저장하면 /<plugin>:<file>이 됩니다. 하위 디렉터리는 세그먼트를 추가하므로 commands/db/migrate.md는 /my-plugin:db:migrate가 됩니다.

명령 파일은 스킬과 동일한 frontmatter를 사용합니다.

매니페스트에서 명령 정의하기

이 방법은 명령 파일을 commands/가 아닌 다른 위치에 두거나, 별도의 Markdown 파일 없이 plugin.json 안에 짧은 명령을 정의하려는 경우에만 필요합니다. commands 매니페스트 키를 설정하면 Claude Code는 commands/를 스캔하는 대신 이 키를 읽습니다. 이 키는 경로, 경로 배열, 또는 각 명령 이름을 source 파일이나 인라인 content에 매핑하는 객체를 받습니다.

다음 매니페스트는 Markdown 파일 없이 /my-plugin:about을 인라인으로 정의합니다.

{
  "name": "my-plugin",
  "commands": {
    "about": {
      "content": "Summarize what this repository does in three sentences.",
      "description": "Summarize the repository"
    }
  }
}

플러그인을 로드하고 세션에서 /my-plugin:about을 실행하여 로드되었는지 확인합니다.

전체 키 구문은 commands를 참조하십시오.

Agents

서브에이전트는 자체 지침과 컨텍스트 윈도우를 가진 별도의 어시스턴트로, Claude가 작업을 위임할 수 있습니다. agents/ 아래의 각 Markdown 파일이 하나의 서브에이전트를 정의합니다.

---
name: security-reviewer
description: Reviews code changes for security issues. Use after edits to authentication or input handling.
model: sonnet
---

You are a security reviewer. Read the changed files and report injection, authentication, and secrets-handling risks.

이 에이전트의 이름은 my-plugin:security-reviewer이며, 사용자는 @agent-my-plugin:security-reviewer로 명시적으로 호출할 수 있습니다. 이름 형식은 <plugin>:<name>이며, <name>은 frontmatter의 name 필드에서 가져오고, 해당 필드가 없으면 파일 이름에서 가져옵니다.

agents 매니페스트 키는 agents/ 스캔을 대체합니다.

하위 폴더로 에이전트 정리하기

플러그인 에이전트 파일을 agents/의 하위 폴더에 둘 수 있습니다. Claude Code는 이를 재귀적으로 로드하며, 플러그인 이름, 각 하위 폴더 이름, 파일 이름을 콜론으로 연결하여 에이전트의 범위 지정 이름을 만듭니다. 예를 들어 my-plugin이라는 플러그인의 agents/review/security.md는 my-plugin:review:security로 로드됩니다. 다음 두 가지 설정이 이 이름을 변경합니다.

플러그인 에이전트의 frontmatter 필드

플러그인 에이전트의 frontmatter는 다음 규칙을 따릅니다.

각 필드의 역할과 우선순위 규칙은 Subagents를 참조하십시오.

Hooks

훅은 파일을 편집할 때마다와 같이 Claude Code 수명 주기의 특정 시점에 셸 명령, HTTP 요청, MCP 도구 호출, 모델에 대한 프롬프트 또는 서브에이전트를 자동으로 실행합니다. 플러그인의 훅은 플러그인 루트의 hooks/hooks.json에 최상위 "hooks" 키 아래에, settings.json의 hooks 객체와 동일한 형태로 저장합니다. 따라서 기존 설정 훅을 그대로 복사해 넣을 수 있습니다.

다음 훅은 모든 Write 또는 Edit 이후에 번들된 스크립트를 실행합니다.

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "\"${CLAUDE_PLUGIN_ROOT}/scripts/format.sh\""
          }
        ]
      }
    ]
  }
}

스크립트를 scripts/format.sh에 저장하고 실행 가능하게 만듭니다.

플러그인을 로드하고 Claude에게 파일 편집을 요청합니다. 0으로 종료되는 PostToolUse 훅은 트랜스크립트에 아무것도 표시하지 않으므로, 디버그 로깅을 사용하거나 스크립트 자체가 변경한 내용을 통해 실행 여부를 확인하십시오.

hooks/hooks.json의 훅과 hooks 매니페스트 키의 훅은 모두 로드됩니다. 모든 이벤트와 해당 페이로드는 Hook events를 참조하십시오.

Claude Code 내부에서 실행되고 인터페이스에 그릴 수 있는 JavaScript 함수로 훅을 작성하려면, 같은 hooks/hooks.json의 modules 키 아래에 모듈 파일을 나열합니다. 이러한 모듈이 있는 플러그인이 mod입니다. mod 만들기를 참조하십시오.

플러그인 훅이 실행되는 시점

플러그인의 훅은 플러그인의 스킬이나 명령이 사용될 때까지 기다리지 않습니다. Claude Code는 세션이 플러그인을 로드할 때 훅을 등록하며, 그 이후부터 해당 이벤트에서 훅이 실행됩니다. 훅의 실행 시점을 제한하려면 matcher의 범위를 좁히십시오.

훅이 전혀 실행되지 않는다면 실행되지 않는 훅을 참조하십시오.

환경, 따옴표 처리 및 MCP 도구 매칭

훅의 환경, ${CLAUDE_PLUGIN_ROOT}의 따옴표 처리, 플러그인 자체 MCP 도구에 대한 matcher는 다음과 같이 작동합니다.

MCP servers

MCP 서버는 외부 시스템의 도구를 Claude에 제공합니다. 플러그인 루트의 .mcp.json에 프로젝트 .mcp.json과 동일한 형태로 선언합니다. 다음 .mcp.json은 db라는 서버 하나를 선언합니다.

{
  "mcpServers": {
    "db": {
      "command": "node",
      "args": ["${CLAUDE_PLUGIN_ROOT}/server.js"]
    }
  }
}

mcpServers 래퍼를 생략하고 db를 파일의 최상위에 둘 수도 있습니다.

플러그인을 로드하고 /mcp를 실행하여 서버가 plugin:my-plugin:db로 표시되는지 확인합니다.

claude plugin validate는 .mcp.json을 검사하고, Claude Code가 로드 시점에 제외할 서버 항목을 오류로 보고합니다. Claude Code v2.1.281 이상이 필요합니다.

잘못된 항목이 로드 시점에 어디에 표시되는지는 시작되지 않는 MCP 서버를 참조하십시오.

mcpServers 매니페스트 키는 인라인 서버 맵, JSON 파일 경로, 또는 이들의 배열을 받습니다. 매니페스트 서버가 .mcp.json의 서버와 이름이 같으면 매니페스트 서버가 이를 대체합니다.

claude.ai 및 Cowork 사용자에게 제공하기

MCP servers의 db 서버와 같은 로컬 stdio 서버는 Claude Code와 Claude Desktop 앱에서 사용자의 컴퓨터로 실행되는 Cowork 세션에서는 실행되지만 claude.ai에서는 실행되지 않습니다. 해당 사용자에게도 제공하려면 Bundle an MCP connector with its skill에 나온 것처럼 https:// URL로 원격 서버를 참조하십시오. claude.ai와 Cowork는 이를 사용자에게 커넥터로 제공합니다.

서버 이름, 도구 이름 및 다시 로드

서버의 이름, 변수 치환, 다시 로드 동작은 다음 규칙을 따릅니다.

패키징된 MCPB 서버 포함하기

mcpServers 키는 확장자가 .mcpb 또는 이전 형식인 .dxt인 MCPB 파일로 패키징된 서버도 받습니다. 키가 플러그인 내부 경로 또는 https:// URL로 파일을 가리키도록 지정합니다.

{
  "name": "my-plugin",
  "mcpServers": "./servers/db.mcpb"
}

서버 이름은 번들 매니페스트의 name을 따릅니다.

번들 자체의 매니페스트는 user_config 블록에서 서버가 사용자로부터 필요로 하는 설정을 선언할 수 있습니다. 필수 설정에 저장된 값이 없는 번들 서버는 시작되지 않습니다. /plugin Errors 탭에 Bundled MCP server "<name>" was not started: it needs configuration이 표시됩니다.

사용자는 다음 두 가지 방법 중 하나로 값을 제공합니다.

전송 방식과 인증에 대해서는 MCP를 참조하십시오.

LSP servers

LSP 서버는 특정 언어에 대한 진단과 코드 탐색 기능을 Claude에 제공합니다. 공식 코드 인텔리전스 플러그인이 이미 해당 언어를 지원한다면 직접 작성하는 대신 그 플러그인을 설치하십시오. 그렇지 않으면 플러그인 루트의 .lsp.json에 서버를 선언합니다.

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

이 파일은 맵을 감싸는 래퍼 객체 없이 각 서버 이름을 해당 구성에 직접 매핑합니다. command는 바이너리 이름이며, 인수는 args에 지정합니다. extensionToLanguage에는 .으로 시작하는 확장자가 하나 이상 필요합니다.

claude plugin validate는 이 파일을 읽지 않습니다. 항목 중 하나라도 유효하지 않으면 로드 시 파일 전체를 건너뛰며, /plugin Errors 탭에 Invalid LSP server config for ".lsp.json"이 표시됩니다.

플러그인은 연결을 구성하지만 서버 바이너리를 설치하지는 않으며, 각 파일 확장자에는 하나의 서버만 할당됩니다.

lspServers 매니페스트 키는 같은 맵을 인라인으로, JSON 파일 경로로, 또는 이들의 배열로 받으며, 해당 서버는 .lsp.json의 서버에 추가됩니다. 매니페스트 서버가 .lsp.json의 서버와 이름이 같으면 매니페스트 서버가 이를 대체합니다.

transport, 타임아웃, 재시작 및 기타 필드는 lspServers를 참조하십시오.

로그 출력은 stdout이 아닌 stderr로 보내십시오. Claude Code는 서버의 stdout을 프로토콜 메시지로만 읽으며, 최대 64 KiB의 메시지 헤더와 최대 32 MiB의 메시지 본문을 허용합니다.

Claude Code는 두 제한 중 하나를 초과하거나 stdout에 프로토콜이 아닌 출력을 쓰는 서버의 연결을 끊고, 이 연결 해제를 restartOnCrash 및 maxRestarts에 대한 충돌로 집계합니다. --debug로 실행하면 Claude Code가 원인을 명시한 오류를 디버그 로그에 기록합니다.

Executables

플러그인 루트의 bin/에 있는 파일은 플러그인이 활성화된 동안 Bash 도구 셸의 PATH에 포함되므로, Claude가 이를 단독 명령으로 실행할 수 있습니다. 실행 가능한 스크립트를 추가합니다.

#!/bin/bash
echo "hello from my-plugin"

chmod +x bin/hello-plugin으로 실행 가능하게 만들고 플러그인을 로드합니다. Claude에게 hello-plugin 실행을 요청하면 Bash 도구 결과에 스크립트의 출력이 표시됩니다.

플러그인 bin/ 디렉터리는 사용자 자체의 PATH 항목 뒤에 위치하므로, 플러그인이 git, ls 또는 기타 시스템 명령을 가릴 수 없습니다.

claude.ai와 Cowork는 최상위 bin/ 디렉터리가 있는 플러그인을 설치하지 않으며, claude.ai 조직 설정을 통해 배포하는 플러그인도 마찬가지입니다.

Default settings

플러그인이 활성화된 동안 적용되는 기본값을 설정하려면 플러그인 루트에 settings.json을 추가하거나, 같은 객체를 settings 매니페스트 키에 인라인으로 넣습니다. 적용되는 키는 agent와 subagentStatusLine 두 가지이며, 그 외의 키는 모두 제외됩니다.

플러그인 자체 에이전트 중 하나를 메인 스레드로 실행하려면 agent를 설정합니다.

{
  "agent": "security-reviewer"
}

플러그인을 로드하고 세션을 시작합니다. 그러면 Claude가 메인 대화에서 security-reviewer 에이전트의 시스템 프롬프트와 모델로 응답합니다.

이 키가 제어하는 모든 항목은 agent 설정을 참조하십시오.

같은 키가 여러 곳에 설정된 경우 다음 규칙에 따라 적용할 값이 결정됩니다.

subagentStatusLine의 형태는 서브에이전트 상태줄을 참조하십시오.

Themes and output styles

플러그인에는 색상 테마와 출력 스타일을 포함할 수 있습니다. 둘 다 사용자 자체의 항목과 같은 선택기에 표시됩니다. 두 경우 모두 매니페스트 키를 설정하면 폴더 스캔이 대체됩니다.

구성 요소 저장 위치 형식 표시 위치 매니페스트 키
테마 themes/<slug>.json 사용자가 ~/.claude/themes/에 작성하는 사용자 지정 테마 파일 형식 /theme, 파일의 name으로 표시 experimental.themes
출력 스타일 output-styles/<name>.md name 및 description frontmatter를 포함하는 사용자 지정 출력 스타일 형식 /output-style, <plugin>:<name>으로 표시 outputStyles

플러그인 테마는 읽기 전용이므로, 사용자가 /theme에서 편집하면 편집 내용은 사용자 자체의 테마 디렉터리에 사본으로 저장됩니다.

다음 테마는 dark 프리셋에서 프롬프트 강조 색상과 오류 텍스트 색상을 변경합니다.

{
  "name": "Dracula",
  "base": "dark",
  "overrides": {
    "claude": "#bd93f9",
    "error": "#ff5555"
  }
}

Channels

채널을 사용하면 채팅 앱과 같은 외부 시스템이 세션으로 메시지를 보낼 수 있습니다. 플러그인에서 채널은 MCP 서버 중 하나와, 이에 바인딩되며 자체 구성을 요청할 수 있는 channels 항목으로 구성됩니다. 다음 매니페스트는 채널을 telegram 서버에 바인딩하고 봇 토큰을 요청합니다.

{
  "name": "my-plugin",
  "mcpServers": {
    "telegram": {
      "command": "node",
      "args": ["${CLAUDE_PLUGIN_ROOT}/server.js"],
      "env": { "BOT_TOKEN": "${user_config.bot_token}" }
    }
  },
  "channels": [
    {
      "server": "telegram",
      "userConfig": {
        "bot_token": {
          "type": "string",
          "title": "Bot token",
          "description": "Telegram bot token",
          "sensitive": true
        }
      }
    }
  ]
}

server는 mcpServers의 키와 일치해야 합니다. 채널별 userConfig는 최상위 userConfig 키와 같은 형태를 가집니다.

서버가 구현해야 하는 사항과 사용자가 채널 플러그인을 활성화하는 방법은 채널 레퍼런스의 플러그인으로 패키징하기를 참조하십시오. 필드 표는 channels를 참조하십시오.

Monitors

모니터는 세션 전체 동안 백그라운드에서 실행되는 셸 명령입니다. 모니터가 출력하는 내용은 알림으로 Claude에 전달되므로, Claude는 감시하라는 요청을 받지 않아도 로그나 상태 변경에 대응할 수 있습니다. 항목은 monitors/monitors.json에 저장합니다.

[
  {
    "name": "error-log",
    "command": "tail -F ./logs/error.log",
    "description": "Application error log"
  }
]

명령은 세션의 현재 작업 디렉터리에서 셸로 실행됩니다. 사용자의 전체 권한으로 샌드박스 외부에서 실행됩니다.

모니터의 명령은 시작 위치와 참조할 수 있는 항목이 제한됩니다.

experimental.monitors 매니페스트 키는 같은 배열을 인라인으로 또는 JSON 파일 경로로 받으며, monitors/monitors.json 대신 읽힙니다.

when 트리거와 기타 필드는 monitors를 참조하십시오.

사용자에게 구성 값을 요청합니다

플러그인이 사용자로부터 필요로 하는 값을 userConfig manifest 키에서 선언하여, 사용자가 settings.json을 자신들이 편집하지 않도록 합니다. 각 옵션은 title을 레이블로 하고 description을 아래에 가진 대화 상자에 나타납니다.

토큰이나 비밀번호의 경우 "sensitive": true를 설정합니다. 대화 상자는 입력을 마스크하고, 값은 settings.json이 아닌 보안 저장소에 저장됩니다.

이 manifest는 엔드포인트와 토큰을 요청합니다:

{
  "name": "my-plugin",
  "userConfig": {
    "api_url": {
      "type": "string",
      "title": "API URL",
      "description": "Base URL of your team's API"
    },
    "api_token": {
      "type": "string",
      "title": "API token",
      "description": "Token for your team's API",
      "sensitive": true
    }
  }
}

구성 대화 상자가 나타날 때

대화 상자는 대화형 /plugin 인터페이스의 일부입니다. 사용자가 다음 중 하나를 수행할 때 아직 설정되지 않은 옵션에 대해 열립니다:

언제든지 동일한 대화 상자를 열려면, 사용자는 /plugin configure <plugin>@<marketplace>를 실행합니다.

VS Code 확장의 플러그인 관리 대화 상자는 설치 후 양식으로 설정되지 않은 옵션을 요청하며, 플러그인의 행에 있는 기어 아이콘은 모든 옵션과 함께 양식을 다시 엽니다.

claude plugin install 셸 명령은 userConfig 값을 프롬프트하지 않습니다. 셸에서 값을 설정하려면, 설치할 때 각각을 --config KEY=VALUE로 전달하거나, 그 후 JSON 객체를 claude plugin configure --values-stdin으로 파이프합니다.

옵션이 설정되지 않으면, claude plugin install은 userConfig options not yet set 라인을 인쇄합니다. 라인의 정확한 텍스트는 The userConfig dialog never appears를 참조합니다.

옵션 필드, 각 값이 저장되는 위치, 컴포넌트가 저장된 값을 참조하는 방법, ${user_config.*}를 거부하는 필드의 경우, 사용자 구성을 참조합니다.

플러그인 경로 참조 및 데이터 저장

플러그인이 어디에 설치될지 모르므로, 고정 경로보다는 이 변수를 통해 파일과 데이터를 참조합니다. 이들은 skill, 명령, agent 콘텐츠에서, hook과 모니터 명령에서, MCP와 LSP 서버 구성에서 대체됩니다. 또한 hook, MCP, LSP 프로세스로 내보내집니다:

데이터 디렉토리 경로에서, <id>는 문자, 숫자, _, - 이외의 모든 문자가 -로 대체된 플러그인 식별자이므로, my-plugin@my-marketplace는 my-plugin-my-marketplace가 됩니다.

Windows에서, 대체된 경로는 셸이 백슬래시를 이스케이프로 읽지 않도록 전진 슬래시를 사용합니다.

데이터 디렉토리에 종속성 설치

마켓플레이스 설치 플러그인의 경우, Claude Code는 플러그인을 캐시할 때 적격 Node.js 패키지 종속성을 자동으로 설치하므로, 자신이 설치할 필요가 없을 수 있습니다. 할 때, 이 SessionStart hook은 첫 실행 시 ${CLAUDE_PLUGIN_DATA}에 node_modules를 설치하고 업데이트가 package.json을 변경한 후 다시 설치합니다:

{
  "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\""
          }
        ]
      }
    ]
  }
}

첫 번째 세션 후, ~/.claude/plugins/data/<id>/node_modules이 존재합니다. MCP 서버는 그 다음 NODE_PATH를 ${CLAUDE_PLUGIN_DATA}/node_modules로 설정할 수 있습니다. 어느 필드가 어느 변수를 대체하는지의 경우, 환경 변수를 참조합니다.

다음 단계