플러그인에 구성요소 추가
기준일: 2026-10-23
공식 기준: Add components to a plugin
개요
Claude Code 플러그인은 skill, agent, hook, MCP 서버 등 구성요소로 만들어집니다. 각 구성요소는 플러그인 안의 기본 폴더, 그 폴더를 대체하거나 보태는 .claude-plugin/plugin.json의 선택적 매니페스트 키, 사용자에게 보이는 이름을 가집니다. 키별 전체 필드 표는 manifest reference.
이미 로드되는 플러그인에 구성요소를 추가할 때 쓰는 페이지입니다. 추가한 뒤에는 실행 중인 세션에서 /reload-plugins를 실행하거나 새 세션을 시작하세요. 로드 전에 파일을 확인하려면 플러그인 디렉터리에서 셸로 claude plugin validate ..
- 첫 플러그인 만들기: Create a plugin
- 다른 사람의 플러그인 설치: Install plugins
- claude.ai/Cowork 사용자: 다른 구성요소 집합이 로드됨. Plugin structure and testing, component support table
핵심 개념
예제 플러그인 my-plugin은 모든 종류의 구성요소를 기본 위치에 하나씩 갖습니다.
| 구성요소 | 기본 위치 | 매니페스트 키 | 사용자에게 보이는 이름 |
|---|---|---|---|
| Skills | skills/<dir>/SKILL.md |
skills (기본 스캔에 추가) |
/<plugin>:<directory> |
| Commands | commands/<file>.md |
commands |
/<plugin>:<file> |
| Agents | agents/*.md |
agents (스캔 대체) |
<plugin>:<name> |
| Hooks | hooks/hooks.json |
hooks (둘 다 로드) |
|
| MCP 서버 | .mcp.json |
mcpServers |
plugin:<plugin>:<server> |
| LSP 서버 | .lsp.json |
lspServers |
|
| Executables | bin/ |
PATH의 bare 명령 | |
| 기본 settings | settings.json |
settings |
|
| 테마 | themes/<slug>.json |
experimental.themes |
/theme |
| Output style | output-styles/<name>.md |
outputStyles |
/output-style의 <plugin>:<name> |
| Channels | channels |
||
| Monitors | monitors/monitors.json |
experimental.monitors |
|
| Workflows | workflows/*.js |
/my-plugin:audit-routes |
예제의 각 파일은 형식의 가장 작은 유효 예이며 모양을 보이기 위한 것입니다. 실제 skill이나 agent는 전체 지침과 보조 파일을 갖고 실제 hook이나 monitor는 실제 작업을 합니다.
상세
예제 플러그인 구성
매니페스트는 플러그인 .claude-plugin/ 디렉터리의 plugin.json입니다. 플러그인 메타데이터와 Claude Code가 사용자에게 묻는 userConfig 값을 담습니다. 없어도 로드되며 파일 안에서 name만 필수입니다. 여기서 description은 /plugin에서 사용자가 보는 텍스트이고 version은 바꾸기 전까지 사용자를 그 버전에 둡니다.
{
"name": "my-plugin",
"version": "1.0.0",
"description": "Review, formatting, and database tools for this team"
}
- 리뷰 skill과
aboutcommand, security-review subagent - Claude가 편집한 파일을 포맷하는 hook과 그것이 부르는
scripts/폴더, log monitor - output style과 color theme, route-audit workflow,
hello-plugin실행 파일 - 기본 settings, 로컬 MCP 서버와 Go language server
scripts/ 이름은 관례일 뿐 Claude Code가 찾는 이름이 아닙니다. hook이 ${CLAUDE_PLUGIN_ROOT}/scripts/format.sh 경로로 파일을 가리킵니다. 포맷터 스크립트 예:
#!/bin/bash
npx prettier --write .
Skills
skill은 description이 작업과 맞을 때 Claude가 로드하는 SKILL.md 파일이며 사용자가 명령으로 실행할 수도 있습니다. 각 skill을 skills/ 아래 자기 디렉터리에 둡니다.
my-plugin/
├── .claude-plugin/
│ └── plugin.json
└── skills/
└── review/
└── SKILL.md
Claude가 언제 쓸지 알도록 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가 skill을 실행합니다.
- 명령 이름:
/<plugin>:<directory>.my-plugin의skills/review/SKILL.md는/my-plugin:review. frontmatter에name을 주면 마지막 세그먼트를 대체하고 플러그인 접두는 유지됨. how a skill gets its command name - 누가 호출하나: Claude, 사용자, 또는 둘 다. frontmatter로 제어. Control who invokes a skill
기본 skills/ 밖에 둘 수도 있습니다.
- 추가 디렉터리:
skills매니페스트 키에 나열.commands,agents와 달리 기본skills/스캔을 대체하지 않고 보탬 - 플러그인 루트의 skill 하나:
skills/디렉터리도skills매니페스트 키도 없으면 루트의SKILL.md가 skill 하나로 로드됨. frontmatter에name을 설정하세요. 아니면 마켓 설치가 플러그인이 아니라 캐시 디렉터리 이름을 skill에 붙임
플러그인에 지침을 넣으려면 skill로 쓰세요. Claude Code는 플러그인 루트의 CLAUDE.md를 로드하지 않으며 claude plugin validate가 CLAUDE.md at the plugin root is not loaded as project context로 경고합니다. 보호 파일 편집 차단처럼 매번 지켜야 하는 규칙은 skill이 아니라 hook으로 추가하세요. 둘의 선택은 Compare similar features의 Hook vs Skill 탭. frontmatter와 보조 파일은 Skills.
Commands
command는 사용자가 이름으로 실행하는 Markdown 파일 하나입니다 (예: /my-plugin:about).
command는 이전 형식이며 새 작업에는 skill이 대체합니다. skill도 같은 방식으로 이름으로 실행되고 자기 디렉터리에 보조 파일도 둘 수 있습니다.
commands/는.claude/commands/에서 옮겨 오는 파일용으로 유지하세요.
commands/<file>.md가 /<plugin>:<file>이 됩니다. 하위 디렉터리는 세그먼트를 더해 commands/db/migrate.md는 /my-plugin:db:migrate입니다. command 파일은 skill과 같은 frontmatter를 받습니다.
---
description: Summarize the repository
---
Summarize what this repository does in three sentences.
매니페스트에서 command 정의
command 파일을 commands/ 밖에 두거나 별도 Markdown 없이 plugin.json 안에 짧은 command를 정의하려 할 때만 필요합니다. commands 매니페스트 키를 설정하면 commands/를 스캔하는 대신 이를 읽습니다. 키는 경로, 경로 배열, 또는 각 command 이름을 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
subagent는 자체 지침과 컨텍스트 창을 가진 별도 어시스턴트로 Claude가 작업을 위임합니다. agents/ 아래 Markdown 파일 하나가 하나를 정의합니다. frontmatter가 이름과 사용 시점을 정하고 본문이 시스템 프롬프트입니다.
---
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.
이 agent의 이름은 my-plugin:security-reviewer이며 사용자가 @agent-my-plugin:security-reviewer로 명시 호출할 수 있습니다. 이름 형식은 <plugin>:<name>이고 <name>은 frontmatter name, 없으면 파일 이름입니다. agents 매니페스트 키는 agents/ 스캔을 대체합니다.
하위 폴더로 agent 정리
플러그인 agent 파일을 agents/의 하위 폴더에 둘 수 있습니다. Claude Code가 재귀로 로드하고 플러그인 이름, 각 하위 폴더 이름, 파일 이름을 콜론으로 이어 scoped 이름을 만듭니다. my-plugin의 agents/review/security.md는 my-plugin:review:security로 로드됩니다. 두 설정이 이름을 바꿉니다.
- frontmatter
name은 파일 이름만 대체:agents/review/security.md의name: audit는my-plugin:review:audit - 매니페스트
agents필드에 나열한 파일은 하위 폴더 이름 없이 로드:"agents": "./custom/review/security.md"는my-plugin:security
플러그인 agent의 frontmatter 필드
- 지원 필드:
name,description,model,effort,maxTurns,autoCompactWindow,tools,disallowedTools,skills,memory,background,omitClaudeMd,isolation,color,experimental의cacheTtl키. 유효한isolation값은"worktree"뿐. 각 필드의 동작은 supported frontmatter fields - 무시되는 필드:
permissionMode,hooks,mcpServers,initialPrompt. agent 파일은 스스로 hook이나 MCP 서버를 추가할 수 없으므로 플러그인 hooks와 MCP 서버로 추가 - 256자 초과
name: 무시하고 필드가 없을 때처럼 파일 이름으로 agent 이름 부여 - 파싱되지 않는 frontmatter: agent는 모든 필드가 무시된 채 로드되고 파일 이름으로 명명되며 description은
Agent from my-plugin plugin. 셸에서claude plugin validate로 이런 파일을 찾음
Hooks
hook은 모든 파일 편집 뒤 같은 Claude Code 생명주기 시점에서 자동으로 무언가를 실행합니다: 셸 명령, HTTP 요청, MCP 도구 호출, 모델에 프롬프트, subagent. 플러그인의 hook을 플러그인 루트의 hooks/hooks.json에 최상위 "hooks" 키 아래 settings.json의 hooks 객체와 같은 모양으로 저장합니다. 기존 settings hook을 그대로 복사할 수 있습니다. 모든 Write, Edit 뒤에 번들 스크립트를 실행하는 hook:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}/scripts/format.sh\""
}
]
}
]
}
}
스크립트를 scripts/format.sh에 저장하고 실행 가능하게 하세요. 플러그인을 로드하고 Claude에게 파일 편집을 시킵니다. exit 0인 PostToolUse hook은 transcript에 아무것도 보이지 않으므로 debug logging이나 스크립트가 바꾼 것으로 실행을 확인하세요. hooks/hooks.json과 hooks 매니페스트 키의 hook은 모두 로드됩니다. 모든 이벤트와 payload는 Hook events. 같은 이름의 다른 활성 플러그인이 있으면 둘 중 하나만 hooks/hooks.json hook을 등록하고 다른 것은 빠집니다. 어느 쪽인지와 /plugin의 노트는 Hooks when two enabled plugins share a name.
hook을 Claude Code 안에서 돌고 인터페이스에 그릴 수 있는 JavaScript 함수로 쓰려면 같은 hooks/hooks.json의 modules 키 아래에 module 파일을 나열합니다. 그런 플러그인이 mod입니다. Create a mod.
플러그인 hook이 발동하는 때
플러그인 hook은 플러그인의 skill이나 command가 쓰이기를 기다리지 않습니다. 세션이 플러그인을 로드할 때 Claude Code가 등록하고 이후 해당 이벤트에서 발동합니다. 실행 시점을 제한하려면 matcher를 좁히세요. hook이 발동하지 않으면 hooks that don't fire.
환경, 따옴표, MCP 도구 매칭
- 환경: 모든 hook 프로세스는 환경에
CLAUDE_PLUGIN_ROOT,CLAUDE_PLUGIN_DATA, 각 사용자 구성 값의CLAUDE_PLUGIN_OPTION_<KEY>를 받으므로 스크립트가 거기서 읽을 수 있음 - 따옴표:
command에args가 없으면 셸을 거치므로${CLAUDE_PLUGIN_ROOT}경로를 큰따옴표로 감싸 확장된 경로가 셸 단어 하나로 유지되게 함 (위hooks/hooks.json예처럼). 대신args를 주면 각 요소가 셸 없이 하나의 인수로 전달되어 따옴표가 필요 없음. exec form and shell form - 플러그인 자체 MCP 도구 매칭: 이 플러그인이 선언한 MCP 서버의 도구는
mcp__plugin_<plugin>_<server>__<tool>로 명명되므로 matcher에 그 전체 이름을 쓰세요. 서버 이름만의 matcher는 발동하지 않습니다. Match MCP tools
MCP servers
MCP 서버는 외부 시스템의 도구를 Claude에게 줍니다. 플러그인 루트의 .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 servers that don't start. mcpServers 매니페스트 키는 인라인 서버 맵, JSON 파일 경로, 또는 그 배열을 받습니다. 매니페스트 서버가 .mcp.json의 서버와 이름이 같으면 매니페스트 서버가 대체합니다.
claude.ai와 Cowork 사용자에게 도달
MCP servers의 db 같은 로컬 stdio 서버는 Claude Code와 Claude Desktop 앱의 내 기기에서 도는 Cowork 세션에서 실행되지만 claude.ai에서는 실행되지 않습니다. 거기 사용자에게도 도달하려면 원격 서버를 https:// URL로 참조합니다. claude.ai와 Cowork가 이를 connector로 사용자에게 제공합니다. Bundle an MCP connector with its skill.
서버 이름, 도구 이름, 리로드
- 서버 이름:
plugin:<plugin>:<server>.my-plugin의db서버는/mcp에서plugin:my-plugin:db.mcp_toolhook에서 서버를 지목할 때도 같은 형식 - 도구 이름:
mcp__plugin_<plugin>_<server>__<tool>. 그db서버의query도구는mcp__plugin_my-plugin_db__query. 권한 규칙과 hook matcher에 쓸 이름 - 치환:
${CLAUDE_PLUGIN_ROOT}등 path 변수가command,args,env에서 치환됨.args는 각 요소가 하나의 인수로 전달되므로 따옴표 불필요 - 리로드: 사용자가
/reload-plugins를 실행하고 리로드가 적용되면 구성이 그대로인 서버는 연결을 유지, 구성이 바뀐 서버는 재연결, 제거한 서버는 연결 해제
패키지된 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을 보여 줍니다. 사용자가 값을 주는 방법 둘:
/plugin에서: Installed 탭에서 플러그인을 선택하고 Configure- 셸에서 설치할 때:
claude plugin install에--config <server>.<key>=<value>전달. Claude Code v2.1.285 이상이며 플러그인 안에 패키지된 번들에만 동작
transport와 인증은 MCP.
LSP servers
LSP 서버는 언어에 대해 진단과 코드 탐색을 Claude에게 줍니다. 공식 code intelligence 플러그인이 내 언어를 이미 다룬다면 직접 쓰지 말고 그것을 설치하세요. 아니면 플러그인 루트의 .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"이 나타납니다.
플러그인은 연결을 구성할 뿐 서버 바이너리를 설치하지 않으며 파일 확장자마다 서버는 하나입니다.
- 바이너리 없음: Claude Code는 사용자
PATH에서command를 이름으로 시작함. 없으면 서버가 시작하지 못하고claude --debug가LSP server <name> failed to start를 기록 - 확장자 충돌: 활성 서버 둘이 같은 확장자를 주장하면(한 플러그인이든 둘이든) 먼저 등록된 쪽이 그 파일을 처리하고 다른 쪽은 쓰이지 않음.
/pluginErrors 탭이LSP server "<name>" is not used for <ext> files경고를 표시
lspServers 매니페스트 키는 같은 맵을 인라인, JSON 파일 경로, 또는 그 배열로 받으며 그 서버는 .lsp.json의 서버에 더해집니다. 매니페스트 서버가 .lsp.json의 서버와 이름이 같으면 매니페스트 서버가 대체합니다. transport, 타임아웃, 재시작 등 다른 필드는 lspServers.
로그는 stdout이 아닌 stderr로 보내세요. Claude Code는 서버의 stdout을 프로토콜 메시지로만 읽고 메시지 헤더 최대 64 KiB, 본문 최대 32 MiB를 받습니다. 둘 중 하나를 넘거나 stdout에 프로토콜이 아닌 출력을 쓰는 서버는 연결을 끊고, 이 단절은 restartOnCrash, maxRestarts에서 crash로 셉니다. --debug로 실행하면 원인을 명시한 오류를 debug log에 기록합니다.
Executables
플러그인 루트 bin/의 파일은 플러그인이 활성화된 동안 Bash 도구 셸의 PATH에 있어 Claude가 bare 명령으로 실행할 수 있습니다. PowerShell 도구로 sandbox 밖에서 실행하는 명령도 PATH에서 찾고, sandbox 안의 PowerShell 명령은 찾지 못합니다. 실행 스크립트 추가:
#!/bin/bash
echo "hello from my-plugin"
chmod +x bin/hello-plugin으로 실행 가능하게 하고 플러그인을 로드합니다. Claude에게 hello-plugin 실행을 시키면 Bash 도구 결과에 스크립트 출력이 보입니다. 플러그인 bin/ 디렉터리는 사용자 자신의 PATH 항목 뒤에 오므로 git, ls 같은 시스템 명령을 가릴 수 없습니다. claude.ai와 Cowork는 claude.ai 조직 설정으로 배포하는 경우를 포함해 최상위 bin/ 디렉터리가 있는 플러그인을 설치하지 않습니다.
기본 settings
플러그인이 활성화된 동안 적용할 기본값은 플러그인 루트의 settings.json 또는 settings 매니페스트 키에 같은 객체를 인라인으로 둡니다. 효력이 있는 키는 agent와 subagentStatusLine 둘이고 다른 키는 모두 버려집니다. agent로 플러그인 자체 agent 하나를 메인 스레드로 실행:
{
"agent": "security-reviewer"
}
플러그인을 로드하고 세션을 시작하면 Claude가 메인 대화에서 security-reviewer agent의 시스템 프롬프트와 모델로 답합니다. 키가 제어하는 전부는 agent setting. 같은 키가 여러 곳에 있으면:
- 파일이 매니페스트보다 우선: 둘 다 있고
settings.json이 지원 키를 하나 이상 설정하면settings.json이 적용되고 매니페스트의settings는 무시됨 - 사용자 settings가 플러그인 기본값보다 우선: settings 소스 중 플러그인 기본값이 가장 낮은 layer라
~/.claude/settings.json의 사용자 자신의agent가 내 것을 덮어씀 - 두 플러그인이 같은 키 설정: 나중에 로드된 플러그인의 값이 적용되고
claude --debug가overrides setting을 기록
subagentStatusLine 형태는 subagent status lines.
테마와 output style
플러그인은 color theme와 output style을 포함할 수 있으며 둘 다 사용자 자신의 것과 같은 picker에 나타납니다. 둘 다 매니페스트 키를 설정하면 폴더 스캔을 대체합니다.
| 구성요소 | 저장 위치 | 형식 | 나타나는 곳 | 매니페스트 키 |
|---|---|---|---|---|
| Theme | themes/<slug>.json |
사용자가 ~/.claude/themes/에 쓰는 custom theme 파일 형식 |
/theme의 파일 name 아래 |
experimental.themes |
| Output style | output-styles/<name>.md |
name, description frontmatter를 가진 custom output style 형식 |
/output-style의 <plugin>:<name> |
outputStyles |
플러그인 테마는 읽기 전용이라 사용자가 /theme에서 편집하면 자기 themes 디렉터리에 사본으로 저장됩니다. dark preset에서 프롬프트 accent와 오류 텍스트를 재색칠하는 테마:
{
"name": "Dracula",
"base": "dark",
"overrides": {
"claude": "#bd93f9",
"error": "#ff5555"
}
}
output style은 Claude의 응답 형식과 표현을 바꿉니다. output-styles/<name>.md로 저장하며 /output-style에 my-plugin:terse로 나타나는 예:
---
name: terse
description: Answer in as few words as possible
keep-coding-instructions: true
---
Keep every reply short. Skip preambles and summaries.
Workflows
workflows/ 폴더는 meta 블록과 여러 subagent를 조율하는 스크립트 본문으로 이루어진 workflow .js 파일을 둡니다. 이 예는 /my-plugin:audit-routes로 실행됩니다.
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)
Channels
channel은 채팅 앱 같은 외부 시스템이 세션에 메시지를 보내게 합니다. 플러그인에서 channel은 MCP 서버 하나와 그것에 묶이며 자체 구성을 요청할 수 있는 channels 항목입니다. telegram 서버에 channel을 묶고 bot token을 요청하는 매니페스트:
{
"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의 키와 일치해야 합니다. channel별 userConfig는 최상위 userConfig 키와 같은 모양입니다. 서버가 구현할 것과 사용자가 channel 플러그인을 켜는 방법은 channels reference의 Package as a plugin, 필드 표는 channels.
Monitors
monitor는 세션 내내 백그라운드로 실행되는 셸 명령입니다. 출력이 알림으로 Claude에게 도달해 Claude가 지켜보라는 요청 없이 로그나 상태 변화에 반응할 수 있습니다. 세션 시작 때 Claude Code가 시작해 세션이 끝날 때까지 유지하며, when 필드로 대신 이름 붙은 skill이 처음 실행될 때 시작할 수도 있습니다. 항목을 monitors/monitors.json에 저장:
[
{
"name": "error-log",
"command": "tail -F ./logs/error.log",
"description": "Application error log"
}
]
명령은 세션의 현재 작업 디렉터리에서 셸로 실행되며 전체 사용자 권한으로 sandbox 밖에서 실행됩니다. 명령이 시작되는 곳과 참조할 수 있는 것에는 제한이 있습니다.
- 인터랙티브 세션만: 플러그인 monitor는 인터랙티브 세션에서 시작하고
-p비대화 모드에서는 시작하지 않음. API 제공자나 텔레메트리 설정 때문에 Monitor 도구를 쓸 수 없는 세션에서도 시작하지 않음 - 사용자 구성 불가:
command는 path 변수와 환경의${ENV_VAR}를 받지만${user_config.*}는 받지 않음. 이를 참조하는 monitor는 시작하지 않고 monitor 프로세스는CLAUDE_PLUGIN_OPTION_<KEY>도 받지 않음 - 세션 중 비활성화: 세션 중 플러그인을 비활성화해도 이미 실행 중인 monitor는 멈추지 않고 세션이 끝날 때 멈춤
experimental.monitors 매니페스트 키는 같은 배열을 인라인으로, 또는 JSON 파일 경로로 받으며 monitors/monitors.json 대신 읽습니다. when 트리거와 다른 필드는 monitors.
사용자 구성 값 요청
사용자가 settings.json을 직접 편집하지 않도록 플러그인이 사용자에게 필요한 값을 userConfig 매니페스트 키에 선언합니다. 각 옵션은 title을 레이블로, 아래에 description을 둔 대화상자에 나타납니다. 토큰이나 비밀번호에는 "sensitive": true를 설정하세요. 대화상자가 입력을 가리고 값이 settings.json이 아니라 보안 저장소에 저장됩니다. 엔드포인트와 토큰을 요청하는 매니페스트:
{
"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에서 플러그인 설치- 세션 안에서
/plugin install <plugin>@<marketplace>실행 /plugin의 Installed 탭에서 플러그인 활성화
같은 대화상자를 언제든 열려면 /plugin configure <plugin>@<marketplace>. VS Code 확장의 Manage plugins 대화상자는 설치 뒤 미설정 옵션을 폼으로 묻고, 플러그인 행의 톱니 아이콘이 모든 옵션이 있는 폼을 다시 엽니다. 셸의 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.*}를 거부하는 필드는 User configuration.
플러그인 경로와 데이터 저장
플러그인이 어디에 설치될지 알 수 없으므로 고정 경로 대신 다음 변수로 파일과 데이터를 참조합니다. skill·command·agent 내용, hook·monitor 명령, MCP·LSP 서버 구성에서 치환되고 hook·MCP·LSP 프로세스로도 export됩니다.
${CLAUDE_PLUGIN_ROOT}: 플러그인의 설치 디렉터리. 버전마다 자체 캐시 디렉터리를 가지므로 플러그인이 업데이트되면 경로가 바뀜. 여기에 상태를 쓰지 마세요${CLAUDE_PLUGIN_DATA}: 업데이트 후에도 유지되는 디렉터리 (node_modules, 가상 환경, 캐시용).~/.claude/plugins/data/<id>/로 해석되고 처음 참조될 때 생성${CLAUDE_PROJECT_DIR}: 프로젝트 루트. hook이 받는 값과 같음
데이터 디렉터리 경로의 <id>는 영문자, 숫자, _, - 외의 모든 문자를 -로 바꾼 플러그인 식별자라 my-plugin@my-marketplace는 my-plugin-my-marketplace가 됩니다. Windows에서는 셸이 백슬래시를 escape로 읽지 않도록 치환된 경로가 슬래시를 씁니다.
데이터 디렉터리에 의존성 설치
마켓에서 설치한 플러그인은 Claude Code가 플러그인을 캐시할 때 적합한 Node.js 패키지 의존성을 자동 설치하므로 직접 설치할 필요가 없을 수 있습니다. 직접 해야 한다면 이 SessionStart hook이 첫 실행과 업데이트가 package.json을 바꾼 뒤에 ${CLAUDE_PLUGIN_DATA}에 node_modules를 설치합니다.
{
"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 서버는 env에서 NODE_PATH를 ${CLAUDE_PLUGIN_DATA}/node_modules로 설정할 수 있습니다. 어떤 필드가 어떤 변수를 치환하는지는 Environment variables.
체크리스트
- 구성요소를 기본 위치에 두고
/reload-plugins -
claude plugin validate .로 파일 확인 - 경로는
${CLAUDE_PLUGIN_ROOT}, 영속 데이터는${CLAUDE_PLUGIN_DATA} - hook 명령의
${CLAUDE_PLUGIN_ROOT}는 큰따옴표로 감싸거나args사용 - 필수 지침은 skill이 아니라 hook으로
- 사용자 값은
userConfig, 비밀은"sensitive": true
함께 보기
- Plugin manifest reference
- Test plugins with evals
- Publish and distribute a plugin
- Troubleshoot plugins
기준일
- 문서 작성·동기화 기준일: 2026-10-23 (v2.1.309 반영)
- 원문: https://code.claude.com/docs/en/plugins/components