클로드 코드 마켓플레이스: 플러그인 배포하기
클로드 코드 플러그인을 설치해서 쓰다 보면 “이걸 우리 팀에 맞게 직접 만들 수 있지 않을까?”라는 생각이 들기 마련입니다.
.claude/ 디렉토리에 스킬이나 Hooks를 설정해서 잘 쓰고 있다면 이미 플러그인의 반은 만든 셈이에요.
이 글에서는 간단한 스킬 하나짜리 플러그인부터 시작해서 Hooks, MCP 서버, LSP 서버를 포함하는 완전한 플러그인을 만들고 마켓플레이스를 통해 팀이나 커뮤니티에 배포하는 과정까지 다룹니다. 플러그인을 설치하고 관리하는 방법은 플러그인 사용법을 참고하세요.
첫 플러그인 만들기
간단한 인사 스킬을 가진 플러그인부터 시작해보겠습니다. 먼저 플러그인 디렉토리와 매니페스트 파일을 만듭니다.
mkdir -p my-first-plugin/.claude-plugin
.claude-plugin/plugin.json에 플러그인의 메타데이터를 작성합니다.
{
"name": "my-first-plugin",
"description": "인사 플러그인",
"version": "1.0.0",
"author": {
"name": "Your Name"
}
}
여기서 name 필드가 네임스페이스로 사용됩니다. 이 플러그인의 스킬은 /my-first-plugin:스킬이름 형식으로 호출하게 되죠. 나중에 마켓플레이스에 등록할 때도 이 이름으로 식별되니 팀이나 프로젝트를 반영하는 이름을 붙이는 게 좋습니다.
다음으로 스킬을 추가합니다. 스킬은 skills/ 디렉토리에 폴더 단위로 만들고, 폴더 안에 SKILL.md 파일을 작성하면 됩니다.
mkdir -p my-first-plugin/skills/hello
---
description: Greet the user with a friendly message
---
사용자에게 따뜻하게 인사하고, 오늘 어떤 도움이 필요한지 물어보세요.
description 필드는 영문으로 작성합니다. 클로드 코드가 스킬을 선택할 때 이 필드를 참고하기 때문에 영문이 매칭 정확도가 높아요. 반면 본문은 한글로 작성해도 됩니다. 클로드가 한국어를 잘 이해하니까요.
이렇게 작성하면 클로드 코드에서 /my-first-plugin:hello 슬래시 커맨드를 통해 스킬을 활성화시킬 수 있습니다.
테스트하기
완성된 플러그인은 --plugin-dir 플래그로 로드해서 테스트합니다:
claude --plugin-dir ./my-first-plugin
클로드 코드가 시작되면 /my-first-plugin:hello를 실행해볼 수 있습니다. /help를 실행하면 플러그인의 스킬 목록도 확인할 수 있죠. 여러 플러그인을 동시에 테스트하고 싶다면 플래그를 반복 지정하면 됩니다:
claude --plugin-dir ./plugin-one --plugin-dir ./plugin-two
스킬이 /help 목록에 나타나지 않으면 디렉토리 구조를 다시 확인해보세요. SKILL.md 파일이 skills/스킬이름/SKILL.md 경로에 있어야 합니다. skills/SKILL.md처럼 중간 폴더 없이 바로 넣으면 인식되지 않습니다.
플러그인 디렉토리 구조
플러그인에는 스킬 말고도 넣을 수 있는 컴포넌트가 더 있습니다. 완전한 플러그인의 구조를 보겠습니다:
my-plugin/
├── .claude-plugin/
│ └── plugin.json # 매니페스트 (여기에만 위치)
├── commands/ # 슬래시 커맨드 (레거시, 새 스킬은 skills/ 권장)
│ └── deploy.md
├── agents/ # 서브에이전트
│ └── security-reviewer.md
├── skills/ # 에이전트 스킬
│ └── code-review/
│ └── SKILL.md
├── hooks/ # 이벤트 핸들러
│ └── hooks.json
├── .mcp.json # MCP 서버 설정
├── .lsp.json # LSP 서버 설정
└── scripts/ # Hook 스크립트
└── format-code.sh
.claude-plugin/ 디렉토리에는 plugin.json만 넣어야 합니다. 매니페스트 자체는 선택 사항이라 생략하면 디렉토리 이름이 플러그인 이름으로 사용되지만, 메타데이터나 커스텀 컴포넌트 경로가 필요하면 만들어야 해요. commands/, agents/, skills/, hooks/ 같은 디렉토리는 반드시 플러그인 루트에 위치해야 합니다. .claude-plugin/ 안에 넣으면 로드되지 않습니다.
commands/와 skills/의 차이가 헷갈릴 수 있는데, commands/에 넣은 파일은 사용자가 /플러그인:커맨드 형식으로 직접 호출하는 슬래시 커맨드가 됩니다. skills/에 넣은 스킬은 클로드가 작업 중에 필요하다고 판단하면 자동으로 불러오기도 하고 사용자가 직접 호출할 수도 있어요. 명확한 사용자 액션이 필요하면 commands/, 클로드의 자율적 판단까지 허용하려면 skills/를 쓰면 됩니다. 공식 문서에서는 commands/를 레거시로 분류하고 새 스킬은 skills/에 작성할 것을 권장하고 있습니다.
Hooks 설정
플러그인에서 Hooks를 설정하려면 hooks/hooks.json 파일을 만듭니다. 형식은 settings.json의 hooks 객체와 동일합니다.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/format-code.sh"
}
]
}
]
}
}
Hook의 type은 세 가지를 지원합니다. command는 셸 명령어를 실행하고, prompt는 LLM에 프롬프트를 평가시킵니다. $ARGUMENTS 플레이스홀더로 컨텍스트를 전달할 수 있어요. agent는 도구를 사용할 수 있는 에이전트 검증기를 실행합니다.
${CLAUDE_PLUGIN_ROOT} 환경 변수는 플러그인이 설치된 디렉토리의 절대 경로를 가리킵니다. 플러그인은 설치할 때 캐시 디렉토리(~/.claude/plugins/cache)로 복사되기 때문에 스크립트 경로를 참조할 때 반드시 이 변수를 써야 해요. ./scripts/format-code.sh처럼 상대 경로로 작성하면 클로드 코드의 현재 작업 디렉토리 기준으로 해석돼서 파일을 찾지 못합니다.
MCP 서버 설정
외부 서비스 연동이 필요하다면 플러그인 루트에 .mcp.json 파일을 두면 됩니다.
{
"mcpServers": {
"my-database": {
"command": "${CLAUDE_PLUGIN_ROOT}/servers/db-server",
"args": ["--config", "${CLAUDE_PLUGIN_ROOT}/config.json"],
"env": {
"DB_PATH": "${CLAUDE_PLUGIN_ROOT}/data"
}
}
}
}
플러그인이 활성화되면 MCP 서버도 자동으로 시작됩니다. 사용자가 별도로 MCP 설정을 건드릴 필요가 없어서 온보딩 부담이 줄어들죠.
LSP 서버 설정
공식 마켓플레이스에서 지원하지 않는 언어가 있다면 .lsp.json으로 직접 연결하거나 plugin.json의 lspServers 필드에 인라인으로 설정할 수 있습니다.
{
"go": {
"command": "gopls",
"args": ["serve"],
"extensionToLanguage": {
".go": "go"
}
}
}
다만 사용자 환경에 해당 언어 서버 바이너리가 설치되어 있어야 합니다. 플러그인은 언어 서버의 연결 설정만 제공하고 바이너리 설치까지 해주지는 않아요. 플러그인 설명이나 README에 필요한 사전 설치 항목을 안내해두면 사용자가 헤매지 않습니다.
마켓플레이스 만들기
플러그인을 하나만 배포할 때는 Git 저장소에 올리고 /plugin install로 설치하면 됩니다. 그런데 플러그인이 여러 개라면? 사용자가 저장소 URL을 하나하나 기억해야 하고, 어떤 플러그인이 있는지 찾아보기도 번거롭습니다.
마켓플레이스는 여러 플러그인을 하나의 카탈로그로 묶어주는 역할을 합니다. .claude-plugin/marketplace.json 파일이 있는 디렉토리(또는 Git 저장소)가 곧 마켓플레이스예요.
my-marketplace/
├── .claude-plugin/
│ └── marketplace.json
└── plugins/
├── review-plugin/
│ ├── .claude-plugin/
│ │ └── plugin.json
│ └── skills/
│ └── review/
│ └── SKILL.md
└── formatter-plugin/
└── ...
marketplace.json에 마켓플레이스의 이름과 포함된 플러그인 목록을 정의합니다.
{
"name": "my-plugins",
"owner": {
"name": "My Team"
},
"plugins": [
{
"name": "review-plugin",
"source": "./plugins/review-plugin",
"description": "코드 리뷰 스킬을 추가합니다",
"version": "1.0.0"
},
{
"name": "formatter-plugin",
"source": {
"source": "github",
"repo": "my-org/formatter-plugin"
},
"description": "코드 포매팅 자동화"
}
]
}
실제로 Anthropic이 운영하는 두 마켓플레이스의 marketplace.json을 보면 구조를 바로 파악할 수 있습니다. 공식 마켓플레이스는 LSP 플러그인에 strict: false와 인라인 lspServers를 사용하고, Figma·Sentry 같은 외부 플러그인에는 Git URL 소스를 활용합니다. claude-code 마켓플레이스는 상대 경로 소스만 쓰는 더 단순한 구조예요.
source 필드를 보면 상대 경로(./plugins/review-plugin)와 GitHub 저장소(my-org/formatter-plugin)를 섞어 쓸 수 있습니다. 마켓플레이스 저장소 안에 직접 포함된 플러그인은 상대 경로로, 별도 저장소에서 관리하는 플러그인은 GitHub 참조로 지정하는 식이죠. Git URL, npm, pip 소스도 지원하므로 다양한 배포 채널을 활용할 수 있습니다.
마켓플레이스 메타데이터에 metadata.pluginRoot를 설정하면 상대 경로의 기본 디렉토리를 지정할 수 있어요. 예를 들어 "pluginRoot": "./plugins"로 설정하면 source에 "formatter"만 써도 ./plugins/formatter로 해석됩니다.
플러그인 항목의 strict 필드도 알아두면 좋습니다. 기본값은 true인데 두 모드의 동작이 꽤 다릅니다.
strict: true (기본값) — 플러그인이 자신의 plugin.json으로 컴포넌트를 관리하고, 마켓플레이스는 보충만 합니다. 양쪽에 정의된 컴포넌트가 병합됩니다.
{
"plugins": [
{
"name": "review-plugin",
"source": "./plugins/review-plugin",
"description": "코드 리뷰 자동화",
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/lint.sh"
}
]
}
]
}
}
]
}
이 경우 review-plugin의 plugin.json에 정의된 스킬이나 에이전트는 그대로 유지되고, 마켓플레이스에서 추가한 Hook이 병합됩니다. 플러그인 작성자가 기본 기능을 관리하고, 마켓플레이스 운영자가 팀에 맞는 Hook이나 커맨드를 얹는 패턴이죠.
strict: false — 마켓플레이스 항목이 전체 정의가 됩니다. 플러그인 저장소에는 원본 파일만 있고, 어떤 파일을 노출할지는 마켓플레이스가 결정합니다.
{
"plugins": [
{
"name": "utils-plugin",
"source": {
"source": "github",
"repo": "community/awesome-utils"
},
"strict": false,
"description": "커뮤니티 유틸리티 중 선별된 스킬만 제공",
"commands": ["./commands/deploy.md", "./commands/rollback.md"],
"agents": ["./agents/security-reviewer.md"]
}
]
}
community/awesome-utils 저장소에 수십 개의 커맨드와 에이전트가 있더라도, 마켓플레이스에서 지정한 deploy.md, rollback.md, security-reviewer.md만 사용자에게 노출됩니다. 단, 이 모드에서는 플러그인의 plugin.json에 컴포넌트 정의가 있으면 충돌로 로드가 실패하니 주의하세요.
두 모드의 우선순위를 정리하면 이렇습니다:
| 항목 | strict: true (기본값) | strict: false |
|---|---|---|
| 컴포넌트 (commands, agents, hooks 등) | plugin.json 우선, 양쪽 병합 | marketplace.json만 사용 |
| 버전 | plugin.json 항상 우선 | marketplace.json 사용 |
| 메타데이터 (description, author 등) | plugin.json 우선 | marketplace.json 사용 |
대부분의 경우 기본값(strict: true)으로 충분합니다. 마켓플레이스 운영자가 플러그인의 컴포넌트 구성을 직접 큐레이션해야 할 때만 strict: false를 쓰세요.
GitHub에 배포하기
마켓플레이스를 GitHub 저장소에 올리면 사용자들이 간편하게 추가할 수 있습니다.
# 마켓플레이스 등록
/plugin marketplace add my-org/my-marketplace
# 마켓플레이스의 플러그인 설치
/plugin install review-plugin@my-plugins
review-plugin@my-plugins 형식에서 @ 뒤가 마켓플레이스 이름입니다. 마켓플레이스를 등록해두면 그 안에 포함된 플러그인을 이름만으로 설치할 수 있어요.
비공개 저장소도 지원합니다. git clone이 되는 저장소라면 클로드 코드에서도 설치가 가능합니다. 백그라운드 자동 업데이트를 위해서는 인증 토큰 환경 변수가 필요합니다.
- GitHub —
GITHUB_TOKEN또는GH_TOKEN - GitLab —
GITLAB_TOKEN또는GL_TOKEN - Bitbucket —
BITBUCKET_TOKEN
버전 관리에서 주의할 점이 하나 있습니다. plugin.json과 marketplace.json 양쪽에 version을 설정하면 plugin.json이 항상 우선하는데, 이 동작이 조용히 일어나서 마켓플레이스의 버전이 무시될 수 있어요. 상대 경로 플러그인은 마켓플레이스 항목에, 그 외 소스의 플러그인은 plugin.json에 버전을 두는 것을 권장합니다. 코드를 변경했는데 버전을 올리지 않으면 캐싱 때문에 기존 사용자에게 변경이 반영되지 않으니 주의하세요.
팀원들이 프로젝트를 열 때 자동으로 플러그인이 설치되게 하는 방법은 플러그인 사용법에서 다루고 있습니다.
커뮤니티 전체에 플러그인을 공개하고 싶다면 claude.com/plugins 디렉토리에 제출할 수도 있습니다. Anthropic이 검토한 뒤 디렉토리에 등록되면 설치 수와 “Anthropic verified” 배지가 표시되어 플러그인의 신뢰도를 높일 수 있어요.
기존 설정을 플러그인으로 변환
이미 .claude/ 디렉토리에 스킬이나 Hooks를 설정해둔 경우, 이를 플러그인으로 변환하면 팀 전체에 쉽게 배포할 수 있습니다. 실제로 팀에서 가장 많이 하는 작업이 바로 이거예요.
# 1. 플러그인 구조 생성
mkdir -p my-plugin/.claude-plugin
# 2. 매니페스트 작성
cat > my-plugin/.claude-plugin/plugin.json << 'EOF'
{
"name": "my-plugin",
"description": "기존 설정을 플러그인으로 변환",
"version": "1.0.0"
}
EOF
# 3. 기존 파일 복사
cp -r .claude/commands my-plugin/
cp -r .claude/skills my-plugin/
# 4. Hooks 설정 복사
mkdir my-plugin/hooks
# settings.json의 hooks 객체를 hooks/hooks.json으로 복사
# 5. 테스트
claude --plugin-dir ./my-plugin
Hooks를 복사할 때 주의할 점이 하나 있습니다. settings.json에서는 스크립트 경로를 상대 경로로 쓸 수 있지만 플러그인에서는 ${CLAUDE_PLUGIN_ROOT}를 사용해야 해요. 경로를 변환하지 않으면 플러그인이 설치된 후 스크립트를 찾지 못합니다.
변환이 끝나면 .claude/의 원본 파일을 삭제해서 중복을 방지하세요.
문제 해결
플러그인이 로드되지 않을 때는 claude --debug 또는 /debug를 실행하면 로딩 과정을 상세히 볼 수 있습니다. 매니페스트의 JSON 문법이 의심되면 claude plugin validate . 또는 /plugin validate .로 검증할 수 있어요. 자주 발생하는 문제를 정리하면 이렇습니다.
디렉토리 구조 오류—commands/,agents/등이.claude-plugin/안에 있으면 안 됩니다. 플러그인 루트에 놓으세요실행 권한 누락— Hook 스크립트에chmod +x script.sh로 실행 권한을 부여하세요상대 경로 문제— Hook 스크립트 경로에${CLAUDE_PLUGIN_ROOT}를 빠뜨리면 파일을 찾지 못합니다외부 파일 참조— 플러그인은 캐시 디렉토리로 복사되므로../같은 경로는 동작하지 않습니다. 외부 파일이 꼭 필요하면 심볼릭 링크를 플러그인 디렉토리 안에 만들면 복사 시 따라갑니다
마치며
.claude/ 디렉토리에서 잘 쓰던 설정을 플러그인으로 묶어두면 팀 온보딩이 “이 플러그인 설치해”로 끝납니다. 처음에는 스킬 하나짜리 작은 플러그인으로 시작해보고, 팀에서 반복적으로 쓰는 패턴이 생기면 Hooks나 MCP 서버를 추가해 나가면 됩니다.
플러그인을 설치하고 관리하는 방법이 궁금하다면 클로드 코드 플러그인 사용법을 참고하세요. 클로드 코드 자체가 궁금하다면 클로드 코드를, Hooks 설정이 더 필요하다면 클로드 코드 Hooks를 확인해보세요. 보안이 중요한 환경이라면 샌드박스로 OS 레벨 격리를 적용하는 것도 고려해보세요. 공식 문서에서 더 자세한 기술 명세를 찾을 수 있습니다.
This work is licensed under
CC BY 4.0