내 패턴 · 확장점: Skills와 Slash-Commands (SKILL.md 프론트매터와 트리거)
내 패턴 · 확장점: Skills와 Slash-Commands (SKILL.md 프론트매터와 트리거)
한 줄 요약
Claude Code(하네스)에 기능을 끼우는 두 통로 — Skill(모델이 알아서 펼치는 매뉴얼)과 Slash-Command(사람이 /이름으로 누르는 단축 버튼) — 의 파일 형식과 호출 방식을 배운다. 이게 “내 절차서를 AI가 언제·어떻게 꺼내 쓸지”를 정하는 가장 기본 확장점이다.
그림
flowchart TD
subgraph 만들기[1. 파일로 만든다]
SK["skills/이름/SKILL.md<br/>(YAML 명패 + 본문 절차서)"]
CM["commands/이름.md<br/>(슬래시 커맨드 디스패처)"]
PJ["plugin.json<br/>skills[] / commands 경로 등록"]
end
subgraph 호출[2. 셋 중 하나로 불려 나온다]
A["(a) 모델 자율 호출<br/>description 보고 스스로 판단"]
B["(b) 키워드 강제 주입<br/>UserPromptSubmit 훅이 잡음"]
C["(c) 사람이 직접<br/>/이름 입력"]
end
SK --> A
SK --> B
CM --> C
PJ -.등록.-> SK
PJ -.등록.-> CM
A --> OPEN["본문 전체가 그제서야 펼쳐짐<br/>= 점진 공개(컨텍스트 절약)"]
B --> OPEN
C --> OPEN
OPEN --> RUN["모델이 절차서대로 실행"]
쉽게 풀기
Skill = 책장에 꽂힌 매뉴얼. skills/<이름>/SKILL.md 마크다운 한 장. 맨 위 YAML이 이름·설명·트리거 같은 “명패”, 그 아래 본문이 “이럴 땐 이렇게 해라” 절차서다.
핵심 비유: 모델은 평소 명패(설명)만 흘끗 본다. 실제로 필요해지는 순간에야 본문 전체를 펼쳐 읽는다 = 점진 공개(progressive disclosure). 매뉴얼 100권을 전부 펼치면 책상(컨텍스트)이 꽉 차니, 평소엔 책등(설명)만 보이게 꽂아 두는 절약 전략이다.
Slash-Command = 그 매뉴얼로 가는 단축 버튼. commands/<이름>.md, 사용자가 /이름을 직접 쳐서 부르는 명시적 진입점. 본문은 대개 짧고 “해당 SKILL.md를 읽고 따르라”고 넘기는 디스패처 역할만 한다.
둘의 진짜 차이는 “누가 부르냐”다. 스킬은 (a)모델이 설명 보고 자율 호출하거나 (b)훅이 키워드 잡아 강제 주입. 커맨드는 (c)사람이 슬래시로 직접.
flowchart LR D["description<br/>= 책등 라벨<br/>(무슨 책인지)"] BD["본문<br/>= 실제 작업 순서"] KW["키워드 강제 주입<br/>= '지금 이 책 펴!'<br/>사서의 외침"] D -.판단.-> BD KW ==강제==> BD
핵심 정리
A. Skill 프론트매터 (skills/<name>/SKILL.md 맨 위 YAML)
| 필드 | 필수 | 핵심 의미 |
|---|---|---|
name | 권장 | 식별자, 디렉터리명과 일치 (team, wiki, dd) |
description | 필수 | 모델이 자율 호출을 판단하는 매칭 텍스트 = “언제 쓰는지” |
triggers | 선택 | 자동 활성 키워드 목록 |
aliases / argument-hint / level | 선택 | 별칭 / 인자 힌트 / 복잡도 등급 |
[!note] description은 “정확도의 핵심” 모델이 “이 요청이 이 스킬에 맞나?”를 판단하는 유일한 재료다. dd는 여기에 한국어/영어 트리거 문구를 통째로 박아 매칭률을 높인다. 모호하면 엉뚱한 스킬이 불린다.
[!note]- 펼쳐보기: 고급 메타 필드 (AGENTS.md 템플릿)
agent/model/pipeline/next-skill/handoff필드는 실행 에이전트·모델 오버라이드·다단계 체인을 정의한다. 있으면 OMC가 렌더 프롬프트에 핸드오프 블록을 덧붙인다.triggers는 AGENTS.md 템플릿에선 블록 리스트 형태도 허용된다.
본문(YAML 아래)은 # 제목 + ## Usage / ## Workflow(번호 단계) / ## Architecture 같은 자유 마크다운 절차서다.
B. Slash-Command (commands/<name>.md)
| 필드 | 필수 | 핵심 의미 |
|---|---|---|
description | 필수(빈 OK) | 설명. OMC 호환은 ""로 비워 로딩 비용 제거 |
allowed-tools | 선택 | 쓸 도구 화이트리스트 (dd: [Bash, Read]) |
| 본문(markdown) | 필수 | $ARGUMENTS로 인자를 받는 실행 디스패처 |
C. 등록 (plugin.json / .claude-plugin/plugin.json)
-
skills(string[]): 스킬 디렉터리 경로 (예"./skills/team/") -
commands(string): 커맨드 디렉터리 경로 (예"./commands/"— 안의*.md전부 등록) - 호출 네임스페이스 =
<plugin>:<skill>(예oh-my-claudecode:team,dd:dd)
실제 예시
핵심만: 스킬 프론트매터(triggers 유무), 디스패처 커맨드, 등록 JSON.
# skills/wiki/SKILL.md — triggers[]가 자동 활성 키워드
---
name: wiki
description: LLM Wiki — persistent markdown knowledge base...
triggers: ["wiki", "wiki add", "wiki lint", "wiki query"]
---
<!-- commands/wiki.md — 빈 description + $ARGUMENTS 디스패처 -->
---
description: ""
---
## Dispatch
1. Read the full bundled skill: `skills/wiki/SKILL.md`.
2. Follow that SKILL.md exactly, treating arguments as:
$ARGUMENTS
// .claude-plugin/plugin.json
{ "name": "oh-my-claudecode",
"skills": ["./skills/team/", "./skills/wiki/"],
"commands": "./commands/" }
[!note]- 펼쳐보기: 전체 예시 모음 (team/dd 프론트매터, dd 캡처 커맨드)
# skills/team/SKILL.md — argument-hint·aliases·level --- name: team description: N coordinated agents on shared task list using Claude Code native teams argument-hint: "[N:agent-type] [ralph] <task description>" aliases: [] level: 4 --- # Team Skill Spawn N coordinated agents working on a shared task list...<!-- dd/commands/dd.md — allowed-tools + 인라인 캡처 --> --- name: dd description: Drop the current OS clipboard (text or image) into context... argument-hint: "[request about the clipboard, optional]" allowed-tools: - Bash - Read --- # /dd — Drop clipboard into context As your VERY FIRST action, capture the clipboard: `python3 "${CLAUDE_PLUGIN_ROOT}/skills/dd/scripts/dd_clipboard.py" --json` Then read the full policy: Read `${CLAUDE_PLUGIN_ROOT}/skills/dd/SKILL.md` The user's request (may be empty): $ARGUMENTS
두 호출 경로 (형식은 같은 SKILL.md, 진입 방식만 다름)
경로 (a) — description 매칭으로 자율 호출. 세션 시작 시 하네스는 각 스킬의 name+description만(본문 아님) 카탈로그로 모델에게 보여준다. 사용자가 자연어로 말하면 모델이 “이 description에 맞다”고 판단해 Skill 도구로 호출 → 그제서야 본문이 펼쳐진다(점진 공개). 그래서 OMC 호환 커맨드는 description:""로 카탈로그 부피를 줄인다.
경로 (b) — UserPromptSubmit 훅의 keyword-detector가 키워드→스킬 강제 주입. hooks/hooks.json이 keyword-detector.mjs를 5초 타임아웃으로 건다. 흐름:
flowchart TD
U[사용자 프롬프트 제출] --> H["UserPromptSubmit 훅<br/>keyword-detector.mjs"]
H --> S["정제: 코드블록·인용·붙여넣은 echo·git diff 제거"]
S --> M{"실행성 키워드?<br/>ralph/ulw/autopilot/ccg..."}
M -- 아니오 --> P["continue:true, suppressOutput<br/>(그냥 통과)"]
M -- 예 --> C["정보성 질문/배너 echo 인지 가드"]
C --> R["충돌 해소: 우선순위 정렬<br/>cancel>ralph>autopilot>ultrawork"]
R --> St["ralph/autopilot/ultrawork면<br/>state.json 활성화"]
St --> A["additionalContext에<br/>'["MAGIC KEYWORD: X"]' 주입"]
A --> Mo["모델: 해당 스킬 즉시 시작<br/>SKILL.md fallback 경로 안내"]
주입 텍스트는 SKILL.md 본문을 인라인하지 않고 경로만 알려주는 컴팩트 가이드다(토큰 폭증 방지).
[!note]- 펼쳐보기: 전체 키워드 매핑 + MAGIC KEYWORD 포맷 키워드 매핑(실측):
ralph→ralph,ulw/ultrawork→ultrawork,autopilot→autopilot,ccg→ccg,ralplan→ralplan,deep interview/ouroboros→deep-interview,tdd→TDD 모드,cancelomc/stopomc→cancel.[MAGIC KEYWORD: RALPH] Skill routing detected: ralph Preferred invocation: /oh-my-claudecode:ralph Read fallback: open <...>/skills/ralph/SKILL.md and follow its instructions. User request (compact echo; original prompt remains authoritative): <사용자 프롬프트 1200자로 압축> IMPORTANT: Start the ralph workflow immediately...
[!note] 왜 셋을 모두 쓰나 + 안전장치 description은 라우팅 판단 재료, 본문은 실행 절차서, MAGIC KEYWORD 블록은 “지금 켜라”는 강제 신호다.
team은 의도적으로 키워드 자동 트리거에서 빠져 명시적/team만 허용한다(워커가 “team”을 보고 무한 스폰하는 걸 막음). 또OMC_TEAM_WORKER환경변수가 있으면 훅이 키워드 감지를 통째로 스킵한다.
커맨드 경로 (c): /wiki 입력 → 하네스가 commands/wiki.md 본문을 펼침 → 그 본문이 “skills/wiki/SKILL.md를 읽고 $ARGUMENTS로 따르라”는 디스패처라 결국 스킬 본문으로 합류. dd 커맨드는 디스패처 전에 allowed-tools로 Bash/Read만 허용하고 첫 액션으로 캡처 스크립트를 실행한다.
직접 만들 때 템플릿
<!-- <plugin>/skills/my-skill/SKILL.md -->
---
name: my-skill
description: <언제 쓰는지 한 문장 — 라우팅 판단 기준, 트리거 어구를 녹여라>
aliases: [ms]
triggers: ["my-skill", "do the thing"]
level: 2
---
# My Skill
## Workflow
1. 1단계 2. 2단계 3. 검증
## Usage
/<plugin>:my-skill <arg>
// <plugin>/.claude-plugin/plugin.json
{ "skills": ["./skills/my-skill/"], "commands": "./commands/" }
커맨드(commands/my-skill.md)는 위 wiki 디스패처 패턴 그대로(description:"" + skills/my-skill/SKILL.md 읽기 + $ARGUMENTS). 강제 키워드 주입까지 원하면 hooks/hooks.json의 UserPromptSubmit에 keyword-detector류 훅을 등록하고, [MAGIC KEYWORD: MY-SKILL] 블록을 hookSpecificOutput.additionalContext로 출력하게 한다.
만들기 체크리스트
-
skills/<name>/SKILL.md생성, YAML에 최소name+description. - description에 “언제 쓰는지” + 트리거 어구 명확히 (자율 호출 정확도 좌우).
- 자동 활성 원하면
triggers[]또는 keyword-detector 매핑 추가. - 본문은
## Workflow번호 단계 — 점진 공개 대상이라 자족적이어야. -
commands/<name>.md는description:""+$ARGUMENTS디스패처. -
plugin.json의skills[]/commands에 경로 등록. - 무한 스폰 위험 스킬(team류)은 키워드 자동 트리거 제외 + 워커 가드 환경변수.
요약 & 셀프체크
3줄 요약
- Skill은
skills/<이름>/SKILL.md한 장(YAML 명패 + 본문 절차서), 평소엔 description만 보이다 필요할 때 본문이 펼쳐진다(점진 공개). - Slash-Command는
commands/<이름>.md로 사람이/이름을 직접 눌러 부르며, 보통 “해당 SKILL.md를 읽고 따르라”는 디스패처다. - 호출 경로는 셋 — (a)모델 자율, (b)키워드 훅 강제 주입(
[MAGIC KEYWORD]), (c)사람이 슬래시 — 이며 셋 다plugin.json등록이 전제다.
스스로 답해 보기
- description을 잘 쓰는 것이 왜 자율 호출(경로 a)의 정확도를 좌우할까?
team스킬은 왜 키워드 자동 트리거에서 일부러 빠졌고, 어떤 환경변수가 추가 안전장치인가?/wiki를 눌렀을 때, 짧은 커맨드 본문이 결국 어떻게 긴 스킬 절차서로 이어지는가?
근거 파일
[!note]- 펼쳐보기: 전체 근거 파일 목록
omc/skills/team/SKILL.md(name/description/argument-hint/aliases/level)omc/skills/wiki/SKILL.md(triggers[])omc/skills/project-session-manager/SKILL.md(aliases [psm], level:2)omc/skills/AGENTS.md(스킬 템플릿·자동활성 표·생성 절차)omc/commands/wiki.md,commands/skill.md(디스패처 커맨드, description:"")omc/.claude-plugin/plugin.json(skills[]/commands 등록)omc/hooks/hooks.json(UserPromptSubmit→keyword-detector.mjs)omc/templates/hooks/keyword-detector.mjs(키워드→스킬 강제 주입, [MAGIC KEYWORD] 포맷, team 제외/워커 가드)gptaku-plugins/plugins/dd/skills/dd/SKILL.md,dd/commands/dd.md,dd/.claude-plugin/plugin.json(allowed-tools, 한/영 트리거, 캡처 스크립트) 경로 접두사:/home/seunghyeong/.claude/plugins/marketplaces/
연결
MINE_개요 · _분석축_루브릭 · MINE_30_hooks-lifecycle (키워드 강제 주입의 훅 메커니즘) · MINE_50_subagents-format (스킬이 호출하는 에이전트 형식)