Agent SDK Skillsの使い方 — スラッシュコマンドでの呼び出し方
Agent SDKでSkillsを制御するskillsオプションとsettingSourcesの関係、スラッシュコマンドでの直接呼び出し、ツールの事前承認、よくあるトラブルの直し方までまとめました。
Agent SDKでSkillsを動かす3つの設定
Agent SDKのSkillsは、ファイルシステム上のSKILL.mdをClaudeが呼び出す仕組みです。.claude/skills/<name>/SKILL.mdとしてディスクに置くと、セッション起動時にメタデータが読み込まれ、使われる瞬間に本文が展開されます。Subagentsのようにagentsオプションへ直接定義する方法は無く、必ずファイルとして用意します。
動かすには、役割の違う3つの設定が関わります。
Skillsを動かす3つの設定
settingSources
Skillsをディスクから発見するかどうか。ここが外れていると、以降の設定は意味を持ちません。
skills
Claudeが自分の判断で呼べるSkillsの範囲。名前の配列、
"all"、[]で指定します。allowedTools
Skillが使うツールを、承認の確認なしで動かすかどうか。
呼び出しの経路も2種類あります。Claudeが会話の文脈から選ぶ「モデル起動」と、プロンプトに/<name>を書く「ユーザー起動」です。skillsオプションの許可リストが効くのは片方だけです。
skillsオプションが効く経路・効かない経路
モデル起動
Claudeが文脈から判断して呼ぶ経路です。リストに無い名前はモデルに見えず、Skill toolも拒否します。
ユーザー起動
プロンプトの/<name>で直接実行する経路です。skillsのリストに載せていないSkillも実行できます。
SKILL.mdのfrontmatterや本文構成の書き方はClaude Code Skills完全ガイドにまとまっています。Agent SDKの導入自体がまだの場合はClaude Agent SDK入門から始めると、query()の基本設計が先に頭に入ります。
skillsオプションでSkillsの利用範囲を絞る
query()のskillsオプションの値は次の3パターンです。
| 指定値 | Claudeが呼べる範囲 |
|---|---|
省略、または"all" | Claudeが呼べる範囲発見済みの全Skillsを許可 |
["pdf", "docx"]のような配列 | Claudeが呼べる範囲列挙した名前のみ許可 |
[] | Claudeが呼べる範囲どのSkillsも呼べない |
TypeScriptとPythonの指定は次の通りです。
const options = { skills: ["pdf", "docx"] };options = ClaudeAgentOptions(skills=["pdf", "docx"])skillsを設定すると、SDKはSkillツールをallowedToolsへ自動的に追加します。toolsリストを自分で明示している場合は、"Skill"を含めておかないとClaudeがSkillsを呼び出せません。
配列に渡す名前は、SKILL.mdのnameか、Skillのディレクトリ名と完全一致させます。プラグインのSkillはplugin:skillの形です。外れた名前を渡すと、セッションが始まる前にquery()がエラーで弾きます。
- 空文字
- 括弧・カンマ・制御文字を含む名前
- 前後に空白が付いた名前
*や:*で終わるワイルドカード
TypeScriptはError、PythonはValueErrorで、違反したルールを含むメッセージが返ります。skills: ["docs:*"]なら、次の文面です。
Invalid skill name "docs:*": wildcard-suffix names are not allowed; list each skill by its exact name.このチェックはTypeScript Agent SDK 0.3.221、Python Agent SDK 0.2.129で追加されました。それより古いバージョンでは、無効な名前を渡してもチェックが走りません。
リストから外したSkillのファイルは消えず、ReadやBashのような通常ツールからは読めます。ワイルドカードでの全許可はできません。
settingSourcesがSkillsの発見条件を決める
skillsで許可を絞る前に、Skillsがディスクから読み込まれている必要があります。SDKはユーザー(~/.claude/skills/)とプロジェクト(<cwd>/.claude/skills/、リポジトリルートまでの親ディレクトリを含む)から発見します。この発見元を制御するのがsettingSources(Pythonはsetting_sources)です。
settingSourcesを明示して"user"と"project"を両方外すと、Skillsは1つも読み込まれません。省略すればuser / project / localのすべてが読み込まれるので、通常は意識せずにSkillsが動きます。additionalDirectories(Pythonはadd_dirs)で渡したディレクトリの.claude/skills/も、プロジェクトソースの一部として扱われます。
# Skillsが読み込まれない: settingSourcesがuser/projectを含まない
options = ClaudeAgentOptions(setting_sources=[], skills="all")
# Skillsが読み込まれる
options = ClaudeAgentOptions(
setting_sources=["user", "project"],
skills="all",
)settingSourcesはSkills専用ではなく、CLAUDE.mdやfilesystem hooksの読み込みにも効く共通のスイッチです。値を触るときは、Skills以外への影響も一緒に見ます。
[]にしても、すべてが止まるわけではありません。管理ポリシー設定、~/.claude.json、~/.claude/projects/<project>/memory/の自動メモリーは、settingSourcesと無関係に読まれます。claude.aiのMCPコネクタも、claude.aiのログインで認証したセッションでは同様に読まれます。テナントごとに分離したいマルチテナント用途では、テナントごとにファイルシステムを分け、settingSources: []にCLAUDE_CODE_DISABLE_AUTO_MEMORY=1を組み合わせる構成が公式に示されています。
ターミナルのclaudeにも、同じ考え方のフラグがあります。v2.1.287のclaude --helpでは、次のように出ます。
claude --help | grep -E "setting-sources|disable-slash-commands" --disable-slash-commands Disable all skills
--setting-sources <sources> Comma-separated list of setting sources--setting-sourcesの説明は次の行に続き、読み込み元としてuser、project、localを指定できます。
initメッセージでロード結果を確認する
セッション開始直後に流れるsystem初期化メッセージ(subtype: "init")のskills配列を見ると、ユーザー起動可能なSkillsが実際に読み込まれたか確認できます。配列には、自分で書いたSkillsに加えてClaude Codeに同梱されているbundled skillsも並びます。descriptionかwhen_to_useを持たないSkillは載りません。
frontmatterでuser-invocable: falseを指定したSkillは、ディスクから読み込まれてClaudeは使えますが、skills配列には出ません。skillsオプションで許可したかどうかに関わらず、セッションが発見した内容がそのまま並びます。
同じinitメッセージのslash_commandsには、ビルトインコマンド・bundled skills・自分のユーザー起動Skills・.claude/commands/ファイルがまとまって並びます。インタラクティブな端末を必要とする/themeや/terminal-setupは載りません。MCPサーバーを設定したセッションでは、MCPのプロンプトもコマンドとして加わります。
if (message.type === "system" && message.subtype === "init") {
console.log("Available commands:", message.slash_commands);
}出力は次のような並びになります。
Available commands: ["clear", "compact", "context", "usage", "code-review", "verify", "security-check", ...]スラッシュコマンドで名前指定して呼び出す
プロンプト文字列に/<name>を書けば、Claudeの判断を待たずにSkillを直接実行できます。プラグイン経由のSkillsは/plugin-name:skill-nameの形で呼びます。
存在しない名前を送ったときの挙動は、バージョンで違います。
| 送った名前 | v2.1.274以降 | v2.1.274より前 |
|---|---|---|
セッションにもビルトインにも無い/<name> | v2.1.274以降通常のメッセージとしてClaudeに渡り、コマンドが実行されなかった旨の注記が付く。モデルの1ターンを使う | v2.1.274より前Unknown command: /<name>が結果として返り、モデルは呼ばれない |
端末専用で使えないビルトイン(/themeなど) | v2.1.274以降/theme isn't available in this environment.が結果として返る(モデルは呼ばれない) | v2.1.274より前— |
タイプミスのコマンドがエラーにならず、モデルの1ターン分の費用をかけて返答が来る点に注意が要ります。
/compactのように会話履歴を操作するコマンドは、要約する履歴が無いと成立しません。単発のquery()は毎回空のコンテキストから始まるので、ストリーミング入力モードか、resumeでセッションを再開した状態で使います。履歴が足りないときもエラーにはならず、successの結果にNot enough messages to compact.のような理由が入ります。/clearも同じ型で、会話を空に戻しますが、前の会話はディスクに残り、セッションIDをresumeに渡せば戻れます。単発のquery()で送っても、実質的な効果はありません。
コマンドの実行も通常のプロンプトと同じくmaxTurns(Pythonはmax_turns)の上限にかかります。上限に達するとsuccessではなくエラー付きの結果でクエリが終わります。長引きそうならtry/catch(Pythonはtry/except)で囲むか、上限に余裕を持たせます。
Skillに引数を渡すときは、/security-check src/のように名前の後ろへテキストを続けます。SKILL.md側で$ARGUMENTSや$0・$1といった置換変数を定義しておけば、渡した文字列が展開された状態で本文が実行されます。
Skillsが使うツールを事前承認する
Skillsはセッションのツールをそのまま使って動きます。ファイル読み取りが必要なSkillを承認なしで走らせたいなら、allowedTools(Pythonはallowed_tools)にツール名を渡します。
options = ClaudeAgentOptions(
setting_sources=["user", "project"],
skills="all",
allowed_tools=["Read", "Grep", "Glob"],
)プロジェクト / ユーザーSkillsでは、SKILL.mdのfrontmatterにあるallowed-toolsフィールドもSDKセッションで適用されます。allowedToolsオプションと併せて、二重に事前承認できる形です。claude.aiから同期されたSkillsだけは、同期されたfrontmatterのルールに従います。組織が管理設定でallowManagedPermissionRulesOnlyを有効にしている場合、この2つはどちらも無視されます。
このリストは指定したツールを承認するだけで、それ以外のツールを禁止するものではありません。権限モードやcanUseToolコールバックを含む全体の権限フローは別に設計します。
Skillsが動かないときの切り分け
症状ごとに、まずinitメッセージのskills配列に名前があるかを見ると原因の層が分かれます。
切り分けの順番
- 1
initのskills配列に名前が無い
発見の問題です。
settingSourcesとcwd、ファイルの置き場所を疑います。 - 2
配列にはあるのにClaudeが呼ばない
skillsの許可リストか、SKILL.mdのdescriptionが原因です。 - 3
呼ばれたが承認で止まる
allowedToolsか権限モードの設定を見ます。
Skillsが見つからない: settingSourcesを明示していてuser / projectを含めていないケースをまず疑います。次がcwdのずれで、SDKはcwdと、そこからリポジトリルートまでの各親ディレクトリの.claude/skills/を探します。cwdが対象ディレクトリの外やリポジトリの外を指していると見つかりません。ls .claude/skills/*/SKILL.mdでファイルの実在を先に確かめます。
設定が合っているのに直らないときは、SDKのバージョンも疑います。TypeScript Agent SDKでは0.1.25で、'project'を指定してもプロジェクトレベルのSkillsが読み込まれないバグが修正されました。詳しい切り分けはこのバグの切り分け方にまとめています。
Skillが呼ばれない: skillsに配列を渡しているなら、名前が入っているかを見ます。許可リストに無いSkillをClaudeが呼ぼうとすると、Skill toolはSkill <name> is not in this session's skills allowlistを返して止まります。名前を足すか、/<name>で直接呼べば許可リストを経由せずに動きます。それでも呼ばれなければSKILL.mdのdescriptionです。具体的なキーワードを含む説明でないと、Claudeが「関連する」と判断しません。書き方のパターンはClaude Code Skillsの書き方にあります。
名前を渡したのにエラーで弾かれる: 前の節で挙げた4種類の名前のどれかです。エラーメッセージに違反したルールがそのまま書かれているので、読んで名前を直します。
Agent SDK Skillsをどう使い分けるか
セッションの性質でskillsの選び方は変わります。開発中でCLIと同じ挙動が欲しいなら省略、本番で使わせるSkillsを固定したいなら配列で明示、Skillsをモデルから呼べなくしたいなら[]です。
よくある質問
.claude/commands/のファイルはskillsオプションの対象になりますか
skillsの許可リストが効くのは、Claudeが文脈から呼ぶSkillの範囲です。.claude/commands/のコマンドファイルはslash_commandsに並び、/<name>での直接実行は許可リストとは無関係に動きます。コマンドファイルは.claude/skills/<name>/SKILL.mdのSkillと同じ/<name>を作り、同じように動きます。
Claude Codeに同梱されているbundled skillsは止められますか
skillsはClaudeが呼べるSkillの範囲を絞るオプションです。bundled skillsを無効にするには、まとめて止める場合はdisableBundledSkills、1つだけ隠す場合はskillOverridesでそのSkillを"off"にします。/doctorはv2.1.205以降、disableBundledSkillsを有効にしても入力できます。隠すにはDISABLE_DOCTOR_COMMAND環境変数か、skillOverridesの"doctor": "off"を使います。
同じ名前のSkillと.claude/commands/ファイルがあると、どちらが動きますか
組み合わせで結果が逆になります。自分で置いたSkillと同名のコマンドファイルなら、Skillが動きます。Claude Code同梱のbundled skillと同名のコマンドファイルなら、コマンドファイルが同梱Skillを覆います。たとえば.claude/commands/code-review.mdを作ると、同梱のcode-reviewより先にそのファイルが使われ、slash_commandsには名前が1つだけ並びます。
まとめ
ユーザーのプロンプトをそのままquery()へ渡す設計では、/<name>で許可リスト外のSkillも動く前提で、置くSkillを選びます。