Slash Commands in the SDK
agent-sdk/slash-commands
This page was removed upstream on . Its history is below, and the last text this site read is still at .md on this URL.
History
agent-sdk/slash-commands Page removed · 514 lines, page removed
# Slash Commands in the SDK ## Discovering Available Slash Commands ## Sending Slash Commands ## Common Slash Commands ### `/compact` - Compact conversation history ### `/clear` - Reset conversation context ## Creating Custom Slash Commands ### File Locations ### File Format #### Basic Example #### With Frontmatter ### Using Custom Commands in the SDK ### Advanced Features #### Arguments and Placeholders #### Bash Command Execution #### File References ### Organization with Namespacing ### Practical Examples #### Pull Request Review Command #### Test Runner Command ## See Also
The page is gone upstream. What it last said is kept here.
agent-sdk/slash-commands First recorded · 514 lines, first recorded
# Slash Commands in the SDK ## Discovering Available Slash Commands ## Sending Slash Commands ## Common Slash Commands ### `/compact` - Compact conversation history ### `/clear` - Reset conversation context ## Creating Custom Slash Commands ### File Locations ### File Format #### Basic Example #### With Frontmatter ### Using Custom Commands in the SDK ### Advanced Features #### Arguments and Placeholders #### Bash Command Execution #### File References ### Organization with Namespacing ### Practical Examples #### Pull Request Review Command #### Test Runner Command ## See Also
The first capture of this source. The page was already there, and this is what it said.
# Slash Commands in the SDK
> Learn how to use slash commands to control Claude Code sessions through the SDK
Slash commands provide a way to control Claude Code sessions with special commands that start with `/`. These commands can be sent through the SDK to perform actions like compacting context, listing context usage, or invoking custom commands. Only commands that work without an interactive terminal are dispatchable through the SDK; the `system/init` message lists the ones available in your session.
## Discovering Available Slash Commands
The Claude Agent SDK provides information about available slash commands in the system initialization message. Access this information when your session starts:
<CodeGroup>
```typescript TypeScript theme={null}
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "Hello Claude",
options: { maxTurns: 1 }
})) {
if (message.type === "system" && message.subtype === "init") {
console.log("Available slash commands:", message.slash_commands);
// Includes built-in commands plus bundled skills, for example:
// ["clear", "compact", "context", "usage", "code-review", "verify", ...]
}
}
```
```python Python theme={null}
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, SystemMessage
async def main():
async for message in query(prompt="Hello Claude", options=ClaudeAgentOptions(max_turns=1)):
if isinstance(message, SystemMessage) and message.subtype == "init":
print("Available slash commands:", message.data["slash_commands"])
# Includes built-in commands plus bundled skills, for example:
# ["clear", "compact", "context", "usage", "code-review", "verify", ...]
asyncio.run(main())
```
</CodeGroup>
## Sending Slash Commands
Send slash commands by including them in your prompt string, just like regular text. Commands that act on conversation history, such as `/compact`, need prior messages to work with, so the examples below ask a question first and then send the command as a follow-up to the same conversation:
<CodeGroup>
```typescript TypeScript theme={null}
import { query } from "@anthropic-ai/claude-agent-sdk";
// Build up conversation history first
try {
for await (const message of query({
prompt: "What does the README in this directory cover?",
options: { maxTurns: 2 }
})) {
if (message.type === "result" && message.subtype === "success") {
console.log(message.result);
}
}
} catch (error) {
// A single-shot query() throws after yielding an error result,
// so the follow-up query below still runs.
console.error(`Session ended with an error: ${error}`);
}
// Send a slash command as a follow-up to the same conversation
for await (const message of query({
prompt: "/compact",
options: { continue: true, maxTurns: 1 }
})) {
if (message.type === "result") {
console.log("Command executed, result subtype:", message.subtype);
// Example output: Command executed, result subtype: success
}
}
```
```python Python theme={null}
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage
async def main():
# Build up conversation history first
try:
async for message in query(
prompt="What does the README in this directory cover?",
options=ClaudeAgentOptions(max_turns=2),
):
if isinstance(message, ResultMessage) and message.subtype == "success":
print(message.result)
except Exception as error:
# A single-shot query() raises after yielding an error result,
# so the follow-up query below still runs.
print(f"Session ended with an error: {error}")
# Send a slash command as a follow-up to the same conversation
async for message in query(
prompt="/compact",
options=ClaudeAgentOptions(continue_conversation=True, max_turns=1),
):
if isinstance(message, ResultMessage):
print("Command executed, result subtype:", message.subtype)
# Example output: Command executed, result subtype: success
asyncio.run(main())
```
</CodeGroup>
<Note>
A query can end with an error result, for example when the `maxTurns` / `max_turns` limit is reached before the work completes. The final result message then has `is_error: true` and an error subtype such as `error_max_turns` instead of `success`.
After yielding that final result message, the SDK raises an error, because the CLI process exits with a non-zero code.
Wrap the loop in a `try`/`catch` in TypeScript or `try`/`except` in Python if your command might hit the limit, as shown in [Single Message Input](/docs/en/agent-sdk/streaming-vs-single-mode#single-message-input), or set `maxTurns` high enough for the work to complete. In Python, catch `Exception`: the SDK surfaces error results as a plain `Exception`.
</Note>
## Common Slash Commands
### `/compact` - Compact conversation history
The `/compact` command reduces the size of your conversation history by summarizing older messages while preserving important context. Compaction needs an existing conversation with at least two prior exchanges to summarize. This example has a conversation first, then compacts it and reads the `compact_boundary` system message that reports the result:
<CodeGroup>
```typescript TypeScript theme={null}
import { query } from "@anthropic-ai/claude-agent-sdk";
// Compaction needs existing history, so have a conversation first
try {
for await (const message of query({
prompt: "Explain what this project does",
options: { maxTurns: 2 }
})) {
if (message.type === "result" && message.subtype === "success") {
console.log(message.result);
}
}
} catch (error) {
// A single-shot query() throws after yielding an error result,
// so the follow-up query below still runs.
console.error(`Session ended with an error: ${error}`);
}
// Compact the same conversation
for await (const message of query({
prompt: "/compact",
options: { continue: true, maxTurns: 1 }
})) {
if (message.type === "system" && message.subtype === "compact_boundary") {
console.log("Compaction completed");
console.log("Pre-compaction tokens:", message.compact_metadata.pre_tokens);
console.log("Trigger:", message.compact_metadata.trigger);
// Example output:
// Compaction completed
// Pre-compaction tokens: 1842
// Trigger: manual
}
}
```
```python Python theme={null}
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage, SystemMessage
async def main():
# Compaction needs existing history, so have a conversation first
try:
async for message in query(
prompt="Explain what this project does",
options=ClaudeAgentOptions(max_turns=2),
):
if isinstance(message, ResultMessage) and message.subtype == "success":
print(message.result)
except Exception as error:
# A single-shot query() raises after yielding an error result,
# so the follow-up query below still runs.
print(f"Session ended with an error: {error}")
# Compact the same conversation
async for message in query(
prompt="/compact",
options=ClaudeAgentOptions(continue_conversation=True, max_turns=1),
):
if isinstance(message, SystemMessage) and message.subtype == "compact_boundary":
print("Compaction completed")
print("Pre-compaction tokens:", message.data["compact_metadata"]["pre_tokens"])
print("Trigger:", message.data["compact_metadata"]["trigger"])
# Example output:
# Compaction completed
# Pre-compaction tokens: 1842
# Trigger: manual
asyncio.run(main())
```
</CodeGroup>
<Note>
A `compact_boundary` message only arrives when compaction ran. With nothing to summarize, `/compact` reports the reason instead of raising: the run still ends with a `success` result, no `compact_boundary` message is emitted, and the result text carries the message, for example `Not enough messages to compact.` after a single short exchange. A fresh one-shot `query()` call starts with empty context, so use this pattern in a session with prior turns, for example in [streaming input mode](/docs/en/agent-sdk/streaming-vs-single-mode) or when resuming a session.
</Note>
### `/clear` - Reset conversation context
The `/clear` command resets the conversation to an empty context, so subsequent prompts start with no prior conversation history. The previous conversation remains on disk and can be returned to by passing its session ID to the [`resume` option](/docs/en/agent-sdk/sessions#resume-by-id).
This is useful in [streaming input mode](/docs/en/agent-sdk/streaming-vs-single-mode), where you send multiple prompts over a single connection. For one-shot `query()` calls, each call already starts with empty context, so sending `/clear` has no practical effect; start a new `query()` instead.
## Creating Custom Slash Commands
In addition to using built-in slash commands, you can create your own custom commands that are available through the SDK. You define custom commands as markdown files in specific directories, the same way you configure subagents.
<Note>
Custom commands have been merged into skills. A file in `.claude/commands/` and a skill at `.claude/skills/<name>/SKILL.md` both create `/name` and work the same way. For new work, prefer skills, which add features like a directory for supporting files; see [Skills](/docs/en/agent-sdk/skills) for SDK usage. The CLI supports both locations, and the examples below remain accurate for `.claude/commands/`.
</Note>
### File Locations
Save custom slash commands in one of these directories, depending on their scope:
* **Project commands**: `.claude/commands/` - Available only in the current project. For new work, prefer `.claude/skills/`.
* **Personal commands**: `~/.claude/commands/` - Available across all your projects. For new work, prefer `~/.claude/skills/`.
### File Format
Each custom command is a markdown file where:
* The filename (without `.md` extension) becomes the command name
* The file content defines what the command does
* Optional YAML frontmatter provides configuration
#### Basic Example
Create the `.claude/commands` directory in your project if it doesn't exist, then create `.claude/commands/refactor.md`:
```markdown theme={null}
Refactor the selected code to improve readability and maintainability.
Focus on clean code principles and best practices.
```
This creates the `/refactor` command that you can use through the SDK.
#### With Frontmatter
Create `.claude/commands/security-check.md`:
```markdown theme={null}
---
allowed-tools: Read, Grep, Glob
description: Run security vulnerability scan
model: claude-opus-4-8
---
Analyze the codebase for security vulnerabilities including:
- SQL injection risks
- XSS vulnerabilities
- Exposed credentials
- Insecure configurations
```
### Using Custom Commands in the SDK
Once defined in the filesystem, custom commands are automatically available through the SDK:
<CodeGroup>
```typescript TypeScript theme={null}
import { query } from "@anthropic-ai/claude-agent-sdk";
// Use a custom command
try {
for await (const message of query({
prompt: "/refactor src/auth/login.ts",
options: { maxTurns: 3 }
})) {
if (message.type === "assistant") {
console.log("Refactoring suggestions:", message.message);
}
}
} catch (error) {
// A single-shot query() throws after yielding an error result,
// so the second query below still runs.
console.error(`Session ended with an error: ${error}`);
}
// Custom commands appear in the slash_commands list
for await (const message of query({
prompt: "Hello",
options: { maxTurns: 1 }
})) {
if (message.type === "system" && message.subtype === "init") {
console.log("Available commands:", message.slash_commands);
// Includes built-in commands plus bundled skills and your custom commands, for example:
// ["clear", "compact", "context", "usage", "code-review", "verify", "refactor", "security-check", ...]
}
}
```
Cut at 300 lines.