Claude Code의 커스텀 슬래시 명령어: 명령어가 스킬(skills)로 통합된 후의 작동 방식
요약
Claude Code의 커스텀 슬래시 명령어가 '스킬(skills)' 시스템으로 통합됨에 따라 변화된 작동 방식과 활용법을 설명합니다. 기존 마크다운 기반 명령어의 유지 방식과 더불어, 디렉토리 지원 및 자동 호출 기능이 추가된 스킬의 차이점을 다룹니다.
핵심 포인트
- 커스텀 명령어가 스킬(skills)로 통합되어 더 강력한 기능 제공
- 스킬은 디렉토리 지원, 호출 제어, 자동 호출 기능을 포함함
- 단순 단축키는 commands/, 확장 및 공유용은 skills/ 권장
- $ARGUMENTS 및 인덱스 접근($0)을 통한 인자 처리 규칙 설명
당신이 /fix-issue 123을 입력하면 Claude Code는 팀의 표준이 첨부된 전체 프롬프트로 이를 확장합니다. 커스텀 슬래시 명령어(Custom slash commands)는 Claude Code에서 가장 저렴한 자동화 방식입니다. 마크다운 파일 하나면 충분하며 별도의 설정도 필요 없습니다. 그런데 이 명령어들이 놓치기 쉬운 방식으로 변경되었습니다. 바로 커스텀 명령어가 스킬(skills)로 통합된 것입니다. 기존의 .claude/commands/ 파일들은 계속 작동하지만, 통합된 모델은 버그처럼 보이는 몇 가지 현상(인자(arguments)가 확장되지 않음, 작업 도중 도구 권한(tool grants)이 사라짐 등)을 설명해주며, 기존 명령어에는 없던 기능들을 추가했습니다.
다음은 2026년 7월 말 기준 공식 문서를 통해 확인된 현재의 동작 방식입니다.
단일 파일 버전은 여전히 작동합니다
프로젝트에 마크다운 파일을 넣으세요:
<!-- .claude/commands/fix-issue.md -->
---
description: "Fix a GitHub issue by number"
...
/fix-issue 123을 입력하면 $ARGUMENTS가 123으로 대체된 상태로 해당 콘텐츠가 전송됩니다.
이번 통합으로 인해 이 파일과 .claude/skills/fix-issue/SKILL.md에 있는 스킬은 모두 /fix-issue를 생성하며 동일하게 작동합니다. 스킬이 추가로 제공하는 기능은 다음과 같습니다:
- 지원 파일들을 위한 디렉토리 (템플릿, 스크립트, Claude가 필요할 때만 로드하는 참조 문서 등)
- 누가 이를 호출할지 제어하는 프론트매터(frontmatter) — 사용자, Claude, 또는 둘 다
- 자동 호출(automatic invocation): 대화 내용이 설명과 일치할 때 Claude가 이를 로드할 수 있음
명령어와 스킬의 이름이 같을 경우, 스킬이 우선권을 갖습니다. 저의 실무적인 규칙은 다음과 같습니다: 일회성 개인용 단축키는 commands/에 두어도 되지만, 확장하거나 공유할 모든 것은 skills/에 속해야 합니다. (실제로 트리거를 유발하는 설명을 작성하는 방법은 별도의 주제입니다. 저는 이를 SKILL.md 가이드에서 다루었습니다.)
인자(Arguments): $ARGUMENTS, $0, 그리고 인용 규칙
제가 목격하는 거의 모든 혼란을 해결해 주는 세 가지 확장 규칙이 있습니다:
1. $ARGUMENTS는 입력된 문자열 전체입니다. /fix-issue 123 high-priority → $ARGUMENTS는 123 high-priority가 됩니다.
2. 인덱스 접근(Indexed access)은 0부터 시작하며 셸 인용(shell-quoted)됩니다. $ARGUMENTS[0] (또는 약어 $0)이 첫 번째 인자입니다. 인용구는 단어들을 그룹화합니다:
/migrate-component "search bar" React Vue
→ $0 = search bar, $1 = React, $2 = Vue
3. 누락된 값은 플레이스홀더(placeholder) 유형에 따라 다르게 동작합니다. 일치하는 인자가 없는 인덱스 플레이스홀더(예: 인자를 하나만 전달했을 때의 $2)는 텍스트 내에 변경되지 않은 채 그대로 남습니다. 프론트매터(frontmatter)에 선언된 이름이 지정된 플레이스홀더(named placeholder)는 _빈 문자열(empty string)_로 확장됩니다. 만약 본문에서 문자 그대로의 달러-숫자 표기(예: $1.00)가 필요하다면, 이스케이프(escape) 처리를 하세요: \$1.00.
하나 더 안전장치를 말씀드리자면: 인자를 전달했지만 파일에 $ARGUMENTS가 전혀 포함되어 있지 않은 경우, Claude Code는 파일 끝에 ARGUMENTS: <사용자 입력>을 추가하므로 사용자의 입력이 조용히 누락되는 일은 없습니다.
실시간 데이터 주입: !`command`
이 기능은 정형화된 프롬프트를 근거가 있는(grounded) 프롬프트로 바꿔줍니다. 다음과 같은 줄은:
## Current diff
!`git diff HEAD`
Claude가 확인하기 전"에 셸 명령어를 실행하며, 그 출력값이 플레이스홀더를 대체합니다. Claude는 데이터를 가져오라는 명령을 받는 것이 아니라 실제 diff를 직접 전달받습니다. 이를 통해 도구 사용(tool round-trip) 횟수를 한 번 줄일 수 있으며, 모델이 읽지도 않은 diff를 "요약"해버릴 가능성도 차단합니다.
치환은 단일 패스(single pass)로 이루어집니다. 즉, 명령어의 출력이 두 번째 확장을 위한 또 다른 !`…` 플레이스홀더를 생성할 수는 없습니다. 이를 매크로가 아닌 데이터로 취급하세요.
allowed-tools는 세션 설정이 아닌 단일 턴(one-turn) 권한 부여입니다
통합된 모델에서 가장 흔히 발생하는 의외의 상황입니다. 다음과 같은 프론트매터는:
allowed-tools: Bash(git add:*), Bash(git commit:*)
해당 스킬을 호출하는 해당 턴(turn)에 대해서만 해당 도구들을 사전 승인합니다. 스킬의 _내용(content)_은 컨텍스트에 유지되지만, 권한 부여는 다음 메시지를 보낼 때 해제됩니다. 따라서 "왜 Claude가 동일한 명령에 대해 다시 권한을 요청하는가?"라는 질문의 답은 대개 이렇습니다: 지침(instructions)은 유지되었지만, 권한 부여(grant)는 유지되지 않았기 때문입니다. 스킬을 다시 호출하면 권한도 다시 적용됩니다.
관련된 두 가지 참고 사항은 다음과 같습니다:
allowed-tools는 아무것도 제한하지 않습니다. 목록에 없는 도구들은 사용자의 일반적인 권한 설정에 따라 계속 사용할 수 있습니다.${CLAUDE_SKILL_DIR}는 본문(body)과allowed-tools모두에서 확장되므로, 스킬이 스크립트를 포함하고 해당 스크립트의 호출만을 정확하게 사전 승인(pre-approve)할 수 있습니다. 프롬프트나 와일드카드(wildcard)는 필요하지 않습니다.
세션 전체 동안 유지되는 권한(grant)을 원한다면, 대신 권한 규칙(permission rules)에 포함시켜야 합니다. allow/deny/ask 매칭 로직은 그 자체로 지뢰밭입니다.
누가 호출할 수 있는지 결정하기
기본적으로 사용자와 Claude 모두 모든 스킬을 실행할 수 있습니다. 두 가지 프론트매터(frontmatter) 스위치가 이를 변경합니다:
disable-model-invocation: true— 사용자만이 이를 트리거할 수 있습니다. 타이밍이 중요한 부수 효과(side effects)가 있는 작업에 사용하세요:/deploy,/commit,/send-release-notes. 코드가 "준비된 것처럼 보인다"는 이유로 모델이 직접 배포하는 상황을 방지하고 싶을 때 유용합니다.user-invocable: false— Claude만이 이를 로드할 수 있습니다.legacy-system-context스킬과 같이 유의미한 동작은 아니지만 배경 지식이 필요한 경우에 사용하세요.
스킬의 _설명(descriptions)_은 항상 컨텍스트에 포함되어 있어 Claude가 무엇이 존재하는지 알 수 있지만, _본문(body)_은 호출 시에만 로드됩니다.
본문은 유지됩니다 — 상시 명령(standing orders)처럼 작성하세요
한 번 호출되면, 렌더링된 콘텐츠는 세션이 끝날 때까지 대화에 유지됩니다(동일한 스킬을 다시 호출하면 중복되는 대신 "이미 로드됨"이라는 짧은 메모가 추가됩니다). 이로 인해 두 가지 결과가 발생합니다:
- 모든 줄은 반복적인 토큰 비용을 발생시킵니다. 무엇을 해야 하는지 명시하되, 왜 해야 하는지에 대한 에세이는 생략하세요.
- 일회성 단계가 아닌 상시 규칙("Y를 편집한 후에는 항상 X를 실행하라")으로 지침을 작성하세요. Claude는 이후의 턴에서 해당 파일을 다시 읽지 않습니다.
컨텍스트 압축(context compaction) 이후에는 최근 스킬들이 정해진 토큰 예산 내에서 다시 연결되므로, 긴 세션에서는 오래된 스킬들이 조용히 누락될 수 있습니다. 자세한 내용은 압축 시 무엇이 유지되는가를 참조하세요.
슬래시 명령어가 잘못된 도구인 경우
- Claude가 항상 알고 있어야 하는 사실 (fact) → CLAUDE.md에 한 줄로 작성.
- 계속해서 붙여넣게 되는 절차 (procedure) → 스킬 (skill). 이것이 가장 적합한 활용 사례입니다.
- 매번 결정론적으로 (deterministically) 반드시 실행되어야 하는 것 → 훅 (hook). 스킬은 모델이 준수하기로 선택하는 것에 의존하지만, 훅은 요청하지 않습니다.
- 컨텍스트(context)에 담기에 너무 큰 참조 자료 → 지원 파일과 함께 구성된 스킬로 만들고, SKILL.md에서 참조하여 필요할 때 로드합니다.
빠른 주의사항 체크리스트 (Quick gotcha checklist)
$0은 첫 번째 인자(0부터 시작)이며, 따옴표는 단어들을 그룹화합니다.- 일치하지 않는
$N은 문자 그대로 유지되며, 일치하지 않는 이름이 지정된 인자(named args)는 빈 값이 됩니다. !`command`는 Claude가 무엇인가를 읽기 전에 실행되며, 단 한 번만 통과(single pass)합니다.allowed-tools는 다음 메시지를 보낼 때 초기화됩니다.- 번들된 것과 같은 이름(
code-review)을 가진 프로젝트 스킬은 기존 것을 **대체(replaces)**합니다. .claude/commands/는 여전히 작동하지만, 스킬(skills)이 권장되는 경로입니다.
저는 Claude Code, Cursor, Codex를 위한 버전 관리형 규칙 및 스킬 팩인 Rulestack을 관리하고 있으며, 다음과 같은 변경 사항과 동기화하여 유지합니다: https://rulestack.gumroad.com?ref=devto
AI 코딩 워크플로우에 대한 데일리 노트는 Bluesky에서 확인할 수 있습니다: https://bsky.app/profile/ai-shop.bsky.social
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기