가이드 ·
Claude Code 플러그인 만들어 배포하기 — 스킬·에이전트를 묶어 명령 한 줄로 설치하게
Claude Code 플러그인은 스킬·서브에이전트·hooks·MCP 서버를 한 폴더에 묶은 것이다. plugin.json에 무엇을 적는지, --plugin-dir로 시험하는 법, claude plugin validate로 검사하는 법, marketplace.json으로 배포하는 법, 저장소 하나로 내보내는 예까지 정리했다.
Claude Code 플러그인은 스킬·서브에이전트·hooks·MCP 서버를 한 단위로 묶은 폴더다. 매니페스트는 .claude-plugin/plugin.json이고 꼭 필요한 칸은 name 하나다. skills/·agents/·hooks/hooks.json·.mcp.json은 .claude-plugin/ 안이 아니라 플러그인 맨 위에 둔다. 플러그인 스킬은 /플러그인이름:스킬이름으로 불린다. 만드는 중에는 claude --plugin-dir로 한 세션만 불러 시험하고, claude plugin validate로 검사한다. 배포는 폴더나 .zip을 직접 주기, 내 마켓플레이스(.claude-plugin/marketplace.json이 든 git 저장소), Anthropic 디렉터리 제출 세 가지다. 사용자는 claude plugin marketplace add 소유자/저장소 뒤 claude plugin install 이름@마켓플레이스로 설치한다. version을 적었다면 릴리스마다 올려야 업데이트가 간다.
Claude Code 한국어 실전 가이드 · 6/10편
결론부터. 플러그인은 스킬·서브에이전트·hooks를 한 폴더에 묶어, 남이 명령 한 줄로 설치하게 만드는 포장이다. 폴더 맨 위에 .claude-plugin/plugin.json을 두고, 그 옆에 skills/·agents/ 같은 폴더를 둔다. 배포는 이 폴더가 든 git 저장소에 marketplace.json을 하나 더 넣으면 끝난다. 이 글은 AI(Claude)가 썼고, 내용은 Claude Code 공식 문서 — Plugins와 그 아래 문서들과 대조했다.
언제 플러그인으로 만드나
스킬·서브에이전트·hooks·MCP 서버는 모두 플러그인 없이도 돈다. 5편의 스킬은 ~/.claude/skills/에 두면 내 모든 프로젝트에서 쓰인다. 공식 문서는 이렇게 가른다.
- 나 혼자, 한 프로젝트에서만 쓰면 → 그대로 둔다
- 팀과 나누거나, 여러 프로젝트에 깔거나, 버전을 붙여 내보내려면 → 플러그인으로 묶는다
플러그인으로 옮기면 바뀌는 게 둘 있다. 파일이 플러그인 폴더 아래로 가고, 이름 앞에 플러그인 이름이 붙는다. hello 스킬은 /my-plugin:hello가 된다. 그래서 두 플러그인이 같은 이름의 스킬을 가져도 부딪치지 않는다.
비용도 있다. 켜 둔 플러그인은 모든 세션에 들어온다. 스킬·에이전트의 이름과 설명이 매 턴 컨텍스트에 올라가고, hooks는 이벤트마다 돈다. 모두 내 권한으로 돈다.
폴더 모양
플러그인 맨 위 폴더를 '플러그인 루트'라고 부른다. 쓰는 폴더만 만들면 된다.
| 위치 | 담는 것 |
|---|---|
.claude-plugin/plugin.json |
매니페스트(이름·설명·버전 등) |
skills/<이름>/SKILL.md |
스킬. 폴더 하나에 하나 |
agents/<이름>.md |
서브에이전트. 파일 하나에 하나 |
hooks/hooks.json |
hooks 설정 |
.mcp.json |
MCP 서버 정의 |
commands/ |
옛 형식 명령. 새로 만들 땐 skills/를 쓴다 |
공식 문서가 경고로 박아 둔 것 둘.
.claude-plugin/안에는plugin.json만 둔다.skills/를 그 안에 넣으면 불러오지 않는다. "플러그인은 뜨는데 스킬이 없다"는 증상의 흔한 원인이다.- 플러그인 루트에 둔
CLAUDE.md는 읽히지 않는다. 지침은 스킬로 넣는다.
plugin.json 칸
공식 문서: 매니페스트는 선택이고, 쓴다면 필수 칸은 name 하나다. 매니페스트가 없으면 기본 폴더에서 찾은 것을 불러오고, 이름은 폴더 이름(또는 마켓플레이스 항목)에서 온다.
| 칸 | 정하는 것 |
|---|---|
name |
플러그인 식별자. kebab-case. 모든 스킬·에이전트 이름 앞에 붙음 |
displayName |
화면에 name 대신 보일 이름. 띄어쓰기 가능 |
version |
버전 글. 적으면 바꿀 때까지 사용자가 그 버전에 머문다 |
description |
/plugin에서 보이는 설명 |
author |
name 필수, email·url 선택 |
homepage |
문서 URL. URL로 안 읽히면 플러그인이 안 뜬다 |
repository·license·keywords |
저장소 주소, SPDX 라이선스(MIT 등), 검색 태그 |
userConfig |
켤 때 사용자에게 물어볼 값(토큰은 sensitive: true) |
skills·agents·hooks·mcpServers 칸으로 기본 폴더 말고 다른 위치도 가리킬 수 있다. 경로는 플러그인 루트 기준이고 ./로 시작해야 하며, ..로 루트 밖을 가리키면 안 뜬다.
모르는 최상위 칸은 오류 없이 지워지고, 검사에서 경고만 뜬다.
첫 플러그인 만들고 돌려 보기
공식 문서의 첫 예제 순서다.
mkdir -p my-first-plugin/.claude-plugin
mkdir -p my-first-plugin/skills/hello
my-first-plugin/.claude-plugin/plugin.json:
{
"name": "my-first-plugin",
"description": "A greeting plugin to learn the basics",
"version": "1.0.0",
"author": { "name": "Your Name" }
}
skills/hello/SKILL.md는 5편의 스킬 파일 그대로다. 이제 검사하고 불러 본다.
claude plugin validate ./my-first-plugin
claude --plugin-dir ./my-first-plugin
검사가 통과하면 ✔ Validation passed가 찍힌다. 세션이 뜨면 /my-first-plugin:hello를 친다.
--plugin-dir은 그 세션에만 불러오고 설정에 아무것도 쓰지 않는다. 폴더 대신.zip도 된다.- 세션 중에 파일을 고쳤으면
/reload-plugins를 친다. - 안 뜨면
/plugin의 Errors 탭을 본다. 없는 경로는path not found로 뜬다.
이미 .claude/에 만들어 둔 게 있다면
.claude/ 아래 skills·agents·commands를 플러그인 루트로 복사하고, settings.json의 hooks 덩어리는 모양 그대로 hooks/hooks.json에 옮긴다. 주의점 하나. 원본을 지우기 전까지 hooks는 두 번 돈다. hooks에는 플러그인 이름 같은 구분이 없기 때문이다. 플러그인이 잘 도는 걸 확인하고 원본을 지운다.
배포하는 세 가지 길
| 길 | 누가 설치하나 | 업데이트 |
|---|---|---|
폴더나 .zip을 직접 준다 |
받은 사람 | 없음. 받은 사본 그대로 |
| 내 마켓플레이스 | 저장소에 접근할 수 있는 사람(비공개 저장소도 됨) | 사용자가 claude plugin update, 또는 자동 업데이트를 켰을 때 |
| Anthropic 디렉터리 제출 | claude.ai·Cowork에서 추가한 사람. Claude Code에도 계정 동기화로 들어옴 | 제출한 버전이 공개된 뒤 |
디렉터리 제출은 유료 claude.ai 요금제가 필요하고, claude.ai/directory/manage 개발자 포털에서 한다. 공식 마켓플레이스(claude-plugins-official)는 이 포털로 받지 않는다.
마켓플레이스 만들기
마켓플레이스는 가게가 아니라 목록이다. .claude-plugin/marketplace.json이 든 폴더나 저장소이고, 여기에 플러그인 이름과 가져올 곳을 적는다. 필수 칸은 name·owner·plugins 셋이고, plugins의 항목마다 name과 source가 필요하다.
source는 플러그인이 어디 있느냐로 고른다.
| source | 쓰는 때 |
|---|---|
"./plugins/my-plugin" 같은 상대 경로 |
플러그인이 같은 저장소 안에 있을 때 |
github |
플러그인이 따로 GitHub 저장소일 때 |
git-subdir |
다른 저장소(모노레포)의 하위 폴더일 때 |
url·archive·npm·command |
다른 git 호스트, HTTPS zip, npm 패키지, 명령 출력 |
상대 경로는 .claude-plugin/의 바깥, 마켓플레이스 루트에서 센다. 공식 문서는 설치 실패 대부분이 이 기준을 틀렸거나 항목 name과 plugin.json의 name이 다를 때라고 한다. 두 이름은 같게 둔다.
푸시하고 나면 사용자는 셸에서 두 줄을 친다.
claude plugin marketplace add your-org/your-marketplace
claude plugin install deploy-helper@your-marketplace
설치 아이디는 플러그인이름@마켓플레이스이름이다. Claude Code v2.1.275부터는 세션 안에서 /plugin install deploy-helper --marketplace your-org/your-marketplace 한 줄로 둘을 같이 할 수 있다.
예: 저장소 하나에 마켓플레이스와 플러그인 같이 두기
혼자 플러그인 하나를 내보낼 때 흔한 모양이다. 저장소 하나가 마켓플레이스이자 플러그인 보관소다. 이름은 예로 team-tools를 쓴다.
team-tools/
├── .claude-plugin/
│ └── marketplace.json (마켓플레이스 목록)
└── plugin/ (플러그인 루트)
├── .claude-plugin/
│ ├── plugin.json
│ └── icon.png
├── skills/review/SKILL.md
├── agents/ (checker.md 등)
└── README.md
저장소 맨 위 marketplace.json:
{
"name": "team-tools",
"owner": { "name": "your-org" },
"plugins": [
{ "name": "team-tools", "source": "./plugin" }
]
}
plugin/.claude-plugin/plugin.json:
{
"name": "team-tools",
"displayName": "Team Tools",
"version": "0.1.0",
"description": "Review skill and checker agent for our team",
"author": { "name": "your-org" },
"license": "MIT",
"icon": "./.claude-plugin/icon.png",
"privacyPolicyUrl": "https://example.com/privacy"
}
공식 문서와 맞춰 보면 이렇다.
- 플러그인을
plugin/하위 폴더에 뒀다. 그래서source가"./plugin"이고, 저장소의 다른 코드와 섞이지 않는다. - 마켓플레이스 항목과
plugin.json의name이 둘 다team-tools다. 설치 아이디는team-tools@team-tools가 된다. - 에이전트는
team-tools:checker처럼 플러그인 이름이 붙는다. 스킬도/team-tools:review다. README에/review라고 적는 실수가 흔하다. 플러그인 에이전트는permissionMode·hooks·mcpServers·initialPrompt머리말이 무시되니, hooks·MCP 서버는 플러그인 쪽에 둔다. icon·privacyPolicyUrl은 Claude Code가 읽지 않는 칸이다. Anthropic 디렉터리 목록이 읽는다. 공식 문서는 이 칸들을 마켓플레이스 항목이 아니라plugin.json에만 두라고 한다.version을 적었다. 그래서 릴리스할 때마다 숫자를 올려야 한다(아래 실수 목록 참고).
README의 설치 안내는 한 줄이면 된다.
/plugin install team-tools --marketplace your-org/team-tools
v2.1.275보다 옛 버전에서는 /plugin marketplace add your-org/team-tools 뒤 /plugin install team-tools@team-tools로 나눠 친다.
자주 하는 실수
version을 그대로 두고 푸시한다.plugin.json에version을 적었는데 숫자를 안 올리면,claude plugin update가 "이미 최신"이라며 옛 사본을 둔다. 릴리스마다 올리거나, git 마켓플레이스라면version을 빼서 커밋 SHA를 버전으로 쓰게 한다.- 배포한 플러그인의
name을 바꾼다. 기존 설치는 옛 이름으로 기록돼 있어서 플러그인이 사라진다. 보이는 이름만 바꾸려면displayName을 쓰고, 꼭 바꿔야 하면marketplace.json의renames를 쓴다. --plugin-dir에 마켓플레이스 루트를 준다. 이 옵션은marketplace.json을 읽지 않는다. 오류도 없이 플러그인이 안 뜬다. 플러그인 폴더 하나를 가리킨다.- hooks 스크립트 경로를 고정 경로로 쓴다. 설치 위치는 사람마다 다르다.
"${CLAUDE_PLUGIN_ROOT}"/scripts/format.sh처럼 쓴다. 이 경로는 업데이트 때 바뀌니 남길 데이터는${CLAUDE_PLUGIN_DATA}에 둔다. - 검사만 하고 설치는 안 해 본다. 없는 폴더를 가리킨 상대 경로는
validate를 통과하고 설치 때 실패한다. 공유 전에claude plugin marketplace add ./경로로 직접 설치해 본다.
자주 묻는 질문
플러그인과 스킬은 뭐가 다른가요?
스킬은 일하는 법을 적은 SKILL.md 한 장이고, 플러그인은 스킬·서브에이전트·hooks·MCP 서버를 묶은 포장이다. 남에게 나누거나 버전을 붙여 내보낼 때 플러그인으로 묶는다.
배포 전에 무엇을 검사하나요?
셸에서 claude plugin validate --strict ./내-플러그인을 돌린다. --strict는 경고도 실패로 친다. 마켓플레이스 폴더에 돌리면 marketplace.json과 상대 경로 플러그인들의 plugin.json까지 본다.
이름에 claude를 넣어도 되나요?
claude-나 anthropic-으로 시작하면 검사에서 오류가 난다. mcp-for-claude처럼 중간에 단어로 들어가면 경고가 뜬다. 마켓플레이스 이름도 claude-plugins-official 같은 공식 이름은 쓸 수 없다.
참고한 링크
- Claude Code 공식 문서 — Plugins overview
- Claude Code 공식 문서 — Create a plugin
- Claude Code 공식 문서 — Plugin components
- Claude Code 공식 문서 — Plugin manifest reference
- Claude Code 공식 문서 — Create a marketplace
- Claude Code 공식 문서 — Marketplace reference
- Claude Code 공식 문서 — Publish and distribute a plugin
- Claude Code 스킬 만들기 (5편)
- Claude Code 서브에이전트 만들기 (4편)