Claude Code · 확장점: Slash Commands (사용자 정의 명령)
한 줄 요약
자주 쓰는 지시문을 마크다운 파일 하나로 저장해 두고 /이름 한 줄로 불러 쓰는 기능이다.
왜 배우나: 똑같은 프롬프트를 매번 복붙하는 수고를 없애고, 팀 전체가 같은 작업 방식을 공유하게 만드는 가장 쉬운 확장점이기 때문이다.
그림
사용자가 /명령을 입력한 순간부터 모델이 작업을 끝낼 때까지의 흐름이다. 핵심은 “글자 끼워넣기와 셸 실행은 모델이 아니라 시스템이 먼저 처리한다(전처리)“는 점이다.
flowchart TD A["사용자가 /commit-push-pr arg 입력<br/>또는 Claude가 맥락 보고 자동 선택"] --> B["파일 찾고 우선순위 정리<br/>엔터프라이즈 > 개인 > 프로젝트, 스킬 > 커맨드"] B --> C["맨 위 설정값(frontmatter) 읽기<br/>설명 / 인자힌트 / 허용도구 / 실행모드"] C --> D["본문 채워넣기(전처리)<br/>$ARGUMENTS·$1·$name 끼워넣기<br/>!cmd·셸블록 실행 후 결과 삽입<br/>@파일 내용 삽입"] D --> E{"격리 실행(fork) 인가?"} E -- 아니오 --> F["완성된 본문을 한 통의 메시지로<br/>지금 대화에 그대로 넣음"] E -- 예 --> G["별도 서브에이전트 생성<br/>본문이 그 에이전트의 단독 지시문이 됨"] F --> H["모델 실행<br/>허용도구는 승인 없이 바로 사용"] G --> H H --> I["결과 처리: 도구 호출·출력<br/>격리 실행이면 요약해 본 대화로 반환"]
쉽게 풀기
비유로 시작하자. 슬래시 명령은 주방의 “레시피 카드”다. 손님이 올 때마다 요리법을 처음부터 설명하는 대신, 카드 한 장을 꺼내 “이대로 해”라고 건네는 것과 같다.
- 카드 본문 = 요리법(프롬프트): 파일의 본문 자체가 Claude에게 보낼 지시문이다. 사람에게 설명하는 글이 아니라, “지금 이 작업을 해”라는 명령문으로 쓴다.
- 카드 머리말 = 설정표(frontmatter): 파일 맨 위 YAML 영역에 “이 카드가 뭐 하는 건지(
description)”, “어떤 재료를 받는지(argument-hint)”, “어떤 도구를 미리 허락할지(allowed-tools)“를 적는다. /이름 값= 카드 꺼내기 + 재료 넣기:/deploy 123처럼 뒤에 붙인 값은 본문의$ARGUMENTS나$1자리에 자동으로 끼워진다.!`git status`= 미리 조사하기: 본문에 이런 줄을 쓰면, Claude가 카드를 받아보기 전에 그 셸 명령이 먼저 실행되고 그 결과가 카드에 박혀 들어간다. 덕분에 모델은 “지금 깃 상태가 이렇다”는 최신 정보를 가진 채로 작업을 시작한다.
알아둘 변경: "슬래시 명령 = 단일 파일 버전의 스킬"
공식 문서 기준으로 커스텀 커맨드는 스킬(Skill)로 통합되었다.
.claude/commands/deploy.md와.claude/skills/deploy/SKILL.md는 둘 다/deploy를 만들고 똑같이 동작한다. 기존commands/파일은 그대로 계속 쓰이며 같은 머리말 형식을 지원한다. 즉 슬래시 명령을 “파일 한 장짜리 간단한 스킬”로 이해하면 된다.
명령 이름은 어디서 정해지나
명령 이름은 내가 따로 정하는 게 아니라 파일 위치가 자동으로 결정한다.
.claude/commands/deploy.md→ 파일명에서 따와/deploy.claude/skills/deploy-staging/SKILL.md→ 폴더명에서 따와/deploy-staging- 플러그인 안의 명령 →
플러그인이름:명령이름형태로 호출 (예:/my-plugin:review)
이름이 겹치면 누가 이기나
같은 이름이 여러 곳에 있으면 엔터프라이즈 > 개인 > 프로젝트 순으로 덮어쓴다. 그리고 스킬과 커맨드가 같은 이름이면 스킬이 우선한다. 플러그인 명령은
플러그인이름:네임스페이스가 붙어 다른 레벨과 절대 충돌하지 않는다.
핵심 정리
자주 쓰는 머리말(frontmatter) 설정값이다. 셋만 기억하면 된다: description(정체성), argument-hint(받을 값), allowed-tools(미리 허락할 도구).
| 설정값 | 한마디로 | 언제 쓰나 |
|---|---|---|
description | 무엇을·언제 하는 명령인지 | 거의 항상 (자동 호출 정확도 직결) |
argument-hint | 받을 인자 모양 힌트 | 인자를 받을 때 |
allowed-tools | 승인 없이 자동 허용할 도구 | git/gh 등 반복 도구 쓸 때 |
안전·고급 설정 (필요할 때만)
disable-model-invocation: true— Claude가 멋대로 못 켜고 사용자만/이름으로 호출. deploy·commit·send처럼 부작용 있는 명령에 권장user-invocable: false—/메뉴에서 숨김(Claude만 호출)disallowed-tools— 이 명령 동안 특정 도구를 풀에서 제거model/effort— 이 명령 동안만 모델·추론 강도를 바꾸고 다음 프롬프트에 원복context: fork(+agent) — 격리된 서브에이전트에서 실행, 본문이 그 단독 프롬프트가 됨paths— 글롭 패턴에 맞는 파일을 다룰 때만 자동 활성shell— 셸 임베드에 쓸 셸 지정(bash기본 /powershell)
본문 안에서 쓰는 끼워넣기·삽입 문법이다.
| 문법 | 무슨 뜻인가 |
|---|---|
$ARGUMENTS | 넘긴 인자 전체(원문 그대로) |
$1, $ARGUMENTS[1] | 개별 인자 접근($0=첫째, $1=둘째) |
$name | 머리말 arguments에 선언한 명명 인자 |
!`cmd` | Claude가 보기 전에 셸 실행 → 결과를 그 자리에 삽입 |
```! | 여러 줄 셸 명령용 삽입 블록 |
@file | 파일 내용을 본문에 끌어와 삽입 |
셸 임베드의 두 가지 함정
!`...`삽입은 원본 파일에 대해 딱 한 번만 수행되고, 그 출력은 다시 스캔되지 않는다. 즉 출력이 또 다른 자리표시자를 만들 수 없다."disableSkillShellExecution": true설정이 켜져 있으면 모든 셸 명령은[shell command execution disabled by policy]로 바뀌어 실행되지 않는다.
실제 예시
예시 1 — 저장소 실사용: 커밋·푸시·PR 한 번에
allowed-tools로 git/gh 도구를 패턴 단위로 미리 허락하고, ## Context에서 셸 3개를 임베드해 최신 깃 상태를 본문에 박은 뒤, ## Your task가 모델에게 줄 지시가 된다.
// /home/seunghyeong/harness-work/claude-code/.claude/commands/commit-push-pr.md
---
allowed-tools: Bash(git checkout --branch:*), Bash(git add:*), Bash(git status:*), Bash(git push:*), Bash(git commit:*), Bash(gh pr create:*)
description: Commit, push, and open a PR
---
## Context
- Current git status: !`git status`
- Current git diff (staged and unstaged changes): !`git diff HEAD`
- Current branch: !`git branch --show-current`
## Your task
Based on the above changes:
1. Create a new branch if on main
2. Create a single commit with an appropriate message
3. Push the branch to origin
4. Create a pull request using `gh pr create`
5. You have the capability to call multiple tools in a single response. You MUST do all of the above in a single message. ...예시 2 — 플러그인 명령: 인자 + 멀티라인 셸 + 네임스페이스
argument-hint로 자동완성 힌트를 주고, allowed-tools를 YAML 리스트로 적었으며, ${CLAUDE_PLUGIN_ROOT}로 스크립트 경로를 이식성 있게 참조했다. ```! 블록이 멀티라인 셸 임베드이고, $ARGUMENTS가 사용자가 넘긴 PROMPT/플래그를 스크립트로 흘려보낸다. 플러그인 안에 있어 /ralph-wiggum:ralph-loop로 호출된다.
// /home/seunghyeong/harness-work/claude-code/plugins/ralph-wiggum/commands/ralph-loop.md
---
description: "Start Ralph Wiggum loop in current session"
argument-hint: "PROMPT [--max-iterations N] [--completion-promise TEXT]"
allowed-tools: ["Bash(${CLAUDE_PLUGIN_ROOT}/scripts/setup-ralph-loop.sh:*)"]
hide-from-slash-command-tool: "true"
---
# Ralph Loop Command
Execute the setup script to initialize the Ralph loop:
```!
"${CLAUDE_PLUGIN_ROOT}/scripts/setup-ralph-loop.sh" $ARGUMENTSPlease work on the task. When you try to exit, the Ralph loop will feed the SAME PROMPT back to you …
> [!note] 장문 절차형 예시
>
> `/home/seunghyeong/harness-work/claude-code/plugins/plugin-dev/commands/create-plugin.md`는 `allowed-tools`를 `["Read","Write","Grep","Glob","Bash","TodoWrite","AskUserQuestion","Skill","Task"]` 배열로, `argument-hint: Optional plugin description`로 선언하고, 본문 `**Initial request:** $ARGUMENTS` 한 줄로 인자를 받아 8단계 워크플로 프롬프트를 펼치는 "긴 절차형" 명령의 대표 사례다.
### 예시 3 — 내가 직접 만들 때 최소 템플릿
```markdown
// .claude/commands/fix-issue.md
---
description: 깃허브 이슈를 우리 코딩 표준대로 수정한다. 사용자가 "이슈 N번 고쳐줘"라고 할 때 쓴다.
argument-hint: [issue-number]
allowed-tools: Bash(gh issue view:*), Read, Edit, Bash(git commit:*)
disable-model-invocation: true
---
## 컨텍스트
- 대상 이슈: !`gh issue view $ARGUMENTS`
## 작업
이슈 $ARGUMENTS 를 우리 표준에 맞춰 수정한다.
1. 이슈 요구사항 파악
2. 수정 구현
3. 테스트 작성
4. 커밋 생성
→ /fix-issue 123을 실행하면 $ARGUMENTS가 123으로 바뀌고, !`gh issue view 123` 출력이 본문에 박혀 모델에게 전달된다.
만들 때 점검표:
- 파일 위치로 명령 이름이 정해진다(파일명/디렉토리명). 플러그인이면
plugin:command네임스페이스 확인 -
description은 사용자가 실제로 말할 키워드로 “무엇을+언제”를 적기 - 인자 받으면
argument-hint추가 + 본문에$ARGUMENTS/$1/$name배치 - 부작용 있는 명령(deploy/commit/send)은
disable-model-invocation: true - 자동 승인 도구는 패턴(
Bash(git add *))으로 최소 권한만 - 실시간 데이터가 필요하면
!`cmd`(한 줄) 또는```!(여러 줄)로 임베드 - 본문은 사용자가 아니라 Claude에게 주는 명령문으로 작성
- 긴 절차는 단계로 쪼개되 본문은 간결하게(세션 내내 토큰 비용)
요약 & 셀프체크
3줄 요약:
- 슬래시 명령은 자주 쓰는 지시문을 마크다운 한 장으로 저장해
/이름으로 부르는 기능이며, 이제 스킬의 한 형태로 통합됐다. - 머리말(frontmatter)은 동작 설정, 본문은 모델에게 줄 프롬프트이고,
$ARGUMENTS·!`cmd`·@file은 모델이 보기 전에 시스템이 먼저 채워넣는다. - 부작용 있는 명령은
disable-model-invocation으로 잠그고, 도구는allowed-tools패턴으로 최소 권한만 열어 안전하게 쓴다.
스스로 답해보기:
!`git status`의 출력은 누가, 언제 본문에 채워넣는가? (모델? 시스템 전처리?)- 같은 이름의 명령이 프로젝트와 개인 레벨에 둘 다 있으면 무엇이 이기는가?
- deploy 명령을 만들 때 Claude가 멋대로 실행하지 못하게 하려면 어떤 설정을 켜는가?
근거 파일
/mnt/d/6study/10_프레임워크분석/_원문아카이브/claude-code/slash-commands.md(공식문서 아카이브 1차 출처, 출처 URL: code.claude.com/docs/en/slash-commands, 수집 2026-06-15)/home/seunghyeong/harness-work/claude-code/.claude/commands/commit-push-pr.md(저장소 실사용: allowed-tools 패턴 +!`...`임베드)/home/seunghyeong/harness-work/claude-code/plugins/ralph-wiggum/commands/ralph-loop.md(플러그인 실사용: argument-hint, YAML 리스트 allowed-tools,```!블록,${CLAUDE_PLUGIN_ROOT},$ARGUMENTS, hide-from-slash-command-tool, 네임스페이스)/home/seunghyeong/harness-work/claude-code/plugins/plugin-dev/commands/create-plugin.md(플러그인 실사용: description/argument-hint/allowed-tools 배열, 본문$ARGUMENTS+ 장문 절차형 task content)