はじめに / 対象と前提
Claude Code を業務で使っていると、「この差分をレビューして。観点は〜」「テストを書いて。規約は〜」のような定型プロンプトを毎回打ち直していることに気づく。自分もレビュー依頼のたびに 10 行近い指示をコピペしていて、さすがに無駄だと思った。
この定型作業は カスタムスラッシュコマンド に切り出せる。.claude/commands/ に Markdown ファイルを置くだけで /review のような自前コマンドが生えて、引数も渡せる。この記事では最小構成から引数・コマンド実行結果の埋め込みまでの手順と、自分が実際に踏んだ 3 つのハマりどころをまとめる。
- 想定読者:Claude Code を日常的に使っていて、定型プロンプトのコピペ運用から抜けたい人
- 環境:Claude Code v2.x(2026年7月時点)/ macOS(Linux でも同じ)
TL;DR
-
.claude/commands/<name>.mdを作ると/<name>コマンドになる(ファイル名=コマンド名) - 本文中の
$ARGUMENTSが呼び出し時の引数に置換される。$1$2で個別参照も可 - frontmatter の
allowed-toolsを書かないと、!によるコマンド事前実行が動かない
手順 / 動かし方
1. 最小のコマンドを作る
プロジェクト直下で:
mkdir -p .claude/commands
cat > .claude/commands/review.md <<'EOF'
以下の観点で現在の差分をレビューしてほしい。
- バグ・エッジケースの見落とし
- 命名と責務の一貫性
- テストの不足
指摘は重要度順に、修正案付きで。
EOF
Claude Code を起動して /review と打つと、この本文がそのままプロンプトとして送られる。/ を打った時点の補完一覧にも review (project) として出てくる。これだけでコピペ運用は終わり。
2. 引数を受け取る
$ARGUMENTS プレースホルダを本文に書くと、/review src/api.ts の src/api.ts 部分が丸ごと差し込まれる。
---
description: 指定ファイルを重点レビュー
argument-hint: <file-path>
---
$ARGUMENTS を重点的にレビューしてほしい。
観点:バグ / 命名 / テスト不足。重要度順に修正案付きで。
frontmatter の description は補完一覧に説明として表示され、argument-hint は引数のヒント表示になる。引数が複数ある場合は $1 $2 で個別に拾える。/compare old.ts new.ts なら $1=old.ts、$2=new.ts。
3. コンテキストを自動で仕込む
行内の ! 記法でシェルコマンドの実行結果を、@ でファイル内容をプロンプトに埋め込める。コミットメッセージ生成コマンドの例:
---
description: 現在の差分からコミットメッセージを生成
allowed-tools: Bash(git status:*), Bash(git diff:*)
---
## 現在の状態
- ステータス: !`git status -s`
- staged 差分: !`git diff --staged`
この差分の内容で Conventional Commits 形式のコミットメッセージを提案して。
動作確認:変更を git add してから /commit-msg と打つと、staged 差分が埋め込まれたプロンプトが組み立てられ、feat: ... 形式のメッセージ案が返ってきた。差分を手で貼る必要がなくなる。
4. スコープを選ぶ
| 置き場所 | スコープ | 用途 |
|---|---|---|
.claude/commands/ |
プロジェクト | チーム共有(git 管理に含める) |
~/.claude/commands/ |
ユーザー | 個人用、全プロジェクト共通 |
チームで使うレビュー観点はプロジェクト側、個人の口癖的な指示はユーザー側、と分けるのが運用しやすい。
ハマりどころ
1. $ARGUMENTS が置換されずそのまま送られる
${ARGUMENTS} や $ARGUMENT(単数形)と書いてしまうと置換されない。有効なのは波括弧なし・大文字・複数形の $ARGUMENTS だけ。
もう 1 つ紛らわしいのが、本文に $ARGUMENTS を書かずに引数付きで呼んだ場合。このとき引数はプロンプト末尾に追記される仕様なので、「引数が効いてないように見えて実は末尾に居る」状態になる。意図した位置に差し込みたいならプレースホルダを明示的に書くこと。
2. ! の事前実行が動かない/毎回権限確認が出る
原因は allowed-tools に該当コマンドを書いていないこと。上の例のように Bash(git diff:*) の形式で列挙する。この記法は settings.json の permissions と同じで、Bash(git diff:*) は「git diff で始まるコマンドを許可」の意味。:* を付け忘れると完全一致扱いになり、git diff --staged のようにオプションが付いた瞬間マッチしなくなる。ここで 20 分溶かした。
3. サブディレクトリは名前空間になる(コマンド名には入らない)
整理のつもりで .claude/commands/frontend/component.md と置くと、コマンドは /frontend/component ではなく /component になる。ディレクトリ名は補完一覧に (project:frontend) と表示されるだけで、呼び出し名には含まれない。別ディレクトリに同名ファイルを置くと衝突するので、ファイル名自体をユニークに保つ必要がある。
背景・補足
スラッシュコマンドは「プロンプトのテンプレ展開」であって、別コンテキストで動く仕組みではない。似た機能のサブエージェント(.claude/agents)は独立したコンテキストで自律動作するので、役割が違う。
- いまの会話に定型指示を差し込みたい → スラッシュコマンド
- 調査や検証を別コンテキストに投げたい → サブエージェント
と使い分けている。まずはコピペしているプロンプトをそのまま 1 ファイルにするところから始めるのが手っ取り早い。
まとめ
- 定型プロンプトは
.claude/commands/*.mdに切り出すと/コマンドとして呼べる -
$ARGUMENTS/$1で引数、!+allowed-toolsでコマンド実行結果の埋め込みができる - ハマったら「スペル(
$ARGUMENTS固定)」「allowed-toolsの:*漏れ」「サブディレクトリの名前空間」の 3 点を疑う - チーム共有はプロジェクトスコープ、個人用はユーザースコープに置く