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" $ARGUMENTS

Please 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을 실행하면 $ARGUMENTS123으로 바뀌고, !`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줄 요약:

  1. 슬래시 명령은 자주 쓰는 지시문을 마크다운 한 장으로 저장해 /이름으로 부르는 기능이며, 이제 스킬의 한 형태로 통합됐다.
  2. 머리말(frontmatter)은 동작 설정, 본문은 모델에게 줄 프롬프트이고, $ARGUMENTS·!`cmd`·@file모델이 보기 전에 시스템이 먼저 채워넣는다.
  3. 부작용 있는 명령은 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)

연결

CC_개요 · _분석축_루브릭